Index: HelenOS.config
===================================================================
--- HelenOS.config	(revision 76ecb300e88900544c3ed958ebd01eea01eda40e)
+++ HelenOS.config	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -509,2 +509,12 @@
 % Write core files
 ! CONFIG_WRITE_CORE_FILES (n/y)
+
+% Networking architecture
+@ "none" No networking
+@ "modular" Modular
+@ "module" One module
+! NETWORKING (choice)
+
+% DP8390 (NE2k) network interface
+! [NETWORKING=modular|NETWORKING=module] CONFIG_NETIF_DP8390 (y/n)
+
Index: boot/Makefile.common
===================================================================
--- boot/Makefile.common	(revision 76ecb300e88900544c3ed958ebd01eea01eda40e)
+++ boot/Makefile.common	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -85,2 +85,46 @@
 	COMPONENTS += $(USPACEDIR)/srv/fs/fat/fat
 endif
+
+CFG =
+
+NET_SRVS = \
+	$(USPACEDIR)/srv/net/net/net \
+	$(USPACEDIR)/srv/net/netif/lo/lo \
+	$(USPACEDIR)/srv/net/netif/dp8390/dp8390 \
+	$(USPACEDIR)/srv/net/nil/eth/eth \
+	$(USPACEDIR)/srv/net/nil/nildummy/nildummy \
+	$(USPACEDIR)/srv/net/app/echo/echo
+
+NET_APPS = \
+	$(USPACEDIR)/srv/net/net/start/netstart \
+	$(USPACEDIR)/srv/net/app/ping/ping \
+	$(USPACEDIR)/srv/net/app/nettest1/nettest1 \
+	$(USPACEDIR)/srv/net/app/nettest2/nettest2
+
+NET_CFG = \
+	$(USPACEDIR)/srv/net/cfg/$(NETWORKING)/general \
+	$(USPACEDIR)/srv/net/cfg/$(NETWORKING)/lo \
+	$(USPACEDIR)/srv/net/cfg/$(NETWORKING)/ne2k
+
+ifeq ($(NETWORKING), module)
+	RD_APPS +=	$(NET_APPS)
+
+	RD_SRVS +=	$(NET_SRVS)
+
+	CFG		+=	$(NET_CFG)
+else
+ifeq ($(NETWORKING), modular)
+	RD_APPS +=	$(NET_APPS)
+
+	RD_SRVS +=	$(NET_SRVS)
+
+	RD_SRVS +=	$(USPACEDIR)/srv/net/il/ip/ip \
+			$(USPACEDIR)/srv/net/il/arp/arp \
+			$(USPACEDIR)/srv/net/tl/udp/udp \
+			$(USPACEDIR)/srv/net/tl/tcp/tcp \
+			$(USPACEDIR)/srv/net/tl/icmp/icmp
+
+	CFG		+=	$(NET_CFG)
+endif
+endif
+
Index: boot/arch/amd64/Makefile.inc
===================================================================
--- boot/arch/amd64/Makefile.inc	(revision 76ecb300e88900544c3ed958ebd01eea01eda40e)
+++ boot/arch/amd64/Makefile.inc	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -39,5 +39,5 @@
 build: $(BASE)/image.iso
 
-$(BASE)/image.iso: arch/$(BARCH)/grub/stage2_eltorito $(KERNELDIR)/kernel.bin $(INIT_TASKS) $(RD_SRVS) $(RD_APPS)
+$(BASE)/image.iso: arch/$(BARCH)/grub/stage2_eltorito $(KERNELDIR)/kernel.bin $(INIT_TASKS) $(RD_SRVS) $(RD_APPS) $(CFG)
 	mkdir -p $(TMP)/boot/grub
 	cp arch/$(BARCH)/grub/stage2_eltorito $(TMP)/boot/grub/
@@ -56,4 +56,8 @@
 	done
 	
+	rm -f $(USPACEDIR)/dist/srv/*
+	rm -f $(USPACEDIR)/dist/app/*
+	rm -f $(USPACEDIR)/dist/cfg/net/*
+	
 	cp $(KERNELDIR)/kernel.bin $(TMP)/boot/
 	for task in $(INIT_TASKS) ; do \
@@ -65,4 +69,7 @@
 	for file in $(RD_APPS) ; do \
 		cp $$file $(USPACEDIR)/dist/app/ ; \
+	done
+	for file in $(NET_CFG) ; do \
+		cp $$file $(USPACEDIR)/dist/cfg/net/ ; \
 	done
 	
@@ -78,4 +85,8 @@
 
 clean:
+	rm -f $(USPACEDIR)/dist/srv/*
+	rm -f $(USPACEDIR)/dist/app/*
+	rm -f $(USPACEDIR)/dist/cfg/net/*
+
 	for file in $(RD_SRVS) ; do \
 		rm -f $(USPACEDIR)/dist/srv/`basename $$file` ; \
@@ -84,4 +95,7 @@
 		rm -f $(USPACEDIR)/dist/app/`basename $$file` ; \
 	done
+	for file in $(NET_CFG) ; do \
+		rm -f $(USPACEDIR)/dist/cfg/net/`basename $$file` ; \
+	done
 	rm -fr $(TMP)
 	rm -f $(BASE)/image.iso
Index: boot/arch/arm32/loader/Makefile
===================================================================
--- boot/arch/arm32/loader/Makefile	(revision 76ecb300e88900544c3ed958ebd01eea01eda40e)
+++ boot/arch/arm32/loader/Makefile	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -37,4 +37,8 @@
 
 clean:
+	rm -f $(USPACEDIR)/dist/srv/*
+	rm -f $(USPACEDIR)/dist/app/*
+	rm -f $(USPACEDIR)/dist/cfg/net/*
+
 	for file in $(RD_SRVS) ; do \
 		rm -f $(USPACEDIR)/dist/srv/`basename $$file` ; \
@@ -43,4 +47,7 @@
 		rm -f $(USPACEDIR)/dist/app/`basename $$file` ; \
 	done
+	for file in $(NET_CFG) ; do \
+		rm -f $(USPACEDIR)/dist/cfg/net/`basename $$file` ; \
+	done
 	rm -f $(DEPEND) $(DEPEND_PREV) $(JOB) $(OUTPUT) $(COMPS).h $(COMPS).c $(LINK) $(INITRD).img $(INITRD).fs
 	find . -name '*.o' -follow -exec rm \{\} \;
Index: boot/arch/arm32/loader/Makefile.build
===================================================================
--- boot/arch/arm32/loader/Makefile.build	(revision 76ecb300e88900544c3ed958ebd01eea01eda40e)
+++ boot/arch/arm32/loader/Makefile.build	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -76,4 +76,8 @@
 
 $(DEPEND):
+	rm -f $(USPACEDIR)/dist/srv/*
+	rm -f $(USPACEDIR)/dist/app/*
+	rm -f $(USPACEDIR)/dist/cfg/net/*
+
 	for file in $(RD_SRVS) ; do \
 		cp $$file $(USPACEDIR)/dist/srv/ ; \
@@ -81,4 +85,7 @@
 	for file in $(RD_APPS) ; do \
 		cp $$file $(USPACEDIR)/dist/app/ ; \
+	done
+	for file in $(NET_CFG) ; do \
+		cp $$file $(USPACEDIR)/dist/cfg/net/ ; \
 	done
 ifeq ($(RDFMT),tmpfs)
Index: boot/arch/ia64/loader/Makefile
===================================================================
--- boot/arch/ia64/loader/Makefile	(revision 76ecb300e88900544c3ed958ebd01eea01eda40e)
+++ boot/arch/ia64/loader/Makefile	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -40,4 +40,9 @@
 	$(MAKE) -C gefi clean
 	$(MAKE) -C gefi/HelenOS clean
+
+	rm -f $(USPACEDIR)/dist/srv/*
+	rm -f $(USPACEDIR)/dist/app/*
+	rm -f $(USPACEDIR)/dist/cfg/net/*
+
 	for file in $(RD_SRVS) ; do \
 		rm -f $(USPACEDIR)/dist/srv/`basename $$file` ; \
@@ -46,4 +51,7 @@
 		rm -f $(USPACEDIR)/dist/app/`basename $$file` ; \
 	done
+	for file in $(NET_CFG) ; do \
+		rm -f $(USPACEDIR)/dist/cfg/net/`basename $$file` ; \
+	done
 	rm -f $(DEPEND) $(DEPEND_PREV) $(JOB) $(OUTPUT) $(HELLO) $(COMPS).h $(COMPS).c $(LINK) $(INITRD).img $(INITRD).fs
 	find . -name '*.o' -follow -exec rm \{\} \;
Index: boot/arch/ia64/loader/Makefile.build
===================================================================
--- boot/arch/ia64/loader/Makefile.build	(revision 76ecb300e88900544c3ed958ebd01eea01eda40e)
+++ boot/arch/ia64/loader/Makefile.build	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -77,4 +77,8 @@
 
 $(DEPEND):
+	rm -f $(USPACEDIR)/dist/srv/*
+	rm -f $(USPACEDIR)/dist/app/*
+	rm -f $(USPACEDIR)/dist/cfg/net/*
+
 	for file in $(RD_SRVS) ; do \
 		cp $$file $(USPACEDIR)/dist/srv/ ; \
@@ -82,4 +86,7 @@
 	for file in $(RD_APPS) ; do \
 		cp $$file $(USPACEDIR)/dist/app/ ; \
+	done
+	for file in $(NET_CFG) ; do \
+		cp $$file $(USPACEDIR)/dist/cfg/net/ ; \
 	done
 ifeq ($(RDFMT),tmpfs)
Index: boot/arch/mips32/loader/Makefile
===================================================================
--- boot/arch/mips32/loader/Makefile	(revision 76ecb300e88900544c3ed958ebd01eea01eda40e)
+++ boot/arch/mips32/loader/Makefile	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -37,4 +37,8 @@
 
 clean:
+	rm -f $(USPACEDIR)/dist/srv/*
+	rm -f $(USPACEDIR)/dist/app/*
+	rm -f $(USPACEDIR)/dist/cfg/net/*
+
 	for file in $(RD_SRVS) ; do \
 		rm -f $(USPACEDIR)/dist/srv/`basename $$file` ; \
@@ -43,4 +47,7 @@
 		rm -f $(USPACEDIR)/dist/app/`basename $$file` ; \
 	done
+	for file in $(NET_CFG) ; do \
+		rm -f $(USPACEDIR)/dist/cfg/net/`basename $$file` ; \
+	done
 	rm -f $(DEPEND) $(DEPEND_PREV) $(JOB) $(OUTPUT) $(RAW) $(COMPS).h $(COMPS).c $(LINK) $(INITRD).img $(INITRD).fs
 	find . -name '*.o' -follow -exec rm \{\} \;
Index: boot/arch/mips32/loader/Makefile.build
===================================================================
--- boot/arch/mips32/loader/Makefile.build	(revision 76ecb300e88900544c3ed958ebd01eea01eda40e)
+++ boot/arch/mips32/loader/Makefile.build	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -77,4 +77,8 @@
 
 $(DEPEND):
+	rm -f $(USPACEDIR)/dist/srv/*
+	rm -f $(USPACEDIR)/dist/app/*
+	rm -f $(USPACEDIR)/dist/cfg/net/*
+
 	for file in $(RD_SRVS) ; do \
 		cp $$file $(USPACEDIR)/dist/srv/ ; \
@@ -82,4 +86,7 @@
 	for file in $(RD_APPS) ; do \
 		cp $$file $(USPACEDIR)/dist/app/ ; \
+	done
+	for file in $(NET_CFG) ; do \
+		cp $$file $(USPACEDIR)/dist/cfg/net/ ; \
 	done
 ifeq ($(RDFMT),tmpfs)
Index: boot/arch/ppc32/loader/Makefile
===================================================================
--- boot/arch/ppc32/loader/Makefile	(revision 76ecb300e88900544c3ed958ebd01eea01eda40e)
+++ boot/arch/ppc32/loader/Makefile	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -37,4 +37,8 @@
 
 clean:
+	rm -f $(USPACEDIR)/dist/srv/*
+	rm -f $(USPACEDIR)/dist/app/*
+	rm -f $(USPACEDIR)/dist/cfg/net/*
+
 	for file in $(RD_SRVS) ; do \
 		rm -f $(USPACEDIR)/dist/srv/`basename $$file` ; \
@@ -43,4 +47,7 @@
 		rm -f $(USPACEDIR)/dist/app/`basename $$file` ; \
 	done
+	for file in $(NET_CFG) ; do \
+		rm -f $(USPACEDIR)/dist/cfg/net/`basename $$file` ; \
+	done
 	rm -f $(DEPEND) $(DEPEND_PREV) $(JOB) $(OUTPUT) $(COMPS).h $(COMPS).c $(LINK) $(INITRD).img $(INITRD).fs
 	find . -name '*.o' -follow -exec rm \{\} \;
Index: boot/arch/ppc32/loader/Makefile.build
===================================================================
--- boot/arch/ppc32/loader/Makefile.build	(revision 76ecb300e88900544c3ed958ebd01eea01eda40e)
+++ boot/arch/ppc32/loader/Makefile.build	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -77,4 +77,8 @@
 
 $(DEPEND):
+	rm -f $(USPACEDIR)/dist/srv/*
+	rm -f $(USPACEDIR)/dist/app/*
+	rm -f $(USPACEDIR)/dist/cfg/net/*
+
 	for file in $(RD_SRVS) ; do \
 		cp $$file $(USPACEDIR)/dist/srv/ ; \
@@ -82,4 +86,7 @@
 	for file in $(RD_APPS) ; do \
 		cp $$file $(USPACEDIR)/dist/app/ ; \
+	done
+	for file in $(NET_CFG) ; do \
+		cp $$file $(USPACEDIR)/dist/cfg/net/ ; \
 	done
 ifeq ($(RDFMT),tmpfs)
Index: boot/arch/sparc64/loader/Makefile
===================================================================
--- boot/arch/sparc64/loader/Makefile	(revision 76ecb300e88900544c3ed958ebd01eea01eda40e)
+++ boot/arch/sparc64/loader/Makefile	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -37,4 +37,8 @@
 
 clean:
+	rm -f $(USPACEDIR)/dist/srv/*
+	rm -f $(USPACEDIR)/dist/app/*
+	rm -f $(USPACEDIR)/dist/cfg/net/*
+
 	for file in $(RD_SRVS) $(RD_SRVS_GENERIC) ; do \
 		rm -f $(USPACEDIR)/dist/srv/`basename $$file` ; \
@@ -43,4 +47,7 @@
 		rm -f $(USPACEDIR)/dist/app/`basename $$file` ; \
 	done
+	for file in $(NET_CFG) ; do \
+		rm -f $(USPACEDIR)/dist/cfg/net/`basename $$file` ; \
+	done
 	rm -f $(DEPEND) $(DEPEND_PREV) $(JOB) $(OUTPUT) $(COMPS).h $(COMPS).c $(LINK) $(INITRD).img $(INITRD).fs
 	find . -name '*.o' -follow -exec rm \{\} \;
Index: boot/arch/sparc64/loader/Makefile.build
===================================================================
--- boot/arch/sparc64/loader/Makefile.build	(revision 76ecb300e88900544c3ed958ebd01eea01eda40e)
+++ boot/arch/sparc64/loader/Makefile.build	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -88,4 +88,8 @@
 
 $(DEPEND):
+	rm -f $(USPACEDIR)/dist/srv/*
+	rm -f $(USPACEDIR)/dist/app/*
+	rm -f $(USPACEDIR)/dist/cfg/net/*
+
 	for file in $(RD_SRVS) ; do \
 		cp $$file $(USPACEDIR)/dist/srv/ ; \
@@ -93,4 +97,7 @@
 	for file in $(RD_APPS) ; do \
 		cp $$file $(USPACEDIR)/dist/app/ ; \
+	done
+	for file in $(NET_CFG) ; do \
+		cp $$file $(USPACEDIR)/dist/cfg/net/ ; \
 	done
 ifeq ($(RDFMT),tmpfs)
Index: contrib/conf/net-qe.bat
===================================================================
--- contrib/conf/net-qe.bat	(revision 209faf93503c78d1423ac244db45224381577454)
+++ contrib/conf/net-qe.bat	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,26 @@
+REM Start qemu on windows.
+REM tested with qemu-0.10.6-windows
+
+@ECHO OFF
+
+REM SDL_VIDEODRIVER=directx is faster than windib. But keyboard cannot work well.
+SET SDL_VIDEODRIVER=windib
+
+REM SDL_AUDIODRIVER=waveout or dsound can be used. Only if QEMU_AUDIO_DRV=sdl.
+SET SDL_AUDIODRIVER=dsound
+
+REM QEMU_AUDIO_DRV=dsound or fmod or sdl or none can be used. See qemu -audio-help.
+SET QEMU_AUDIO_DRV=dsound
+
+REM QEMU_AUDIO_LOG_TO_MONITOR=1 displays log messages in QEMU monitor.
+SET QEMU_AUDIO_LOG_TO_MONITOR=0
+
+REM PCI-based PC(default): -M pc 
+REM ISA-based PC         : -M isapc
+REM -M isapc is added for NE2000 ISA card.
+
+REM the -L argument should point to the qemu libraries
+
+set arguments=-L . -vga std -no-kqemu -M isapc -net nic,model=ne2k_isa -net user -redir udp:8080::8080 -redir udp:8081::8081 -redir tcp:8080::8080 -redir tcp:8081::8081 -boot d -cdrom image.iso
+
+qemu.exe %* %arguments%
Index: contrib/conf/net-qe.sh
===================================================================
--- contrib/conf/net-qe.sh	(revision 209faf93503c78d1423ac244db45224381577454)
+++ contrib/conf/net-qe.sh	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+arguments="-vga std -M isapc -net nic,model=ne2k_isa -net user -boot d -redir udp:8080::8080 -redir udp:8081::8081 -redir tcp:8080::8080 -redir tcp:8081::8081 -cdrom image.iso"
+
+#qemu 0.10.2 and later 0.10.*:
+#qemu $@ -no-kqemu $arguments
+
+#qemu 0.11:
+qemu $@ $arguments
Index: defaults/amd64/Makefile.config
===================================================================
--- defaults/amd64/Makefile.config	(revision 76ecb300e88900544c3ed958ebd01eea01eda40e)
+++ defaults/amd64/Makefile.config	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -61,2 +61,5 @@
 # Mount /data on startup
 CONFIG_MOUNT_DATA = n
+
+# Default networking architecture
+NETWORKING = modular
Index: defaults/arm32/Makefile.config
===================================================================
--- defaults/arm32/Makefile.config	(revision 76ecb300e88900544c3ed958ebd01eea01eda40e)
+++ defaults/arm32/Makefile.config	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -37,2 +37,5 @@
 # Mount /data on startup
 CONFIG_MOUNT_DATA = n
+
+# Default networking architecture
+NETWORKING = modular
Index: defaults/ia32/Makefile.config
===================================================================
--- defaults/ia32/Makefile.config	(revision 76ecb300e88900544c3ed958ebd01eea01eda40e)
+++ defaults/ia32/Makefile.config	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -67,2 +67,5 @@
 # Mount /data on startup
 CONFIG_MOUNT_DATA = n
+
+# Default networking architecture
+NETWORKING = modular
Index: defaults/ia64/Makefile.config
===================================================================
--- defaults/ia64/Makefile.config	(revision 76ecb300e88900544c3ed958ebd01eea01eda40e)
+++ defaults/ia64/Makefile.config	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -49,2 +49,5 @@
 # Mount /data on startup
 CONFIG_MOUNT_DATA = n
+
+# Default networking architecture
+NETWORKING = modular
Index: defaults/mips32/Makefile.config
===================================================================
--- defaults/mips32/Makefile.config	(revision 76ecb300e88900544c3ed958ebd01eea01eda40e)
+++ defaults/mips32/Makefile.config	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -43,2 +43,5 @@
 # Mount /data on startup
 CONFIG_MOUNT_DATA = n
+
+# Default networking architecture
+NETWORKING = modular
Index: defaults/ppc32/Makefile.config
===================================================================
--- defaults/ppc32/Makefile.config	(revision 76ecb300e88900544c3ed958ebd01eea01eda40e)
+++ defaults/ppc32/Makefile.config	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -43,2 +43,5 @@
 # Mount /data on startup
 CONFIG_MOUNT_DATA = n
+
+# Default networking architecture
+NETWORKING = modular
Index: defaults/sparc64/Makefile.config
===================================================================
--- defaults/sparc64/Makefile.config	(revision 76ecb300e88900544c3ed958ebd01eea01eda40e)
+++ defaults/sparc64/Makefile.config	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -61,2 +61,5 @@
 # Mount /data on startup
 CONFIG_MOUNT_DATA = n
+
+# Default networking architecture
+NETWORKING = modular
Index: kernel/arch/amd64/include/interrupt.h
===================================================================
--- kernel/arch/amd64/include/interrupt.h	(revision 76ecb300e88900544c3ed958ebd01eea01eda40e)
+++ kernel/arch/amd64/include/interrupt.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -54,4 +54,5 @@
 #define IRQ_PIC_SPUR		7
 #define IRQ_MOUSE		12
+#define IRQ_DP8390		9
 
 /* this one must have four least significant bits set to ones */
Index: kernel/arch/amd64/src/amd64.c
===================================================================
--- kernel/arch/amd64/src/amd64.c	(revision 76ecb300e88900544c3ed958ebd01eea01eda40e)
+++ kernel/arch/amd64/src/amd64.c	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -228,4 +228,9 @@
 	    (uintptr_t) I8042_BASE);
 #endif
+
+#ifdef CONFIG_NETIF_DP8390
+	trap_virtual_enable_irqs(1 << IRQ_DP8390);
+	sysinfo_set_item_val("netif.dp8390.inr", NULL, IRQ_DP8390);
+#endif
 }
 
Index: kernel/arch/ia32/include/interrupt.h
===================================================================
--- kernel/arch/ia32/include/interrupt.h	(revision 76ecb300e88900544c3ed958ebd01eea01eda40e)
+++ kernel/arch/ia32/include/interrupt.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -54,4 +54,5 @@
 #define IRQ_PIC_SPUR	7
 #define IRQ_MOUSE	12
+#define IRQ_DP8390	9
 
 /* this one must have four least significant bits set to ones */
Index: kernel/arch/ia32/src/ia32.c
===================================================================
--- kernel/arch/ia32/src/ia32.c	(revision 76ecb300e88900544c3ed958ebd01eea01eda40e)
+++ kernel/arch/ia32/src/ia32.c	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -186,4 +186,9 @@
 	    (uintptr_t) I8042_BASE);
 #endif
+
+#ifdef CONFIG_NETIF_DP8390
+	trap_virtual_enable_irqs(1 << IRQ_DP8390);
+	sysinfo_set_item_val("netif.dp8390.inr", NULL, IRQ_DP8390);
+#endif
 }
 
Index: kernel/arch/ia64/include/interrupt.h
===================================================================
--- kernel/arch/ia64/include/interrupt.h	(revision 76ecb300e88900544c3ed958ebd01eea01eda40e)
+++ kernel/arch/ia64/include/interrupt.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -61,4 +61,5 @@
 #define IRQ_KBD    (0x01 + LEGACY_INTERRUPT_BASE)
 #define IRQ_MOUSE  (0x0c + LEGACY_INTERRUPT_BASE)
+#define IRQ_DP8390 (0x09 + LEGACY_INTERRUPT_BASE)
 
 /** General Exception codes. */
Index: kernel/arch/ia64/src/ia64.c
===================================================================
--- kernel/arch/ia64/src/ia64.c	(revision 76ecb300e88900544c3ed958ebd01eea01eda40e)
+++ kernel/arch/ia64/src/ia64.c	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -212,5 +212,10 @@
 	    (uintptr_t) I8042_BASE);
 #endif
-	
+
+#ifdef CONFIG_NETIF_DP8390
+	trap_virtual_enable_irqs(1 << IRQ_DP8390);
+	sysinfo_set_item_val("netif.dp8390.inr", NULL, IRQ_DP8390);
+#endif
+
 	sysinfo_set_item_val("ia64_iospace", NULL, true);
 	sysinfo_set_item_val("ia64_iospace.address", NULL, true);
Index: kernel/generic/include/ipc/ipc.h
===================================================================
--- kernel/generic/include/ipc/ipc.h	(revision 76ecb300e88900544c3ed958ebd01eea01eda40e)
+++ kernel/generic/include/ipc/ipc.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -227,5 +227,5 @@
 #ifdef KERNEL
 
-#define IPC_MAX_PHONES  16
+#define IPC_MAX_PHONES  32
 
 #include <synch/spinlock.h>
Index: kernel/generic/include/time/clock.h
===================================================================
--- kernel/generic/include/time/clock.h	(revision 76ecb300e88900544c3ed958ebd01eea01eda40e)
+++ kernel/generic/include/time/clock.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -38,5 +38,5 @@
 #include <arch/types.h>
 
-#define HZ		100
+#define HZ		1000
 
 /** Uptime structure */
Index: uspace/Makefile
===================================================================
--- uspace/Makefile	(revision 76ecb300e88900544c3ed958ebd01eea01eda40e)
+++ uspace/Makefile	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -63,5 +63,6 @@
 	srv/hid/fb \
 	srv/hid/kbd \
-	srv/hw/char/i8042
+	srv/hw/char/i8042 \
+	srv/net
 
 ifneq ($(UARCH),abs32le)
Index: uspace/doc/doxygroups.h
===================================================================
--- uspace/doc/doxygroups.h	(revision 76ecb300e88900544c3ed958ebd01eea01eda40e)
+++ uspace/doc/doxygroups.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -26,5 +26,120 @@
 	 * @ingroup srvcs
 	 */
-	
+
+	/**
+	 * @defgroup net Networking Stack
+	 * @ingroup srvcs
+	 */
+
+		/**
+		 * @defgroup netif Network interface drivers
+		 * @ingroup net
+		 */
+
+			/**
+			 * @defgroup lo Loopback Service
+			 * @ingroup netif
+			 */
+
+			/**
+			 * @defgroup dp8390 Generic DP8390 network interface family service
+			 * @ingroup netif
+			 */
+
+				/**
+				 * @defgroup ne2k NE2000 network interface family
+				 * @ingroup dp8390
+				 */
+
+		/**
+		 * @defgroup net_nil Network interface layer
+		 * @ingroup net
+		 */
+
+			/**
+			 * @defgroup eth Ethernet (IEEE 802.3) network interface layer Service
+			 * @ingroup net_nil
+			 */
+
+			/**
+			 * @defgroup nildummy Dummy network interface layer Service
+			 * @ingroup net_nil
+			 */
+
+		/**
+		 * @defgroup net_il Inter-networking layer
+		 * @ingroup net
+		 */
+
+			/**
+			 * @defgroup arp Address Resolution Protocol (ARP) Service
+			 * @ingroup net_il
+			 */
+
+			/**
+			 * @defgroup ip Internet Protocol (IP) Service
+			 * @ingroup net_il
+			 */
+
+		/**
+		 * @defgroup net_tl Transport layer
+		 * @ingroup net
+		 */
+
+			/**
+			 * @defgroup icmp Internet Control Message Protocol (ICMP) Service
+			 * @ingroup net_tl
+			 */
+
+			/**
+			 * @defgroup udp User Datagram Protocol (UDP) Service
+			 * @ingroup net_tl
+			 */
+
+			/**
+			 * @defgroup tcp Transmission Control Protocol (TCP) Service
+			 * @ingroup net_tl
+			 */
+
+		/**
+		 * @defgroup packet Packet management system
+		 * @ingroup net
+		 */
+
+		/**
+		 * @defgroup net_app Applications
+		 * @ingroup net
+		 */
+
+			/**
+			 * @defgroup echo Echo Service
+			 * @ingroup net_app
+			 */
+
+			/**
+			 * @defgroup ping Ping
+			 * @ingroup net_app
+			 */
+
+			/**
+			 * @defgroup nettest Networking tests
+			 * @ingroup net_app
+			 */
+
+		/**
+		 * @defgroup net_lib Application library
+		 * @ingroup net
+		 */
+
+			/**
+			 * @defgroup socket Sockets
+			 * @ingroup net_lib
+			 */
+
+			/**
+			 * @defgroup netdb Netdb
+			 * @ingroup net_lib
+			 */
+
 	/**
 	 * @cond amd64
Index: uspace/lib/libc/include/ipc/services.h
===================================================================
--- uspace/lib/libc/include/ipc/services.h	(revision 76ecb300e88900544c3ed958ebd01eea01eda40e)
+++ uspace/lib/libc/include/ipc/services.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -47,5 +47,17 @@
 	SERVICE_FHC,
 	SERVICE_OBIO,
-	SERVICE_CLIPBOARD
+	SERVICE_CLIPBOARD,
+	SERVICE_NETWORKING,
+	SERVICE_LO,
+	SERVICE_DP8390,
+	SERVICE_ETHERNET,
+	SERVICE_NILDUMMY,
+	SERVICE_IP,
+	SERVICE_ARP,
+	SERVICE_RARP,
+	SERVICE_ICMP,
+	SERVICE_UDP,
+	SERVICE_TCP,
+	SERVICE_SOCKET
 } services_t;
 
Index: uspace/srv/net/Doxyfile
===================================================================
--- uspace/srv/net/Doxyfile	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/Doxyfile	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,298 @@
+# Doxyfile 1.5.6
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+DOXYFILE_ENCODING      = UTF-8
+PROJECT_NAME           = "Networking and TCP/IP stack for HelenOS system"
+PROJECT_NUMBER         = "Master thesis 2009"
+OUTPUT_DIRECTORY       = doc/
+CREATE_SUBDIRS         = YES
+OUTPUT_LANGUAGE        = English
+BRIEF_MEMBER_DESC      = YES
+REPEAT_BRIEF           = YES
+ABBREVIATE_BRIEF       = "The $name class           " \
+                         "The $name widget           " \
+                         "The $name file           " \
+                         is \
+                         provides \
+                         specifies \
+                         contains \
+                         represents \
+                         a \
+                         an \
+                         the
+ALWAYS_DETAILED_SEC    = NO
+INLINE_INHERITED_MEMB  = NO
+FULL_PATH_NAMES        = YES
+STRIP_FROM_PATH        = .
+STRIP_FROM_INC_PATH    = 
+SHORT_NAMES            = YES
+JAVADOC_AUTOBRIEF      = YES
+QT_AUTOBRIEF           = NO
+MULTILINE_CPP_IS_BRIEF = NO
+DETAILS_AT_TOP         = NO
+INHERIT_DOCS           = YES
+SEPARATE_MEMBER_PAGES  = NO
+TAB_SIZE               = 2
+ALIASES                = 
+OPTIMIZE_OUTPUT_FOR_C  = YES
+OPTIMIZE_OUTPUT_JAVA   = NO
+OPTIMIZE_FOR_FORTRAN   = NO
+OPTIMIZE_OUTPUT_VHDL   = NO
+BUILTIN_STL_SUPPORT    = NO
+CPP_CLI_SUPPORT        = NO
+SIP_SUPPORT            = NO
+IDL_PROPERTY_SUPPORT   = YES
+DISTRIBUTE_GROUP_DOC   = NO
+SUBGROUPING            = YES
+TYPEDEF_HIDES_STRUCT   = NO
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+EXTRACT_ALL            = YES
+EXTRACT_PRIVATE        = NO
+EXTRACT_STATIC         = YES
+EXTRACT_LOCAL_CLASSES  = YES
+EXTRACT_LOCAL_METHODS  = NO
+EXTRACT_ANON_NSPACES   = NO
+HIDE_UNDOC_MEMBERS     = YES
+HIDE_UNDOC_CLASSES     = YES
+HIDE_FRIEND_COMPOUNDS  = NO
+HIDE_IN_BODY_DOCS      = NO
+INTERNAL_DOCS          = NO
+CASE_SENSE_NAMES       = YES
+HIDE_SCOPE_NAMES       = NO
+SHOW_INCLUDE_FILES     = YES
+INLINE_INFO            = YES
+SORT_MEMBER_DOCS       = YES
+SORT_BRIEF_DOCS        = NO
+SORT_GROUP_NAMES       = NO
+SORT_BY_SCOPE_NAME     = NO
+GENERATE_TODOLIST      = YES
+GENERATE_TESTLIST      = YES
+GENERATE_BUGLIST       = YES
+GENERATE_DEPRECATEDLIST= YES
+ENABLED_SECTIONS       = 
+MAX_INITIALIZER_LINES  = 30
+SHOW_USED_FILES        = YES
+SHOW_DIRECTORIES       = YES
+SHOW_FILES             = YES
+SHOW_NAMESPACES        = YES
+FILE_VERSION_FILTER    = 
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+QUIET                  = NO
+WARNINGS               = YES
+WARN_IF_UNDOCUMENTED   = YES
+WARN_IF_DOC_ERROR      = YES
+WARN_NO_PARAMDOC       = YES
+WARN_FORMAT            = "$file:$line: $text           "
+WARN_LOGFILE           = doc/doxygen_warnings.txt
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+INPUT                  = ./ \
+                         ../../doc/doxygroups.h \
+                         ./documentation.txt
+INPUT_ENCODING         = UTF-8
+FILE_PATTERNS          = *.c \
+                         *.cc \
+                         *.cxx \
+                         *.cpp \
+                         *.c++ \
+                         *.d \
+                         *.java \
+                         *.ii \
+                         *.ixx \
+                         *.ipp \
+                         *.i++ \
+                         *.inl \
+                         *.h \
+                         *.hh \
+                         *.hxx \
+                         *.hpp \
+                         *.h++ \
+                         *.idl \
+                         *.odl \
+                         *.cs \
+                         *.php \
+                         *.php3 \
+                         *.inc \
+                         *.m \
+                         *.mm \
+                         *.dox \
+                         *.py \
+                         *.C \
+                         *.CC \
+                         *.C++ \
+                         *.II \
+                         *.I++ \
+                         *.H \
+                         *.HH \
+                         *.H++ \
+                         *.CS \
+                         *.PHP \
+                         *.PHP3 \
+                         *.M \
+                         *.MM \
+                         *.PY
+RECURSIVE              = YES
+EXCLUDE                = 
+EXCLUDE_SYMLINKS       = NO
+EXCLUDE_PATTERNS       = *.svn*
+EXCLUDE_SYMBOLS        = packed
+EXAMPLE_PATH           = 
+EXAMPLE_PATTERNS       = *
+EXAMPLE_RECURSIVE      = NO
+IMAGE_PATH             = 
+INPUT_FILTER           = 
+FILTER_PATTERNS        = 
+FILTER_SOURCE_FILES    = NO
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+SOURCE_BROWSER         = NO
+INLINE_SOURCES         = NO
+STRIP_CODE_COMMENTS    = YES
+REFERENCED_BY_RELATION = YES
+REFERENCES_RELATION    = YES
+REFERENCES_LINK_SOURCE = YES
+USE_HTAGS              = NO
+VERBATIM_HEADERS       = NO
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+ALPHABETICAL_INDEX     = YES
+COLS_IN_ALPHA_INDEX    = 4
+IGNORE_PREFIX          = 
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+GENERATE_HTML          = YES
+HTML_OUTPUT            = 
+HTML_FILE_EXTENSION    = .html
+HTML_HEADER            = 
+HTML_FOOTER            = 
+HTML_STYLESHEET        = 
+HTML_ALIGN_MEMBERS     = YES
+GENERATE_HTMLHELP      = NO
+GENERATE_DOCSET        = NO
+DOCSET_FEEDNAME        = "Doxygen generated docs"
+DOCSET_BUNDLE_ID       = org.doxygen.Project
+HTML_DYNAMIC_SECTIONS  = YES
+CHM_FILE               = 
+HHC_LOCATION           = 
+GENERATE_CHI           = NO
+CHM_INDEX_ENCODING     = 
+BINARY_TOC             = NO
+TOC_EXPAND             = NO
+DISABLE_INDEX          = NO
+ENUM_VALUES_PER_LINE   = 4
+GENERATE_TREEVIEW      = NO
+TREEVIEW_WIDTH         = 250
+FORMULA_FONTSIZE       = 10
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+GENERATE_LATEX         = NO
+LATEX_OUTPUT           = latex
+LATEX_CMD_NAME         = latex
+MAKEINDEX_CMD_NAME     = makeindex
+COMPACT_LATEX          = NO
+PAPER_TYPE             = a4wide
+EXTRA_PACKAGES         = 
+LATEX_HEADER           = 
+PDF_HYPERLINKS         = NO
+USE_PDFLATEX           = NO
+LATEX_BATCHMODE        = NO
+LATEX_HIDE_INDICES     = NO
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+GENERATE_RTF           = NO
+RTF_OUTPUT             = rtf
+COMPACT_RTF            = NO
+RTF_HYPERLINKS         = NO
+RTF_STYLESHEET_FILE    = 
+RTF_EXTENSIONS_FILE    = 
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+GENERATE_MAN           = NO
+MAN_OUTPUT             = man
+MAN_EXTENSION          = .3
+MAN_LINKS              = NO
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+GENERATE_XML           = NO
+XML_OUTPUT             = xml
+XML_SCHEMA             = 
+XML_DTD                = 
+XML_PROGRAMLISTING     = YES
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+GENERATE_AUTOGEN_DEF   = NO
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+GENERATE_PERLMOD       = NO
+PERLMOD_LATEX          = NO
+PERLMOD_PRETTY         = YES
+PERLMOD_MAKEVAR_PREFIX = 
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor   
+#---------------------------------------------------------------------------
+ENABLE_PREPROCESSING   = YES
+MACRO_EXPANSION        = NO
+EXPAND_ONLY_PREDEF     = NO
+SEARCH_INCLUDES        = YES
+INCLUDE_PATH           = 
+INCLUDE_FILE_PATTERNS  = 
+PREDEFINED             = 
+EXPAND_AS_DEFINED      = 
+SKIP_FUNCTION_MACROS   = YES
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references   
+#---------------------------------------------------------------------------
+TAGFILES               = 
+GENERATE_TAGFILE       = 
+ALLEXTERNALS           = NO
+EXTERNAL_GROUPS        = YES
+PERL_PATH              = /usr/bin/perl
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool   
+#---------------------------------------------------------------------------
+CLASS_DIAGRAMS         = YES
+MSCGEN_PATH            = 
+HIDE_UNDOC_RELATIONS   = YES
+HAVE_DOT               = YES
+DOT_FONTNAME           = FreeSans
+DOT_FONTPATH           = 
+CLASS_GRAPH            = YES
+COLLABORATION_GRAPH    = YES
+GROUP_GRAPHS           = YES
+UML_LOOK               = YES
+TEMPLATE_RELATIONS     = NO
+INCLUDE_GRAPH          = YES
+INCLUDED_BY_GRAPH      = YES
+CALL_GRAPH             = YES
+CALLER_GRAPH           = YES
+GRAPHICAL_HIERARCHY    = YES
+DIRECTORY_GRAPH        = YES
+DOT_IMAGE_FORMAT       = png
+DOT_PATH               = 
+DOTFILE_DIRS           = 
+DOT_GRAPH_MAX_NODES    = 50
+MAX_DOT_GRAPH_DEPTH    = 1000
+DOT_TRANSPARENT        = NO
+DOT_MULTI_TARGETS      = YES
+GENERATE_LEGEND        = YES
+DOT_CLEANUP            = YES
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine   
+#---------------------------------------------------------------------------
+SEARCHENGINE           = NO
Index: uspace/srv/net/Makefile
===================================================================
--- uspace/srv/net/Makefile	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/Makefile	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,83 @@
+#
+# 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.
+#
+
+include ../../../Makefile.config
+
+DIRS = \
+	netif/lo \
+	netif/dp8390 \
+	nil/eth \
+	nil/nildummy \
+	net \
+	net/start \
+	socket \
+	app/echo \
+	app/ping \
+	app/nettest1 \
+	app/nettest2
+
+DIRS_MODULAR = \
+		il/arp \
+		il/ip \
+		tl/icmp \
+		tl/udp \
+		tl/tcp \
+
+DIRS_ALL = $(DIRS) $(DIRS_MODULAR)
+
+ifeq ($(NETWORKING), module)
+	BUILDS := $(addsuffix .build,$(DIRS))
+else
+ifeq ($(NETWORKING), modular)
+	BUILDS := $(addsuffix .build,$(DIRS_ALL))
+endif
+endif
+
+CLEANS := $(addsuffix .clean,$(DIRS_ALL))
+
+CHECKS := $(addsuffix .check,$(basename $(BUILDS)))
+
+.PHONY: all build $(BUILDS) $(CLEANS) clean
+
+all: $(BUILDS)
+
+build: $(BUILDS)
+
+check: $(CHECKS)
+
+clean: $(CLEANS)
+	find $(DIRS_ALL) ./ -name '*.o' -follow -exec rm \{\} \;
+
+$(CHECKS):
+	-$(MAKE) -C $(basename $@) check
+
+$(CLEANS):
+	-$(MAKE) -C $(basename $@) clean
+
+$(BUILDS):
+	$(MAKE) -C $(basename $@) all
Index: uspace/srv/net/Makefile.module
===================================================================
--- uspace/srv/net/Makefile.module	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/Makefile.module	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,85 @@
+#
+# 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.
+#
+
+## Setup toolchain
+#
+
+LIBC_PREFIX = $(NET_BASE)../../lib/libc
+SOFTINT_PREFIX = $(NET_BASE)../../lib/softint
+include $(LIBC_PREFIX)/Makefile.toolchain
+
+CFLAGS += -Iinclude -I../libadt/include
+
+CHECK_CFLAGS = -fsyntax-only -Wextra -Wno-div-by-zero -Wsystem-headers -Wfloat-equal -Wdeclaration-after-statement -Wundef -Wno-endif-labels -Wshadow -Wlarger-than-1500 -Wpointer-arith -Wbad-function-cast -Wcast-qual -Wcast-align -Wwrite-strings -Wconversion -Wsign-compare -Waggregate-return -Wstrict-prototypes -Wold-style-definition -Wmissing-prototypes -Wmissing-declarations -Wmissing-field-initializers -Wmissing-noreturn -Wmissing-format-attribute -Wno-multichar -Wno-deprecated-declarations -Wpacked -Wpadded -Wredundant-decls -Wnested-externs -Wunreachable-code -Winline -Winvalid-pch -Wlong-long -Wvariadic-macros -Wdisabled-optimization -Wno-pointer-sign
+#-Wtraditional
+
+LIBS += $(LIBC_PREFIX)/libc.a
+
+DEPEND = Makefile.depend
+DEPEND_PREV = $(DEPEND).prev
+
+DEFS += $(NET_DEFS)
+
+OBJECTS := $(addsuffix .o,$(basename $(SOURCES)))
+DISASMS := $(addsuffix .disasm,$(basename $(OUTPUT)))
+
+.PHONY: all clean disasm
+
+all: $(OUTPUT) $(LIB) $(DISASMS)
+
+check:
+	$(CC) $(DEFS) $(CFLAGS) $(CHECK_CFLAGS) *.c
+
+-include $(DEPEND)
+
+clean:
+	-rm -f $(OUTPUT) $(LIB) $(OUTPUT).map $(addsuffix .map,$(basename $(SOURCES))) $(DISASMS) $(DEPEND)
+
+$(OUTPUT): $(OBJECTS) $(LIBS)
+	$(LD) -T $(LIBC_PREFIX)/arch/$(UARCH)/_link.ld $(OBJECTS) $(LIBS) $(LFLAGS) -o $@ -Map $(OUTPUT).map
+
+$(LIB): $(OBJECTS)
+	$(AR) rc $(LIB) $(OBJECTS)
+
+disasm: $(DISASMS)
+
+%.disasm: %
+	$(OBJDUMP) -d $< >$@
+
+%.o: %.S
+	$(CC) $(DEFS) $(AFLAGS) $(CFLAGS) -D__ASM__ -c $< -o $@
+
+%.o: %.s
+	$(AS) $(AFLAGS) $< -o $@
+
+%.o: %.c $(DEPEND)
+	$(CC) $(DEFS) $(CFLAGS) -c $< -o $@
+
+$(DEPEND):
+	makedepend -f - -- $(DEPEND_DEFS) $(CFLAGS) -- $(SOURCES) > $@ 2> /dev/null
+	-[ -f $(DEPEND_PREV) ] && diff -q $(DEPEND_PREV) $@ && mv -f $(DEPEND_PREV) $@
Index: uspace/srv/net/app/echo/Makefile
===================================================================
--- uspace/srv/net/app/echo/Makefile	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/app/echo/Makefile	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,47 @@
+#
+# 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.
+#
+
+NAME = echo
+
+NET_BASE = ../../
+STRUCTURES = $(NET_BASE)structures/
+
+include ../../../../../Makefile.config
+
+## Sources
+#
+
+OUTPUT = $(NAME)
+SOURCES = \
+	$(NAME).c \
+	$(NET_BASE)app/parse.c \
+	$(NET_BASE)app/print_error.c
+
+LIBS += ../../socket/libsocket.a
+
+include $(NET_BASE)Makefile.module
Index: uspace/srv/net/app/echo/echo.c
===================================================================
--- uspace/srv/net/app/echo/echo.c	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/app/echo/echo.c	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,361 @@
+/*
+ * 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 echo
+ *  @{
+ */
+
+/** @file
+ *  Echo application.
+ *  Answers received packets.
+ */
+
+#include <malloc.h>
+#include <stdio.h>
+#include <string.h>
+#include <task.h>
+
+#include "../../include/in.h"
+#include "../../include/in6.h"
+#include "../../include/inet.h"
+#include "../../include/socket.h"
+
+#include "../../err.h"
+
+#include "../parse.h"
+#include "../print_error.h"
+
+/** Echo module name.
+ */
+#define NAME	"Echo"
+
+/** Module entry point.
+ *  Reads command line parameters and starts listenning.
+ *  @param[in] argc The number of command line parameters.
+ *  @param[in] argv The command line parameters.
+ *  @returns EOK on success.
+ */
+int		main( int argc, char * argv[] );
+
+/** Prints the application help.
+ */
+void	echo_print_help( void );
+
+/** Translates the character string to the protocol family number.
+ *  @param[in] name The protocol family name.
+ *  @returns The corresponding protocol family number.
+ *  @returns EPFNOSUPPORTED if the protocol family is not supported.
+ */
+int		echo_parse_protocol_family( const char * name );
+
+/** Translates the character string to the socket type number.
+ *  @param[in] name The socket type name.
+ *  @returns The corresponding socket type number.
+ *  @returns ESOCKNOSUPPORTED if the socket type is not supported.
+ */
+int		echo_parse_socket_type( const char * name );
+
+void echo_print_help( void ){
+	printf(
+		"Network Echo aplication\n" \
+		"Usage: echo [options]\n" \
+		"Where options are:\n" \
+		"-b backlog | --backlog=size\n" \
+		"\tThe size of the accepted sockets queue. Only for SOCK_STREAM. The default is 3.\n" \
+		"\n" \
+		"-c count | --count=count\n" \
+		"\tThe number of received messages to handle. A negative number means infinity. The default is infinity.\n" \
+		"\n" \
+		"-f protocol_family | --family=protocol_family\n" \
+		"\tThe listenning socket protocol family. Only the PF_INET and PF_INET6 are supported.\n"
+		"\n" \
+		"-h | --help\n" \
+		"\tShow this application help.\n"
+		"\n" \
+		"-p port_number | --port=port_number\n" \
+		"\tThe port number the application should listen at. The default is 7.\n" \
+		"\n" \
+		"-r reply_string | --reply=reply_string\n" \
+		"\tThe constant reply string. The default is the original data received.\n" \
+		"\n" \
+		"-s receive_size | --size=receive_size\n" \
+		"\tThe maximum receive data size the application should accept. The default is 1024 bytes.\n" \
+		"\n" \
+		"-t socket_type | --type=socket_type\n" \
+		"\tThe listenning socket type. Only the SOCK_DGRAM and the SOCK_STREAM are supported.\n" \
+		"\n" \
+		"-v | --verbose\n" \
+		"\tShow all output messages.\n"
+	);
+}
+
+int echo_parse_protocol_family( const char * name ){
+	if( str_lcmp( name, "PF_INET", 7 ) == 0 ){
+		return PF_INET;
+	}else if( str_lcmp( name, "PF_INET6", 8 ) == 0 ){
+		return PF_INET6;
+	}
+	return EPFNOSUPPORT;
+}
+
+int echo_parse_socket_type( const char * name ){
+	if( str_lcmp( name, "SOCK_DGRAM", 11 ) == 0 ){
+		return SOCK_DGRAM;
+	}else if( str_lcmp( name, "SOCK_STREAM", 12 ) == 0 ){
+		return SOCK_STREAM;
+	}
+	return ESOCKTNOSUPPORT;
+}
+
+int main( int argc, char * argv[] ){
+	ERROR_DECLARE;
+
+	size_t				size			= 1024;
+	int					verbose			= 0;
+	char *				reply			= NULL;
+	sock_type_t			type			= SOCK_DGRAM;
+	int					count			= -1;
+	int					family			= PF_INET;
+	uint16_t			port			= 7;
+	int					backlog			= 3;
+
+	socklen_t			max_length		= sizeof( struct sockaddr_in6 );
+	uint8_t				address_data[ max_length ];
+	struct sockaddr *		address		= ( struct sockaddr * ) address_data;
+	struct sockaddr_in *	address_in		= ( struct sockaddr_in * ) address;
+	struct sockaddr_in6 *	address_in6	= ( struct sockaddr_in6 * ) address;
+	socklen_t			addrlen;
+	char				address_string[ INET6_ADDRSTRLEN ];
+	uint8_t *			address_start;
+	int					socket_id;
+	int					listening_id;
+	char * 				data;
+	size_t				length;
+	int					index;
+	size_t				reply_length;
+	int					value;
+
+	printf( "Task %d - ", task_get_id());
+	printf( "%s\n", NAME );
+
+	for( index = 1; index < argc; ++ index ){
+		if( argv[ index ][ 0 ] == '-' ){
+			switch( argv[ index ][ 1 ] ){
+				case 'b':	ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & backlog, "accepted sockets queue size", 0 ));
+							break;
+				case 'c':	ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & count, "message count", 0 ));
+							break;
+				case 'f':	ERROR_PROPAGATE( parse_parameter_name_int( argc, argv, & index, & family, "protocol family", 0, echo_parse_protocol_family ));
+							break;
+				case 'h':	echo_print_help();
+							return EOK;
+							break;
+				case 'p':	ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & value, "port number", 0 ));
+							port = ( uint16_t ) value;
+							break;
+				case 'r':	ERROR_PROPAGATE( parse_parameter_string( argc, argv, & index, & reply, "reply string", 0 ));
+							break;
+				case 's':	ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & value, "receive size", 0 ));
+							size = (value >= 0 ) ? ( size_t ) value : 0;
+							break;
+				case 't':	ERROR_PROPAGATE( parse_parameter_name_int( argc, argv, & index, & value, "socket type", 0, echo_parse_socket_type ));
+							type = ( sock_type_t ) value;
+							break;
+				case 'v':	verbose = 1;
+							break;
+				case '-':	if( str_lcmp( argv[ index ] + 2, "backlog=", 6 ) == 0 ){
+								ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & backlog, "accepted sockets queue size", 8 ));
+							}else if( str_lcmp( argv[ index ] + 2, "count=", 6 ) == 0 ){
+								ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & count, "message count", 8 ));
+							}else if( str_lcmp( argv[ index ] + 2, "family=", 7 ) == 0 ){
+								ERROR_PROPAGATE( parse_parameter_name_int( argc, argv, & index, & family, "protocol family", 9, echo_parse_protocol_family ));
+							}else if( str_lcmp( argv[ index ] + 2, "help", 5 ) == 0 ){
+								echo_print_help();
+								return EOK;
+							}else if( str_lcmp( argv[ index ] + 2, "port=", 5 ) == 0 ){
+								ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & value, "port number", 7 ));
+								port = ( uint16_t ) value;
+							}else if( str_lcmp( argv[ index ] + 2, "reply=", 6 ) == 0 ){
+								ERROR_PROPAGATE( parse_parameter_string( argc, argv, & index, & reply, "reply string", 8 ));
+							}else if( str_lcmp( argv[ index ] + 2, "size=", 5 ) == 0 ){
+								ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & value, "receive size", 7 ));
+								size = (value >= 0 ) ? ( size_t ) value : 0;
+							}else if( str_lcmp( argv[ index ] + 2, "type=", 5 ) == 0 ){
+								ERROR_PROPAGATE( parse_parameter_name_int( argc, argv, & index, & value, "socket type", 7, echo_parse_socket_type ));
+								type = ( sock_type_t ) value;
+							}else if( str_lcmp( argv[ index ] + 2, "verbose", 8 ) == 0 ){
+								verbose = 1;
+							}else{
+								print_unrecognized( index, argv[ index ] + 2 );
+								echo_print_help();
+								return EINVAL;
+							}
+							break;
+				default:
+					print_unrecognized( index, argv[ index ] + 1 );
+					echo_print_help();
+					return EINVAL;
+			}
+		}else{
+			print_unrecognized( index, argv[ index ] );
+			echo_print_help();
+			return EINVAL;
+		}
+	}
+
+	if( size <= 0 ){
+		fprintf( stderr, "Receive size too small (%d). Using 1024 bytes instead.\n", size );
+		size = 1024;
+	}
+	// size plus terminating null (\0)
+	data = ( char * ) malloc( size + 1 );
+	if( ! data ){
+		fprintf( stderr, "Failed to allocate receive buffer.\n" );
+		return ENOMEM;
+	}
+
+	reply_length = reply ? str_length( reply ) : 0;
+
+	listening_id = socket( family, type, 0 );
+	if( listening_id < 0 ){
+		socket_print_error( stderr, listening_id, "Socket create: ", "\n" );
+		return listening_id;
+	}
+
+	bzero( address_data, max_length );
+	switch( family ){
+		case PF_INET:
+			address_in->sin_family = AF_INET;
+			address_in->sin_port = htons( port );
+			addrlen = sizeof( struct sockaddr_in );
+			break;
+		case PF_INET6:
+			address_in6->sin6_family = AF_INET6;
+			address_in6->sin6_port = htons( port );
+			addrlen = sizeof( struct sockaddr_in6 );
+			break;
+		default:
+			fprintf( stderr, "Protocol family is not supported\n" );
+			return EAFNOSUPPORT;
+	}
+
+	listening_id = socket( family, type, 0 );
+	if( listening_id < 0 ){
+		socket_print_error( stderr, listening_id, "Socket create: ", "\n" );
+		return listening_id;
+	}
+
+	if( type == SOCK_STREAM ){
+		if( backlog <= 0 ){
+			fprintf( stderr, "Accepted sockets queue size too small (%d). Using 3 instead.\n", size );
+			backlog = 3;
+		}
+		if( ERROR_OCCURRED( listen( listening_id, backlog ))){
+			socket_print_error( stderr, ERROR_CODE, "Socket listen: ", "\n" );
+			return ERROR_CODE;
+		}
+	}
+
+	if( ERROR_OCCURRED( bind( listening_id, address, addrlen ))){
+		socket_print_error( stderr, ERROR_CODE, "Socket bind: ", "\n" );
+		return ERROR_CODE;
+	}
+
+	if( verbose ) printf( "Socket %d listenning at %d\n", listening_id, port );
+
+	socket_id = listening_id;
+
+	while( count ){
+		addrlen = max_length;
+		if( type == SOCK_STREAM ){
+			socket_id = accept( listening_id, address, & addrlen );
+			if( socket_id <= 0 ){
+				socket_print_error( stderr, socket_id, "Socket accept: ", "\n" );
+			}else{
+				if( verbose ) printf( "Socket %d accepted\n", socket_id );
+			}
+		}
+		if( socket_id > 0 ){
+			value = recvfrom( socket_id, data, size, 0, address, & addrlen );
+			if( value < 0 ){
+				socket_print_error( stderr, value, "Socket receive: ", "\n" );
+			}else{
+				length = ( size_t ) value;
+				if( verbose ){
+					address_start = NULL;
+					switch( address->sa_family ){
+						case AF_INET:
+							port = ntohs( address_in->sin_port );
+							address_start = ( uint8_t * ) & address_in->sin_addr.s_addr;
+							break;
+						case AF_INET6:
+							port = ntohs( address_in6->sin6_port );
+							address_start = ( uint8_t * ) & address_in6->sin6_addr.s6_addr;
+							break;
+						default:
+							fprintf( stderr, "Address family %d (0x%X) is not supported.\n", address->sa_family );
+					}
+					if( address_start ){
+						if( ERROR_OCCURRED( inet_ntop( address->sa_family, address_start, address_string, sizeof( address_string )))){
+							fprintf( stderr, "Received address error %d\n", ERROR_CODE );
+						}else{
+							data[ length ] = '\0';
+							printf( "Socket %d received %d bytes from %s:%d\n%s\n", socket_id, length, address_string, port, data );
+						}
+					}
+				}
+				if( ERROR_OCCURRED( sendto( socket_id, reply ? reply : data, reply ? reply_length : length, 0, address, addrlen ))){
+					socket_print_error( stderr, ERROR_CODE, "Socket send: ", "\n" );
+				}
+			}
+			if( type == SOCK_STREAM ){
+				if( ERROR_OCCURRED( closesocket( socket_id ))){
+					socket_print_error( stderr, ERROR_CODE, "Close socket: ", "\n" );
+				}
+			}
+		}
+		if( count > 0 ){
+			-- count;
+			if( verbose ) printf( "Waiting for next %d packet(s)\n", count );
+		}
+	}
+
+	if( verbose ) printf( "Closing the socket\n" );
+
+	if( ERROR_OCCURRED( closesocket( listening_id ))){
+		socket_print_error( stderr, ERROR_CODE, "Close socket: ", "\n" );
+		return ERROR_CODE;
+	}
+
+	if( verbose ) printf( "Exiting\n" );
+
+	return EOK;
+}
+
+/** @}
+ */
Index: uspace/srv/net/app/nettest1/Makefile
===================================================================
--- uspace/srv/net/app/nettest1/Makefile	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/app/nettest1/Makefile	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,47 @@
+#
+# 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.
+#
+
+NAME = nettest1
+
+NET_BASE = ../../
+STRUCTURES = $(NET_BASE)structures/
+
+include ../../../../../Makefile.config
+
+## Sources
+#
+
+OUTPUT = $(NAME)
+SOURCES = \
+	$(NAME).c \
+	$(NET_BASE)app/parse.c \
+	$(NET_BASE)app/print_error.c
+
+LIBS += ../../socket/libsocket.a
+
+include $(NET_BASE)Makefile.module
Index: uspace/srv/net/app/nettest1/nettest1.c
===================================================================
--- uspace/srv/net/app/nettest1/nettest1.c	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/app/nettest1/nettest1.c	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,613 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup nettest
+ *  @{
+ */
+
+/** @file
+ *  Networking test 1 application - sockets.
+ */
+
+#include <malloc.h>
+#include <stdio.h>
+#include <string.h>
+#include <task.h>
+#include <time.h>
+
+#include "../../include/in.h"
+#include "../../include/in6.h"
+#include "../../include/inet.h"
+#include "../../include/socket.h"
+
+#include "../../err.h"
+
+#include "../parse.h"
+#include "../print_error.h"
+
+/** Echo module name.
+ */
+#define NAME	"Nettest1"
+
+/** Packet data pattern.
+ */
+#define NETTEST1_TEXT	"Networking test 1 - sockets"
+
+/** Module entry point.
+ *  Starts testing.
+ *  @param[in] argc The number of command line parameters.
+ *  @param[in] argv The command line parameters.
+ *  @returns EOK on success.
+ */
+int		main( int argc, char * argv[] );
+
+/** Prints the application help.
+ */
+void	print_help( void );
+
+/** Translates the character string to the protocol family number.
+ *  @param[in] name The protocol family name.
+ *  @returns The corresponding protocol family number.
+ *  @returns EPFNOSUPPORTED if the protocol family is not supported.
+ */
+int		parse_protocol_family( const char * name );
+
+/** Translates the character string to the socket type number.
+ *  @param[in] name The socket type name.
+ *  @returns The corresponding socket type number.
+ *  @returns ESOCKNOSUPPORTED if the socket type is not supported.
+ */
+int		parse_socket_type( const char * name );
+
+/** Refreshes the data.
+ *  Fills the data block with the NETTEST1_TEXT pattern.
+ *  @param[out] data The data block.
+ *  @param[in] size The data block size in bytes.
+ */
+void	refresh_data( char * data, size_t size );
+
+/** Creates new sockets.
+ *  @param[in] verbose A value indicating whether to print out verbose information.
+ *  @param[out] socket_ids A field to store the socket identifiers.
+ *  @param[in] sockets The number of sockets to create. Should be at most the size of the field.
+ *  @param[in] family The socket address family.
+ *  @param[in] type The socket type.
+ *  @returns EOK on success.
+ *  @returns Other error codes as defined for the socket() function.
+ */
+int	sockets_create( int verbose, int * socket_ids, int sockets, int family, sock_type_t type );
+
+/** Closes sockets.
+ *  @param[in] verbose A value indicating whether to print out verbose information.
+ *  @param[in] socket_ids A field of stored socket identifiers.
+ *  @param[in] sockets The number of sockets in the field. Should be at most the size of the field.
+ *  @returns EOK on success.
+ *  @returns Other error codes as defined for the closesocket() function.
+ */
+int	sockets_close( int verbose, int * socket_ids, int sockets );
+
+/** Connects sockets.
+ *  @param[in] verbose A value indicating whether to print out verbose information.
+ *  @param[in] socket_ids A field of stored socket identifiers.
+ *  @param[in] sockets The number of sockets in the field. Should be at most the size of the field.
+ *  @param[in] address The destination host address to connect to.
+ *  @param[in] addrlen The length of the destination address in bytes.
+ *  @returns EOK on success.
+ *  @returns Other error codes as defined for the connect() function.
+ */
+int	sockets_connect( int verbose, int * socket_ids, int sockets, struct sockaddr * address, socklen_t addrlen );
+
+/** Sends data via sockets.
+ *  @param[in] verbose A value indicating whether to print out verbose information.
+ *  @param[in] socket_ids A field of stored socket identifiers.
+ *  @param[in] sockets The number of sockets in the field. Should be at most the size of the field.
+ *  @param[in] address The destination host address to send data to.
+ *  @param[in] addrlen The length of the destination address in bytes.
+ *  @param[in] data The data to be sent.
+ *  @param[in] size The data size in bytes.
+ *  @param[in] messages The number of datagrams per socket to be sent.
+ *  @returns EOK on success.
+ *  @returns Other error codes as defined for the sendto() function.
+ */
+int	sockets_sendto( int verbose, int * socket_ids, int sockets, struct sockaddr * address, socklen_t addrlen, char * data, int size, int messages );
+
+/** Receives data via sockets.
+ *  @param[in] verbose A value indicating whether to print out verbose information.
+ *  @param[in] socket_ids A field of stored socket identifiers.
+ *  @param[in] sockets The number of sockets in the field. Should be at most the size of the field.
+ *  @param[in] address The source host address of received datagrams.
+ *  @param[in,out] addrlen The maximum length of the source address in bytes. The actual size of the source address is set instead.
+ *  @param[out] data The received data.
+ *  @param[in] size The maximum data size in bytes.
+ *  @param[in] messages The number of datagrams per socket to be received.
+ *  @returns EOK on success.
+ *  @returns Other error codes as defined for the recvfrom() function.
+ */
+int	sockets_recvfrom( int verbose, int * socket_ids, int sockets, struct sockaddr * address, socklen_t * addrlen, char * data, int size, int messages );
+
+/** Sends and receives data via sockets.
+ *  Each datagram is sent and a reply read consequently.
+ *  The next datagram is sent after the reply is received.
+ *  @param[in] verbose A value indicating whether to print out verbose information.
+ *  @param[in] socket_ids A field of stored socket identifiers.
+ *  @param[in] sockets The number of sockets in the field. Should be at most the size of the field.
+ *  @param[in,out] address The destination host address to send data to. The source host address of received datagrams is set instead.
+ *  @param[in] addrlen The length of the destination address in bytes.
+ *  @param[in,out] data The data to be sent. The received data are set instead.
+ *  @param[in] size The data size in bytes.
+ *  @param[in] messages The number of datagrams per socket to be received.
+ *  @returns EOK on success.
+ *  @returns Other error codes as defined for the recvfrom() function.
+ */
+int	sockets_sendto_recvfrom( int verbose, int * socket_ids, int sockets, struct sockaddr * address, socklen_t * addrlen, char * data, int size, int messages );
+
+/** Prints a mark.
+ *  If the index is a multiple of ten, a different mark is printed.
+ *  @param[in] index The index of the mark to be printed.
+ */
+void	print_mark( int index );
+
+void print_help( void ){
+	printf(
+		"Network Networking test 1 aplication - sockets\n" \
+		"Usage: echo [options] numeric_address\n" \
+		"Where options are:\n" \
+		"-f protocol_family | --family=protocol_family\n" \
+		"\tThe listenning socket protocol family. Only the PF_INET and PF_INET6 are supported.\n"
+		"\n" \
+		"-h | --help\n" \
+		"\tShow this application help.\n"
+		"\n" \
+		"-m count | --messages=count\n" \
+		"\tThe number of messages to send and receive per socket. The default is 10.\n" \
+		"\n" \
+		"-n sockets | --sockets=count\n" \
+		"\tThe number of sockets to use. The default is 10.\n" \
+		"\n" \
+		"-p port_number | --port=port_number\n" \
+		"\tThe port number the application should send messages to. The default is 7.\n" \
+		"\n" \
+		"-s packet_size | --size=packet_size\n" \
+		"\tThe packet data size the application sends. The default is 28 bytes.\n" \
+		"\n" \
+		"-v | --verbose\n" \
+		"\tShow all output messages.\n"
+	);
+}
+
+int parse_protocol_family( const char * name ){
+	if( str_lcmp( name, "PF_INET", 7 ) == 0 ){
+		return PF_INET;
+	}else if( str_lcmp( name, "PF_INET6", 8 ) == 0 ){
+		return PF_INET6;
+	}
+	return EPFNOSUPPORT;
+}
+
+int parse_socket_type( const char * name ){
+	if( str_lcmp( name, "SOCK_DGRAM", 11 ) == 0 ){
+		return SOCK_DGRAM;
+	}else if( str_lcmp( name, "SOCK_STREAM", 12 ) == 0 ){
+		return SOCK_STREAM;
+	}
+	return ESOCKTNOSUPPORT;
+}
+
+void refresh_data( char * data, size_t size ){
+	size_t	length;
+
+	// fill the data
+	length = 0;
+	while( size > length + sizeof( NETTEST1_TEXT ) - 1 ){
+		memcpy( data + length, NETTEST1_TEXT, sizeof( NETTEST1_TEXT ) - 1 );
+		length += sizeof( NETTEST1_TEXT ) - 1;
+	}
+	memcpy( data + length, NETTEST1_TEXT, size - length );
+	data[ size ] = '\0';
+}
+
+int sockets_create( int verbose, int * socket_ids, int sockets, int family, sock_type_t type ){
+	int	index;
+
+	if( verbose ) printf( "Create\t" );
+	fflush( stdout );
+	for( index = 0; index < sockets; ++ index ){
+		socket_ids[ index ] = socket( family, type, 0 );
+		if( socket_ids[ index ] < 0 ){
+			printf( "Socket %d (%d) error:\n", index, socket_ids[ index ] );
+			socket_print_error( stderr, socket_ids[ index ], "Socket create: ", "\n" );
+			return socket_ids[ index ];
+		}
+		if( verbose ){
+			print_mark( index );
+		}
+	}
+	return EOK;
+}
+
+int sockets_close( int verbose, int * socket_ids, int sockets ){
+	ERROR_DECLARE;
+
+	int	index;
+
+	if( verbose ) printf( "\tClose\t" );
+	fflush( stdout );
+	for( index = 0; index < sockets; ++ index ){
+		if( ERROR_OCCURRED( closesocket( socket_ids[ index ] ))){
+			printf( "Socket %d (%d) error:\n", index, socket_ids[ index ] );
+			socket_print_error( stderr, ERROR_CODE, "Socket close: ", "\n" );
+			return ERROR_CODE;
+		}
+		if( verbose ) print_mark( index );
+	}
+	return EOK;
+}
+
+int sockets_connect( int verbose, int * socket_ids, int sockets, struct sockaddr * address, socklen_t addrlen ){
+	ERROR_DECLARE;
+
+	int	index;
+
+	if( verbose ) printf( "\tConnect\t" );
+	fflush( stdout );
+	for( index = 0; index < sockets; ++ index ){
+		if( ERROR_OCCURRED( connect( socket_ids[ index ], address, addrlen ))){
+			socket_print_error( stderr, ERROR_CODE, "Socket connect: ", "\n" );
+			return ERROR_CODE;
+		}
+		if( verbose ) print_mark( index );
+	}
+	return EOK;
+}
+
+int sockets_sendto( int verbose, int * socket_ids, int sockets, struct sockaddr * address, socklen_t addrlen, char * data, int size, int messages ){
+	ERROR_DECLARE;
+
+	int	index;
+	int	message;
+
+	if( verbose ) printf( "\tSendto\t" );
+	fflush( stdout );
+	for( index = 0; index < sockets; ++ index ){
+		for( message = 0; message < messages; ++ message ){
+			if( ERROR_OCCURRED( sendto( socket_ids[ index ], data, size, 0, address, addrlen ))){
+				printf( "Socket %d (%d), message %d error:\n", index, socket_ids[ index ], message );
+				socket_print_error( stderr, ERROR_CODE, "Socket send: ", "\n" );
+				return ERROR_CODE;
+			}
+		}
+		if( verbose ) print_mark( index );
+	}
+	return EOK;
+}
+
+int sockets_recvfrom( int verbose, int * socket_ids, int sockets, struct sockaddr * address, socklen_t * addrlen, char * data, int size, int messages ){
+	int	value;
+	int	index;
+	int	message;
+
+	if( verbose ) printf( "\tRecvfrom\t" );
+	fflush( stdout );
+	for( index = 0; index < sockets; ++ index ){
+		for( message = 0; message < messages; ++ message ){
+			value = recvfrom( socket_ids[ index ], data, size, 0, address, addrlen );
+			if( value < 0 ){
+				printf( "Socket %d (%d), message %d error:\n", index, socket_ids[ index ], message );
+				socket_print_error( stderr, value, "Socket receive: ", "\n" );
+				return value;
+			}
+		}
+		if( verbose ) print_mark( index );
+	}
+	return EOK;
+}
+
+int sockets_sendto_recvfrom( int verbose, int * socket_ids, int sockets, struct sockaddr * address, socklen_t * addrlen, char * data, int size, int messages ){
+	ERROR_DECLARE;
+
+	int	value;
+	int	index;
+	int	message;
+
+	if( verbose ) printf( "\tSendto and recvfrom\t" );
+	fflush( stdout );
+	for( index = 0; index < sockets; ++ index ){
+		for( message = 0; message < messages; ++ message ){
+			if( ERROR_OCCURRED( sendto( socket_ids[ index ], data, size, 0, address, * addrlen ))){
+				printf( "Socket %d (%d), message %d error:\n", index, socket_ids[ index ], message );
+				socket_print_error( stderr, ERROR_CODE, "Socket send: ", "\n" );
+				return ERROR_CODE;
+			}
+			value = recvfrom( socket_ids[ index ], data, size, 0, address, addrlen );
+			if( value < 0 ){
+				printf( "Socket %d (%d), message %d error:\n", index, socket_ids[ index ], message );
+				socket_print_error( stderr, value, "Socket receive: ", "\n" );
+				return value;
+			}
+		}
+		if( verbose ) print_mark( index );
+	}
+	return EOK;
+}
+
+void print_mark( int index ){
+	if(( index + 1 ) % 10 ){
+		printf( "*" );
+	}else{
+		printf( "|" );
+	}
+	fflush( stdout );
+}
+
+int main( int argc, char * argv[] ){
+	ERROR_DECLARE;
+
+	size_t				size			= 27;
+	int					verbose			= 0;
+	sock_type_t			type			= SOCK_DGRAM;
+	int					sockets			= 10;
+	int					messages		= 10;
+	int					family			= PF_INET;
+	uint16_t			port			= 7;
+
+	socklen_t			max_length		= sizeof( struct sockaddr_in6 );
+	uint8_t				address_data[ max_length ];
+	struct sockaddr *		address		= ( struct sockaddr * ) address_data;
+	struct sockaddr_in *	address_in		= ( struct sockaddr_in * ) address;
+	struct sockaddr_in6 *	address_in6	= ( struct sockaddr_in6 * ) address;
+	socklen_t			addrlen;
+//	char				address_string[ INET6_ADDRSTRLEN ];
+	uint8_t *			address_start;
+
+	int *				socket_ids;
+	char * 				data;
+	int					value;
+	int					index;
+	struct timeval		time_before;
+	struct timeval		time_after;
+
+	printf( "Task %d - ", task_get_id());
+	printf( "%s\n", NAME );
+
+	if( argc <= 1 ){
+		print_help();
+		return EINVAL;
+	}
+
+	for( index = 1; ( index < argc - 1 ) || (( index == argc ) && ( argv[ index ][ 0 ] == '-' )); ++ index ){
+		if( argv[ index ][ 0 ] == '-' ){
+			switch( argv[ index ][ 1 ] ){
+				case 'f':	ERROR_PROPAGATE( parse_parameter_name_int( argc, argv, & index, & family, "protocol family", 0, parse_protocol_family ));
+							break;
+				case 'h':	print_help();
+							return EOK;
+							break;
+				case 'm':	ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & messages, "message count", 0 ));
+							break;
+				case 'n':	ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & sockets, "socket count", 0 ));
+							break;
+				case 'p':	ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & value, "port number", 0 ));
+							port = ( uint16_t ) value;
+							break;
+				case 's':	ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & value, "packet size", 0 ));
+							size = (value >= 0 ) ? ( size_t ) value : 0;
+							break;
+				case 't':	ERROR_PROPAGATE( parse_parameter_name_int( argc, argv, & index, & value, "socket type", 0, parse_socket_type ));
+							type = ( sock_type_t ) value;
+							break;
+				case 'v':	verbose = 1;
+							break;
+				case '-':	if( str_lcmp( argv[ index ] + 2, "family=", 7 ) == 0 ){
+								ERROR_PROPAGATE( parse_parameter_name_int( argc, argv, & index, & family, "protocol family", 9, parse_protocol_family ));
+							}else if( str_lcmp( argv[ index ] + 2, "help", 5 ) == 0 ){
+								print_help();
+								return EOK;
+							}else if( str_lcmp( argv[ index ] + 2, "messages=", 6 ) == 0 ){
+								ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & messages, "message count", 8 ));
+							}else if( str_lcmp( argv[ index ] + 2, "sockets=", 6 ) == 0 ){
+								ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & sockets, "socket count", 8 ));
+							}else if( str_lcmp( argv[ index ] + 2, "port=", 5 ) == 0 ){
+								ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & value, "port number", 7 ));
+								port = ( uint16_t ) value;
+							}else if( str_lcmp( argv[ index ] + 2, "type=", 5 ) == 0 ){
+								ERROR_PROPAGATE( parse_parameter_name_int( argc, argv, & index, & value, "socket type", 7, parse_socket_type ));
+								type = ( sock_type_t ) value;
+							}else if( str_lcmp( argv[ index ] + 2, "verbose", 8 ) == 0 ){
+								verbose = 1;
+							}else{
+								print_unrecognized( index, argv[ index ] + 2 );
+								print_help();
+								return EINVAL;
+							}
+							break;
+				default:
+					print_unrecognized( index, argv[ index ] + 1 );
+					print_help();
+					return EINVAL;
+			}
+		}else{
+			print_unrecognized( index, argv[ index ] );
+			print_help();
+			return EINVAL;
+		}
+	}
+
+	bzero( address_data, max_length );
+	switch( family ){
+		case PF_INET:
+			address_in->sin_family = AF_INET;
+			address_in->sin_port = htons( port );
+			address_start = ( uint8_t * ) & address_in->sin_addr.s_addr;
+			addrlen = sizeof( struct sockaddr_in );
+			break;
+		case PF_INET6:
+			address_in6->sin6_family = AF_INET6;
+			address_in6->sin6_port = htons( port );
+			address_start = ( uint8_t * ) & address_in6->sin6_addr.s6_addr;
+			addrlen = sizeof( struct sockaddr_in6 );
+			break;
+		default:
+			fprintf( stderr, "Address family is not supported\n" );
+			return EAFNOSUPPORT;
+	}
+
+	if( ERROR_OCCURRED( inet_pton( family, argv[ argc - 1 ], address_start ))){
+		fprintf( stderr, "Address parse error %d\n", ERROR_CODE );
+		return ERROR_CODE;
+	}
+
+	if( size <= 0 ){
+		fprintf( stderr, "Data buffer size too small (%d). Using 1024 bytes instead.\n", size );
+		size = 1024;
+	}
+	// size plus terminating null (\0)
+	data = ( char * ) malloc( size + 1 );
+	if( ! data ){
+		fprintf( stderr, "Failed to allocate data buffer.\n" );
+		return ENOMEM;
+	}
+	refresh_data( data, size );
+
+	if( sockets <= 0 ){
+		fprintf( stderr, "Socket count too small (%d). Using 2 instead.\n", sockets );
+		sockets = 2;
+	}
+	// count plus terminating null (\0)
+	socket_ids = ( int * ) malloc( sizeof( int ) * ( sockets + 1 ));
+	if( ! socket_ids ){
+		fprintf( stderr, "Failed to allocate receive buffer.\n" );
+		return ENOMEM;
+	}
+	socket_ids[ sockets ] = NULL;
+
+	if( verbose ) printf( "Starting tests\n" );
+
+	if( verbose ) printf( "1 socket, 1 message\n" );
+
+	if( ERROR_OCCURRED( gettimeofday( & time_before, NULL ))){
+		fprintf( stderr, "Get time of day error %d\n", ERROR_CODE );
+		return ERROR_CODE;
+	}
+
+	ERROR_PROPAGATE( sockets_create( verbose, socket_ids, 1, family, type ));
+	ERROR_PROPAGATE( sockets_close( verbose, socket_ids, 1 ));
+	if( verbose ) printf( "\tOK\n" );
+
+	ERROR_PROPAGATE( sockets_create( verbose, socket_ids, 1, family, type ));
+	if( type == SOCK_STREAM ){
+		ERROR_PROPAGATE( sockets_connect( verbose, socket_ids, 1, address, addrlen ));
+	}
+	ERROR_PROPAGATE( sockets_sendto_recvfrom( verbose, socket_ids, 1, address, & addrlen, data, size, 1 ));
+	ERROR_PROPAGATE( sockets_close( verbose, socket_ids, 1 ));
+	if( verbose ) printf( "\tOK\n" );
+
+	ERROR_PROPAGATE( sockets_create( verbose, socket_ids, 1, family, type ));
+	if( type == SOCK_STREAM ){
+		ERROR_PROPAGATE( sockets_connect( verbose, socket_ids, 1, address, addrlen ));
+	}
+	ERROR_PROPAGATE( sockets_sendto( verbose, socket_ids, 1, address, addrlen, data, size, 1 ));
+	ERROR_PROPAGATE( sockets_recvfrom( verbose, socket_ids, 1, address, & addrlen, data, size, 1 ));
+	ERROR_PROPAGATE( sockets_close( verbose, socket_ids, 1 ));
+	if( verbose ) printf( "\tOK\n" );
+
+	if( verbose ) printf( "1 socket, %d messages\n", messages );
+
+	ERROR_PROPAGATE( sockets_create( verbose, socket_ids, 1, family, type ));
+	if( type == SOCK_STREAM ){
+		ERROR_PROPAGATE( sockets_connect( verbose, socket_ids, 1, address, addrlen ));
+	}
+	ERROR_PROPAGATE( sockets_sendto_recvfrom( verbose, socket_ids, 1, address, & addrlen, data, size, messages ));
+	ERROR_PROPAGATE( sockets_close( verbose, socket_ids, 1 ));
+	if( verbose ) printf( "\tOK\n" );
+
+	ERROR_PROPAGATE( sockets_create( verbose, socket_ids, 1, family, type ));
+	if( type == SOCK_STREAM ){
+		ERROR_PROPAGATE( sockets_connect( verbose, socket_ids, 1, address, addrlen ));
+	}
+	ERROR_PROPAGATE( sockets_sendto( verbose, socket_ids, 1, address, addrlen, data, size, messages ));
+	ERROR_PROPAGATE( sockets_recvfrom( verbose, socket_ids, 1, address, & addrlen, data, size, messages ));
+	ERROR_PROPAGATE( sockets_close( verbose, socket_ids, 1 ));
+	if( verbose ) printf( "\tOK\n" );
+
+	if( verbose ) printf( "%d sockets, 1 message\n", sockets );
+
+	ERROR_PROPAGATE( sockets_create( verbose, socket_ids, sockets, family, type ));
+	ERROR_PROPAGATE( sockets_close( verbose, socket_ids, sockets ));
+	if( verbose ) printf( "\tOK\n" );
+
+	ERROR_PROPAGATE( sockets_create( verbose, socket_ids, sockets, family, type ));
+	if( type == SOCK_STREAM ){
+		ERROR_PROPAGATE( sockets_connect( verbose, socket_ids, sockets, address, addrlen ));
+	}
+	ERROR_PROPAGATE( sockets_sendto_recvfrom( verbose, socket_ids, sockets, address, & addrlen, data, size, 1 ));
+	ERROR_PROPAGATE( sockets_close( verbose, socket_ids, sockets ));
+	if( verbose ) printf( "\tOK\n" );
+
+	ERROR_PROPAGATE( sockets_create( verbose, socket_ids, sockets, family, type ));
+	if( type == SOCK_STREAM ){
+		ERROR_PROPAGATE( sockets_connect( verbose, socket_ids, sockets, address, addrlen ));
+	}
+	ERROR_PROPAGATE( sockets_sendto( verbose, socket_ids, sockets, address, addrlen, data, size, 1 ));
+	ERROR_PROPAGATE( sockets_recvfrom( verbose, socket_ids, sockets, address, & addrlen, data, size, 1 ));
+	ERROR_PROPAGATE( sockets_close( verbose, socket_ids, sockets ));
+	if( verbose ) printf( "\tOK\n" );
+
+	if( verbose ) printf( "%d sockets, %d messages\n", sockets, messages );
+
+	ERROR_PROPAGATE( sockets_create( verbose, socket_ids, sockets, family, type ));
+	if( type == SOCK_STREAM ){
+		ERROR_PROPAGATE( sockets_connect( verbose, socket_ids, sockets, address, addrlen ));
+	}
+	ERROR_PROPAGATE( sockets_sendto_recvfrom( verbose, socket_ids, sockets, address, & addrlen, data, size, messages ));
+	ERROR_PROPAGATE( sockets_close( verbose, socket_ids, sockets ));
+	if( verbose ) printf( "\tOK\n" );
+
+	ERROR_PROPAGATE( sockets_create( verbose, socket_ids, sockets, family, type ));
+	if( type == SOCK_STREAM ){
+		ERROR_PROPAGATE( sockets_connect( verbose, socket_ids, sockets, address, addrlen ));
+	}
+	ERROR_PROPAGATE( sockets_sendto( verbose, socket_ids, sockets, address, addrlen, data, size, messages ));
+	ERROR_PROPAGATE( sockets_recvfrom( verbose, socket_ids, sockets, address, & addrlen, data, size, messages ));
+	ERROR_PROPAGATE( sockets_close( verbose, socket_ids, sockets ));
+
+	if( ERROR_OCCURRED( gettimeofday( & time_after, NULL ))){
+		fprintf( stderr, "Get time of day error %d\n", ERROR_CODE );
+		return ERROR_CODE;
+	}
+
+	if( verbose ) printf( "\tOK\n" );
+
+	printf( "Tested in %d microseconds\n", tv_sub( & time_after, & time_before ));
+
+	if( verbose ) printf( "Exiting\n" );
+
+	return EOK;
+}
+
+/** @}
+ */
Index: uspace/srv/net/app/nettest2/Makefile
===================================================================
--- uspace/srv/net/app/nettest2/Makefile	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/app/nettest2/Makefile	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,47 @@
+#
+# 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.
+#
+
+NAME = nettest2
+
+NET_BASE = ../../
+STRUCTURES = $(NET_BASE)structures/
+
+include ../../../../../Makefile.config
+
+## Sources
+#
+
+OUTPUT = $(NAME)
+SOURCES = \
+	$(NAME).c \
+	$(NET_BASE)app/parse.c \
+	$(NET_BASE)app/print_error.c
+
+LIBS += ../../socket/libsocket.a
+
+include $(NET_BASE)Makefile.module
Index: uspace/srv/net/app/nettest2/nettest2.c
===================================================================
--- uspace/srv/net/app/nettest2/nettest2.c	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/app/nettest2/nettest2.c	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,557 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup nettest
+ *  @{
+ */
+
+/** @file
+ *  Networking test 2 application - transfer.
+ */
+
+#include <malloc.h>
+#include <stdio.h>
+#include <string.h>
+#include <task.h>
+#include <time.h>
+
+#include "../../include/in.h"
+#include "../../include/in6.h"
+#include "../../include/inet.h"
+#include "../../include/socket.h"
+
+#include "../../err.h"
+
+#include "../parse.h"
+#include "../print_error.h"
+
+/** Echo module name.
+ */
+#define NAME	"Nettest2"
+
+/** Packet data pattern.
+ */
+#define NETTEST2_TEXT	"Networking test 2 - transfer"
+
+/** Module entry point.
+ *  Starts testing.
+ *  @param[in] argc The number of command line parameters.
+ *  @param[in] argv The command line parameters.
+ *  @returns EOK on success.
+ */
+int		main( int argc, char * argv[] );
+
+/** Prints the application help.
+ */
+void	print_help( void );
+
+/** Translates the character string to the protocol family number.
+ *  @param[in] name The protocol family name.
+ *  @returns The corresponding protocol family number.
+ *  @returns EPFNOSUPPORTED if the protocol family is not supported.
+ */
+int		parse_protocol_family( const char * name );
+
+/** Translates the character string to the socket type number.
+ *  @param[in] name The socket type name.
+ *  @returns The corresponding socket type number.
+ *  @returns ESOCKNOSUPPORTED if the socket type is not supported.
+ */
+int		parse_socket_type( const char * name );
+
+/** Refreshes the data.
+ *  Fills the data block with the NETTEST1_TEXT pattern.
+ *  @param[out] data The data block.
+ *  @param[in] size The data block size in bytes.
+ */
+void	refresh_data( char * data, size_t size );
+
+/** Creates new sockets.
+ *  @param[in] verbose A value indicating whether to print out verbose information.
+ *  @param[out] socket_ids A field to store the socket identifiers.
+ *  @param[in] sockets The number of sockets to create. Should be at most the size of the field.
+ *  @param[in] family The socket address family.
+ *  @param[in] type The socket type.
+ *  @returns EOK on success.
+ *  @returns Other error codes as defined for the socket() function.
+ */
+int	sockets_create( int verbose, int * socket_ids, int sockets, int family, sock_type_t type );
+
+/** Closes sockets.
+ *  @param[in] verbose A value indicating whether to print out verbose information.
+ *  @param[in] socket_ids A field of stored socket identifiers.
+ *  @param[in] sockets The number of sockets in the field. Should be at most the size of the field.
+ *  @returns EOK on success.
+ *  @returns Other error codes as defined for the closesocket() function.
+ */
+int	sockets_close( int verbose, int * socket_ids, int sockets );
+
+/** Connects sockets.
+ *  @param[in] verbose A value indicating whether to print out verbose information.
+ *  @param[in] socket_ids A field of stored socket identifiers.
+ *  @param[in] sockets The number of sockets in the field. Should be at most the size of the field.
+ *  @param[in] address The destination host address to connect to.
+ *  @param[in] addrlen The length of the destination address in bytes.
+ *  @returns EOK on success.
+ *  @returns Other error codes as defined for the connect() function.
+ */
+int	sockets_connect( int verbose, int * socket_ids, int sockets, struct sockaddr * address, socklen_t addrlen );
+
+/** Sends data via sockets.
+ *  @param[in] verbose A value indicating whether to print out verbose information.
+ *  @param[in] socket_ids A field of stored socket identifiers.
+ *  @param[in] sockets The number of sockets in the field. Should be at most the size of the field.
+ *  @param[in] address The destination host address to send data to.
+ *  @param[in] addrlen The length of the destination address in bytes.
+ *  @param[in] data The data to be sent.
+ *  @param[in] size The data size in bytes.
+ *  @param[in] messages The number of datagrams per socket to be sent.
+ *  @returns EOK on success.
+ *  @returns Other error codes as defined for the sendto() function.
+ */
+int	sockets_sendto( int verbose, int * socket_ids, int sockets, struct sockaddr * address, socklen_t addrlen, char * data, int size, int messages );
+
+/** Receives data via sockets.
+ *  @param[in] verbose A value indicating whether to print out verbose information.
+ *  @param[in] socket_ids A field of stored socket identifiers.
+ *  @param[in] sockets The number of sockets in the field. Should be at most the size of the field.
+ *  @param[in] address The source host address of received datagrams.
+ *  @param[in,out] addrlen The maximum length of the source address in bytes. The actual size of the source address is set instead.
+ *  @param[out] data The received data.
+ *  @param[in] size The maximum data size in bytes.
+ *  @param[in] messages The number of datagrams per socket to be received.
+ *  @returns EOK on success.
+ *  @returns Other error codes as defined for the recvfrom() function.
+ */
+int	sockets_recvfrom( int verbose, int * socket_ids, int sockets, struct sockaddr * address, socklen_t * addrlen, char * data, int size, int messages );
+
+/** Sends and receives data via sockets.
+ *  Each datagram is sent and a reply read consequently.
+ *  The next datagram is sent after the reply is received.
+ *  @param[in] verbose A value indicating whether to print out verbose information.
+ *  @param[in] socket_ids A field of stored socket identifiers.
+ *  @param[in] sockets The number of sockets in the field. Should be at most the size of the field.
+ *  @param[in,out] address The destination host address to send data to. The source host address of received datagrams is set instead.
+ *  @param[in] addrlen The length of the destination address in bytes.
+ *  @param[in,out] data The data to be sent. The received data are set instead.
+ *  @param[in] size The data size in bytes.
+ *  @param[in] messages The number of datagrams per socket to be received.
+ *  @returns EOK on success.
+ *  @returns Other error codes as defined for the recvfrom() function.
+ */
+int	sockets_sendto_recvfrom( int verbose, int * socket_ids, int sockets, struct sockaddr * address, socklen_t * addrlen, char * data, int size, int messages );
+
+/** Prints a mark.
+ *  If the index is a multiple of ten, a different mark is printed.
+ *  @param[in] index The index of the mark to be printed.
+ */
+void	print_mark( int index );
+
+void print_help( void ){
+	printf(
+		"Network Networking test 2 aplication - UDP transfer\n" \
+		"Usage: echo [options] numeric_address\n" \
+		"Where options are:\n" \
+		"-f protocol_family | --family=protocol_family\n" \
+		"\tThe listenning socket protocol family. Only the PF_INET and PF_INET6 are supported.\n"
+		"\n" \
+		"-h | --help\n" \
+		"\tShow this application help.\n"
+		"\n" \
+		"-m count | --messages=count\n" \
+		"\tThe number of messages to send and receive per socket. The default is 10.\n" \
+		"\n" \
+		"-n sockets | --sockets=count\n" \
+		"\tThe number of sockets to use. The default is 10.\n" \
+		"\n" \
+		"-p port_number | --port=port_number\n" \
+		"\tThe port number the application should send messages to. The default is 7.\n" \
+		"\n" \
+		"-s packet_size | --size=packet_size\n" \
+		"\tThe packet data size the application sends. The default is 29 bytes.\n" \
+		"\n" \
+		"-v | --verbose\n" \
+		"\tShow all output messages.\n"
+	);
+}
+
+int parse_protocol_family( const char * name ){
+	if( str_lcmp( name, "PF_INET", 7 ) == 0 ){
+		return PF_INET;
+	}else if( str_lcmp( name, "PF_INET6", 8 ) == 0 ){
+		return PF_INET6;
+	}
+	return EPFNOSUPPORT;
+}
+
+int parse_socket_type( const char * name ){
+	if( str_lcmp( name, "SOCK_DGRAM", 11 ) == 0 ){
+		return SOCK_DGRAM;
+	}else if( str_lcmp( name, "SOCK_STREAM", 12 ) == 0 ){
+		return SOCK_STREAM;
+	}
+	return ESOCKTNOSUPPORT;
+}
+
+void refresh_data( char * data, size_t size ){
+	size_t	length;
+
+	// fill the data
+	length = 0;
+	while( size > length + sizeof( NETTEST2_TEXT ) - 1 ){
+		memcpy( data + length, NETTEST2_TEXT, sizeof( NETTEST2_TEXT ) - 1 );
+		length += sizeof( NETTEST2_TEXT ) - 1;
+	}
+	memcpy( data + length, NETTEST2_TEXT, size - length );
+	data[ size ] = '\0';
+}
+
+int sockets_create( int verbose, int * socket_ids, int sockets, int family, sock_type_t type ){
+	int	index;
+
+	if( verbose ) printf( "Create\t" );
+	fflush( stdout );
+	for( index = 0; index < sockets; ++ index ){
+		socket_ids[ index ] = socket( family, type, 0 );
+		if( socket_ids[ index ] < 0 ){
+			printf( "Socket %d (%d) error:\n", index, socket_ids[ index ] );
+			socket_print_error( stderr, socket_ids[ index ], "Socket create: ", "\n" );
+			return socket_ids[ index ];
+		}
+		if( verbose ) print_mark( index );
+	}
+	return EOK;
+}
+
+int sockets_close( int verbose, int * socket_ids, int sockets ){
+	ERROR_DECLARE;
+
+	int	index;
+
+	if( verbose ) printf( "\tClose\t" );
+	fflush( stdout );
+	for( index = 0; index < sockets; ++ index ){
+		if( ERROR_OCCURRED( closesocket( socket_ids[ index ] ))){
+			printf( "Socket %d (%d) error:\n", index, socket_ids[ index ] );
+			socket_print_error( stderr, ERROR_CODE, "Socket close: ", "\n" );
+			return ERROR_CODE;
+		}
+		if( verbose ) print_mark( index );
+	}
+	return EOK;
+}
+
+int sockets_connect( int verbose, int * socket_ids, int sockets, struct sockaddr * address, socklen_t addrlen ){
+	ERROR_DECLARE;
+
+	int	index;
+
+	if( verbose ) printf( "\tConnect\t" );
+	fflush( stdout );
+	for( index = 0; index < sockets; ++ index ){
+		if( ERROR_OCCURRED( connect( socket_ids[ index ], address, addrlen ))){
+			socket_print_error( stderr, ERROR_CODE, "Socket connect: ", "\n" );
+			return ERROR_CODE;
+		}
+		if( verbose ) print_mark( index );
+	}
+	return EOK;
+}
+
+int sockets_sendto( int verbose, int * socket_ids, int sockets, struct sockaddr * address, socklen_t addrlen, char * data, int size, int messages ){
+	ERROR_DECLARE;
+
+	int	index;
+	int	message;
+
+	if( verbose ) printf( "\tSendto\t" );
+	fflush( stdout );
+	for( index = 0; index < sockets; ++ index ){
+		for( message = 0; message < messages; ++ message ){
+			if( ERROR_OCCURRED( sendto( socket_ids[ index ], data, size, 0, address, addrlen ))){
+				printf( "Socket %d (%d), message %d error:\n", index, socket_ids[ index ], message );
+				socket_print_error( stderr, ERROR_CODE, "Socket send: ", "\n" );
+				return ERROR_CODE;
+			}
+		}
+		if( verbose ) print_mark( index );
+	}
+	return EOK;
+}
+
+int sockets_recvfrom( int verbose, int * socket_ids, int sockets, struct sockaddr * address, socklen_t * addrlen, char * data, int size, int messages ){
+	int	value;
+	int	index;
+	int	message;
+
+	if( verbose ) printf( "\tRecvfrom\t" );
+	fflush( stdout );
+	for( index = 0; index < sockets; ++ index ){
+		for( message = 0; message < messages; ++ message ){
+			value = recvfrom( socket_ids[ index ], data, size, 0, address, addrlen );
+			if( value < 0 ){
+				printf( "Socket %d (%d), message %d error:\n", index, socket_ids[ index ], message );
+				socket_print_error( stderr, value, "Socket receive: ", "\n" );
+				return value;
+			}
+		}
+		if( verbose ) print_mark( index );
+	}
+	return EOK;
+}
+
+int sockets_sendto_recvfrom( int verbose, int * socket_ids, int sockets, struct sockaddr * address, socklen_t * addrlen, char * data, int size, int messages ){
+	ERROR_DECLARE;
+
+	int	value;
+	int	index;
+	int	message;
+
+	if( verbose ) printf( "\tSendto and recvfrom\t" );
+	fflush( stdout );
+	for( index = 0; index < sockets; ++ index ){
+		for( message = 0; message < messages; ++ message ){
+			if( ERROR_OCCURRED( sendto( socket_ids[ index ], data, size, 0, address, * addrlen ))){
+				printf( "Socket %d (%d), message %d error:\n", index, socket_ids[ index ], message );
+				socket_print_error( stderr, ERROR_CODE, "Socket send: ", "\n" );
+				return ERROR_CODE;
+			}
+			value = recvfrom( socket_ids[ index ], data, size, 0, address, addrlen );
+			if( value < 0 ){
+				printf( "Socket %d (%d), message %d error:\n", index, socket_ids[ index ], message );
+				socket_print_error( stderr, value, "Socket receive: ", "\n" );
+				return value;
+			}
+		}
+		if( verbose ) print_mark( index );
+	}
+	return EOK;
+}
+
+void print_mark( int index ){
+	if(( index + 1 ) % 10 ){
+		printf( "*" );
+	}else{
+		printf( "|" );
+	}
+	fflush( stdout );
+}
+
+int main( int argc, char * argv[] ){
+	ERROR_DECLARE;
+
+	size_t				size			= 28;
+	int					verbose			= 0;
+	sock_type_t			type			= SOCK_DGRAM;
+	int					sockets			= 10;
+	int					messages		= 10;
+	int					family			= PF_INET;
+	uint16_t			port			= 7;
+
+	socklen_t			max_length		= sizeof( struct sockaddr_in6 );
+	uint8_t				address_data[ max_length ];
+	struct sockaddr *		address		= ( struct sockaddr * ) address_data;
+	struct sockaddr_in *	address_in		= ( struct sockaddr_in * ) address;
+	struct sockaddr_in6 *	address_in6	= ( struct sockaddr_in6 * ) address;
+	socklen_t			addrlen;
+//	char				address_string[ INET6_ADDRSTRLEN ];
+	uint8_t *			address_start;
+
+	int *				socket_ids;
+	char * 				data;
+	int					value;
+	int					index;
+	struct timeval		time_before;
+	struct timeval		time_after;
+
+	printf( "Task %d - ", task_get_id());
+	printf( "%s\n", NAME );
+
+	if( argc <= 1 ){
+		print_help();
+		return EINVAL;
+	}
+
+	for( index = 1; ( index < argc - 1 ) || (( index == argc ) && ( argv[ index ][ 0 ] == '-' )); ++ index ){
+		if( argv[ index ][ 0 ] == '-' ){
+			switch( argv[ index ][ 1 ] ){
+				case 'f':	ERROR_PROPAGATE( parse_parameter_name_int( argc, argv, & index, & family, "protocol family", 0, parse_protocol_family ));
+							break;
+				case 'h':	print_help();
+							return EOK;
+							break;
+				case 'm':	ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & messages, "message count", 0 ));
+							break;
+				case 'n':	ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & sockets, "socket count", 0 ));
+							break;
+				case 'p':	ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & value, "port number", 0 ));
+							port = ( uint16_t ) value;
+							break;
+				case 's':	ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & value, "packet size", 0 ));
+							size = (value >= 0 ) ? ( size_t ) value : 0;
+							break;
+				case 't':	ERROR_PROPAGATE( parse_parameter_name_int( argc, argv, & index, & value, "socket type", 0, parse_socket_type ));
+							type = ( sock_type_t ) value;
+							break;
+				case 'v':	verbose = 1;
+							break;
+				case '-':	if( str_lcmp( argv[ index ] + 2, "family=", 7 ) == 0 ){
+								ERROR_PROPAGATE( parse_parameter_name_int( argc, argv, & index, & family, "protocol family", 9, parse_protocol_family ));
+							}else if( str_lcmp( argv[ index ] + 2, "help", 5 ) == 0 ){
+								print_help();
+								return EOK;
+							}else if( str_lcmp( argv[ index ] + 2, "messages=", 6 ) == 0 ){
+								ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & messages, "message count", 8 ));
+							}else if( str_lcmp( argv[ index ] + 2, "sockets=", 6 ) == 0 ){
+								ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & sockets, "socket count", 8 ));
+							}else if( str_lcmp( argv[ index ] + 2, "port=", 5 ) == 0 ){
+								ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & value, "port number", 7 ));
+								port = ( uint16_t ) value;
+							}else if( str_lcmp( argv[ index ] + 2, "type=", 5 ) == 0 ){
+								ERROR_PROPAGATE( parse_parameter_name_int( argc, argv, & index, & value, "socket type", 7, parse_socket_type ));
+								type = ( sock_type_t ) value;
+							}else if( str_lcmp( argv[ index ] + 2, "verbose", 8 ) == 0 ){
+								verbose = 1;
+							}else{
+								print_unrecognized( index, argv[ index ] + 2 );
+								print_help();
+								return EINVAL;
+							}
+							break;
+				default:
+					print_unrecognized( index, argv[ index ] + 1 );
+					print_help();
+					return EINVAL;
+			}
+		}else{
+			print_unrecognized( index, argv[ index ] );
+			print_help();
+			return EINVAL;
+		}
+	}
+
+	bzero( address_data, max_length );
+	switch( family ){
+		case PF_INET:
+			address_in->sin_family = AF_INET;
+			address_in->sin_port = htons( port );
+			address_start = ( uint8_t * ) & address_in->sin_addr.s_addr;
+			addrlen = sizeof( struct sockaddr_in );
+			break;
+		case PF_INET6:
+			address_in6->sin6_family = AF_INET6;
+			address_in6->sin6_port = htons( port );
+			address_start = ( uint8_t * ) & address_in6->sin6_addr.s6_addr;
+			addrlen = sizeof( struct sockaddr_in6 );
+			break;
+		default:
+			fprintf( stderr, "Address family is not supported\n" );
+			return EAFNOSUPPORT;
+	}
+
+	if( ERROR_OCCURRED( inet_pton( family, argv[ argc - 1 ], address_start ))){
+		fprintf( stderr, "Address parse error %d\n", ERROR_CODE );
+		return ERROR_CODE;
+	}
+
+	if( size <= 0 ){
+		fprintf( stderr, "Data buffer size too small (%d). Using 1024 bytes instead.\n", size );
+		size = 1024;
+	}
+	// size plus terminating null (\0)
+	data = ( char * ) malloc( size + 1 );
+	if( ! data ){
+		fprintf( stderr, "Failed to allocate data buffer.\n" );
+		return ENOMEM;
+	}
+	refresh_data( data, size );
+
+	if( sockets <= 0 ){
+		fprintf( stderr, "Socket count too small (%d). Using 2 instead.\n", sockets );
+		sockets = 2;
+	}
+	// count plus terminating null (\0)
+	socket_ids = ( int * ) malloc( sizeof( int ) * ( sockets + 1 ));
+	if( ! socket_ids ){
+		fprintf( stderr, "Failed to allocate receive buffer.\n" );
+		return ENOMEM;
+	}
+	socket_ids[ sockets ] = NULL;
+
+	if( verbose ) printf( "Starting tests\n" );
+
+	ERROR_PROPAGATE( sockets_create( verbose, socket_ids, sockets, family, type ));
+
+	if( type == SOCK_STREAM ){
+		ERROR_PROPAGATE( sockets_connect( verbose, socket_ids, sockets, address, addrlen ));
+	}
+
+	if( verbose ) printf( "\n" );
+
+	if( ERROR_OCCURRED( gettimeofday( & time_before, NULL ))){
+		fprintf( stderr, "Get time of day error %d\n", ERROR_CODE );
+		return ERROR_CODE;
+	}
+
+	ERROR_PROPAGATE( sockets_sendto_recvfrom( verbose, socket_ids, sockets, address, & addrlen, data, size, messages ));
+
+	if( ERROR_OCCURRED( gettimeofday( & time_after, NULL ))){
+		fprintf( stderr, "Get time of day error %d\n", ERROR_CODE );
+		return ERROR_CODE;
+	}
+
+	if( verbose ) printf( "\tOK\n" );
+
+	printf( "sendto + recvfrom tested in %d microseconds\n", tv_sub( & time_after, & time_before ));
+
+	if( ERROR_OCCURRED( gettimeofday( & time_before, NULL ))){
+		fprintf( stderr, "Get time of day error %d\n", ERROR_CODE );
+		return ERROR_CODE;
+	}
+
+	ERROR_PROPAGATE( sockets_sendto( verbose, socket_ids, sockets, address, addrlen, data, size, messages ));
+	ERROR_PROPAGATE( sockets_recvfrom( verbose, socket_ids, sockets, address, & addrlen, data, size, messages ));
+
+	if( ERROR_OCCURRED( gettimeofday( & time_after, NULL ))){
+		fprintf( stderr, "Get time of day error %d\n", ERROR_CODE );
+		return ERROR_CODE;
+	}
+
+	if( verbose ) printf( "\tOK\n" );
+
+	printf( "sendto, recvfrom tested in %d microseconds\n", tv_sub( & time_after, & time_before ));
+
+	ERROR_PROPAGATE( sockets_close( verbose, socket_ids, sockets ));
+
+	if( verbose ) printf( "\nExiting\n" );
+
+	return EOK;
+}
+
+/** @}
+ */
Index: uspace/srv/net/app/parse.c
===================================================================
--- uspace/srv/net/app/parse.c	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/app/parse.c	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup net_app
+ *  @{
+ */
+
+/** @file
+ *  Generic application parsing functions implementation.
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "../err.h"
+
+#include "parse.h"
+
+int parse_parameter_int( int argc, char ** argv, int * index, int * value, const char * name, int offset ){
+	char *	rest;
+
+	if( offset ){
+		* value = strtol( argv[ * index ] + offset, & rest, 10 );
+	}else if(( * index ) + 1 < argc ){
+		++ ( * index );
+		* value = strtol( argv[ * index ], & rest, 10 );
+	}else{
+		fprintf( stderr, "Command line error: missing %s\n", name );
+		return EINVAL;
+	}
+	if( rest && ( * rest )){
+		fprintf( stderr, "Command line error: %s unrecognized (%d: %s)\n", name, * index, argv[ * index ] );
+		return EINVAL;
+	}
+	return EOK;
+}
+
+int parse_parameter_string( int argc, char ** argv, int * index, char ** value, const char * name, int offset ){
+	if( offset ){
+		* value = argv[ * index ] + offset;
+	}else if(( * index ) + 1 < argc ){
+		++ ( * index );
+		* value = argv[ * index ];
+	}else{
+		fprintf( stderr, "Command line error: missing %s\n", name );
+		return EINVAL;
+	}
+	return EOK;
+}
+
+int parse_parameter_name_int( int argc, char ** argv, int * index, int * value, const char * name, int offset, int ( * parse_value )( const char * value )){
+	ERROR_DECLARE;
+
+	char *	parameter;
+
+	ERROR_PROPAGATE( parse_parameter_string( argc, argv, index, & parameter, name, offset ));
+	* value = ( * parse_value )( parameter );
+	if(( * value ) == ENOENT ){
+		fprintf( stderr, "Command line error: unrecognized %s value (%d: %s)\n", name, * index, parameter );
+		return ENOENT;
+	}
+	return EOK;
+}
+
+void print_unrecognized( int index, const char * parameter ){
+	fprintf( stderr, "Command line error - unrecognized parameter (%d: %s)\n", index, parameter );
+}
+
+/** @}
+ */
Index: uspace/srv/net/app/parse.h
===================================================================
--- uspace/srv/net/app/parse.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/app/parse.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup net_app
+ *  @{
+ */
+
+/** @file
+ *  Generic command line arguments parsing functions.
+ */
+
+#ifndef __NET_APP_PARSE__
+#define __NET_APP_PARSE__
+
+/** Prints the parameter unrecognized message and the application help.
+ *  @param[in] index The index of the parameter.
+ *  @param[in] parameter The parameter name.
+ */
+void	print_unrecognized( int index, const char * parameter );
+
+/** Parses the next parameter as an integral number.
+ *  The actual parameter is pointed by the index.
+ *  Parses the offseted actual parameter value if the offset is set or the next one if not.
+ *  @param[in] argc The total number of the parameters.
+ *  @param[in] argv The parameters.
+ *  @param[in,out] index The actual parameter index. The index is incremented by the number of processed parameters.
+ *  @param[out] value The parsed parameter value.
+ *  @param[in] name The parameter name to be printed on errors.
+ *  @param[in] offset The value offset in the actual parameter. If not set, the next parameter is parsed instead.
+ *  @returns EOK on success.
+ *  @returns EINVAL if the parameter is missing.
+ *  @returns EINVAL if the parameter is in wrong format.
+ */
+int	parse_parameter_int( int argc, char ** argv, int * index, int * value, const char * name, int offset );
+
+/** Parses the next parameter as a character string.
+ *  The actual parameter is pointed by the index.
+ *  Uses the offseted actual parameter value if the offset is set or the next one if not.
+ *  Increments the actual index by the number of processed parameters.
+ *  @param[in] argc The total number of the parameters.
+ *  @param[in] argv The parameters.
+ *  @param[in,out] index The actual parameter index. The index is incremented by the number of processed parameters.
+ *  @param[out] value The parsed parameter value.
+ *  @param[in] name The parameter name to be printed on errors.
+ *  @param[in] offset The value offset in the actual parameter. If not set, the next parameter is parsed instead.
+ *  @returns EOK on success.
+ *  @returns EINVAL if the parameter is missing.
+ */
+int	parse_parameter_string( int argc, char ** argv, int * index, char ** value, const char * name, int offset );
+
+/** Parses the next named parameter as an integral number.
+ *  The actual parameter is pointed by the index.
+ *  Uses the offseted actual parameter if the offset is set or the next one if not.
+ *  Translates the parameter using the parse_value function.
+ *  Increments the actual index by the number of processed parameters.
+ *  @param[in] argc The total number of the parameters.
+ *  @param[in] argv The parameters.
+ *  @param[in,out] index The actual parameter index. The index is incremented by the number of processed parameters.
+ *  @param[out] value The parsed parameter value.
+ *  @param[in] name The parameter name to be printed on errors.
+ *  @param[in] offset The value offset in the actual parameter. If not set, the next parameter is parsed instead.
+ *  @param[in] parse_value The translation function to parse the named value.
+ *  @returns EOK on success.
+ *  @returns EINVAL if the parameter is missing.
+ *  @returns ENOENT if the parameter name has not been found.
+ */
+int	parse_parameter_name_int( int argc, char ** argv, int * index, int * value, const char * name, int offset, int ( * parse_value )( const char * value ));
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/app/ping/Makefile
===================================================================
--- uspace/srv/net/app/ping/Makefile	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/app/ping/Makefile	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,49 @@
+#
+# 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.
+#
+
+NAME = ping
+
+NET_BASE = ../../
+STRUCTURES = $(NET_BASE)structures/
+
+include ../../../../../Makefile.config
+
+## Sources
+#
+
+OUTPUT = $(NAME)
+SOURCES = \
+	$(NAME).c \
+	$(NET_BASE)app/parse.c \
+	$(NET_BASE)app/print_error.c \
+	$(NET_BASE)inet.c \
+	$(NET_BASE)modules.c \
+	$(NET_BASE)tl/icmp/icmp_api.c \
+	$(NET_BASE)tl/icmp/icmp_common.c
+
+include $(NET_BASE)Makefile.module
Index: uspace/srv/net/app/ping/ping.c
===================================================================
--- uspace/srv/net/app/ping/ping.c	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/app/ping/ping.c	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,280 @@
+/*
+ * 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 ping
+ *  @{
+ */
+
+/** @file
+ *  Ping application.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <task.h>
+#include <time.h>
+#include <ipc/services.h>
+
+#include "../../include/icmp_api.h"
+#include "../../include/in.h"
+#include "../../include/in6.h"
+#include "../../include/inet.h"
+#include "../../include/ip_codes.h"
+#include "../../include/socket_errno.h"
+
+#include "../../err.h"
+
+#include "../parse.h"
+#include "../print_error.h"
+
+/** Echo module name.
+ */
+#define NAME	"Ping"
+
+/** Module entry point.
+ *  Reads command line parameters and pings.
+ *  @param[in] argc The number of command line parameters.
+ *  @param[in] argv The command line parameters.
+ *  @returns EOK on success.
+ */
+int		main( int argc, char * argv[] );
+
+/** Prints the application help.
+ */
+void	print_help( void );
+
+/** Translates the character string to the address family number.
+ *  @param[in] name The address family name.
+ *  @returns The corresponding address family number.
+ *  @returns EAFNOSUPPORTED if the address family is not supported.
+ */
+int		parse_address_family( const char * name );
+
+void print_help( void ){
+	printf(
+		"Network Ping aplication\n" \
+		"Usage: ping [options] numeric_address\n" \
+		"Where options are:\n" \
+		"\n" \
+		"-c request_count | --count=request_count\n" \
+		"\tThe number of packets the application sends. The default is three (3).\n" \
+		"\n" \
+		"--dont_fragment\n" \
+		"\tDisable packet fragmentation.\n"
+		"\n" \
+		"-f address_family | --family=address_family\n" \
+		"\tThe given address family. Only the AF_INET and AF_INET6 are supported.\n"
+		"\n" \
+		"-h | --help\n" \
+		"\tShow this application help.\n"
+		"\n" \
+		"-s packet_size | --size=packet_size\n" \
+		"\tThe packet data size the application sends. The default is 38 bytes.\n" \
+		"\n" \
+		"-t timeout | --timeout=timeout\n" \
+		"\tThe number of miliseconds the application waits for a reply. The default is three thousands (3 000).\n" \
+		"\n" \
+		"--tos=tos\n" \
+		"\tThe type of service to be used.\n" \
+		"\n" \
+		"--ttl=ttl\n" \
+		"\tThe time to live to be used.\n" \
+		"\n" \
+		"-v | --verbose\n" \
+		"\tShow all output messages.\n"
+	);
+}
+
+int parse_address_family( const char * name ){
+	if( str_lcmp( name, "AF_INET", 7 ) == 0 ){
+		return AF_INET;
+	}else if( str_lcmp( name, "AF_INET6", 8 ) == 0 ){
+		return AF_INET6;
+	}
+	return EAFNOSUPPORT;
+}
+
+int main( int argc, char * argv[] ){
+	ERROR_DECLARE;
+
+	size_t				size			= 38;
+	int					verbose			= 0;
+	int					dont_fragment	= 0;
+	ip_ttl_t			ttl				= 0;
+	ip_tos_t			tos				= 0;
+	int					count			= 3;
+	suseconds_t			timeout			= 3000;
+	int					family			= AF_INET;
+
+	socklen_t			max_length		= sizeof( struct sockaddr_in6 );
+	uint8_t				address_data[ max_length ];
+	struct sockaddr *		address		= ( struct sockaddr * ) address_data;
+	struct sockaddr_in *	address_in		= ( struct sockaddr_in * ) address;
+	struct sockaddr_in6 *	address_in6	= ( struct sockaddr_in6 * ) address;
+	socklen_t			addrlen;
+	char				address_string[ INET6_ADDRSTRLEN ];
+	uint8_t *			address_start;
+	int					icmp_phone;
+	struct timeval		time_before;
+	struct timeval		time_after;
+	int					result;
+	int					value;
+	int					index;
+
+	printf( "Task %d - ", task_get_id());
+	printf( "%s\n", NAME );
+
+	if( argc <= 1 ){
+		print_help();
+		return EINVAL;
+	}
+
+	for( index = 1; ( index < argc - 1 ) || (( index == argc ) && ( argv[ index ][ 0 ] == '-' )); ++ index ){
+		if( argv[ index ][ 0 ] == '-' ){
+			switch( argv[ index ][ 1 ] ){
+				case 'c':	ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & count, "count", 0 ));
+							break;
+				case 'f':	ERROR_PROPAGATE( parse_parameter_name_int( argc, argv, & index, & family, "address family", 0, parse_address_family ));
+							break;
+				case 'h':	print_help();
+							return EOK;
+							break;
+				case 's':	ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & value, "packet size", 0 ));
+							size = (value >= 0 ) ? ( size_t ) value : 0;
+							break;
+				case 't':	ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & value, "timeout", 0 ));
+							timeout = (value >= 0 ) ? ( suseconds_t ) value : 0;
+							break;
+				case 'v':	verbose = 1;
+							break;
+				case '-':	if( str_lcmp( argv[ index ] + 2, "count=", 6 ) == 0 ){
+								ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & count, "received count", 8 ));
+							}else if( str_lcmp( argv[ index ] + 2, "dont_fragment", 13 ) == 0 ){
+								dont_fragment = 1;
+							}else if( str_lcmp( argv[ index ] + 2, "family=", 7 ) == 0 ){
+								ERROR_PROPAGATE( parse_parameter_name_int( argc, argv, & index, & family, "address family", 9, parse_address_family ));
+							}else if( str_lcmp( argv[ index ] + 2, "help", 5 ) == 0 ){
+								print_help();
+								return EOK;
+							}else if( str_lcmp( argv[ index ] + 2, "size=", 5 ) == 0 ){
+								ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & value, "packet size", 7 ));
+								size = (value >= 0 ) ? ( size_t ) value : 0;
+							}else if( str_lcmp( argv[ index ] + 2, "timeout=", 8 ) == 0 ){
+								ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & value, "timeout", 7 ));
+								timeout = (value >= 0 ) ? ( suseconds_t ) value : 0;
+							}else if( str_lcmp( argv[ index ] + 2, "tos=", 4 ) == 0 ){
+								ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & value, "type of service", 7 ));
+								tos = (value >= 0 ) ? ( ip_tos_t ) value : 0;
+							}else if( str_lcmp( argv[ index ] + 2, "ttl=", 4 ) == 0 ){
+								ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & value, "time to live", 7 ));
+								ttl = (value >= 0 ) ? ( ip_ttl_t ) value : 0;
+							}else if( str_lcmp( argv[ index ] + 2, "verbose", 8 ) == 0 ){
+								verbose = 1;
+							}else{
+								print_unrecognized( index, argv[ index ] + 2 );
+								print_help();
+								return EINVAL;
+							}
+							break;
+				default:
+					print_unrecognized( index, argv[ index ] + 1 );
+					print_help();
+					return EINVAL;
+			}
+		}else{
+			print_unrecognized( index, argv[ index ] );
+			print_help();
+			return EINVAL;
+		}
+	}
+
+	bzero( address_data, max_length );
+	switch( family ){
+		case AF_INET:
+			address_in->sin_family = AF_INET;
+			address_start = ( uint8_t * ) & address_in->sin_addr.s_addr;
+			addrlen = sizeof( struct sockaddr_in );
+			break;
+		case AF_INET6:
+			address_in6->sin6_family = AF_INET6;
+			address_start = ( uint8_t * ) & address_in6->sin6_addr.s6_addr;
+			addrlen = sizeof( struct sockaddr_in6 );
+			break;
+		default:
+			fprintf( stderr, "Address family is not supported\n" );
+			return EAFNOSUPPORT;
+	}
+
+	if( ERROR_OCCURRED( inet_pton( family, argv[ argc - 1 ], address_start ))){
+		fprintf( stderr, "Address parse error %d\n", ERROR_CODE );
+		return ERROR_CODE;
+	}
+
+	icmp_phone = icmp_connect_module( SERVICE_ICMP, ICMP_CONNECT_TIMEOUT );
+	if( icmp_phone < 0 ){
+		fprintf( stderr, "ICMP connect error %d\n", icmp_phone );
+		return icmp_phone;
+	}
+
+	printf( "PING %d bytes of data\n", size );
+	if( ERROR_OCCURRED( inet_ntop( address->sa_family, address_start, address_string, sizeof( address_string )))){
+		fprintf( stderr, "Address error %d\n", ERROR_CODE );
+	}else{
+		printf( "Address %s:\n", address_string );
+	}
+
+	while( count > 0 ){
+		if( ERROR_OCCURRED( gettimeofday( & time_before, NULL ))){
+			fprintf( stderr, "Get time of day error %d\n", ERROR_CODE );
+			return ERROR_CODE;
+		}
+		result = icmp_echo_msg( icmp_phone, size, timeout, ttl, tos, dont_fragment, address, addrlen );
+		if( ERROR_OCCURRED( gettimeofday( & time_after, NULL ))){
+			fprintf( stderr, "Get time of day error %d\n", ERROR_CODE );
+			return ERROR_CODE;
+		}
+		switch( result ){
+			case ICMP_ECHO:
+				printf( "Ping round trip time %d miliseconds\n", tv_sub( & time_after, & time_before ) / 1000 );
+				break;
+			case ETIMEOUT:
+				printf( "Timed out.\n" );
+				break;
+			default:
+				print_error( stdout, result, NULL, "\n" );
+		}
+		-- count;
+	}
+
+	if( verbose ) printf( "Exiting\n" );
+
+	return EOK;
+}
+
+/** @}
+ */
Index: uspace/srv/net/app/print_error.c
===================================================================
--- uspace/srv/net/app/print_error.c	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/app/print_error.c	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup net_app
+ *  @{
+ */
+
+/** @file
+ *  Generic application error printing functions implementation.
+ */
+
+#include <stdio.h>
+
+#include "../include/icmp_codes.h"
+#include "../include/socket_errno.h"
+
+#include "print_error.h"
+
+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 )){
+		socket_print_error( output, error_code, prefix, suffix );
+	}
+}
+
+void icmp_print_error( FILE * output, int error_code, const char * prefix, const char * suffix ){
+	if( output ){
+		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 );
+		}
+	}
+}
+
+void socket_print_error( FILE * output, int error_code, const char * prefix, const char * suffix ){
+	if( output ){
+		if( prefix ){
+			fprintf( output, "%s", prefix );
+		}
+		switch( error_code ){
+			case ENOTSOCK:
+				fprintf( output, "Not a socket (%d) error", error_code );
+				break;
+			case EPROTONOSUPPORT:
+				fprintf( output, "Protocol not supported (%d) error", error_code );
+				break;
+			case ESOCKTNOSUPPORT:
+				fprintf( output, "Socket type not supported (%d) error", error_code );
+				break;
+			case EPFNOSUPPORT:
+				fprintf( output, "Protocol family not supported (%d) error", error_code );
+				break;
+			case EAFNOSUPPORT:
+				fprintf( output, "Address family not supported (%d) error", error_code );
+				break;
+			case EADDRINUSE:
+				fprintf( output, "Address already in use (%d) error", error_code );
+				break;
+			case ENOTCONN:
+				fprintf( output, "Socket not connected (%d) error", error_code );
+				break;
+			case NO_DATA:
+				fprintf( output, "No data (%d) error", error_code );
+				break;
+			case EINPROGRESS:
+				fprintf( output, "Another operation in progress (%d) error", error_code );
+				break;
+			case EDESTADDRREQ:
+				fprintf( output, "Destination address required (%d) error", error_code );
+			case TRY_AGAIN:
+				fprintf( output, "Try again (%d) error", error_code );
+			default:
+				fprintf( output, "Other (%d) error", error_code );
+		}
+		if( suffix ){
+			fprintf( output, "%s", suffix );
+		}
+	}
+}
+
+/** @}
+ */
Index: uspace/srv/net/app/print_error.h
===================================================================
--- uspace/srv/net/app/print_error.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/app/print_error.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup net_app
+ *  @{
+ */
+
+/** @file
+ *  Generic application error printing functions.
+ */
+
+#ifndef __NET_APP_PRINT__
+#define __NET_APP_PRINT__
+
+/** Returns whether the error code may be an ICMP error code.
+ *  @param[in] error_code The error code.
+ *  @returns A value indicating whether the error code may be an ICMP error code.
+ */
+#define IS_ICMP_ERROR( error_code )		(( error_code ) > 0 )
+
+/** Returns whether the error code may be socket error code.
+ *  @param[in] error_code The error code.
+ *  @returns A value indicating whether the error code may be a socket error code.
+ */
+#define IS_SOCKET_ERROR( error_code )	(( error_code ) < 0 )
+
+/** Prints the error description.
+ *  Supports ICMP and socket error codes.
+ *  @param[in] output The description output stream. May be NULL.
+ *  @param[in] error_code The error code.
+ *  @param[in] prefix The error description prefix. May be NULL.
+ *  @param[in] suffix The error description suffix. May be NULL.
+ */
+void print_error( FILE * output, int error_code, const char * prefix, const char * suffix );
+
+/** 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 );
+
+/** Prints the specific socket error description.
+ *  @param[in] output The description output stream. May be NULL.
+ *  @param[in] error_code The socket error code.
+ *  @param[in] prefix The error description prefix. May be NULL.
+ *  @param[in] suffix The error description suffix. May be NULL.
+ */
+void socket_print_error( FILE * output, int error_code, const char * prefix, const char * suffix );
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/cfg/modular/general
===================================================================
--- uspace/srv/net/cfg/modular/general	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/cfg/modular/general	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,9 @@
+# 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: uspace/srv/net/cfg/modular/lo
===================================================================
--- uspace/srv/net/cfg/modular/lo	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/cfg/modular/lo	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,13 @@
+# loopback configuration
+
+NAME=lo
+
+NETIF=lo
+NIL=nildummy
+IL=ip
+
+IP_CONFIG=static
+IP_ADDR=127.0.0.1
+IP_NETMASK=255.0.0.0
+
+MTU=15535
Index: uspace/srv/net/cfg/modular/ne2k
===================================================================
--- uspace/srv/net/cfg/modular/ne2k	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/cfg/modular/ne2k	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,25 @@
+# DP8390 (NE2k) configuration
+
+NAME=ne2k
+
+NETIF=dp8390
+NIL=ethernet
+IL=ip
+
+# sysinfo_value("netif.dp8390.inr")
+IRQ=9
+IO=300
+
+# 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=1492
Index: uspace/srv/net/cfg/module/general
===================================================================
--- uspace/srv/net/cfg/module/general	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/cfg/module/general	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,9 @@
+# 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: uspace/srv/net/cfg/module/lo
===================================================================
--- uspace/srv/net/cfg/module/lo	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/cfg/module/lo	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,13 @@
+# loopback configuration
+
+NAME=lo
+
+NETIF=lo
+NIL=lo
+IL=ip
+
+IP_CONFIG=static
+IP_ADDR=127.0.0.1
+IP_NETMASK=255.0.0.0
+
+MTU=15535
Index: uspace/srv/net/cfg/module/ne2k
===================================================================
--- uspace/srv/net/cfg/module/ne2k	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/cfg/module/ne2k	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,25 @@
+# DP8390 (NE2k) configuration
+
+NAME=ne2k
+
+NETIF=dp8390
+NIL=dp8390
+IL=ip
+
+# sysinfo_value("netif.dp8390.inr")
+IRQ=9
+IO=300
+
+# 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=1492
Index: uspace/srv/net/checksum.c
===================================================================
--- uspace/srv/net/checksum.c	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/checksum.c	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup net
+ *  @{
+ */
+
+/** @file
+ *  General CRC and checksum computation implementation.
+ */
+
+#include <sys/types.h>
+
+#include "include/checksum.h"
+
+/** Big-endian encoding CRC divider.
+ */
+#define CRC_DIVIDER_BE	0x04C11DB7
+
+/** Little-endian encoding CRC divider.
+ */
+#define CRC_DIVIDER_LE	0xEDB88320
+
+uint32_t compute_crc32_le( uint32_t seed, uint8_t * data, size_t length ){
+	size_t	index;
+
+	while( length >= 8 ){
+		seed ^= ( * data );
+		for( index = 0; index < 8; ++ index ){
+			if( seed & 1 ){
+				seed = ( seed >> 1 ) ^ (( uint32_t ) CRC_DIVIDER_LE );
+			}else{
+				seed >>= 1;
+			}
+		}
+		++ data;
+		length -= 8;
+	}
+	if( length > 0 ){
+		seed ^= ( * data ) >> ( 8 - length );
+		for( index = 0; index < length; ++ index ){
+			if( seed & 1 ){
+				seed = ( seed >> 1 ) ^ (( uint32_t ) CRC_DIVIDER_LE );
+			}else{
+				seed >>= 1;
+			}
+		}
+		length -= 8;
+	}
+	return seed;
+}
+
+uint32_t compute_crc32_be( uint32_t seed, uint8_t * data, size_t length ){
+	size_t	index;
+
+	while( length >= 8 ){
+		seed ^= ( * data ) << 24;
+		for( index = 0; index < 8; ++ index ){
+			if( seed & 0x80000000 ){
+				seed = ( seed << 1 ) ^ (( uint32_t ) CRC_DIVIDER_BE );
+			}else{
+				seed <<= 1;
+			}
+		}
+		++ data;
+		length -= 8;
+	}
+	if( length > 0 ){
+		seed ^= (( * data ) & ( 0xFF << ( 8 - length ))) << 24;
+		for( index = 0; index < length; ++ index ){
+			if( seed & 0x80000000 ){
+				seed = ( seed << 1 ) ^ (( uint32_t ) CRC_DIVIDER_BE );
+			}else{
+				seed <<= 1;
+			}
+		}
+		length -= 8;
+	}
+	return seed;
+}
+
+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;
+}
+
+uint16_t compact_checksum( uint32_t sum ){
+	// shorten to the 16 bits
+	while( sum >> 16 ) sum = ( sum & 0xFFFF ) + ( sum >> 16 );
+
+	return ( uint16_t ) sum;
+}
+
+uint16_t flip_checksum( uint16_t checksum ){
+	// flip, zero is returned as 0xFFFF (not flipped)
+	checksum = ~ checksum;
+	return checksum ? checksum : IP_CHECKSUM_ZERO;
+}
+
+uint16_t ip_checksum( uint8_t * data, size_t length ){
+	return flip_checksum( compact_checksum( compute_checksum( 0, data, length )));
+}
+
+/** @}
+ */
Index: uspace/srv/net/configuration.h
===================================================================
--- uspace/srv/net/configuration.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/configuration.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup net
+ *  @{
+ */
+
+/** @file
+ *  Networking subsystem compilation configuration.
+ */
+
+#ifndef __NET_CONFIGURATION_H__
+#define __NET_CONFIGURATION_H__
+
+/** Activates the self test.
+ */
+#define NET_SELF_TEST					0
+
+/** @name Specific self tests switches
+ */
+/*@{*/
+
+/** Activates the measured strings self test.
+ *  The NET_SELF_TEST has to be activated.
+ *  @see measured_strings.h
+ */
+#define NET_SELF_TEST_MEASURED_STRINGS	1
+
+/** Activates the char map self test.
+ *  The NET_SELF_TEST has to be activated.
+ *  @see char_map.h
+ */
+#define NET_SELF_TEST_CHAR_MAP			1
+
+/** Activates the integral map self test.
+ *  The NET_SELF_TEST has to be activated.
+ *  @see int_map.h
+ */
+#define NET_SELF_TEST_INT_MAP			1
+
+/** Activates the generic field self test.
+ *  The NET_SELF_TEST has to be activated.
+ *  @see generic_field.h
+ */
+#define NET_SELF_TEST_GENERIC_FIELD		1
+
+/** Activates the generic char map self test.
+ *  The NET_SELF_TEST has to be activated.
+ *  @see generic_char_map.h
+ */
+#define NET_SELF_TEST_GENERIC_CHAR_MAP	1
+
+/** Activates the CRC computation self test.
+ *  The NET_SELF_TEST has to be activated.
+ *  @see crc.h
+ */
+#define NET_SELF_TEST_CRC	1
+
+/** Activates the dynamic fifo self test.
+ *  The NET_SELF_TEST has to be activated.
+ *  @see dynamic_fifo.h
+ */
+#define NET_SELF_TEST_DYNAMIC_FIFO	1
+
+/*@}*/
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/documentation.txt
===================================================================
--- uspace/srv/net/documentation.txt	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/documentation.txt	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,201 @@
+/**
+
+\mainpage Networking and TCP/IP Stack for HelenOS system
+
+\section introduction Introduction
+
+<p>
+For the microkernel HelenOS a completely new networking stack was designed.
+The networking stack was intended to implement current basic standards of the TCP/IP Stack.
+Only the minimalistic functionality allowing the stack to function was to be implemented.
+The networking stack is written in C.
+</p>
+<p>
+Please see
+</p>
+<ul>
+	<li>\ref build</li>
+	<li>\ref software</li>
+	<li>\ref running</li>
+	<li>\ref testing</li>
+</ul>
+
+\page build Build from sources
+
+<p>
+To compile the HelenOS from sources (the cross compilers from the <code>build/</code> directory are recommended):
+</p>
+<ol>
+	<li>change the working directory to the HelenOS source directory</li>
+	<li>run <code># make config</code></li>
+	<li>check/change the configuration</li>
+	<li>save and exit the configuration tool</li>
+	<li>run <code># make</code></li>
+</ol>
+<p>
+The <code>image.iso</code> should be created on success.
+</p>
+
+\page running Running the HelenOS with networking
+
+\section netstart Starting the networking
+
+<p>
+After starting the HelenOS boot image in <em>Qemu</em>, the command line appears.
+To run <em>Qemu</em> a script <code>contrib/conf/qemu.sh</code> for Linux or <code>contrib/conf/qemu.bat</code> for Windows in the HelenOS source directory can be used.
+The provided scripts set the needed arguments:
+<br><code>-vga std -M isapc -net nic,model=ne2k_isa -net user -redir udp:8080::8080 -redir udp:8081::8081 -boot d -cdrom image.iso</code><br>
+Additional arguments may be specified on the command line, they override these set.
+</p>
+
+<p>
+The networking stack is started and initialized by running a command
+<br><code># netstart</code><br>
+The networking stack is then started and configured network interfaces are enabled.
+The current configuration is printed out.
+Since that networking applications can be run using the command line as well.
+</p>
+
+\section network Qemu network
+
+<p>
+In the common mode <em>Qemu</em> creates a simple network with a gateway and settles the guest system in.
+The network is 10.0.2.*, the gateway's address 10.0.2.2 and the guest system has 10.0.2.15.
+%Even this simple setting was a bit hard to find in the documentation.
+Therefore a static configuration is possible and no additional DHCP nor BOOTP implementations are necessary.
+On the other hand the guest system is behind a firewall.
+<em>Qemu</em> may be configured to forward some ports to the guest system and allows all outgoing traffic except ICMP and ARP protocols, so you can ping only the gateway.
+</p>
+
+\section applications Applications
+
+<p>
+A few networking applications are located in the app/ directory.
+Common functions for parsing command line arguments and printing textual networking error messages are located in that directory as well.
+The networking applications should be built with the libsocket library located in the socket/libsocket.a file.
+They can use functions and definitions from the include/socket.h header file which contains socket API and further includes:
+</p>
+<ul>
+	<li>include/byteorder.h containing byte order manipulation,</li>
+	<li>include/in.h containing IPv4 socket address structure,</li>
+	<li>include/in6.h containing IPv6 socket address structure,</li>
+	<li>include/inet.h containing socket address structure and parsing functions,</li>
+	<li>include/socket codes.h containing address and protocol families and socket types and option levels, and</li>
+	<li>include/socket errno.h containing socket and general error codes.</li>
+</ul>
+
+\page software Software prerequisites
+
+<p>
+The networking and TCP/IP stack is implemented for the ia32 architecture on top of HelenOS 0.4.1 (Escalopino), the most current stable release of HelenOS.
+So far the only one operational network interface supported is in Qemu 0.10.2 and newer.
+To run <em>Qemu</em> a script contrib/conf/qemu.sh for Linux or contrib/conf/qemu.bat for Windows in the HelenOS source directory can be used.
+The qemu and its libraries have to be installed and in the path.
+These scripts set all the necessary parameters
+with some ports redirected from the local host to the guest system.
+For testing purposes at least a low level communication application is recommended, N.E.T., netcat etc.
+</p>
+<p>
+In order to build HelenOS and the networking stack from sources a few tools are
+required:
+<ul>
+	<li>binutils in version 2.19.1,</li>
+	<li>gcc–core in version 4.3.3 11,</li>
+	<li>gcc–objc in version 4.3.3, and</li>
+	<li>gcc–g++ in version 4.3.3.</li>
+</ul>
+<p>
+All these can be downloaded and installed as cross–compilers on Linux using a script contrib/toolchain.sh in the HelenOS source directory.
+In addition rats, a static source code analyzer, and Doxygen, a documentation generator, were used.
+All development was tracked in the HelenOS subversion repository.
+</p>
+<ul>
+	<li>HelenOS website: <a href="http://www.helenos.org/" title="HelenOS website">http://www.helenos.org/</a></li>
+	<li><em>Qemu</em> website: <a href="http://www.qemu.org/" title="Qemu website">http://www.qemu.org/</a></li>
+	<li><em>binutils</em> website: <a href="http://www.gnu.org/software/binutils/" title="binutils website">http://www.gnu.org/software/binutils/</a></li>
+	<li><em>GCC</em> website: <a href="http://gcc.gnu.org/" title="GCC website">http://gcc.gnu.org/</a></li>
+	<li><em>RATS</em> website: <a href="http://www.fortify.com/security-resources/rats.jsp" title="RATS website">http://www.fortify.com/security-resources/rats.jsp</a></li>
+	<li><em>Doxygen</em> website: <a href="http://www.stack.nl/ dimitri/doxygen/index.html" title="Doxygen website">http://www.stack.nl/ dimitri/doxygen/index.html</a></li>
+	<li><em>Subversion</em> website: <a href="http://subversion.tigris.org/" title="Subversion website">http://subversion.tigris.org/</a></li>
+</ul>
+
+\page testing Testing scenarios
+
+<p>
+The scenarios contain the following shortcuts:
+</p>
+<ul>
+	<li>g for the quest system, HelenOS in <em>Qemu</em></li>
+	<li>h for the host system</li>
+	<li>n for the <em>NET</em> application</li>
+	<li>e for echo echo application run in HelenOS</li>
+</ul>
+
+\section scenarios Testing scenarios
+<ul>
+	<li>UDP
+		<ol>
+			<li>g #netstart</li>
+			<li>h wine net.exe (->n) (or net.exe)</li>
+			<li>n set 127.0.0.1:8080 address and port, BuiltinUDP protocol</li>
+			<li>n send some data (an ARP will be generated and the original packet gets lost)</li>
+			<li>n send some data (the port is unreachable and the packet is discarded)</li>
+			<li>g #echo -p 8080 -c 3 -v (->e)</li>
+			<li>g prints Listening</li>
+			<li>n send some data</li>
+			<li>e prints received data</li>
+			<li>h prints reply</li>
+			<li>n click disconnect</li>
+			<li>n set :8081 port</li>
+			<li>n send some data</li>
+			<li>n click disconnect</li>
+			<li>n set :8080 port</li>
+			<li>count-1 times:
+				<ol>
+					<li>n send some data</li>
+					<li>e prints received data</li>
+					<li>h prints reply</li>
+				</ol>
+			</li>
+			<li>e prints Exiting</li>
+			<li>e quits</li>
+			<li>n send some data (the port is unreachable and the packet is discarded)</li>
+		</ol>
+	</li>
+	<li>ICMP echo to 10.0.2.2
+		<ol>
+			<li>g #netstart</li>
+			<li>g #ping 10.0.2.2 (->p)</li>
+			<li>g prints ARP request for 10.0.2.2</li>
+			<li>g prints ARP reply from 10.0.2.2</li>
+			<li>p prints timeouted</li>
+			<li>p prints round trip time</li>
+			<li>p prints round trip time</li>
+			<li>p quits</li>
+		</ol>
+	</li>
+	<li>ICMP echo to 127.0.0.1
+		<ol>
+			<li>g #netstart</li>
+			<li>g #ping 127.0.0.1 (->p)</li>
+			<li>p prints round trip time</li>
+			<li>p prints round trip time</li>
+			<li>p prints round trip time</li>
+			<li>p quits</li>
+		</ol>
+	</li>
+	<li>ICMP with no internet on the host system (!)
+		<ol>
+			<li>g #netstart</li>
+			<li>g #ping 123.123.123.3 (->p)</li>
+			<li>g prints ARP request for 10.0.2.2</li>
+			<li>g prints ARP reply from 10.0.2.2</li>
+			<li>p prints timeouted</li>
+			<li>p prints destination unreachable</li>
+			<li>p prints destination unreachable</li>
+			<li>p quits</li>
+		</ol>
+	</li>
+</ul>
+
+*/
Index: uspace/srv/net/err.h
===================================================================
--- uspace/srv/net/err.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/err.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup net
+ *  @{
+ */
+
+/** @file
+ *  Common error processing codes and routines.
+ */
+
+#ifndef __NET_ERR_H__
+#define __NET_ERR_H__
+
+#include <errno.h>
+
+#ifdef CONFIG_DEBUG
+
+#include <stdio.h>
+
+#endif
+
+/** An actual stored error code.
+ */
+#define ERROR_CODE					error_check_return_value
+
+/** An error processing routines declaration.
+ *  This has to be declared in the block where the error processing is desired.
+ */
+#define ERROR_DECLARE				int ERROR_CODE
+
+/** Stores the value as an error code and checks if an error occurred.
+ *  @param[in] value The value to be checked. May be a function call.
+ *  @returns FALSE if the value indicates success (EOK).
+ *  @returns TRUE otherwise.
+ */
+#ifdef CONFIG_DEBUG
+
+#define ERROR_OCCURRED( value )		((( ERROR_CODE = ( value )) != EOK ) && ({ printf( "error at %s:%d %d\n", __FILE__, __LINE__, ERROR_CODE ); 1; }))
+
+#else
+
+#define ERROR_OCCURRED( value )		(( ERROR_CODE = ( value )) != EOK )
+
+#endif
+
+/** Checks if an error occurred and immediately exits the actual function returning the error code.
+ *  @param[in] value The value to be checked. May be a function call.
+ */
+
+#define ERROR_PROPAGATE( value )	if( ERROR_OCCURRED( value )) return ERROR_CODE
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/il/arp/Makefile
===================================================================
--- uspace/srv/net/il/arp/Makefile	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/il/arp/Makefile	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,51 @@
+#
+# 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.
+#
+
+NAME = arp
+
+NET_BASE = ../../
+STRUCTURES = $(NET_BASE)structures/
+
+## Sources
+#
+
+OUTPUT = $(NAME)
+SOURCES = \
+	$(NAME).c \
+	$(NAME)_module.c \
+	$(NET_BASE)module.c \
+	$(NET_BASE)modules.c \
+	$(NET_BASE)net/net_remote.c \
+	$(NET_BASE)nil/nil_remote.c \
+	$(STRUCTURES)char_map.c \
+	$(STRUCTURES)measured_strings.c \
+	$(STRUCTURES)packet/packet.c \
+	$(STRUCTURES)packet/packet_client.c \
+	$(STRUCTURES)packet/packet_remote.c
+
+include $(NET_BASE)Makefile.module
Index: uspace/srv/net/il/arp/arp.c
===================================================================
--- uspace/srv/net/il/arp/arp.c	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/il/arp/arp.c	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,585 @@
+/*
+ * 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 <stdio.h>
+#include <string.h>
+#include <task.h>
+
+#include <ipc/ipc.h>
+#include <ipc/services.h>
+
+#include "../../err.h"
+#include "../../messages.h"
+#include "../../modules.h"
+
+#include "../../include/byteorder.h"
+#include "../../include/device.h"
+#include "../../include/arp_interface.h"
+#include "../../include/nil_interface.h"
+#include "../../include/protocol_map.h"
+
+#include "../../structures/measured_strings.h"
+#include "../../structures/packet/packet.h"
+#include "../../structures/packet/packet_client.h"
+
+#include "../il_messages.h"
+
+#include "arp.h"
+#include "arp_header.h"
+#include "arp_oc.h"
+#include "arp_module.h"
+#include "arp_messages.h"
+
+/** ARP global data.
+ */
+arp_globals_t	arp_globals;
+
+/** Creates new protocol specific data.
+ *  Allocates and returns the needed memory block as the proto parameter.
+ *  @param[out] proto The allocated protocol specific data.
+ *  @param[in] service The protocol module service.
+ *  @param[in] address The actual protocol device address.
+ *  @returns EOK on success.
+ *  @returns ENOMEM if there is not enough memory left.
+ */
+int	arp_proto_create( arp_proto_ref * proto, services_t service, measured_string_ref address );
+
+/** Clears the device specific data.
+ *  @param[in] device The device specific data.
+ */
+void	arp_clear_device( arp_device_ref device );
+
+/** @name Message processing functions
+ */
+/*@{*/
+
+/** Registers the device.
+ *  Creates new device entry in the cache or updates the protocol address if the device with the device identifier and the driver service exists.
+ *  @param[in] device_id The device identifier.
+ *  @param[in] service The device driver service.
+ *  @param[in] protocol The protocol service.
+ *  @param[in] address The actual device protocol address.
+ *  @returns EOK on success.
+ *  @returns EEXIST if another device with the same device identifier and different driver service exists.
+ *  @returns ENOMEM if there is not enough memory left.
+ *  @returns Other error codes as defined for the measured_strings_return() function.
+ */
+int	arp_device_message( device_id_t device_id, services_t service, services_t protocol, measured_string_ref address );
+
+/** Returns the hardware address for the given protocol address.
+ *  Sends the ARP request packet if the hardware address is not found in the cache.
+ *  @param[in] device_id The device identifier.
+ *  @param[in] protocol The protocol service.
+ *  @param[in] target The target protocol address.
+ *  @returns The hardware address of the target.
+ *  @returns NULL if the target parameter is NULL.
+ *  @returns NULL if the device is not found.
+ *  @returns NULL if the device packet is too small to send a&nbsp;request.
+ *  @returns NULL if the hardware address is not found in the cache.
+ */
+measured_string_ref	arp_translate_message( device_id_t device_id, services_t protocol, measured_string_ref target );
+
+/** Processes the received ARP packet.
+ *  Updates the source hardware address if the source entry exists or the packet is targeted to my protocol address.
+ *  Responses to the ARP request if the packet is the ARP request and is targeted to my address.
+ *  @param[in] device_id The source device identifier.
+ *  @param[in,out] packet The received packet.
+ *  @returns EOK on success and the packet is no longer needed.
+ *  @returns 1 on success and the packet has been reused.
+ *  @returns EINVAL if the packet is too small to carry an ARP packet.
+ *  @returns EINVAL if the received address lengths differs from the registered values.
+ *  @returns ENOENT if the device is not found in the cache.
+ *  @returns ENOENT if the protocol for the device is not found in the cache.
+ *  @returns ENOMEM if there is not enough memory left.
+ */
+int	arp_receive_message( device_id_t device_id, packet_t packet );
+
+/** 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.
+ *  @returns ENOENT if device is not found.
+ *  @returns EOK on success.
+ */
+int	arp_mtu_changed_message( device_id_t device_id, size_t mtu );
+
+/*@}*/
+
+DEVICE_MAP_IMPLEMENT( arp_cache, arp_device_t )
+
+INT_MAP_IMPLEMENT( arp_protos, arp_proto_t )
+
+GENERIC_CHAR_MAP_IMPLEMENT( arp_addr, measured_string_t )
+
+task_id_t arp_task_get_id( void ){
+	return task_get_id();
+}
+
+int arp_clear_device_req( int arp_phone, device_id_t device_id ){
+	arp_device_ref	device;
+
+	fibril_rwlock_write_lock( & arp_globals.lock );
+	device = arp_cache_find( & arp_globals.cache, device_id );
+	if( ! device ){
+		fibril_rwlock_write_unlock( & arp_globals.lock );
+		return ENOENT;
+	}
+	arp_clear_device( device );
+	printf( "Device %d cleared\n", device_id );
+	fibril_rwlock_write_unlock( & arp_globals.lock );
+	return EOK;
+}
+
+int arp_clear_address_req( int arp_phone, device_id_t device_id, services_t protocol, measured_string_ref address ){
+	arp_device_ref	device;
+	arp_proto_ref	proto;
+
+	fibril_rwlock_write_lock( & arp_globals.lock );
+	device = arp_cache_find( & arp_globals.cache, device_id );
+	if( ! device ){
+		fibril_rwlock_write_unlock( & arp_globals.lock );
+		return ENOENT;
+	}
+	proto = arp_protos_find( & device->protos, protocol );
+	if( ! proto ){
+		fibril_rwlock_write_unlock( & arp_globals.lock );
+		return ENOENT;
+	}
+	arp_addr_exclude( & proto->addresses, address->value, address->length );
+	fibril_rwlock_write_unlock( & arp_globals.lock );
+	return EOK;
+}
+
+int arp_clean_cache_req( int arp_phone ){
+	int				count;
+	arp_device_ref	device;
+
+	fibril_rwlock_write_lock( & arp_globals.lock );
+	for( count = arp_cache_count( & arp_globals.cache ) - 1; count >= 0; -- count ){
+		device = arp_cache_get_index( & arp_globals.cache, count );
+		if( device ){
+			arp_clear_device( device );
+			if( device->addr_data ) free( device->addr_data );
+			if( device->broadcast_data ) free( device->broadcast_data );
+		}
+	}
+	arp_cache_clear( & arp_globals.cache );
+	fibril_rwlock_write_unlock( & arp_globals.lock );
+	printf( "Cache cleaned\n" );
+	return EOK;
+}
+
+int arp_device_req( int arp_phone, device_id_t device_id, services_t protocol, services_t netif, measured_string_ref address ){
+	ERROR_DECLARE;
+
+	measured_string_ref tmp;
+
+	// copy the given address for exclusive use
+	tmp = measured_string_copy( address );
+	if( ERROR_OCCURRED( arp_device_message( device_id, netif, protocol, tmp ))){
+		free( tmp->value );
+		free( tmp );
+	}
+	return ERROR_CODE;
+}
+
+int arp_translate_req( int arp_phone, device_id_t device_id, services_t protocol, measured_string_ref address, measured_string_ref * translation, char ** data ){
+	measured_string_ref	tmp;
+
+	fibril_rwlock_read_lock( & arp_globals.lock );
+	tmp = arp_translate_message( device_id, protocol, address );
+	if( tmp ){
+		* translation = measured_string_copy( tmp );
+		fibril_rwlock_read_unlock( & arp_globals.lock );
+		if( * translation ){
+			* data = ( ** translation ).value;
+			return EOK;
+		}else{
+			return ENOMEM;
+		}
+	}else{
+		fibril_rwlock_read_unlock( & arp_globals.lock );
+		return ENOENT;
+	}
+}
+
+int arp_initialize( async_client_conn_t client_connection ){
+	ERROR_DECLARE;
+
+	fibril_rwlock_initialize( & arp_globals.lock );
+	fibril_rwlock_write_lock( & arp_globals.lock );
+	arp_globals.client_connection = client_connection;
+	ERROR_PROPAGATE( arp_cache_initialize( & arp_globals.cache ));
+	fibril_rwlock_write_unlock( & arp_globals.lock );
+	return EOK;
+}
+
+int arp_proto_create( arp_proto_ref * proto, services_t service, measured_string_ref address ){
+	ERROR_DECLARE;
+
+	* proto = ( arp_proto_ref ) malloc( sizeof( arp_proto_t ));
+	if( !( * proto )) return ENOMEM;
+	( ** proto ).service = service;
+	( ** proto ).addr = address;
+	( ** proto ).addr_data = address->value;
+	if( ERROR_OCCURRED( arp_addr_initialize( &( ** proto).addresses ))){
+		free( * proto );
+		return ERROR_CODE;
+	}
+	return EOK;
+}
+
+int arp_device_message( device_id_t device_id, services_t service, services_t protocol, measured_string_ref address ){
+	ERROR_DECLARE;
+
+	arp_device_ref	device;
+	arp_proto_ref	proto;
+	int				index;
+	hw_type_t		hardware;
+
+	fibril_rwlock_write_lock( & arp_globals.lock );
+	// an existing device?
+	device = arp_cache_find( & arp_globals.cache, device_id );
+	if( device ){
+		if( device->service != service ){
+			printf( "Device %d already exists\n", device->device_id );
+			fibril_rwlock_write_unlock( & arp_globals.lock );
+			return EEXIST;
+		}
+		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{
+			if( ERROR_OCCURRED( arp_proto_create( & proto, protocol, address ))){
+				fibril_rwlock_write_unlock( & arp_globals.lock );
+				return ERROR_CODE;
+			}
+			index = arp_protos_add( & device->protos, proto->service, proto );
+			if( index < 0 ){
+				fibril_rwlock_write_unlock( & arp_globals.lock );
+				free( proto );
+				return index;
+			}
+			printf( "New protocol added:\n\tdevice id\t= %d\n\tproto\t= %d", device_id, protocol );
+		}
+	}else{
+		hardware = hardware_map( service );
+		if( ! hardware ) return ENOENT;
+		// create a new device
+		device = ( arp_device_ref ) malloc( sizeof( arp_device_t ));
+		if( ! device ){
+			fibril_rwlock_write_unlock( & arp_globals.lock );
+			return ENOMEM;
+		}
+		device->hardware = hardware;
+		device->device_id = device_id;
+		if( ERROR_OCCURRED( arp_protos_initialize( & device->protos ))
+		|| ERROR_OCCURRED( arp_proto_create( & proto, protocol, address ))){
+			fibril_rwlock_write_unlock( & arp_globals.lock );
+			free( device );
+			return ERROR_CODE;
+		}
+		index = arp_protos_add( & device->protos, proto->service, proto );
+		if( index < 0 ){
+			fibril_rwlock_write_unlock( & arp_globals.lock );
+			arp_protos_destroy( & device->protos );
+			free( device );
+			return index;
+		}
+		device->service = service;
+		// bind the new one
+		device->phone = nil_bind_service( device->service, ( ipcarg_t ) device->device_id, SERVICE_ARP, arp_globals.client_connection );
+		if( device->phone < 0 ){
+			fibril_rwlock_write_unlock( & arp_globals.lock );
+			arp_protos_destroy( & device->protos );
+			free( device );
+			return EREFUSED;
+		}
+		// get packet dimensions
+		if( ERROR_OCCURRED( nil_packet_size_req( device->phone, device_id, & device->addr_len, & device->prefix, & device->content, & device->suffix ))){
+			fibril_rwlock_write_unlock( & arp_globals.lock );
+			arp_protos_destroy( & device->protos );
+			free( device );
+			return ERROR_CODE;
+		}
+		// get hardware address
+		if( ERROR_OCCURRED( nil_get_addr_req( device->phone, device_id, & device->addr, & device->addr_data ))){
+			fibril_rwlock_write_unlock( & arp_globals.lock );
+			arp_protos_destroy( & device->protos );
+			free( device );
+			return ERROR_CODE;
+		}
+		// get broadcast address
+		if( ERROR_OCCURRED( nil_get_broadcast_addr_req( device->phone, device_id, & device->broadcast_addr, & device->broadcast_data ))){
+			fibril_rwlock_write_unlock( & arp_globals.lock );
+			free( device->addr );
+			free( device->addr_data );
+			arp_protos_destroy( & device->protos );
+			free( device );
+			return ERROR_CODE;
+		}
+		if( ERROR_OCCURRED( arp_cache_add( & arp_globals.cache, device->device_id, device ))){
+			fibril_rwlock_write_unlock( & arp_globals.lock );
+			free( device->addr );
+			free( device->addr_data );
+			free( device->broadcast_addr );
+			free( device->broadcast_data );
+			arp_protos_destroy( & device->protos );
+			free( device );
+			return ERROR_CODE;
+		}
+		printf( "New device registered:\n\tid\t= %d\n\ttype\t= 0x%x\n\tservice\t= %d\n\tproto\t= %d\n", device->device_id, device->hardware, device->service, protocol );
+	}
+	fibril_rwlock_write_unlock( & arp_globals.lock );
+	return EOK;
+}
+
+measured_string_ref arp_translate_message( device_id_t device_id, services_t protocol, measured_string_ref target ){
+	arp_device_ref		device;
+	arp_proto_ref		proto;
+	measured_string_ref	addr;
+	size_t				length;
+	packet_t			packet;
+	arp_header_ref		header;
+
+	if( ! target ) return NULL;
+	device = arp_cache_find( & arp_globals.cache, device_id );
+	if( ! device ) return NULL;
+	proto = arp_protos_find( & device->protos, protocol );
+	if(( ! proto ) || ( proto->addr->length != target->length )) return NULL;
+	addr = arp_addr_find( & proto->addresses, target->value, target->length );
+	if( addr ) return addr;
+	// ARP packet content size = header + ( address + translation ) * 2
+	length = 8 + ( CONVERT_SIZE( char, uint8_t, proto->addr->length ) + CONVERT_SIZE( char, uint8_t, device->addr->length )) * 2;
+	if( length > device->content ) return NULL;
+	packet = packet_get_4( arp_globals.net_phone, device->addr_len, device->prefix, length, device->suffix );
+	if( ! packet ) return NULL;
+	header = ( arp_header_ref ) packet_suffix( packet, length );
+	if( ! header ){
+		pq_release( arp_globals.net_phone, packet_get_id( packet ));
+		return NULL;
+	}
+	header->hardware = htons( device->hardware );
+	header->hardware_length = ( uint8_t ) device->addr->length;
+	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->value, device->addr->length );
+	length += device->addr->length;
+	memcpy((( uint8_t * ) header ) + length, proto->addr->value, proto->addr->length );
+	length += proto->addr->length;
+	bzero((( uint8_t * ) header ) + length, device->addr->length );
+	length += device->addr->length;
+	memcpy((( uint8_t * ) header ) + length, target->value, target->length );
+	if( packet_set_addr( packet, ( uint8_t * ) device->addr->value, ( uint8_t * ) device->broadcast_addr->value, CONVERT_SIZE( char, uint8_t, device->addr->length )) != EOK ){
+		pq_release( arp_globals.net_phone, packet_get_id( packet ));
+		return NULL;
+	}
+	nil_send_msg( device->phone, device_id, packet, SERVICE_ARP );
+	return NULL;
+}
+
+int arp_receive_message( device_id_t device_id, packet_t packet ){
+	ERROR_DECLARE;
+
+	size_t				length;
+	arp_header_ref		header;
+	arp_device_ref		device;
+	arp_proto_ref		proto;
+	measured_string_ref	hw_source;
+	uint8_t *			src_hw;
+	uint8_t *			src_proto;
+	uint8_t *			des_hw;
+	uint8_t *			des_proto;
+
+	length = packet_get_data_length( packet );
+	if( length <= sizeof( arp_header_t )) return EINVAL;
+	device = arp_cache_find( & arp_globals.cache, device_id );
+	if( ! device ) return ENOENT;
+	header = ( arp_header_ref ) 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;
+	}
+	proto = arp_protos_find( & device->protos, protocol_unmap( device->service, ntohs( header->protocol )));
+	if( ! proto ) return ENOENT;
+	src_hw = (( uint8_t * ) header ) + sizeof( arp_header_t );
+	src_proto = src_hw + header->hardware_length;
+	des_hw = src_proto + header->protocol_length;
+	des_proto = des_hw + header->hardware_length;
+	hw_source = arp_addr_find( & proto->addresses, ( char * ) src_proto, CONVERT_SIZE( uint8_t, char, header->protocol_length ));
+	// exists?
+	if( hw_source ){
+		if( hw_source->length != CONVERT_SIZE( uint8_t, char, header->hardware_length )){
+			return EINVAL;
+		}
+		memcpy( hw_source->value, src_hw, hw_source->length );
+	}
+	// is my protocol address?
+	if( proto->addr->length != CONVERT_SIZE( uint8_t, char, header->protocol_length )){
+		return EINVAL;
+	}
+	if( ! str_lcmp( proto->addr->value, ( char * ) des_proto, proto->addr->length )){
+		// not already upadted?
+		if( ! hw_source ){
+			hw_source = measured_string_create_bulk(( char * ) src_hw, CONVERT_SIZE( uint8_t, char, header->hardware_length ));
+			if( ! hw_source ) return ENOMEM;
+			ERROR_PROPAGATE( arp_addr_add( & proto->addresses, ( char * ) src_proto, CONVERT_SIZE( uint8_t, char, header->protocol_length ), hw_source ));
+		}
+		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->value, device->addr_len );
+			memcpy( des_hw, hw_source->value, header->hardware_length );
+			ERROR_PROPAGATE( packet_set_addr( packet, src_hw, des_hw, header->hardware_length ));
+			nil_send_msg( device->phone, device_id, packet, SERVICE_ARP );
+			return 1;
+		}
+	}
+	return EOK;
+}
+
+void arp_clear_device( arp_device_ref device ){
+	int				count;
+	arp_proto_ref	proto;
+
+	for( count = arp_protos_count( & device->protos ) - 1; count >= 0; -- count ){
+		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_addr_destroy( & proto->addresses );
+		}
+	}
+	arp_protos_clear( & device->protos );
+}
+
+int arp_connect_module( services_t service ){
+	if( service != SERVICE_ARP ) return EINVAL;
+	return EOK;
+}
+
+int arp_mtu_changed_message( device_id_t device_id, size_t mtu ){
+	arp_device_ref	device;
+
+	fibril_rwlock_write_lock( & arp_globals.lock );
+	device = arp_cache_find( & arp_globals.cache, device_id );
+	if( ! device ){
+		fibril_rwlock_write_unlock( & arp_globals.lock );
+		return ENOENT;
+	}
+	device->content = mtu;
+	printf( "arp - device %d changed mtu to %d\n\n", device_id, mtu );
+	fibril_rwlock_write_unlock( & arp_globals.lock );
+	return EOK;
+}
+
+int arp_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){
+	ERROR_DECLARE;
+
+	measured_string_ref	address;
+	measured_string_ref	translation;
+	char *				data;
+	packet_t			packet;
+	packet_t			next;
+
+//	printf( "message %d - %d\n", IPC_GET_METHOD( * call ), NET_ARP_FIRST );
+	* answer_count = 0;
+	switch( IPC_GET_METHOD( * call )){
+		case IPC_M_PHONE_HUNGUP:
+			return EOK;
+		case NET_ARP_DEVICE:
+			ERROR_PROPAGATE( measured_strings_receive( & address, & data, 1 ));
+			if( ERROR_OCCURRED( arp_device_message( IPC_GET_DEVICE( call ), IPC_GET_SERVICE( call ), ARP_GET_NETIF( call ), address ))){
+				free( address );
+				free( data );
+			}
+			return ERROR_CODE;
+		case NET_ARP_TRANSLATE:
+			ERROR_PROPAGATE( measured_strings_receive( & address, & data, 1 ));
+			fibril_rwlock_read_lock( & arp_globals.lock );
+			translation = arp_translate_message( IPC_GET_DEVICE( call ), IPC_GET_SERVICE( call ), address );
+			free( address );
+			free( data );
+			if( ! translation ){
+				fibril_rwlock_read_unlock( & arp_globals.lock );
+				return ENOENT;
+			}
+			ERROR_CODE = measured_strings_reply( translation, 1 );
+			fibril_rwlock_read_unlock( & arp_globals.lock );
+			return ERROR_CODE;
+		case NET_ARP_CLEAR_DEVICE:
+			return arp_clear_device_req( 0, IPC_GET_DEVICE( call ));
+		case NET_ARP_CLEAR_ADDRESS:
+			ERROR_PROPAGATE( measured_strings_receive( & address, & data, 1 ));
+			arp_clear_address_req( 0, 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( 0 );
+		case NET_IL_DEVICE_STATE:
+			// do nothing - keep the cache
+			return EOK;
+		case NET_IL_RECEIVED:
+			if( ! ERROR_OCCURRED( packet_translate( arp_globals.net_phone, & packet, IPC_GET_PACKET( call )))){
+				fibril_rwlock_read_lock( & arp_globals.lock );
+				do{
+					next = pq_detach( packet );
+					ERROR_CODE = arp_receive_message( IPC_GET_DEVICE( call ), packet );
+					if( ERROR_CODE != 1 ) pq_release( arp_globals.net_phone, packet_get_id( packet ));
+					packet = next;
+				}while( packet );
+				fibril_rwlock_read_unlock( & arp_globals.lock );
+			}
+			return ERROR_CODE;
+		case NET_IL_MTU_CHANGED:
+			return arp_mtu_changed_message( IPC_GET_DEVICE( call ), IPC_GET_MTU( call ));
+	}
+	return ENOTSUP;
+}
+
+/** @}
+ */
Index: uspace/srv/net/il/arp/arp.h
===================================================================
--- uspace/srv/net/il/arp/arp.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/il/arp/arp.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,180 @@
+/*
+ * 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 <fibril_synch.h>
+
+#include <ipc/ipc.h>
+#include <ipc/services.h>
+
+#include "../../include/device.h"
+#include "../../include/hardware.h"
+
+#include "../../structures/generic_char_map.h"
+#include "../../structures/int_map.h"
+#include "../../structures/measured_strings.h"
+
+
+/** Type definition of the ARP global data.
+ *  @see arp_globals
+ */
+typedef struct arp_globals	arp_globals_t;
+
+/** Type definition of the ARP device specific data.
+ *  @see arp_device
+ */
+typedef struct arp_device	arp_device_t;
+
+/** Type definition of the ARP device specific data pointer.
+ *  @see arp_device
+ */
+typedef arp_device_t *		arp_device_ref;
+
+/** Type definition of the ARP protocol specific data.
+ *  @see arp_proto
+ */
+typedef struct arp_proto	arp_proto_t;
+
+/** Type definition of the ARP protocol specific data pointer.
+ *  @see arp_proto
+ */
+typedef arp_proto_t *		arp_proto_ref;
+
+/** 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 address map.
+ *  Translates addresses.
+ *  @see generic_char_map.h
+ */
+GENERIC_CHAR_MAP_DECLARE( arp_addr, measured_string_t )
+
+/** ARP device specific data.
+ */
+struct arp_device{
+	/** Device identifier.
+	 */
+	device_id_t			device_id;
+	/** Hardware type.
+	 */
+	hw_type_t			hardware;
+	/** Reserved packet prefix length.
+	 */
+	size_t				prefix;
+	/** Maximal packet content length.
+	 */
+	size_t				content;
+	/** Reserved packet suffix length.
+	 */
+	size_t				suffix;
+	/** Packet address length.
+	 *  The hardware address length is used.
+	 */
+	size_t				addr_len;
+	/** Actual device hardware address.
+	 */
+	measured_string_ref	addr;
+	/** Actual device hardware address data.
+	 */
+	char *				addr_data;
+	/** Broadcast device hardware address.
+	 */
+	measured_string_ref	broadcast_addr;
+	/** Broadcast device hardware address data.
+	 */
+	char *				broadcast_data;
+	/** Device module service.
+	 */
+	services_t			service;
+	/** Device module phone.
+	 */
+	int					phone;
+	/** Protocol map.
+	 *  Address map for each protocol.
+	 */
+	arp_protos_t		protos;
+};
+
+/** ARP protocol specific data.
+ */
+struct arp_proto{
+	/** Protocol service.
+	 */
+	services_t			service;
+	/** Actual device protocol address.
+	 */
+	measured_string_ref	addr;
+	/** Actual device protocol address data.
+	 */
+	char *				addr_data;
+	/** Address map.
+	 */
+	arp_addr_t			addresses;
+};
+
+/** ARP global data.
+ */
+struct	arp_globals{
+	/** Networking module phone.
+	 */
+	int			net_phone;
+	/** Safety lock.
+	 */
+	fibril_rwlock_t		lock;
+	/** ARP address cache.
+	 */
+	arp_cache_t	cache;
+	/** The client connection processing function.
+	 *  The module skeleton propagates its own one.
+	 */
+	async_client_conn_t client_connection;
+};
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/il/arp/arp_header.h
===================================================================
--- uspace/srv/net/il/arp/arp_header.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/il/arp/arp_header.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,78 @@
+/*
+ * 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 protocol header.
+ *  Based on the RFC~826.
+ */
+
+#ifndef __NET_ARP_HEADER_H__
+#define __NET_ARP_HEADER_H__
+
+#include <sys/types.h>
+
+/** Type definition of an ARP protocol header.
+ *  @see arp_header
+ */
+typedef struct arp_header	arp_header_t;
+
+/** Type definition of an ARP protocol header pointer.
+ *  @see arp_header
+ */
+typedef arp_header_t *		arp_header_ref;
+
+/** 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));
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/il/arp/arp_messages.h
===================================================================
--- uspace/srv/net/il/arp/arp_messages.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/il/arp/arp_messages.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,84 @@
+/*
+ * 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 messages.
+ *  @see arp_interface.h
+ */
+
+#ifndef __NET_ARP_MESSAGES__
+#define __NET_ARP_MESSAGES__
+
+#include <ipc/ipc.h>
+
+#include "../../messages.h"
+
+/** ARP module messages.
+ */
+typedef enum{
+	/** New device message.
+	 *  @see arp_device_req()
+	 */
+	NET_ARP_DEVICE = NET_ARP_FIRST,
+	/** Address translation message.
+	 *  @see arp_translate_req()
+	 */
+	NET_ARP_TRANSLATE,
+	/** Clear device cache message.
+	 *  @see arp_clear_device_req()
+	 */
+	NET_ARP_CLEAR_DEVICE,
+	/** Clear address cache message.
+	 *  @see arp_clear_address_msg()
+	 */
+	NET_ARP_CLEAR_ADDRESS,
+	/** Clean cache message.
+	 *  @see arp_clean_cache()
+	 */
+	NET_ARP_CLEAN_CACHE,
+} arp_messages;
+
+/** @name ARP specific message parameters definitions
+ */
+/*@{*/
+
+/** Returns the protocol service message parameter.
+ *  @param[in] call The message call structure.
+ */
+#define ARP_GET_NETIF( call )		( services_t ) IPC_GET_ARG2( * call )
+
+/*@}*/
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/il/arp/arp_module.c
===================================================================
--- uspace/srv/net/il/arp/arp_module.c	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/il/arp/arp_module.c	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,117 @@
+/*
+ * 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 standalone module implementation.
+ *  Contains skeleton module functions mapping.
+ *  The functions are used by the module skeleton as module specific entry points.
+ *  @see module.c
+ */
+
+#include <async.h>
+#include <stdio.h>
+
+#include <ipc/ipc.h>
+#include <ipc/services.h>
+
+#include "../../err.h"
+#include "../../modules.h"
+
+#include "../../include/net_interface.h"
+
+#include "../../structures/packet/packet.h"
+
+#include "arp.h"
+#include "arp_module.h"
+
+/** ARP module name.
+ */
+#define NAME	"ARP protocol"
+
+/** Prints the module name.
+ *  @see NAME
+ */
+void	module_print_name( void );
+
+/** Starts the ARP module.
+ *  Initializes the client connection serving function, initializes the module, registers the module service and starts the async manager, processing IPC messages in an infinite loop.
+ *  @param[in] client_connection The client connection processing function. The module skeleton propagates its own one.
+ *  @returns EOK on successful module termination.
+ *  @returns Other error codes as defined for the arp_initialize() function.
+ *  @returns Other error codes as defined for the REGISTER_ME() macro function.
+ */
+int	module_start( async_client_conn_t client_connection );
+
+/** Processes the ARP 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.
+ *  @returns EOK on success.
+ *  @returns Other error codes as defined for the arp_message() function.
+ */
+int	module_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count );
+
+/** ARP module global data.
+ */
+extern arp_globals_t	arp_globals;
+
+void module_print_name( void ){
+	printf( "%s", NAME );
+}
+
+int module_start( async_client_conn_t client_connection ){
+	ERROR_DECLARE;
+
+	ipcarg_t	phonehash;
+
+	async_set_client_connection( client_connection );
+	arp_globals.net_phone = net_connect_module( SERVICE_NETWORKING );
+	ERROR_PROPAGATE( pm_init());
+	if( ERROR_OCCURRED( arp_initialize( client_connection ))
+	|| ERROR_OCCURRED( REGISTER_ME( SERVICE_ARP, & phonehash ))){
+		pm_destroy();
+		return ERROR_CODE;
+	}
+
+	async_manager();
+
+	pm_destroy();
+	return EOK;
+}
+
+int	module_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){
+	return arp_message( callid, call, answer, answer_count );
+}
+
+/** @}
+ */
Index: uspace/srv/net/il/arp/arp_module.h
===================================================================
--- uspace/srv/net/il/arp/arp_module.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/il/arp/arp_module.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,65 @@
+/*
+ * 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 functions.
+ *  The functions are used as ARP module entry points.
+ */
+
+#ifndef __NET_ARP_MODULE_H__
+#define __NET_ARP_MODULE_H__
+
+#include <ipc/ipc.h>
+
+/** Initializes the ARP module.
+ *  @param[in] client_connection The client connection processing function. The module skeleton propagates its own one.
+ *  @returns EOK on success.
+ *  @returns ENOMEM if there is not enough memory left.
+ */
+int	arp_initialize( async_client_conn_t client_connection );
+
+/** Processes the ARP 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.
+ *  @returns EOK on success.
+ *  @returns ENOTSUP if the message is not known.
+ *  @see arp_interface.h
+ *  @see IS_NET_ARP_MESSAGE()
+ */
+int	arp_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count );
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/il/arp/arp_oc.h
===================================================================
--- uspace/srv/net/il/arp/arp_oc.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/il/arp/arp_oc.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,141 @@
+/*
+ * 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 operation codes 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 __NET_ARP_ARPOP_H__
+#define __NET_ARP_ARPOP_H__
+
+/** @name ARP operation codes definitions
+ */
+/*@{*/
+
+/** REQUEST operation code.
+ */
+#define ARPOP_REQUEST		1
+
+/** REPLY operation code.
+ */
+#define ARPOP_REPLY		2
+
+/** Reverse request operation code.
+ */
+#define ARPOP_RREQUEST		3
+
+/** Reverse reply operation code.
+ */
+#define ARPOP_RREPLY		4
+
+/** DRARP-Request operation code.
+ */
+#define ARPOP_DRARP_Request		5
+
+/** DRARP-Reply operation code.
+ */
+#define ARPOP_DRARP_Reply		6
+
+/** DRARP-Error operation code.
+ */
+#define ARPOP_DRARP_Error		7
+
+/** InARP-Request operation code.
+ */
+#define ARPOP_InREQUEST		8
+
+/** InARP-Reply operation code.
+ */
+#define ARPOP_InREPLY		9
+
+/** ARP-NAK operation code.
+ */
+#define ARPOP_NAK		10
+
+/** MARS-Request operation code.
+ */
+#define ARPOP_MARS_Request		11
+
+/** MARS-Multi operation code.
+ */
+#define ARPOP_MARS_Multi		12
+
+/** MARS-MServ operation code.
+ */
+#define ARPOP_MARS_MServ		13
+
+/** MARS-Join operation code.
+ */
+#define ARPOP_MARS_Join		14
+
+/** MARS-Leave operation code.
+ */
+#define ARPOP_MARS_Leave		15
+
+/** MARS-NAK operation code.
+ */
+#define ARPOP_MARS_NAK		16
+
+/** MARS-Unserv operation code.
+ */
+#define ARPOP_MARS_Unserv		17
+
+/** MARS-SJoin operation code.
+ */
+#define ARPOP_MARS_SJoin		18
+
+/** MARS-SLeave operation code.
+ */
+#define ARPOP_MARS_SLeave		19
+
+/** MARS-Grouplist-Request operation code.
+ */
+#define ARPOP_MARS_Grouplist_Request		20
+
+/** MARS-Grouplist-Reply operation code.
+ */
+#define ARPOP_MARS_Grouplist_Reply		21
+
+/** MARS-Redirect-Map operation code.
+ */
+#define ARPOP_MARS_Redirect_Map		22
+
+/** MAPOS-UNARP operation code.
+ */
+#define ARPOP_MAPOS_UNARP		23
+
+/*@}*/
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/il/arp/arp_remote.c
===================================================================
--- uspace/srv/net/il/arp/arp_remote.c	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/il/arp/arp_remote.c	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,96 @@
+/*
+ * 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 interface implementation for standalone remote modules.
+ *  @see arp_interface.h
+ */
+
+#include <async.h>
+#include <errno.h>
+
+#include <ipc/ipc.h>
+#include <ipc/services.h>
+
+#include "../../messages.h"
+#include "../../modules.h"
+
+#include "../../include/device.h"
+#include "../../include/arp_interface.h"
+
+#include "../../structures/measured_strings.h"
+
+#include "arp_messages.h"
+
+int arp_device_req( int arp_phone, device_id_t device_id, services_t protocol, services_t netif, measured_string_ref address ){
+	aid_t			message_id;
+	ipcarg_t		result;
+
+	message_id = async_send_3( arp_phone, NET_ARP_DEVICE, ( ipcarg_t ) device_id, protocol, netif, NULL );
+	measured_strings_send( arp_phone, address, 1 );
+	async_wait_for( message_id, & result );
+	return ( int ) result;
+}
+
+int arp_translate_req( int arp_phone, device_id_t device_id, services_t protocol, measured_string_ref address, measured_string_ref * translation, char ** data ){
+	return generic_translate_req( arp_phone, NET_ARP_TRANSLATE, device_id, protocol, address, 1, translation, data );
+}
+
+int arp_clear_device_req( int arp_phone, device_id_t device_id ){
+	return ( int ) async_req_1_0( arp_phone, NET_ARP_CLEAR_DEVICE, ( ipcarg_t ) device_id );
+}
+
+int arp_clear_address_req( int arp_phone, device_id_t device_id, services_t protocol, measured_string_ref address ){
+	aid_t			message_id;
+	ipcarg_t		result;
+
+	message_id = async_send_2( arp_phone, NET_ARP_CLEAR_ADDRESS, ( ipcarg_t ) device_id, protocol, NULL );
+	measured_strings_send( arp_phone, address, 1 );
+	async_wait_for( message_id, & result );
+	return ( int ) result;
+}
+
+int arp_clean_cache_req( int arp_phone ){
+	return ( int ) async_req_0_0( arp_phone, NET_ARP_CLEAN_CACHE );
+}
+
+int arp_connect_module( services_t service ){
+	if( service != SERVICE_ARP ) return EINVAL;
+	return connect_to_service( SERVICE_ARP );
+}
+
+task_id_t arp_task_get_id( void ){
+	return 0;
+}
+
+/** @}
+ */
Index: uspace/srv/net/il/il_messages.h
===================================================================
--- uspace/srv/net/il/il_messages.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/il/il_messages.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup net_il
+ *  @{
+ */
+
+/** @file
+ *  Internetwork layer modules messages.
+ *  @see il_interface.h
+ *  @see ip_interface.h
+ */
+
+#ifndef __NET_IL_MESSAGES_H__
+#define __NET_IL_MESSAGES_H__
+
+#include <ipc/ipc.h>
+
+/** Internet layer modules messages.
+ */
+typedef enum{
+	/** New device message.
+	 *  @see ip_device_req()
+	 */
+	NET_IL_DEVICE = NET_IL_FIRST,
+	/** Device state changed message.
+	 *  @see il_device_state_msg()
+	 */
+	NET_IL_DEVICE_STATE,
+	/** Packet received message.
+	 *  @see il_received_msg()
+	 */
+	NET_IL_RECEIVED,
+	/** Packet send message.
+	 *  @see il_send_msg()
+	 */
+	NET_IL_SEND,
+	/** Packet size message.
+	 *  @see il_packet_size_req()
+	 */
+	NET_IL_PACKET_SPACE,
+	/** Device MTU changed message.
+	 *  @see il_mtu_changed_msg()
+	 */
+	NET_IL_MTU_CHANGED
+} il_messages;
+
+/** @name Internetwork layer specific message parameters definitions
+ */
+/*@{*/
+
+/** Returns the protocol number message parameter.
+ *  @param[in] call The message call structure.
+ */
+#define IL_GET_PROTO( call )		( int ) IPC_GET_ARG1( * call )
+
+/** Returns the registering service message parameter.
+ *  @param[in] call The message call structure.
+ */
+#define IL_GET_SERVICE( call )		( services_t ) IPC_GET_ARG2( * call )
+
+/*@}*/
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/il/ip/Makefile
===================================================================
--- uspace/srv/net/il/ip/Makefile	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/il/ip/Makefile	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,59 @@
+#
+# 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.
+#
+
+NAME = ip
+
+NET_BASE = ../../
+STRUCTURES = $(NET_BASE)structures/
+
+## Sources
+#
+
+OUTPUT = $(NAME)
+SOURCES = \
+	$(NAME).c \
+	$(NAME)_client.c \
+	$(NAME)_module.c \
+	$(NET_BASE)checksum.c \
+	$(NET_BASE)inet.c \
+	$(NET_BASE)module.c \
+	$(NET_BASE)modules.c \
+	$(NET_BASE)il/arp/arp_remote.c \
+	$(NET_BASE)nil/nil_remote.c \
+	$(NET_BASE)net/net_remote.c \
+	$(NET_BASE)tl/icmp/icmp_client.c \
+	$(NET_BASE)tl/icmp/icmp_common.c \
+	$(NET_BASE)tl/icmp/icmp_remote.c \
+	$(STRUCTURES)char_map.c \
+	$(STRUCTURES)measured_strings.c \
+	$(STRUCTURES)module_map.c \
+	$(STRUCTURES)packet/packet.c \
+	$(STRUCTURES)packet/packet_client.c \
+	$(STRUCTURES)packet/packet_remote.c
+
+include $(NET_BASE)Makefile.module
Index: uspace/srv/net/il/ip/ip.c
===================================================================
--- uspace/srv/net/il/ip/ip.c	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/il/ip/ip.c	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,1519 @@
+/*
+ * 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 <string.h>
+
+#include <ipc/ipc.h>
+#include <ipc/services.h>
+
+#include <sys/types.h>
+
+#include "../../err.h"
+#include "../../messages.h"
+#include "../../modules.h"
+
+#include "../../include/arp_interface.h"
+#include "../../include/byteorder.h"
+#include "../../include/checksum.h"
+#include "../../include/device.h"
+#include "../../include/icmp_client.h"
+#include "../../include/icmp_codes.h"
+#include "../../include/icmp_interface.h"
+#include "../../include/il_interface.h"
+#include "../../include/in.h"
+#include "../../include/in6.h"
+#include "../../include/inet.h"
+#include "../../include/ip_client.h"
+#include "../../include/ip_interface.h"
+#include "../../include/net_interface.h"
+#include "../../include/nil_interface.h"
+#include "../../include/tl_interface.h"
+#include "../../include/socket_codes.h"
+#include "../../include/socket_errno.h"
+#include "../../structures/measured_strings.h"
+#include "../../structures/module_map.h"
+#include "../../structures/packet/packet_client.h"
+
+#include "../../nil/nil_messages.h"
+
+#include "../il_messages.h"
+
+#include "ip.h"
+#include "ip_header.h"
+#include "ip_messages.h"
+#include "ip_module.h"
+
+/** 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 )
+
+/** 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.
+ *  @returns EOK on success.
+ *  @returns ENOENT if device is not found.
+ */
+int	ip_mtu_changed_message( device_id_t device_id, size_t mtu );
+
+/** Updates the device state.
+ *  @param[in] device_id The device identifier.
+ *  @param[in] state The new state value.
+ *  @returns EOK on success.
+ *  @returns ENOENT if device is not found.
+ */
+int	ip_device_state_message( device_id_t device_id, device_state_t state );
+
+/** Registers the transport layer protocol.
+ *  The traffic of this protocol will be supplied using either the receive function or IPC message.
+ *  @param[in] protocol The transport layer module protocol.
+ *  @param[in] service The transport layer module service.
+ *  @param[in] phone The transport layer module phone.
+ *  @param[in] tl_received_msg The receiving function.
+ *  @returns EOK on success.
+ *  @returns EINVAL if the protocol parameter and/or the service parameter is zero (0).
+ *  @returns EINVAL if the phone parameter is not a positive number and the tl_receive_msg is NULL.
+ *  @returns ENOMEM if there is not enough memory left.
+ */
+int	ip_register( int protocol, services_t service, int phone, tl_received_msg_t tl_received_msg );
+
+/** 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.
+ *  @returns EOK on success.
+ *  @returns ENOTSUP if DHCP is configured.
+ *  @returns ENOTSUP if IPv6 is configured.
+ *  @returns EINVAL if any of the addresses is invalid.
+ *  @returns EINVAL if the used ARP module is not known.
+ *  @returns ENOMEM if there is not enough memory left.
+ *  @returns Other error codes as defined for the net_get_device_conf_req() function.
+ *  @returns Other error codes as defined for the bind_service() function.
+ *  @returns Other error codes as defined for the specific arp_device_req() function.
+ *  @returns Other error codes as defined for the nil_packet_size_req() function.
+ */
+int	ip_netif_initialize( ip_netif_ref ip_netif );
+
+/** Sends 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 The packet to be sent.
+ *  @param[in] netif The target network interface.
+ *  @param[in] route The target route.
+ *  @param[in] src The source address.
+ *  @param[in] dest The destination address.
+ *  @param[in] error The error module service.
+ *  @returns EOK on success.
+ *  @returns Other error codes as defined for the arp_translate_req() function.
+ *  @returns Other error codes as defined for the ip_prepare_packet() function.
+ */
+int	ip_send_route( packet_t packet, ip_netif_ref netif, ip_route_ref route, in_addr_t * src, in_addr_t dest, services_t error );
+
+/** 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.
+ *  @returns EOK on success.
+ *  @returns EINVAL if the packet is too small to contain the IP header.
+ *  @returns EINVAL if the packet is too long than the IP allows.
+ *  @returns ENOMEM if there is not enough memory left.
+ *  @returns Other error codes as defined for the packet_set_addr() function.
+ */
+int	ip_prepare_packet( in_addr_t * source, in_addr_t dest, packet_t packet, measured_string_ref destination );
+
+/** Checks 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 The packet or the packet queue to be checked.
+ *  @param[in] prefix The minimum prefix size.
+ *  @param[in] content The maximum content size.
+ *  @param[in] suffix The minimum suffix size.
+ *  @param[in] addr_len The minimum address length.
+ *  @param[in] error The error module service.
+ *  @returns The packet or the packet queue of the allowed length.
+ *  @returns NULL if there are no packets left.
+ */
+packet_t	ip_split_packet( packet_t packet, size_t prefix, size_t content, size_t suffix, socklen_t addr_len, services_t error );
+
+/** 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.
+ *  @returns EOK on success.
+ *  @returns EINVAL if the packet_get_addr() function fails.
+ *  @returns EINVAL if the packet does not contain the IP header.
+ *  @returns EPERM if the packet needs to be fragmented and the fragmentation is not allowed.
+ *  @returns ENOMEM if there is not enough memory left.
+ *  @returns ENOMEM if there is no packet available.
+ *  @returns ENOMEM if the packet is too small to contain the IP header.
+ *  @returns Other error codes as defined for the packet_trim() function.
+ *  @returns Other error codes as defined for the ip_create_middle_header() function.
+ *  @returns Other error codes as defined for the ip_fragment_packet_data() function.
+ */
+int	ip_fragment_packet( packet_t packet, size_t length, size_t prefix, size_t suffix, socklen_t addr_len );
+
+/** 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.
+ *  @returns EOK on success.
+ *  @returns ENOMEM if the target packet is too small.
+ *  @returns Other error codes as defined for the packet_set_addr() function.
+ *  @returns Other error codes as defined for the pq_insert_after() function.
+ */
+int	ip_fragment_packet_data( packet_t packet, packet_t new_packet, ip_header_ref header, ip_header_ref new_header, size_t length, const struct sockaddr * src, const struct sockaddr * dest, socklen_t addrlen );
+
+/** 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.
+ *  @returns The prefixed middle header.
+ *  @returns NULL on error.
+ */
+ip_header_ref	ip_create_middle_header( packet_t packet, ip_header_ref last );
+
+/** 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.
+ */
+void ip_create_last_header( ip_header_ref last, ip_header_ref first );
+
+/** Returns the network interface's IP address.
+ *  @param[in] netif The network interface.
+ *  @returns The IP address.
+ *  @returns NULL if no IP address was found.
+ */
+in_addr_t *	ip_netif_address( ip_netif_ref netif );
+
+/** Searches all network interfaces if there is a suitable route.
+ *  @param[in] destination The destination address.
+ *  @returns The found route.
+ *  @returns NULL if no route was found.
+ */
+ip_route_ref	ip_find_route( in_addr_t destination );
+
+/** 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.
+ *  @returns The found route.
+ *  @returns NULL if no route was found.
+ */
+ip_route_ref	ip_netif_find_route( ip_netif_ref netif, in_addr_t destination );
+
+/** Processes the received IP packet or the packet queue one by one.
+ *  The packet is either passed to another module or released on error.
+ *  @param[in] device_id The source device identifier.
+ *  @param[in,out] packet The received packet.
+ *  @returns EOK on success and the packet is no longer needed.
+ *  @returns EINVAL if the packet is too small to carry the IP packet.
+ *  @returns EINVAL if the received address lengths differs from the registered values.
+ *  @returns ENOENT if the device is not found in the cache.
+ *  @returns ENOENT if the protocol for the device is not found in the cache.
+ *  @returns ENOMEM if there is not enough memory left.
+ */
+int	ip_receive_message( device_id_t device_id, packet_t packet );
+
+/** 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 (2).
+ *  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.
+ *  @returns EOK on success.
+ *  @returns EINVAL if the TTL is less than two (2).
+ *  @returns EINVAL if the checksum is invalid.
+ *  @returns EAFNOSUPPORT if the address family is not supported.
+ *  @returns ENOENT if no route was found.
+ *  @returns ENOENT if the packet is for another host and the routing is disabled.
+ */
+int	ip_process_packet( device_id_t device_id, packet_t packet );
+
+/** Returns the packet destination address from the IP header.
+ *  @param[in] header The packet IP header to be read.
+ *  @returns The packet destination address.
+ */
+in_addr_t	ip_get_destination( ip_header_ref header );
+
+/** 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.
+ *  @returns EOK on success.
+ *  @returns ENOTSUP if the packet is a fragment.
+ *  @returns EAFNOSUPPORT if the address family is not supported.
+ *  @returns ENOENT if the target protocol is not found.
+ *  @returns Other error codes as defined for the packet_set_addr() function.
+ *  @returns Other error codes as defined for the packet_trim() function.
+ *  @returns Other error codes as defined for the protocol specific tl_received_msg function.
+ */
+int	ip_deliver_local( device_id_t device_id, packet_t packet, ip_header_ref header, services_t error );
+
+/** Prepares the ICMP notification packet.
+ *  Releases additional packets and keeps only the first one.
+ *  All packets is released on error.
+ *  @param[in] error The packet error service.
+ *  @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.
+ *  @returns The found ICMP phone.
+ *  @returns EINVAL if the error parameter is set.
+ *  @returns EINVAL if the ICMP phone is not found.
+ *  @returns EINVAL if the ip_prepare_icmp() fails.
+ */
+int	ip_prepare_icmp_and_get_phone( services_t error, packet_t packet, ip_header_ref header );
+
+/** Returns the ICMP phone.
+ *  Searches the registered protocols.
+ *  @returns The found ICMP phone.
+ *  @returns ENOENT if the ICMP is not registered.
+ */
+int	ip_get_icmp_phone( void );
+
+/** 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.
+ *  @returns EOK on success.
+ *  @returns EINVAL if there are no data in the packet.
+ *  @returns EINVAL if the packet is a fragment.
+ *  @returns ENOMEM if the packet is too short to contain the IP header.
+ *  @returns EAFNOSUPPORT if the address family is not supported.
+ *  @returns Other error codes as defined for the packet_set_addr().
+ */
+int	ip_prepare_icmp( packet_t packet, ip_header_ref header );
+
+/** 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.
+ */
+int	ip_release_and_return( packet_t packet, int result );
+
+int ip_initialize( async_client_conn_t client_connection ){
+	ERROR_DECLARE;
+
+	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.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;
+	ERROR_PROPAGATE( ip_netifs_initialize( & ip_globals.netifs ));
+	ERROR_PROPAGATE( ip_protos_initialize( & ip_globals.protos ));
+	ip_globals.client_connection = client_connection;
+	ERROR_PROPAGATE( modules_initialize( & ip_globals.modules ));
+	ERROR_PROPAGATE( add_module( NULL, & ip_globals.modules, ARP_NAME, ARP_FILENAME, SERVICE_ARP, arp_task_get_id(), arp_connect_module ));
+	fibril_rwlock_write_unlock( & ip_globals.lock );
+	return EOK;
+}
+
+int ip_device_req( int il_phone, device_id_t device_id, services_t netif ){
+	ERROR_DECLARE;
+
+	ip_netif_ref	ip_netif;
+	ip_route_ref	route;
+	int				index;
+	char *			data;
+
+	ip_netif = ( ip_netif_ref ) malloc( sizeof( ip_netif_t ));
+	if( ! ip_netif ) return ENOMEM;
+	if( ERROR_OCCURRED( ip_routes_initialize( & ip_netif->routes ))){
+		free( ip_netif );
+		return ERROR_CODE;
+	}
+	ip_netif->device_id = device_id;
+	ip_netif->service = netif;
+	ip_netif->state = NETIF_STOPPED;
+	fibril_rwlock_write_lock( & ip_globals.netifs_lock );
+	if( ERROR_OCCURRED( ip_netif_initialize( ip_netif ))){
+		fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
+		ip_routes_destroy( & ip_netif->routes );
+		free( ip_netif );
+		return ERROR_CODE;
+	}
+	if( ip_netif->arp ) ++ ip_netif->arp->usage;
+	// print the settings
+	printf( "New device registered:\n\tid\t= %d\n\tphone\t= %d\n\tIPV\t= %d\n", ip_netif->device_id, ip_netif->phone, ip_netif->ipv );
+	printf( "\tconfiguration\t= %s\n", ip_netif->dhcp ? "dhcp" : "static" );
+	// TODO ipv6 addresses
+	data = ( char * ) malloc( INET_ADDRSTRLEN );
+	if( data ){
+		for( index = 0; index < ip_routes_count( & ip_netif->routes ); ++ index ){
+			route = ip_routes_get_index( & ip_netif->routes, index );
+			if( route ){
+				printf( "\tRouting %d:\n", index );
+				inet_ntop( AF_INET, ( uint8_t * ) & route->address.s_addr, data, INET_ADDRSTRLEN );
+				printf( "\t\taddress\t= %s\n", data );
+				inet_ntop( AF_INET, ( uint8_t * ) & route->netmask.s_addr, data, INET_ADDRSTRLEN );
+				printf( "\t\tnetmask\t= %s\n", data );
+				inet_ntop( AF_INET, ( uint8_t * ) & route->gateway.s_addr, data, INET_ADDRSTRLEN );
+				printf( "\t\tgateway\t= %s\n", data );
+			}
+		}
+		inet_ntop( AF_INET, ( uint8_t * ) & ip_netif->broadcast.s_addr, data, INET_ADDRSTRLEN );
+		printf( "\t\tbroadcast\t= %s\n", data );
+		free( data );
+	}
+	fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
+	return EOK;
+}
+
+int ip_netif_initialize( ip_netif_ref ip_netif ){
+	ERROR_DECLARE;
+
+	measured_string_t	names[] = {{ "IPV", 3 }, { "IP_CONFIG", 9 }, { "IP_ADDR", 7 }, { "IP_NETMASK", 10 }, { "IP_GATEWAY", 10 }, { "IP_BROADCAST", 12 }, { "ARP", 3 }, { "IP_ROUTING", 10 }};
+	measured_string_ref	configuration;
+	size_t				count = sizeof( names ) / sizeof( measured_string_t );
+	char *				data;
+	measured_string_t	address;
+	int					index;
+	ip_route_ref		route;
+	in_addr_t			gateway;
+
+	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
+	ERROR_PROPAGATE( net_get_device_conf_req( ip_globals.net_phone, ip_netif->device_id, & configuration, count, & data ));
+	if( configuration ){
+		if( configuration[ 0 ].value ){
+			ip_netif->ipv = strtol( configuration[ 0 ].value, NULL, 0 );
+		}
+		ip_netif->dhcp = ! str_lcmp( 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_ref ) 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( ERROR_OCCURRED( inet_pton( AF_INET, configuration[ 2 ].value, ( uint8_t * ) & route->address.s_addr ))
+			|| ERROR_OCCURRED( inet_pton( AF_INET, configuration[ 3 ].value, ( uint8_t * ) & route->netmask.s_addr ))
+			|| ( inet_pton( AF_INET, configuration[ 4 ].value, ( uint8_t * ) & gateway.s_addr ) == EINVAL )
+			|| ( inet_pton( AF_INET, 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 );
+	}
+	// binds the netif service which also initializes the device
+	ip_netif->phone = nil_bind_service( ip_netif->service, ( ipcarg_t ) ip_netif->device_id, SERVICE_IP, ip_globals.client_connection );
+	if( ip_netif->phone < 0 ){
+		printf( "Failed to contact the nil service %d\n", ip_netif->service );
+		return ip_netif->phone;
+	}
+	// has to be after the device netif module initialization
+	if( ip_netif->arp ){
+		if( route ){
+			address.value = ( char * ) & route->address.s_addr;
+			address.length = CONVERT_SIZE( in_addr_t, char, 1 );
+			ERROR_PROPAGATE( arp_device_req( ip_netif->arp->phone, ip_netif->device_id, SERVICE_IP, ip_netif->service, & address ));
+		}else{
+			ip_netif->arp = 0;
+		}
+	}
+	// get packet dimensions
+	ERROR_PROPAGATE( nil_packet_size_req( ip_netif->phone, ip_netif->device_id, & ip_netif->addr_len, & ip_netif->prefix, & ip_netif->content, & ip_netif->suffix ));
+	if( ip_netif->content < IP_MIN_CONTENT ){
+		printf( "Maximum transmission unit %d bytes is too small, at least %d bytes are needed\n", ip_netif->content, IP_MIN_CONTENT );
+		ip_netif->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;
+	}
+	return EOK;
+}
+
+int ip_mtu_changed_message( device_id_t device_id, size_t mtu ){
+	ip_netif_ref	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->content = mtu;
+	printf( "ip - device %d changed mtu to %d\n\n", device_id, mtu );
+	fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
+	return EOK;
+}
+
+int ip_device_state_message( device_id_t device_id, device_state_t state ){
+	ip_netif_ref	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;
+	printf( "ip - device %d changed state to %d\n\n", device_id, state );
+	fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
+	return EOK;
+}
+
+int ip_connect_module( services_t service ){
+	return EOK;
+}
+
+int ip_bind_service( services_t service, int protocol, services_t me, async_client_conn_t receiver, tl_received_msg_t received_msg ){
+	return ip_register( protocol, me, 0, received_msg );
+}
+
+int ip_register( int protocol, services_t service, int phone, tl_received_msg_t received_msg ){
+	ip_proto_ref	proto;
+	int				index;
+
+	if( !( protocol && service && (( phone > 0 ) || ( received_msg )))) return EINVAL;
+	proto = ( ip_proto_ref ) malloc( sizeof( ip_protos_t ));
+	if( ! proto ) return ENOMEM;
+	proto->protocol = protocol;
+	proto->service = service;
+	proto->phone = phone;
+	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;
+	}
+	printf( "New protocol registered:\n\tprotocol\t= %d\n\tphone\t= %d\n", proto->protocol, proto->phone );
+	fibril_rwlock_write_unlock( & ip_globals.protos_lock );
+	return EOK;
+}
+
+int ip_send_msg( int il_phone, device_id_t device_id, packet_t packet, services_t sender, services_t error ){
+	ERROR_DECLARE;
+
+	int					addrlen;
+	ip_netif_ref		netif;
+	ip_route_ref		route;
+	struct sockaddr *		addr;
+	struct sockaddr_in *	address_in;
+//	struct sockaddr_in6 *	address_in6;
+	in_addr_t *			dest;
+	in_addr_t *			src;
+	int					phone;
+
+	// 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;
+		// TODO IPv6
+/*		case AF_INET6:
+			if( addrlen != sizeof( struct sockaddr_in6 )) return EINVAL;
+			address_in6 = ( struct sockaddr_in6 * ) dest;
+			address_in6.sin6_addr.s6_addr;
+			IPV6_LOCALHOST_ADDRESS;
+*/		default:
+			return ip_release_and_return( packet, EAFNOSUPPORT );
+	}
+	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;
+		}
+	}else{
+		route = ip_find_route( * dest );
+		netif = route ? route->netif : NULL;
+	}
+	if( !( netif && route )){
+		fibril_rwlock_read_unlock( & ip_globals.netifs_lock );
+		phone = ip_prepare_icmp_and_get_phone( error, packet, NULL );
+		if( phone >= 0 ){
+			// unreachable ICMP if no routing
+			icmp_destination_unreachable_msg( phone, 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( route->address.s_addr == dest->s_addr ){
+		// 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 );
+			phone = ip_prepare_icmp_and_get_phone( error, packet, NULL );
+			if( phone >= 0 ){
+				// unreachable ICMP if no routing
+				icmp_destination_unreachable_msg( phone, 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 );
+	}
+	ERROR_CODE = ip_send_route( packet, netif, route, src, * dest, error );
+	fibril_rwlock_read_unlock( & ip_globals.netifs_lock );
+	return ERROR_CODE;
+}
+
+in_addr_t * ip_netif_address( ip_netif_ref netif ){
+	ip_route_ref	route;
+
+	route = ip_routes_get_index( & netif->routes, 0 );
+	return route ? & route->address : NULL;
+}
+
+int ip_send_route( packet_t packet, ip_netif_ref netif, ip_route_ref route, in_addr_t * src, in_addr_t dest, services_t error ){
+	ERROR_DECLARE;
+
+	measured_string_t	destination;
+	measured_string_ref	translation;
+	char *				data;
+	int					phone;
+
+	// get destination hardware address
+	if( netif->arp && ( route->address.s_addr != dest.s_addr )){
+		destination.value = route->gateway.s_addr ? ( char * ) & route->gateway.s_addr : ( char * ) & dest.s_addr;
+		destination.length = CONVERT_SIZE( dest.s_addr, char, 1 );
+		if( ERROR_OCCURRED( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & destination, & translation, & data ))){
+//			sleep( 1 );
+//			ERROR_PROPAGATE( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & destination, & translation, & data ));
+			pq_release( ip_globals.net_phone, packet_get_id( packet ));
+			return ERROR_CODE;
+		}
+		if( !( translation && translation->value )){
+			if( translation ){
+				free( translation );
+				free( data );
+			}
+			phone = ip_prepare_icmp_and_get_phone( error, packet, NULL );
+			if( phone >= 0 ){
+				// unreachable ICMP if no routing
+				icmp_destination_unreachable_msg( phone, ICMP_HOST_UNREACH, 0, packet );
+			}
+			return EINVAL;
+		}
+	}else translation = NULL;
+	if( ERROR_OCCURRED( ip_prepare_packet( src, dest, packet, translation ))){
+		pq_release( ip_globals.net_phone, packet_get_id( packet ));
+	}else{
+		packet = ip_split_packet( packet, netif->prefix, netif->content, netif->suffix, netif->addr_len, error );
+		if( packet ){
+			nil_send_msg( netif->phone, netif->device_id, packet, SERVICE_IP );
+		}
+	}
+	if( translation ){
+		free( translation );
+		free( data );
+	}
+	return ERROR_CODE;
+}
+
+int ip_prepare_packet( in_addr_t * source, in_addr_t dest, packet_t packet, measured_string_ref destination ){
+	ERROR_DECLARE;
+
+	size_t				length;
+	ip_header_ref		header;
+	ip_header_ref		last_header;
+	ip_header_ref		middle_header;
+	packet_t			next;
+
+	length = packet_get_data_length( packet );
+	if(( length < sizeof( ip_header_t )) || ( length > IP_MAX_CONTENT )) return EINVAL;
+	header = ( ip_header_ref ) packet_get_data( packet );
+	if( destination ){
+		ERROR_PROPAGATE( packet_set_addr( packet, NULL, ( uint8_t * ) destination->value, CONVERT_SIZE( char, uint8_t, destination->length )));
+	}else{
+		ERROR_PROPAGATE( packet_set_addr( packet, NULL, NULL, 0 ));
+	}
+	header->version = IPV4;
+	header->fragment_offset_high = 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 );
+//	length = packet_get_data_length( packet );
+	if( pq_next( packet )){
+		last_header = ( ip_header_ref ) 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_ref ) packet_prefix( next, IP_HEADER_LENGTH( last_header ));
+			if( ! middle_header ) return ENOMEM;
+			memcpy( middle_header, last_header, IP_HEADER_LENGTH( last_header ));
+			header->flags |= IPFLAG_MORE_FRAGMENTS;
+			middle_header->total_length = htons( packet_get_data_length( next ));
+			middle_header->fragment_offset_high = 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 ){
+				ERROR_PROPAGATE( packet_set_addr( next, NULL, ( uint8_t * ) destination->value, CONVERT_SIZE( char, uint8_t, destination->length )));
+			}
+			length += packet_get_data_length( next );
+			next = pq_next( next );
+		}
+		middle_header = ( ip_header_ref ) packet_prefix( next, IP_HEADER_LENGTH( last_header ));
+		if( ! middle_header ) return ENOMEM;
+		memcpy( middle_header, last_header, IP_HEADER_LENGTH( last_header ));
+		middle_header->total_length = htons( packet_get_data_length( next ));
+		middle_header->fragment_offset_high = 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 ){
+			ERROR_PROPAGATE( packet_set_addr( next, NULL, ( uint8_t * ) destination->value, CONVERT_SIZE( char, uint8_t, destination->length )));
+		}
+		length += packet_get_data_length( next );
+		free( last_header );
+		header->flags |= IPFLAG_MORE_FRAGMENTS;
+	}
+	header->total_length = htons( length );
+	// unnecessary for all protocols
+	header->header_checksum = IP_HEADER_CHECKSUM( header );
+	return EOK;
+}
+
+int ip_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){
+	ERROR_DECLARE;
+
+	packet_t				packet;
+	struct sockaddr *		addr;
+	size_t					addrlen;
+	ip_pseudo_header_ref	header;
+	size_t					headerlen;
+
+	* answer_count = 0;
+	switch( IPC_GET_METHOD( * call )){
+		case IPC_M_PHONE_HUNGUP:
+			return EOK;
+		case NET_IL_DEVICE:
+			return ip_device_req( 0, IPC_GET_DEVICE( call ), IPC_GET_SERVICE( call ));
+		case IPC_M_CONNECT_TO_ME:
+			return ip_register( IL_GET_PROTO( call ), IL_GET_SERVICE( call ), IPC_GET_PHONE( call ), NULL );
+		case NET_IL_SEND:
+			ERROR_PROPAGATE( packet_translate( ip_globals.net_phone, & packet, IPC_GET_PACKET( call )));
+			return ip_send_msg( 0, IPC_GET_DEVICE( call ), packet, 0, IPC_GET_ERROR( call ));
+		case NET_IL_DEVICE_STATE:
+			return ip_device_state_message( IPC_GET_DEVICE( call ), IPC_GET_STATE( call ));
+		case NET_IL_RECEIVED:
+			ERROR_PROPAGATE( packet_translate( ip_globals.net_phone, & packet, IPC_GET_PACKET( call )));
+			return ip_receive_message( IPC_GET_DEVICE( call ), packet );
+		case NET_IP_RECEIVED_ERROR:
+			ERROR_PROPAGATE( packet_translate( ip_globals.net_phone, & packet, IPC_GET_PACKET( call )));
+			return ip_received_error_msg( 0, IPC_GET_DEVICE( call ), packet, IPC_GET_TARGET( call ), IPC_GET_ERROR( call ));
+		case NET_IP_ADD_ROUTE:
+			return ip_add_route_req( 0, 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( 0, IPC_GET_DEVICE( call ), IP_GET_GATEWAY( call ));
+		case NET_IP_GET_ROUTE:
+			ERROR_PROPAGATE( data_receive(( void ** ) & addr, & addrlen ));
+			ERROR_PROPAGATE( ip_get_route_req( 0, IP_GET_PROTOCOL( call ), addr, ( socklen_t ) addrlen, IPC_SET_DEVICE( answer ), & header, & headerlen ));
+			* IP_SET_HEADERLEN( answer ) = headerlen;
+			* answer_count = 2;
+			if( ! ERROR_OCCURRED( data_reply( & headerlen, sizeof( headerlen )))){
+				ERROR_CODE = data_reply( header, headerlen );
+			}
+			free( header );
+			return ERROR_CODE;
+		case NET_IL_PACKET_SPACE:
+			ERROR_PROPAGATE( ip_packet_size_req( 0, IPC_GET_DEVICE( call ), IPC_SET_ADDR( answer ), IPC_SET_PREFIX( answer ), IPC_SET_CONTENT( answer ), IPC_SET_SUFFIX( answer )));
+			* answer_count = 3;
+			return EOK;
+		case NET_IL_MTU_CHANGED:
+			return ip_mtu_changed_message( IPC_GET_DEVICE( call ), IPC_GET_MTU( call ));
+	}
+	return ENOTSUP;
+}
+
+int ip_packet_size_req( int ip_phone, device_id_t device_id, size_t * addr_len, size_t * prefix, size_t * content, size_t * suffix ){
+	ip_netif_ref	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 ){
+				if( netif->addr_len > * addr_len ) * addr_len = netif->addr_len;
+				if( netif->prefix > * prefix ) * prefix = netif->prefix;
+				if( netif->suffix > * suffix ) * suffix = netif->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->addr_len > IP_ADDR ) ? netif->addr_len : IP_ADDR;
+		* prefix = netif->prefix + IP_PREFIX;
+		* suffix = netif->suffix + IP_SUFFIX;
+	}
+	fibril_rwlock_read_unlock( & ip_globals.netifs_lock );
+	return EOK;
+}
+
+int ip_add_route_req( int ip_phone, device_id_t device_id, in_addr_t address, in_addr_t netmask, in_addr_t gateway ){
+	ip_route_ref	route;
+	ip_netif_ref	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_ref ) 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;
+}
+
+ip_route_ref ip_find_route( in_addr_t destination ){
+	int				index;
+	ip_route_ref	route;
+	ip_netif_ref	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 == NETIF_ACTIVE )){
+			route = ip_netif_find_route( netif, destination );
+			if( route ) return route;
+		}
+		-- index;
+	}
+	return & ip_globals.gateway;
+}
+
+ip_route_ref ip_netif_find_route( ip_netif_ref netif, in_addr_t destination ){
+	int				index;
+	ip_route_ref	route;
+
+	if( netif ){
+		// 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;
+}
+
+int ip_set_gateway_req( int ip_phone, device_id_t device_id, in_addr_t gateway ){
+	ip_netif_ref	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;
+}
+
+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;
+	int				phone;
+
+	next = packet;
+	// check all packets
+	while( next ){
+		length = packet_get_data_length( next );
+		// too long?
+		if( length > content ){
+			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 ){
+					phone = ip_prepare_icmp_and_get_phone( error, next, NULL );
+					if( phone >= 0 ){
+						// fragmentation necessary ICMP
+						icmp_destination_unreachable_msg( phone, ICMP_FRAG_NEEDED, content, next );
+					}
+				}else{
+					pq_release( ip_globals.net_phone, packet_get_id( next ));
+				}
+				next = new_packet;
+				continue;
+			}
+		}
+		next = pq_next( next );
+	}
+	return packet;
+}
+
+int ip_fragment_packet( packet_t packet, size_t length, size_t prefix, size_t suffix, socklen_t addr_len ){
+	ERROR_DECLARE;
+
+	packet_t		new_packet;
+	ip_header_ref	header;
+	ip_header_ref	middle_header;
+	ip_header_ref	last_header;
+	struct sockaddr *		src;
+	struct sockaddr *		dest;
+	socklen_t		addrlen;
+	int				result;
+
+	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_ref ) packet_get_data( packet );
+	if( ! header ) return EINVAL;
+	// fragmentation forbidden?
+	if( header->flags & IPFLAG_DONT_FRAGMENT ){
+		return EPERM;
+	}
+	// create the last fragment
+	new_packet = packet_get_4( ip_globals.net_phone, prefix, length, suffix, (( addrlen > addr_len ) ? addrlen : addr_len ));
+	if( ! new_packet ) return ENOMEM;
+	// allocate as much as originally
+	last_header = ( ip_header_ref ) 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
+	if( ERROR_OCCURRED( packet_trim( new_packet, 0, IP_HEADER_LENGTH( header ) - IP_HEADER_LENGTH( last_header )))){
+		return ip_release_and_return( packet, ERROR_CODE );
+	}
+	// biggest multiple of 8 lower than content
+	// TODO even fragmentation?
+	length = length & ( ~ 0x7 );// ( content / 8 ) * 8
+	if( ERROR_OCCURRED( 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 ))){
+		return ip_release_and_return( packet, ERROR_CODE );
+	}
+	// mark the first as fragmented
+	header->flags |= IPFLAG_MORE_FRAGMENTS;
+	// create middle framgents
+	while( IP_TOTAL_LENGTH( header ) > length ){
+		new_packet = packet_get_4( ip_globals.net_phone, 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 );
+		}
+		if( ERROR_OCCURRED( ip_fragment_packet_data( packet, new_packet, header, middle_header, ( length - IP_HEADER_LENGTH( middle_header )) & ( ~ 0x7 ), src, dest, addrlen ))){
+			return ip_release_and_return( packet, ERROR_CODE );
+		}
+	}
+	// finish the first fragment
+	header->header_checksum = IP_HEADER_CHECKSUM( header );
+	return EOK;
+}
+
+int ip_fragment_packet_data( packet_t packet, packet_t new_packet, ip_header_ref header, ip_header_ref new_header, size_t length, const struct sockaddr * src, const struct sockaddr * dest, socklen_t addrlen ){
+	ERROR_DECLARE;
+
+	void *			data;
+	size_t			offset;
+
+	data = packet_suffix( new_packet, length );
+	if( ! data ) return ENOMEM;
+	memcpy( data, (( void * ) header ) + IP_TOTAL_LENGTH( header ) - length, length );
+	ERROR_PROPAGATE( packet_trim( packet, 0, length ));
+	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 );
+	new_header->fragment_offset_high = 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 );
+	ERROR_PROPAGATE( packet_set_addr( new_packet, ( const uint8_t * ) src, ( const uint8_t * ) dest, addrlen ));
+	return pq_insert_after( packet, new_packet );
+}
+
+ip_header_ref ip_create_middle_header( packet_t packet, ip_header_ref last ){
+	ip_header_ref	middle;
+
+	middle = ( ip_header_ref ) packet_suffix( packet, IP_HEADER_LENGTH( last ));
+	if( ! middle ) return NULL;
+	memcpy( middle, last, IP_HEADER_LENGTH( last ));
+	middle->flags |= IPFLAG_MORE_FRAGMENTS;
+	return middle;
+}
+
+void ip_create_last_header( ip_header_ref last, ip_header_ref first ){
+	ip_option_ref	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 < first->header_length ){
+		option = ( ip_option_ref ) ((( uint8_t * ) first ) + next );
+		// skip end or noop
+		if(( option->type == IPOPT_END ) || ( option->type == IPOPT_NOOP )){
+			++ next;
+		}else{
+			// copy if said 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 ));
+		last->header_length = length / 4 + 1;
+	}else{
+		last->header_length = length / 4;
+	}
+	last->header_checksum = 0;
+}
+
+int ip_receive_message( device_id_t device_id, packet_t packet ){
+	packet_t		next;
+
+	do{
+		next = pq_detach( packet );
+		ip_process_packet( device_id, packet );
+		packet = next;
+	}while( packet );
+	return EOK;
+}
+
+int ip_process_packet( device_id_t device_id, packet_t packet ){
+	ERROR_DECLARE;
+
+	ip_header_ref	header;
+	in_addr_t		dest;
+	ip_route_ref	route;
+	int				phone;
+	struct sockaddr *	addr;
+	struct sockaddr_in	addr_in;
+//	struct sockaddr_in	addr_in6;
+	socklen_t		addrlen;
+
+	header = ( ip_header_ref ) 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 )){
+		phone = ip_prepare_icmp_and_get_phone( 0, packet, header );
+		if( phone >= 0 ){
+			// checksum error ICMP
+			icmp_parameter_problem_msg( phone, ICMP_PARAM_POINTER, (( size_t ) (( void * ) & header->header_checksum )) - (( size_t ) (( void * ) header )), packet );
+		}
+		return EINVAL;
+	}
+	if( header->ttl <= 1 ){
+		phone = ip_prepare_icmp_and_get_phone( 0, packet, header );
+		if( phone >= 0 ){
+			// ttl oxceeded ICMP
+			icmp_time_exceeded_msg( phone, ICMP_EXC_TTL, packet );
+		}
+		return EINVAL;
+	}
+	// process ipopt and get destination
+	dest = ip_get_destination( header );
+	// set the addrination address
+	switch( header->version ){
+		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;
+/*		case IPv6VERSION:
+			addrlen = sizeof( dest_in6 );
+			bzero( & dest_in6, addrlen );
+			dest_in6.sin6_family = AF_INET6;
+			memcpy( & dest_in6.sin6_addr.s6_addr, );
+			dest = ( struct sockaddr * ) & dest_in;
+			break;
+*/		default:
+			return ip_release_and_return( packet, EAFNOSUPPORT );
+	}
+	ERROR_PROPAGATE( packet_set_addr( packet, NULL, ( uint8_t * ) & addr, addrlen ));
+	route = ip_find_route( dest );
+	if( ! route ){
+		phone = ip_prepare_icmp_and_get_phone( 0, packet, header );
+		if( phone >= 0 ){
+			// unreachable ICMP
+			icmp_destination_unreachable_msg( phone, 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 );
+	}else{
+		// only if routing enabled
+		if( route->netif->routing ){
+			-- header->ttl;
+			return ip_send_route( packet, route->netif, route, NULL, dest, 0 );
+		}else{
+			phone = ip_prepare_icmp_and_get_phone( 0, packet, header );
+			if( phone >= 0 ){
+				// unreachable ICMP if no routing
+				icmp_destination_unreachable_msg( phone, ICMP_HOST_UNREACH, 0, packet );
+			}
+			return ENOENT;
+		}
+	}
+}
+
+int ip_received_error_msg( int ip_phone, 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_ref		netif;
+	measured_string_t	address;
+	ip_route_ref		route;
+	ip_header_ref		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_ref )( data + offset );
+			// destination host unreachable?
+			if(( type == ICMP_DEST_UNREACH ) && ( code == ICMP_HOST_UNREACH )){
+				fibril_rwlock_read_lock( & ip_globals.netifs_lock );
+				netif = ip_netifs_find( & ip_globals.netifs, device_id );
+				if( netif && netif->arp ){
+					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 = ( char * ) & header->destination_address;
+						address.length = CONVERT_SIZE( uint8_t, char, sizeof( header->destination_address ));
+						arp_clear_address_req( netif->arp->phone, 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 );
+}
+
+int ip_deliver_local( device_id_t device_id, packet_t packet, ip_header_ref header, services_t error ){
+	ERROR_DECLARE;
+
+	ip_proto_ref	proto;
+	int				phone;
+	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;
+//	struct sockaddr_in	src_in6;
+//	struct sockaddr_in	dest_in6;
+	socklen_t		addrlen;
+
+	if(( header->flags & IPFLAG_MORE_FRAGMENTS ) || IP_FRAGMENT_OFFSET( header )){
+		// TODO fragmented
+		return ENOTSUP;
+	}else{
+		switch( header->version ){
+			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;
+/*			case IPv6VERSION:
+				addrlen = sizeof( src_in6 );
+				bzero( & src_in6, addrlen );
+				src_in6.sin6_family = AF_INET6;
+				memcpy( & dest_in6, & src_in6, addrlen );
+				memcpy( & src_in6.sin6_addr.s6_addr, );
+				memcpy( & dest_in6.sin6_addr.s6_addr, );
+				src = ( struct sockaddr * ) & src_in;
+				dest = ( struct sockaddr * ) & dest_in;
+				break;
+*/			default:
+				return ip_release_and_return( packet, EAFNOSUPPORT );
+		}
+		if( ERROR_OCCURRED( packet_set_addr( packet, ( uint8_t * ) src, ( uint8_t * ) dest, addrlen ))){
+			return ip_release_and_return( packet, ERROR_CODE );
+		}
+		// trim padding if present
+		if(( ! error ) && ( IP_TOTAL_LENGTH( header ) < packet_get_data_length( packet ))){
+			if( ERROR_OCCURRED( packet_trim( packet, 0, packet_get_data_length( packet ) - IP_TOTAL_LENGTH( header )))){
+				return ip_release_and_return( packet, ERROR_CODE );
+			}
+		}
+		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 );
+			phone = ip_prepare_icmp_and_get_phone( error, packet, header );
+			if( phone >= 0 ){
+				// unreachable ICMP
+				icmp_destination_unreachable_msg( phone, 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 );
+			ERROR_CODE = received_msg( device_id, packet, service, error );
+		}else{
+			ERROR_CODE = tl_received_msg( proto->phone, device_id, packet, proto->service, error );
+			fibril_rwlock_read_unlock( & ip_globals.protos_lock );
+		}
+		return ERROR_CODE;
+	}
+}
+
+in_addr_t ip_get_destination( ip_header_ref header ){
+	in_addr_t	destination;
+
+	// TODO search set ipopt route?
+	destination.s_addr = header->destination_address;
+	return destination;
+}
+
+int ip_prepare_icmp( packet_t packet, ip_header_ref header ){
+	packet_t	next;
+	struct sockaddr *	dest;
+	struct sockaddr_in	dest_in;
+//	struct sockaddr_in	dest_in6;
+	socklen_t		addrlen;
+
+	// detach the first packet and release the others
+	next = pq_detach( packet );
+	if( next ){
+		pq_release( ip_globals.net_phone, packet_get_id( next ));
+	}
+	if( ! header ){
+		if( packet_get_data_length( packet ) <= sizeof( ip_header_t )) return ENOMEM;
+		// get header
+		header = ( ip_header_ref ) packet_get_data( packet );
+		if( ! header ) return EINVAL;
+	}
+	// only for the first fragment
+	if( IP_FRAGMENT_OFFSET( header )) return EINVAL;
+	// set the destination address
+	switch( header->version ){
+		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;
+/*		case IPv6VERSION:
+			addrlen = sizeof( dest_in6 );
+			bzero( & dest_in6, addrlen );
+			dest_in6.sin6_family = AF_INET6;
+			memcpy( & dest_in6.sin6_addr.s6_addr, );
+			dest = ( struct sockaddr * ) & dest_in;
+			break;
+*/		default:
+			return EAFNOSUPPORT;
+	}
+	return packet_set_addr( packet, NULL, ( uint8_t * ) dest, addrlen );
+}
+
+int ip_get_icmp_phone( void ){
+	ip_proto_ref	proto;
+	int				phone;
+
+	fibril_rwlock_read_lock( & ip_globals.protos_lock );
+	proto = ip_protos_find( & ip_globals.protos, IPPROTO_ICMP );
+	phone = proto ? proto->phone : ENOENT;
+	fibril_rwlock_read_unlock( & ip_globals.protos_lock );
+	return phone;
+}
+
+int ip_prepare_icmp_and_get_phone( services_t error, packet_t packet, ip_header_ref header ){
+	int	phone;
+
+	phone = ip_get_icmp_phone();
+	if( error || ( phone < 0 ) || ip_prepare_icmp( packet, header )){
+		return ip_release_and_return( packet, EINVAL );
+	}
+	return phone;
+}
+
+int	ip_release_and_return( packet_t packet, int result ){
+	pq_release( ip_globals.net_phone, packet_get_id( packet ));
+	return result;
+}
+
+int ip_get_route_req( int ip_phone, ip_protocol_t protocol, const struct sockaddr * destination, socklen_t addrlen, device_id_t * device_id, ip_pseudo_header_ref * header, size_t * headerlen ){
+	struct sockaddr_in *	address_in;
+//	struct sockaddr_in6 *	address_in6;
+	in_addr_t *				dest;
+	in_addr_t *				src;
+	ip_route_ref			route;
+	ipv4_pseudo_header_ref	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;
+		// TODO IPv6
+/*		case AF_INET6:
+			if( addrlen != sizeof( struct sockaddr_in6 )) return EINVAL;
+			address_in6 = ( struct sockaddr_in6 * ) dest;
+			address_in6.sin6_addr.s6_addr;
+*/		default:
+			return EAFNOSUPPORT;
+	}
+	fibril_rwlock_read_lock( & ip_globals.lock );
+	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_ref ) 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 = ( ip_pseudo_header_ref ) header_in;
+	return EOK;
+}
+
+/** @}
+ */
Index: uspace/srv/net/il/ip/ip.h
===================================================================
--- uspace/srv/net/il/ip/ip.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/il/ip/ip.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,226 @@
+/*
+ * 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 <fibril_synch.h>
+
+#include <ipc/ipc.h>
+#include <ipc/services.h>
+
+#include "../../include/device.h"
+#include "../../include/inet.h"
+#include "../../include/ip_interface.h"
+
+#include "../../structures/int_map.h"
+#include "../../structures/generic_field.h"
+#include "../../structures/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 network interface specific data pointer.
+ *  @see ip_netif
+ */
+typedef ip_netif_t *	ip_netif_ref;
+
+/** Type definition of the IP protocol specific data.
+ *  @see ip_proto
+ */
+typedef struct ip_proto	ip_proto_t;
+
+/** Type definition of the IP protocol specific data pointer.
+ *  @see ip_proto
+ */
+typedef ip_proto_t *	ip_proto_ref;
+
+/** Type definition of the IP route specific data.
+ *  @see ip_route
+ */
+typedef struct ip_route	ip_route_t;
+
+/** Type definition of the IP route specific data pointer.
+ *  @see ip_route
+ */
+typedef ip_route_t *	ip_route_ref;
+
+/** 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{
+	/** Device identifier.
+	 */
+	device_id_t	device_id;
+	/** Netif module service.
+	 */
+	services_t	service;
+	/** Netif module phone.
+	 */
+	int			phone;
+	/** ARP module.
+	 *  Assigned if using ARP.
+	 */
+	module_ref	arp;
+	/** IP version.
+	 */
+	int			ipv;
+	/** Indicates whether using DHCP.
+	 */
+	int			dhcp;
+	/** Indicates whether IP routing is enabled.
+	 */
+	int			routing;
+	/** Device state.
+	 */
+	device_state_t	state;
+	/** Broadcast address.
+	 */
+	in_addr_t	broadcast;
+	/** Routing table.
+	 */
+	ip_routes_t	routes;
+	/** Reserved packet prefix length.
+	 */
+	size_t				prefix;
+	/** Maximal packet content length.
+	 */
+	size_t				content;
+	/** Reserved packet suffix length.
+	 */
+	size_t				suffix;
+	/** Packet address length.
+	 *  The hardware address length is used.
+	 */
+	size_t				addr_len;
+};
+
+/** IP protocol specific data.
+ */
+struct ip_proto{
+	/** Protocol number.
+	 */
+	int	protocol;
+	/** Protocol module service.
+	 */
+	services_t service;
+	/** Protocol module phone.
+	 */
+	int	phone;
+	/** Protocol packet receiving function.
+	 */
+	tl_received_msg_t received_msg;
+};
+
+/** IP route specific data.
+ */
+struct ip_route{
+	/** Target address.
+	 */
+	in_addr_t		address;
+	/** Target network mask.
+	 */
+	in_addr_t		netmask;
+	/** Gateway.
+	 */
+	in_addr_t		gateway;
+	/** Parent netif.
+	 */
+	ip_netif_ref	netif;
+};
+
+/** IP global data.
+ */
+struct	ip_globals{
+	/** Networking module phone.
+	 */
+	int			net_phone;
+	/** Registered network interfaces.
+	 */
+	ip_netifs_t	netifs;
+	/** Netifs safeyt lock.
+	 */
+	fibril_rwlock_t	netifs_lock;
+	/** Registered protocols.
+	 */
+	ip_protos_t	protos;
+	/** Protocols safety lock.
+	 */
+	fibril_rwlock_t	protos_lock;
+	/** Default gateway.
+	 */
+	ip_route_t	gateway;
+	/** Known support modules.
+	 */
+	modules_t	modules;
+	/** Default client connection function for support modules.
+	 */
+	async_client_conn_t client_connection;
+	/** Packet counter.
+	 */
+	uint16_t	packet_counter;
+	/** Safety lock.
+	 */
+	fibril_rwlock_t	lock;
+};
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/il/ip/ip_client.c
===================================================================
--- uspace/srv/net/il/ip/ip_client.c	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/il/ip/ip_client.c	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,148 @@
+/*
+ * 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 client interface implementation.
+ *  @see ip_client.h
+ */
+
+#include <errno.h>
+
+#include <sys/types.h>
+
+#include "../../include/ip_client.h"
+#include "../../include/socket_errno.h"
+
+#include "../../structures/packet/packet.h"
+#include "../../structures/packet/packet_client.h"
+
+#include "ip_header.h"
+
+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_ref	header;
+	uint8_t *		data;
+	size_t			padding;
+
+	padding =  ipopt_length % 4;
+	if( padding ){
+		padding = 4 - padding;
+		ipopt_length += padding;
+	}
+	data = ( uint8_t * ) packet_prefix( packet, sizeof( ip_header_t ) + padding );
+	if( ! data ) return ENOMEM;
+	while( padding -- ) data[ sizeof( ip_header_t ) + padding ] = IPOPT_NOOP;
+	header = ( ip_header_ref ) data;
+	header->header_length = IP_COMPUTE_HEADER_LENGTH( sizeof( ip_header_t ) + ipopt_length );
+	header->ttl = ( ttl ? ttl : IPDEFTTL ); //((( ttl ) <= MAXTTL ) ? ttl : MAXTTL ) : IPDEFTTL;
+	header->tos = tos;
+	header->protocol = protocol;
+	if( dont_fragment ) header->flags = IPFLAG_DONT_FRAGMENT;
+	return EOK;
+}
+
+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_ref	header;
+
+	header = ( ip_header_ref ) 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 = header->flags & 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 );
+	}
+}
+
+size_t ip_client_header_length( packet_t packet ){
+	ip_header_ref	header;
+
+	header = ( ip_header_ref ) packet_get_data( packet );
+	if(( ! header )
+	|| ( packet_get_data_length( packet ) < sizeof( ip_header_t ))){
+		return 0;
+	}
+	return IP_HEADER_LENGTH( header );
+}
+
+int ip_client_set_pseudo_header_data_length( ip_pseudo_header_ref header, size_t headerlen, size_t data_length ){
+	ipv4_pseudo_header_ref	header_in;
+
+	if( ! header ) return EBADMEM;
+	if( headerlen == sizeof( ipv4_pseudo_header_t )){
+		header_in = ( ipv4_pseudo_header_ref ) header;
+		header_in->data_length = htons( data_length );
+		return EOK;
+	}else{
+		return EINVAL;
+	}
+}
+
+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, ip_pseudo_header_ref * header, size_t * headerlen ){
+	ipv4_pseudo_header_ref	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_ref ) 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 = ( ip_pseudo_header_ref ) header_in;
+			return EOK;
+		// TODO IPv6
+/*		case AF_INET6:
+			if( addrlen != sizeof( struct sockaddr_in6 )) return EINVAL;
+			address_in6 = ( struct sockaddr_in6 * ) addr;
+			return EOK;
+*/		default:
+			return EAFNOSUPPORT;
+	}
+}
+
+/** @}
+ */
Index: uspace/srv/net/il/ip/ip_header.h
===================================================================
--- uspace/srv/net/il/ip/ip_header.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/il/ip/ip_header.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,282 @@
+/*
+ * 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 header and options definitions.
+ *  Based on the RFC~791.
+ */
+
+#ifndef __NET_IP_HEADER_H__
+#define __NET_IP_HEADER_H__
+
+#include <byteorder.h>
+#include <sys/types.h>
+
+/** Returns the actual IP header length in bytes.
+ *  @param[in] header The IP packet header.
+ */
+#define IP_HEADER_LENGTH( header )		(( header )->header_length * 4u )
+
+/** 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 actual IP packet total length.
+ *  @param[in] header The IP packet header.
+ */
+#define IP_TOTAL_LENGTH( header )		ntohs(( header )->total_length )
+
+/** 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 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 fragment offest.
+ *  @param[in] header The IP packet header.
+ */
+#define IP_FRAGMENT_OFFSET( header ) (((( header )->fragment_offset_high << 8 ) + ( header )->fragment_offset_low ) * 8u )
+
+/** 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 )
+
+/** Type definition of the internet header.
+ *  @see ip_header
+ */
+typedef struct ip_header	ip_header_t;
+
+/** Type definition of the internet header pointer.
+ *  @see ip_header
+ */
+typedef ip_header_t *		ip_header_ref;
+
+/** Internet header.
+ *  The variable options should be included after the header itself and indicated by the increased header length value.
+ */
+struct ip_header{
+#ifdef ARCH_IS_BIG_ENDIAN
+	/** The Version field indicates the format of the internet header.
+	 */
+	uint8_t		version:4;
+	/** Internet Header Length is the length of the internet header in 32~bit words, and thus points to the beginning of the data.
+	 *  Note that the minimum value for a~correct header is~5.
+	 */
+	uint8_t		header_length:4;
+#else
+	/** Internet Header Length is the length of the internet header in 32~bit words, and thus points to the beginning of the data.
+	 *  Note that the minimum value for a~correct header is~5.
+	 */
+	uint8_t		header_length:4;
+	/** The Version field indicates the format of the internet header.
+	 */
+	uint8_t		version:4;
+#endif
+	/** The Type of Service provides an indication of the abstract parameters of the quality of service desired.
+	 *  These parameters are to be used to guide the selection of the actual service parameters when transmitting a~datagram through a~particular network.
+	 *  Several networks offer service precedence, which somehow treats high precedence traffic as more important than other traffic (generally by accepting only traffic above a~certain precedence at time of high load).
+	 *  The major choice is a~three way tradeoff between low-delay, high-reliability, and high-throughput.
+	 */
+	uint8_t		tos;
+	/** Total Length is the length of the datagram, measured in octets, including internet header and data.
+	 *  This field allows the length of a~datagram to be up to 65,535~octets.
+	 */
+	uint16_t	total_length;
+	/** An identifying value assigned by the sender to aid in assembling the fragments of a~datagram.
+	 */
+	uint16_t	identification;
+#ifdef ARCH_IS_BIG_ENDIAN
+	/** Various control flags.
+	 */
+	uint8_t	flags:3;
+	/** This field indicates where in the datagram this fragment belongs.
+	 *  High bits.
+	 */
+	uint8_t	fragment_offset_high:5;
+#else
+	/** This field indicates where in the datagram this fragment belongs.
+	 *  High bits.
+	 */
+	uint8_t	fragment_offset_high:5;
+	/** Various control flags.
+	 */
+	uint8_t	flags:3;
+#endif
+	/** This field indicates where in the datagram this fragment belongs.
+	 *  Low bits.
+	 */
+	uint8_t	fragment_offset_low;
+	/** This field indicates the maximum time the datagram is allowed to remain in the internet system.
+	 *  If this field contains the value zero, then the datagram must be destroyed.
+	 *  This field is modified in internet header processing.
+	 *  The time is measured in units of seconds, but since every module that processes a~datagram must decrease the TTL by at least one even if it process the datagram in less than a~second, the TTL must be thought of only as an upper bound on the time a~datagram may exist.
+	 *  The intention is to cause undeliverable datagrams to be discarded, and to bound the maximum datagram lifetime.
+	 */
+	uint8_t		ttl;
+	/** This field indicates the next level protocol used in the data portion of the internet datagram.
+	 */
+	uint8_t		protocol;
+	/** A checksum of the header only.
+	 *  Since some header fields change (e.g., time to live), this is recomputed and verified at each point that the internet header is processed.
+	 *  The checksum algorithm is: The checksum field is the 16~bit one's complement of the one's complement sum of all 16~bit words in the header.
+	 *  For purposes of computing the checksum, the value of the checksum field is zero.
+	 */
+	uint16_t	header_checksum;
+	/** The source address.
+	 */
+	uint32_t	source_address;
+	/** The destination address.
+	 */
+	uint32_t	destination_address;
+} __attribute__ ((packed));
+
+/** Type definition of the internet option header.
+ *  @see ip_header
+ */
+typedef struct ip_option	ip_option_t;
+
+/** Type definition of the internet option header pointer.
+ *  @see ip_header
+ */
+typedef ip_option_t *		ip_option_ref;
+
+/** Internet option header.
+ *  Only type field is always valid.
+ *  Other fields' validity depends on the option type.
+ */
+struct ip_option{
+	/** A single octet of option-type.
+	 */
+	uint8_t		type;
+	/** An option length octet.
+	 */
+	uint8_t		length;
+	/** A~pointer.
+	 */
+	uint8_t		pointer;
+#ifdef ARCH_IS_BIG_ENDIAN
+	/** The number of IP modules that cannot register timestamps due to lack of space.
+	 */
+	uint8_t	overflow:4;
+	/** Various internet timestamp control flags.
+	 */
+	uint8_t	flags:4;
+#else
+	/** Various internet timestamp control flags.
+	 */
+	uint8_t	flags:4;
+	/** The number of IP modules that cannot register timestamps due to lack of space.
+	 */
+	uint8_t	overflow:4;
+#endif
+} __attribute__ ((packed));
+
+/** @name IP flags definitions
+ */
+/*@{*/
+
+/** Fragment flag field shift.
+ */
+#define IPFLAG_FRAGMENT_SHIFT		1
+
+/** Fragmented flag field shift.
+ */
+#define IPFLAG_FRAGMENTED_SHIFT		0
+
+/** May fragment flag value.
+ *  Allows the packet fragmentation.
+ */
+#define IPFLAG_MAY_FRAGMENT			( 0x0 << IPFLAG_FRAGMENT_SHIFT )
+
+/** 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 )
+
+/** More fragments flag value.
+ *  Indicates that more packet fragments follow.
+ */
+#define IPFLAG_MORE_FRAGMENTS		( 0x1 << IPFLAG_FRAGMENTED_SHIFT )
+
+/*@}*/
+
+/** Type definition of the internet version 4 pseudo header.
+ *  @see ipv4_pseudo_header
+ */
+typedef struct ipv4_pseudo_header	ipv4_pseudo_header_t;
+
+/** Type definition of the internet version 4 pseudo header pointer.
+ *  @see ipv4_pseudo_header
+ */
+typedef ipv4_pseudo_header_t *		ipv4_pseudo_header_ref;
+
+/** Internet version 4 pseudo header.
+ */
+struct ipv4_pseudo_header{
+	/** The source address.
+	 */
+	uint32_t	source_address;
+	/** The destination address.
+	 */
+	uint32_t	destination_address;
+	/** Reserved byte.
+	 *  Must be zero.
+	 */
+	uint8_t		reserved;
+	/** This field indicates the next level protocol used in the data portion of the internet datagram.
+	 */
+	uint8_t		protocol;
+	/** Data length is the length of the datagram, measured in octets.
+	 */
+	uint16_t	data_length;
+} __attribute__ ((packed));
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/il/ip/ip_messages.h
===================================================================
--- uspace/srv/net/il/ip/ip_messages.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/il/ip/ip_messages.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,101 @@
+/*
+ * 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 messages.
+ *  @see ip_interface.h
+ */
+
+#ifndef __NET_IP_MESSAGES_H__
+#define __NET_IP_MESSAGES_H__
+
+#include <ipc/ipc.h>
+
+#include "../../include/in.h"
+#include "../../include/ip_codes.h"
+
+/** IP module messages.
+ */
+typedef enum{
+	/** Adds the routing entry.
+	 *  @see ip_add_route()
+	 */
+	NET_IP_ADD_ROUTE = NET_IP_FIRST,
+	/** Sets the default gateway.
+	 *  @see ip_set_default_gateway()
+	 */
+	NET_IP_SET_GATEWAY,
+	/** Processes the received error notification.
+	 *  @see ip_received_error_msg()
+	 */
+	NET_IP_RECEIVED_ERROR,
+	/** Gets the actual route information.
+	 *  @see ip_get_route()
+	 */
+	NET_IP_GET_ROUTE
+} ip_messages;
+
+/** @name IP specific message parameters definitions
+ */
+/*@{*/
+
+/** Returns the gateway message parameter.
+ *  @param[in] call The message call structure.
+ */
+#define IP_GET_GATEWAY( call )		({ in_addr_t addr; addr.s_addr = IPC_GET_ARG2( * call ); addr; })
+
+/** Returns the address message parameter.
+ *  @param[in] call The message call structure.
+ */
+#define IP_GET_ADDRESS( call )		({ in_addr_t addr; addr.s_addr = IPC_GET_ARG3( * call ); addr; })
+
+/** Returns the network mask message parameter.
+ *  @param[in] call The message call structure.
+ */
+#define IP_GET_NETMASK( call )		({ in_addr_t addr; addr.s_addr = IPC_GET_ARG4( * call ); addr; })
+
+/** Returns the protocol message parameter.
+ *  @param[in] call The message call structure.
+ */
+#define IP_GET_PROTOCOL( call )		(( ip_protocol_t ) IPC_GET_ARG1( * call ))
+
+/** Sets the header length in the message answer.
+ *  @param[out] answer The message answer structure.
+ */
+#define IP_SET_HEADERLEN( answer )	(( size_t * ) & IPC_GET_ARG2( * answer ))
+
+/*@}*/
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/il/ip/ip_module.c
===================================================================
--- uspace/srv/net/il/ip/ip_module.c	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/il/ip/ip_module.c	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,117 @@
+/*
+ * 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 standalone module implementation.
+ *  Contains skeleton module functions mapping.
+ *  The functions are used by the module skeleton as module specific entry points.
+ *  @see module.c
+ */
+
+#include <async.h>
+#include <stdio.h>
+
+#include <ipc/ipc.h>
+#include <ipc/services.h>
+
+#include "../../err.h"
+#include "../../modules.h"
+
+#include "../../include/net_interface.h"
+
+#include "../../structures/packet/packet.h"
+
+#include "ip.h"
+#include "ip_module.h"
+
+/** IP module name.
+ */
+#define NAME	"IP protocol"
+
+/** Prints the module name.
+ *  @see NAME
+ */
+void	module_print_name( void );
+
+/** Starts the IP module.
+ *  Initializes the client connection serving function, initializes the module, registers the module service and starts the async manager, processing IPC messages in an infinite loop.
+ *  @param[in] client_connection The client connection processing function. The module skeleton propagates its own one.
+ *  @returns EOK on successful module termination.
+ *  @returns Other error codes as defined for the ip_initialize() function.
+ *  @returns Other error codes as defined for the REGISTER_ME() macro function.
+ */
+int	module_start( async_client_conn_t client_connection );
+
+/** 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.
+ *  @returns EOK on success.
+ *  @returns Other error codes as defined for the ip_message() function.
+ */
+int	module_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count );
+
+/** IP module global data.
+ */
+extern ip_globals_t	ip_globals;
+
+void module_print_name( void ){
+	printf( "%s", NAME );
+}
+
+int module_start( async_client_conn_t client_connection ){
+	ERROR_DECLARE;
+
+	ipcarg_t	phonehash;
+
+	async_set_client_connection( client_connection );
+	ip_globals.net_phone = net_connect_module( SERVICE_NETWORKING );
+	ERROR_PROPAGATE( pm_init());
+	if( ERROR_OCCURRED( ip_initialize( client_connection ))
+	|| ERROR_OCCURRED( REGISTER_ME( SERVICE_IP, & phonehash ))){
+		pm_destroy();
+		return ERROR_CODE;
+	}
+
+	async_manager();
+
+	pm_destroy();
+	return EOK;
+}
+
+int	module_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){
+	return ip_message( callid, call, answer, answer_count );
+}
+
+/** @}
+ */
Index: uspace/srv/net/il/ip/ip_module.h
===================================================================
--- uspace/srv/net/il/ip/ip_module.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/il/ip/ip_module.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,66 @@
+/*
+ * 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 functions.
+ *  The functions are used as IP module entry points.
+ */
+
+#ifndef __NET_IP_MODULE_H__
+#define __NET_IP_MODULE_H__
+
+#include <ipc/ipc.h>
+
+/** Initializes the IP module.
+ *  @param[in] client_connection The client connection processing function. The module skeleton propagates its own one.
+ *  @returns EOK on success.
+ *  @returns ENOMEM if there is not enough memory left.
+ */
+int	ip_initialize( async_client_conn_t client_connection );
+
+/** 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.
+ *  @returns EOK on success.
+ *  @returns ENOTSUP if the message is not known.
+ *  @see ip_interface.h
+ *  @see il_interface.h
+ *  @see IS_NET_IP_MESSAGE()
+ */
+int	ip_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count );
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/il/ip/ip_remote.c
===================================================================
--- uspace/srv/net/il/ip/ip_remote.c	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/il/ip/ip_remote.c	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,115 @@
+/*
+ * 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 interface implementation for standalone remote modules.
+ *  @see ip_interface.h
+ *  @see il_interface.h
+ */
+
+#include <ipc/services.h>
+
+#include "../../messages.h"
+#include "../../modules.h"
+
+#include "../../include/device.h"
+#include "../../include/inet.h"
+#include "../../include/ip_interface.h"
+
+#include "../../structures/packet/packet_client.h"
+
+#include "../il_messages.h"
+
+#include "ip_messages.h"
+
+int ip_device_req( int ip_phone, device_id_t device_id, services_t service ){
+	return generic_device_req( ip_phone, NET_IL_DEVICE, device_id, 0, service );
+}
+
+int ip_send_msg( int ip_phone, device_id_t device_id, packet_t packet, services_t sender, services_t error ){
+	return generic_send_msg( ip_phone, NET_IL_SEND, device_id, packet_get_id( packet ), sender, error );
+}
+
+int ip_connect_module( services_t service ){
+	return connect_to_service( SERVICE_IP );
+}
+
+int ip_add_route_req( int ip_phone, device_id_t device_id, in_addr_t address, in_addr_t netmask, in_addr_t gateway ){
+	return ( int ) async_req_4_0( ip_phone, NET_IP_ADD_ROUTE, ( ipcarg_t ) device_id, ( ipcarg_t ) gateway.s_addr, ( ipcarg_t ) address.s_addr, ( ipcarg_t ) netmask.s_addr );
+}
+
+int ip_set_gateway_req( int ip_phone, device_id_t device_id, in_addr_t gateway ){
+	return ( int ) async_req_2_0( ip_phone, NET_IP_SET_GATEWAY, ( ipcarg_t ) device_id, ( ipcarg_t ) gateway.s_addr );
+}
+
+int ip_packet_size_req( int ip_phone, device_id_t device_id, size_t * addr_len, size_t * prefix, size_t * content, size_t * suffix ){
+	return generic_packet_size_req( ip_phone, NET_IL_PACKET_SPACE, device_id, addr_len, prefix, content, suffix );
+}
+
+int ip_bind_service( services_t service, int protocol, services_t me, async_client_conn_t receiver, tl_received_msg_t tl_received_msg ){
+	return ( int ) bind_service( service, ( ipcarg_t ) protocol, me, service, receiver );
+}
+
+int ip_received_error_msg( int ip_phone, device_id_t device_id, packet_t packet, services_t target, services_t error ){
+	return generic_received_msg( ip_phone, NET_IP_RECEIVED_ERROR, device_id, packet_get_id( packet ), target, error );
+}
+
+int ip_get_route_req( int ip_phone, ip_protocol_t protocol, const struct sockaddr * destination, socklen_t addrlen, device_id_t * device_id, ip_pseudo_header_ref * header, size_t * headerlen ){
+	aid_t			message_id;
+	ipcarg_t		result;
+	ipc_call_t		answer;
+
+	if( !( destination && ( addrlen > 0 ))) return EINVAL;
+	if( !( device_id && header && headerlen )) return EBADMEM;
+	* header = NULL;
+	message_id = async_send_1( ip_phone, NET_IP_GET_ROUTE, ( ipcarg_t ) protocol, & answer );
+	if(( async_data_write_start( ip_phone, destination, addrlen ) == EOK )
+	&& ( async_data_read_start( ip_phone, headerlen, sizeof( * headerlen )) == EOK )
+	&& ( * headerlen > 0 )){
+		* header = ( ip_pseudo_header_ref ) malloc( * headerlen );
+		if( * header ){
+			if( async_data_read_start( ip_phone, * header, * headerlen ) != EOK ){
+				free( * header );
+			}
+		}
+	}
+	async_wait_for( message_id, & result );
+	if(( result != EOK ) && ( * header )){
+		free( * header );
+	}else{
+		* device_id = IPC_GET_DEVICE( & answer );
+	}
+	return ( int ) result;
+}
+
+/** @}
+ */
Index: uspace/srv/net/include/arp_interface.h
===================================================================
--- uspace/srv/net/include/arp_interface.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/include/arp_interface.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,129 @@
+/*
+ * 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 interface.
+ *  The same interface is used for standalone remote modules as well as for bundle modules.
+ *  The standalone remote modules have to be compiled with the arp_remote.c source file.
+ *  The bundle modules with the arp.c source file.
+ */
+
+#ifndef __NET_ARP_INTERFACE_H__
+#define __NET_ARP_INTERFACE_H__
+
+#include "../structures/measured_strings.h"
+
+#include "device.h"
+
+/** @name ARP module interface
+ *  This interface is used by other modules.
+ */
+/*@{*/
+
+/** Registers the new device and the requesting protocol service.
+ *  Connects to the network interface layer service.
+ *  Determines the device broadcast address, its address lengths and packet size.
+ *  @param[in] arp_phone The ARP module phone used for (semi)remote calls.
+ *  @param[in] device_id The new device identifier.
+ *  @param[in] protocol The requesting protocol service.
+ *  @param[in] netif The underlying device network interface layer service.
+ *  @param[in] address The local requesting protocol address of the device.
+ *  @returns EOK on success.
+ *  @returns EEXIST if the device is already used.
+ *  @returns ENOMEM if there is not enough memory left.
+ *  @returns ENOENT if the network interface service is not known.
+ *  @returns EREFUSED if the network interface service is not responding.
+ *  @returns Other error codes as defined for the nil_packet_get_size() function.
+ *  @returns Other error codes as defined for the nil_get_addr() function.
+ *  @returns Other error codes as defined for the nil_get_broadcast_addr() function.
+ */
+int	arp_device_req( int arp_phone, device_id_t device_id, services_t protocol, services_t netif, measured_string_ref address );
+
+/** Translates the given protocol address to the network interface address.
+ *  Broadcasts the ARP request if the mapping is not found.
+ *  Allocates and returns the needed memory block as the data parameter.
+ *  @param[in] arp_phone The ARP module phone used for (semi)remote calls.
+ *  @param[in] device_id The device identifier.
+ *  @param[in] protocol The requesting protocol service.
+ *  @param[in] address The local requesting protocol address.
+ *  @param[out] translation The translation of the local protocol address.
+ *  @param[out] data The allocated raw translation data container.
+ *  @returns EOK on success.
+ *  @returns EINVAL if the address parameter is NULL.
+ *  @returns EBADMEM if the translation or the data parameters are NULL.
+ *  @returns ENOENT if the mapping is not found.
+ */
+int	arp_translate_req( int arp_phone, device_id_t device_id, services_t protocol, measured_string_ref address, measured_string_ref * translation, char ** data );
+
+/** Clears the device cache.
+ *  @param[in] arp_phone The ARP module phone used for (semi)remote calls.
+ *  @param[in] device_id The device identifier.
+ *  @returns EOK on success.
+ *  @returns ENOENT if the device is not found.
+ */
+int	arp_clear_device_req( int arp_phone, device_id_t device_id );
+
+/** Clears the given protocol address from the cache.
+ *  @param[in] arp_phone The ARP module phone used for (semi)remote calls.
+ *  @param[in] device_id The device identifier.
+ *  @param[in] protocol The requesting protocol service.
+ *  @param[in] address The protocol address to be cleared.
+ *  @returns EOK on success.
+ *  @returns ENOENT if the mapping is not found.
+ */
+int	arp_clear_address_req( int arp_phone, device_id_t device_id, services_t protocol, measured_string_ref address );
+
+/** Cleans the cache.
+ *  @param[in] arp_phone The ARP module phone used for (semi)remote calls.
+ *  @returns EOK on success.
+ */
+int	arp_clean_cache_req( int arp_phone );
+
+/** Connects to the ARP module.
+ *  @param service The ARP module service. Ignored parameter.
+ *  @returns The ARP module phone on success.
+ *  @returns 0 if called by the bundle module.
+ */
+int	arp_connect_module( services_t service );
+
+/** Returns the ARP task identifier.
+ *  @returns The current task identifier if called by the bundle module.
+ *  @returns 0 if called by the remote module.
+ */
+task_id_t	arp_task_get_id( void );
+
+/*@}*/
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/include/byteorder.h
===================================================================
--- uspace/srv/net/include/byteorder.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/include/byteorder.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup net
+ *  @{
+ */
+
+/** @file
+ *  Host - network byte order manipulation functions.
+ */
+
+#ifndef __NET_BYTEORDER_H__
+#define __NET_BYTEORDER_H__
+
+#include <byteorder.h>
+
+#include <sys/types.h>
+
+#ifdef ARCH_IS_BIG_ENDIAN
+
+// Already in the network byte order.
+
+	/** Converts the given short number ( 16 bit ) from the host byte order to the network byte order ( big endian ).
+	 *  @param[in] number The number in the host byte order to be converted.
+	 *  @returns The number in the network byte order.
+	 */
+	#define htons( number )		( number )
+
+	/** Converts the given long number ( 32 bit ) from the host byte order to the network byte order ( big endian ).
+	 *  @param[in] number The number in the host byte order to be converted.
+	 *  @returns The number in the network byte order.
+	 */
+	#define htonl( number )		( number )
+
+	/** Converts the given short number ( 16 bit ) from the network byte order ( big endian ) to the host byte order.
+	 *  @param[in] number The number in the network byte order to be converted.
+	 *  @returns The number in the host byte order.
+	 */
+	#define ntohs( number ) 	( number )
+
+	/** Converts the given long number ( 32 bit ) from the network byte order ( big endian ) to the host byte order.
+	 *  @param[in] number The number in the network byte order to be converted.
+	 *  @returns The number in the host byte order.
+	 */
+	#define ntohl( number )		( number )
+
+#else
+
+// Has to be swapped.
+
+	/** Converts the given short number ( 16 bit ) from the host byte order to the network byte order ( big endian ).
+	 *  @param[in] number The number in the host byte order to be converted.
+	 *  @returns The number in the network byte order.
+	 */
+	#define htons( number )		uint16_t_byteorder_swap(( uint16_t )( number ))
+
+	/** Converts the given long number ( 32 bit ) from the host byte order to the network byte order ( big endian ).
+	 *  @param[in] number The number in the host byte order to be converted.
+	 *  @returns The number in the network byte order.
+	 */
+	#define htonl( number )		uint32_t_byteorder_swap( number )
+
+	/** Converts the given short number ( 16 bit ) from the network byte order ( big endian ) to the host byte order.
+	 *  @param[in] number The number in the network byte order to be converted.
+	 *  @returns The number in the host byte order.
+	 */
+	#define ntohs( number ) 	uint16_t_byteorder_swap(( uint16_t )( number ))
+
+	/** Converts the given long number ( 32 bit ) from the network byte order ( big endian ) to the host byte order.
+	 *  @param[in] number The number in the network byte order to be converted.
+	 *  @returns The number in the host byte order.
+	 */
+	#define ntohl( number )		uint32_t_byteorder_swap( number )
+
+#endif
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/include/checksum.h
===================================================================
--- uspace/srv/net/include/checksum.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/include/checksum.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup net
+ *  @{
+ */
+
+/** @file
+ *  General CRC and checksum computation.
+ */
+
+#ifndef __NET_CHECKSUM_H__
+#define __NET_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
+
+/**	Computes CRC32 value.
+ *  @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.
+ *  @returns The computed CRC32 of the length bits of the data.
+ */
+#ifdef ARCH_IS_BIG_ENDIAN
+	#define compute_crc32( seed, data, length )	compute_crc32_be( seed, ( uint8_t * ) data, length )
+#else
+	#define compute_crc32( seed, data, length )	compute_crc32_le( seed, ( uint8_t * ) data, length )
+#endif
+
+/**	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.
+ *  @returns The computed CRC32 of the length bits of the data.
+ */
+uint32_t	compute_crc32_le( uint32_t seed, uint8_t * data, size_t length );
+
+/**	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.
+ *  @returns The computed CRC32 of the length bits of the data.
+ */
+uint32_t	compute_crc32_be( uint32_t seed, uint8_t * data, size_t length );
+
+/** 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.
+ *  @returns The computed checksum of the length bytes of the data.
+ */
+uint32_t	compute_checksum( uint32_t seed, uint8_t * data, size_t length );
+
+/** Compacts the computed checksum to the 16 bit number adding the carries.
+ *  @param[in] sum Computed checksum.
+ *  @returns Compacted computed checksum to the 16 bits.
+ */
+uint16_t	compact_checksum( uint32_t sum );
+
+/** Returns or flips the checksum if zero.
+ *  @param[in] checksum The computed checksum.
+ *  @returns The internet protocol header checksum.
+ *  @returns 0xFFFF if the computed checksum is zero.
+ */
+uint16_t	flip_checksum( uint16_t checksum );
+
+/** Computes 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.
+ *  The zero (0) value will be returned in this case if valid.
+ *  @param[in] data The header data.
+ *  @param[in] length The header length in bytes.
+ *  @returns The internet protocol header checksum.
+ *  @returns 0xFFFF if the computed checksum is zero.
+ */
+uint16_t ip_checksum( uint8_t * data, size_t length );
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/include/device.h
===================================================================
--- uspace/srv/net/include/device.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/include/device.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,173 @@
+/*
+ * 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
+ *  @{
+ */
+
+/** @file
+ *  Device identifier, state and usage statistics.
+ */
+
+#ifndef __NET_DEVICE_ID_TYPE_H__
+#define __NET_DEVICE_ID_TYPE_H__
+
+#include "../structures/int_map.h"
+
+/** Device identifier to generic type map declaration.
+ */
+#define DEVICE_MAP_DECLARE		INT_MAP_DECLARE
+
+/** Device identifier to generic type map implementation.
+ */
+#define DEVICE_MAP_IMPLEMENT	INT_MAP_IMPLEMENT
+
+/** Invalid device identifier.
+ */
+#define DEVICE_INVALID_ID		( -1 )
+
+/** Device identifier type.
+ */
+typedef int	device_id_t;
+
+/** Device state type.
+ */
+typedef enum device_state	device_state_t;
+
+/** Type definition of the device usage statistics.
+ *  @see device_stats
+ */
+typedef struct device_stats	device_stats_t;
+
+/** Type definition of the device usage statistics pointer.
+ *  @see device_stats
+ */
+typedef device_stats_t *	device_stats_ref;
+
+/** Device state.
+ */
+enum	device_state{
+	/** Device not present or not initialized.
+	 */
+	NETIF_NULL = 0,
+	/** Device present and stopped.
+	 */
+	NETIF_STOPPED,
+	/** Device present and active.
+	 */
+	NETIF_ACTIVE,
+	/** Device present but unable to transmit.
+	 */
+	NETIF_CARRIER_LOST
+};
+
+/** Device usage statistics.
+ */
+struct	device_stats{
+	/** Total packets received.
+	 */
+	unsigned long	receive_packets;
+	/** Total packets transmitted.
+	 */
+	unsigned long	send_packets;
+	/** Total bytes received.
+	 */
+	unsigned long	receive_bytes;
+	/** Total bytes transmitted.
+	 */
+	unsigned long	send_bytes;
+	/** Bad packets received counter.
+	 */
+	unsigned long	receive_errors;
+	/** Packet transmition problems counter.
+	 */
+	unsigned long	send_errors;
+	/** No space in buffers counter.
+	 */
+	unsigned long	receive_dropped;
+	/** No space available counter.
+	 */
+	unsigned long	send_dropped;
+	/** Total multicast packets received.
+	 */
+	unsigned long	multicast;
+	/** The number of collisions due to congestion on the medium.
+	 */
+	unsigned long	collisions;
+
+	/* detailed receive_errors: */
+	/** Received packet length error counter.
+	 */
+	unsigned long	receive_length_errors;
+	/** Receiver buffer overflow counter.
+	 */
+	unsigned long	receive_over_errors;
+	/** Received packet with crc error counter.
+	 */
+	unsigned long	receive_crc_errors;
+	/** Received frame alignment error counter.
+	 */
+	unsigned long	receive_frame_errors;
+	/** Receiver fifo overrun counter.
+	 */
+	unsigned long	receive_fifo_errors;
+	/** Receiver missed packet counter.
+	 */
+	unsigned long	receive_missed_errors;
+
+	/* detailed send_errors */
+	/** Transmitter aborted counter.
+	 */
+	unsigned long	send_aborted_errors;
+	/** Transmitter carrier errors counter.
+	 */
+	unsigned long	send_carrier_errors;
+	/** Transmitter fifo overrun counter.
+	 */
+	unsigned long	send_fifo_errors;
+	/** Transmitter carrier errors counter.
+	 */
+	unsigned long	send_heartbeat_errors;
+	/** Transmitter window errors counter.
+	 */
+	unsigned long	send_window_errors;
+
+	/* for cslip etc */
+	/** Total compressed packets received.
+	 */
+	unsigned long	receive_compressed;
+	/** Total compressed packet transmitted.
+	 */
+	unsigned long	send_compressed;
+};
+
+#endif
+
+/** @}
+ */
+
Index: uspace/srv/net/include/ethernet_lsap.h
===================================================================
--- uspace/srv/net/include/ethernet_lsap.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/include/ethernet_lsap.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,137 @@
+/*
+ * 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 eth
+ *  @{
+ */
+
+/** @file
+ *  Link service access point identifiers.
+ */
+
+#ifndef __NET_ETHERNET_LSAP_H__
+#define __NET_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
+/** Individual LLC Sublayer Management Function LSAP identifier.
+ */
+#define ETH_LSAP_ISLMF	0x02
+/** Group LLC Sublayer Management Function LSAP identifier.
+ */
+#define ETH_LSAP_GSLMI	0x03
+/** IBM SNA Path Control (individual) LSAP identifier.
+ */
+#define ETH_LSAP_ISNA	0x04
+/** IBM SNA Path Control (group) LSAP identifier.
+ */
+#define ETH_LSAP_GSNA	0x05
+/** ARPANET Internet Protocol (IP) LSAP identifier.
+ */
+#define ETH_LSAP_IP	0x06
+/** SNA LSAP identifier.
+ */
+#define ETH_LSAP_SNA	0x08
+/** SNA LSAP identifier.
+ */
+#define ETH_LSAP_SNA2	0x0C
+/** PROWAY (IEC955) Network Management & Initialization LSAP identifier.
+ */
+#define ETH_LSAP_PROWAY_NMI	0x0E
+/** Texas Instruments LSAP identifier.
+ */
+#define ETH_LSAP_TI	0x18
+/** IEEE 802.1 Bridge Spanning Tree Protocol LSAP identifier.
+ */
+#define ETH_LSAP_BRIDGE	0x42
+/** EIA RS-511 Manufacturing Message Service LSAP identifier.
+ */
+#define ETH_LSAP_EIS	0x4E
+/** ISO 8208 (X.25 over IEEE 802.2 Type 2 LLC) LSAP identifier.
+ */
+#define ETH_LSAP_ISO8208	0x7E
+/** Xerox Network Systems (XNS) LSAP identifier.
+ */
+#define ETH_LSAP_XNS	0x80
+/** Nestar LSAP identifier.
+ */
+#define ETH_LSAP_NESTAR	0x86
+/** PROWAY (IEC 955) Active Station List Maintenance LSAP identifier.
+ */
+#define ETH_LSAP_PROWAY_ASLM	0x8E
+/** ARPANET Address Resolution Protocol (ARP) LSAP identifier.
+ */
+#define ETH_LSAP_ARP	0x98
+/** Banyan VINES LSAP identifier.
+ */
+#define ETH_LSAP_VINES	0xBC
+/** SubNetwork Access Protocol (SNAP) LSAP identifier.
+ */
+#define ETH_LSAP_SNAP	0xAA
+/** Novell NetWare LSAP identifier.
+ */
+#define ETH_LSAP_NETWARE	0xE0
+/** IBM NetBIOS LSAP identifier.
+ */
+#define ETH_LSAP_NETBIOS	0xF0
+/** IBM LAN Management (individual) LSAP identifier.
+ */
+#define ETH_LSAP_ILAN	0xF4
+/** IBM LAN Management (group) LSAP identifier.
+ */
+#define ETH_LSAP_GLAN	0xF5
+/** IBM Remote Program Load (RPL) LSAP identifier.
+ */
+#define ETH_LSAP_RPL	0xF8
+/** Ungermann-Bass LSAP identifier.
+ */
+#define ETH_LSAP_UB	0xFA
+/** ISO Network Layer Protocol LSAP identifier.
+ */
+#define ETH_LSAP_ISONLP	0xFE
+/** Global LSAP LSAP identifier.
+ */
+#define ETH_LSAP_GLSAP	0xFF
+
+/*@}*/
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/include/ethernet_protocols.h
===================================================================
--- uspace/srv/net/include/ethernet_protocols.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/include/ethernet_protocols.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,1012 @@
+/*
+ * 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 eth
+ *  @{
+ */
+
+/** @file
+ *  Ethernet protocol numbers according to the on-line IANA - Ethernet numbers - <http://www.iana.org/assignments/ethernet-numbers>, cited January 17 2009.
+ */
+
+#ifndef __NET_ETHERNET_PROTOCOLS_H__
+#define __NET_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*/
+
+/** Ethernet loopback packet protocol type.
+ */
+#define ETH_P_LOOP		0x0060
+
+/** XEROX PUP (see 0A00) ethernet protocol type.
+ */
+#define ETH_P_PUP		0x0200
+
+/** PUP Addr Trans (see 0A01) ethernet protocol type.
+ */
+#define ETH_P_PUPAT		0x0201
+
+/** Nixdorf ethernet protocol type.
+ */
+#define ETH_P_Nixdorf		0x0400
+
+/** XEROX NS IDP ethernet protocol type.
+ */
+#define ETH_P_XEROX_NS_IDP		0x0600
+
+/** DLOG ethernet protocol type.
+ */
+#define ETH_P_DLOG		0x0660
+
+/** DLOG ethernet protocol type.
+ */
+#define ETH_P_DLOG2		0x0661
+
+/** Internet IP (IPv4) ethernet protocol type.
+ */
+#define ETH_P_IP		0x0800
+
+/** X.75 Internet ethernet protocol type.
+ */
+#define ETH_P_X_75		0x0801
+
+/** NBS Internet ethernet protocol type.
+ */
+#define ETH_P_NBS		0x0802
+
+/** ECMA Internet ethernet protocol type.
+ */
+#define ETH_P_ECMA		0x0803
+
+/** Chaosnet ethernet protocol type.
+ */
+#define ETH_P_Chaosnet		0x0804
+
+/** X.25 Level 3 ethernet protocol type.
+ */
+#define ETH_P_X25		0x0805
+
+/** ARP ethernet protocol type.
+ */
+#define ETH_P_ARP		0x0806
+
+/** XNS Compatability ethernet protocol type.
+ */
+#define ETH_P_XNS_Compatability		0x0807
+
+/** Frame Relay ARP ethernet protocol type.
+ */
+#define ETH_P_Frame_Relay_ARP		0x0808
+
+/** Symbolics Private ethernet protocol type.
+ */
+#define ETH_P_Symbolics_Private		0x081C
+
+/** Xyplex ethernet protocol type.
+ */
+#define ETH_P_Xyplex_MIN		0x0888
+
+/** Xyplex ethernet protocol type.
+ */
+#define ETH_P_Xyplex_MAX		0x088A
+
+/** Ungermann-Bass net debugr ethernet protocol type.
+ */
+#define ETH_P_Ungermann_Bass_net_debugr		0x0900
+
+/** Xerox IEEE802.3 PUP ethernet protocol type.
+ */
+#define ETH_P_IEEEPUP		0x0A00
+
+/** PUP Addr Trans ethernet protocol type.
+ */
+#define ETH_P_IEEEPUPAT		0x0A01
+
+/** Banyan VINES ethernet protocol type.
+ */
+#define ETH_P_Banyan_VINES		0x0BAD
+
+/** VINES Loopback ethernet protocol type.
+ */
+#define ETH_P_VINES_Loopback		0x0BAE
+
+/** VINES Echo ethernet protocol type.
+ */
+#define ETH_P_VINES_Echo		0x0BAF
+
+/** Berkeley Trailer nego ethernet protocol type.
+ */
+#define ETH_P_Berkeley_Trailer_nego		0x1000
+
+/** Berkeley Trailer encap/IP ethernet protocol type.
+ */
+#define ETH_P_Berkeley_Trailer_encapIP_MIN		0x1001
+
+/** Berkeley Trailer encap/IP ethernet protocol type.
+ */
+#define ETH_P_Berkeley_Trailer_encapIP_MAX		0x100F
+
+/** Valid Systems ethernet protocol type.
+ */
+#define ETH_P_Valid_Systems		0x1600
+
+/** PCS Basic Block Protocol ethernet protocol type.
+ */
+#define ETH_P_PCS_Basic_Block_Protocol		0x4242
+
+/** BBN Simnet ethernet protocol type.
+ */
+#define ETH_P_BBN_Simnet		0x5208
+
+/** DEC Unassigned (Exp.) ethernet protocol type.
+ */
+#define ETH_P_DEC		0x6000
+
+/** DEC MOP Dump/Load ethernet protocol type.
+ */
+#define ETH_P_DNA_DL		0x6001
+
+/** DEC MOP Remote Console ethernet protocol type.
+ */
+#define ETH_P_DNA_RC		0x6002
+
+/** DEC DECNET Phase IV Route ethernet protocol type.
+ */
+#define ETH_P_DNA_RT		0x6003
+
+/** DEC LAT ethernet protocol type.
+ */
+#define ETH_P_LAT		0x6004
+
+/** DEC Diagnostic Protocol ethernet protocol type.
+ */
+#define ETH_P_DIAG		0x6005
+
+/** DEC Customer Protocol ethernet protocol type.
+ */
+#define ETH_P_CUST		0x6006
+
+/** DEC LAVC, SCA ethernet protocol type.
+ */
+#define ETH_P_SCA		0x6007
+
+/** DEC Unassigned ethernet protocol type.
+ */
+#define ETH_P_DEC_Unassigned_MIN		0x6008
+
+/** DEC Unassigned ethernet protocol type.
+ */
+#define ETH_P_DEC_Unassigned_MAX		0x6009
+
+/** Com Corporation ethernet protocol type.
+ */
+#define ETH_P_Com_Corporation_MIN		0x6010
+
+/** Com Corporation ethernet protocol type.
+ */
+#define ETH_P_Com_Corporation_MAX		0x6014
+
+/** Trans Ether Bridging ethernet protocol type.
+ */
+#define ETH_P_Trans_Ether_Bridging		0x6558
+
+/** Raw Frame Relay ethernet protocol type.
+ */
+#define ETH_P_Raw_Frame_Relay		0x6559
+
+/** Ungermann-Bass download ethernet protocol type.
+ */
+#define ETH_P_Ungermann_Bass_download		0x7000
+
+/** Ungermann-Bass dia/loop ethernet protocol type.
+ */
+#define ETH_P_Ungermann_Bass_dialoop		0x7002
+
+/** LRT ethernet protocol type.
+ */
+#define ETH_P_LRT_MIN		0x7020
+
+/** LRT ethernet protocol type.
+ */
+#define ETH_P_LRT_MAX		0x7029
+
+/** Proteon ethernet protocol type.
+ */
+#define ETH_P_Proteon		0x7030
+
+/** Cabletron ethernet protocol type.
+ */
+#define ETH_P_Cabletron		0x7034
+
+/** Cronus VLN ethernet protocol type.
+ */
+#define ETH_P_Cronus_VLN		0x8003
+
+/** Cronus Direct ethernet protocol type.
+ */
+#define ETH_P_Cronus_Direct		0x8004
+
+/** HP Probe ethernet protocol type.
+ */
+#define ETH_P_HP_Probe		0x8005
+
+/** Nestar ethernet protocol type.
+ */
+#define ETH_P_Nestar		0x8006
+
+/** AT&T ethernet protocol type.
+ */
+#define ETH_P_AT_T		0x8008
+
+/** Excelan ethernet protocol type.
+ */
+#define ETH_P_Excelan		0x8010
+
+/** SGI diagnostics ethernet protocol type.
+ */
+#define ETH_P_SGI_diagnostics		0x8013
+
+/** SGI network games ethernet protocol type.
+ */
+#define ETH_P_SGI_network_games		0x8014
+
+/** SGI reserved ethernet protocol type.
+ */
+#define ETH_P_SGI_reserved		0x8015
+
+/** SGI bounce server ethernet protocol type.
+ */
+#define ETH_P_SGI_bounce_server		0x8016
+
+/** Apollo Domain ethernet protocol type.
+ */
+#define ETH_P_Apollo_Domain		0x8019
+
+/** Tymshare ethernet protocol type.
+ */
+#define ETH_P_Tymshare		0x802E
+
+/** Tigan, Inc. ethernet protocol type.
+ */
+#define ETH_P_Tigan		0x802F
+
+/** Reverse ARP ethernet protocol type.
+ */
+#define ETH_P_RARP		0x8035
+
+/** Aeonic Systems ethernet protocol type.
+ */
+#define ETH_P_Aeonic_Systems		0x8036
+
+/** DEC LANBridge ethernet protocol type.
+ */
+#define ETH_P_DEC_LANBridge		0x8038
+
+/** DEC Unassigned ethernet protocol type.
+ */
+#define ETH_P_DEC_Unassigned_MIN1		0x8039
+
+/** DEC Unassigned ethernet protocol type.
+ */
+#define ETH_P_DEC_Unassigned_MAX2		0x803C
+
+/** DEC Ethernet Encryption ethernet protocol type.
+ */
+#define ETH_P_DEC_Ethernet_Encryption		0x803D
+
+/** DEC Unassigned ethernet protocol type.
+ */
+#define ETH_P_DEC_Unassigned		0x803E
+
+/** DEC LAN Traffic Monitor ethernet protocol type.
+ */
+#define ETH_P_DEC_LAN_Traffic_Monitor		0x803F
+
+/** DEC Unassigned ethernet protocol type.
+ */
+#define ETH_P_DEC_Unassigned_MIN3		0x8040
+
+/** DEC Unassigned ethernet protocol type.
+ */
+#define ETH_P_DEC_Unassigned_MAX3		0x8042
+
+/** Planning Research Corp. ethernet protocol type.
+ */
+#define ETH_P_Planning_Research_Corp		0x8044
+
+/** AT&T ethernet protocol type.
+ */
+#define ETH_P_AT_T2		0x8046
+
+/** AT&T ethernet protocol type.
+ */
+#define ETH_P_AT_T3		0x8047
+
+/** ExperData ethernet protocol type.
+ */
+#define ETH_P_ExperData		0x8049
+
+/** Stanford V Kernel exp. ethernet protocol type.
+ */
+#define ETH_P_Stanford_V_Kernel_exp		0x805B
+
+/** Stanford V Kernel prod. ethernet protocol type.
+ */
+#define ETH_P_Stanford_V_Kernel_prod		0x805C
+
+/** Evans & Sutherland ethernet protocol type.
+ */
+#define ETH_P_Evans_Sutherland		0x805D
+
+/** Little Machines ethernet protocol type.
+ */
+#define ETH_P_Little_Machines		0x8060
+
+/** Counterpoint Computers ethernet protocol type.
+ */
+#define ETH_P_Counterpoint_Computers		0x8062
+
+/** Univ. of Mass. @ Amherst ethernet protocol type.
+ */
+#define ETH_P_Univ_of_Mass		0x8065
+
+/** Univ. of Mass. @ Amherst ethernet protocol type.
+ */
+#define ETH_P_Univ_of_Mass2		0x8066
+
+/** Veeco Integrated Auto. ethernet protocol type.
+ */
+#define ETH_P_Veeco_Integrated_Auto		0x8067
+
+/** General Dynamics ethernet protocol type.
+ */
+#define ETH_P_General_Dynamics		0x8068
+
+/** AT&T ethernet protocol type.
+ */
+#define ETH_P_AT_T4		0x8069
+
+/** Autophon ethernet protocol type.
+ */
+#define ETH_P_Autophon		0x806A
+
+/** ComDesign ethernet protocol type.
+ */
+#define ETH_P_ComDesign		0x806C
+
+/** Computgraphic Corp. ethernet protocol type.
+ */
+#define ETH_P_Computgraphic_Corp		0x806D
+
+/** Landmark Graphics Corp. ethernet protocol type.
+ */
+#define ETH_P_Landmark_Graphics_Corp_MIN		0x806E
+
+/** Landmark Graphics Corp. ethernet protocol type.
+ */
+#define ETH_P_Landmark_Graphics_Corp_MAX		0x8077
+
+/** Matra ethernet protocol type.
+ */
+#define ETH_P_Matra		0x807A
+
+/** Dansk Data Elektronik ethernet protocol type.
+ */
+#define ETH_P_Dansk_Data_Elektronik		0x807B
+
+/** Merit Internodal ethernet protocol type.
+ */
+#define ETH_P_Merit_Internodal		0x807C
+
+/** Vitalink Communications ethernet protocol type.
+ */
+#define ETH_P_Vitalink_Communications_MIN		0x807D
+
+/** Vitalink Communications ethernet protocol type.
+ */
+#define ETH_P_Vitalink_Communications_MAX		0x807F
+
+/** Vitalink TransLAN III ethernet protocol type.
+ */
+#define ETH_P_Vitalink_TransLAN_III		0x8080
+
+/** Counterpoint Computers ethernet protocol type.
+ */
+#define ETH_P_Counterpoint_Computers_MIN		0x8081
+
+/** Counterpoint Computers ethernet protocol type.
+ */
+#define ETH_P_Counterpoint_Computers_MAX		0x8083
+
+/** Appletalk ethernet protocol type.
+ */
+#define ETH_P_ATALK		0x809B
+
+/** Datability ethernet protocol type.
+ */
+#define ETH_P_Datability_MIN		0x809C
+
+/** Datability ethernet protocol type.
+ */
+#define ETH_P_Datability_MAX		0x809E
+
+/** Spider Systems Ltd. ethernet protocol type.
+ */
+#define ETH_P_Spider_Systems_Ltd		0x809F
+
+/** Nixdorf Computers ethernet protocol type.
+ */
+#define ETH_P_Nixdorf_Computers		0x80A3
+
+/** Siemens Gammasonics Inc. ethernet protocol type.
+ */
+#define ETH_P_Siemens_Gammasonics_Inc_MIN		0x80A4
+
+/** Siemens Gammasonics Inc. ethernet protocol type.
+ */
+#define ETH_P_Siemens_Gammasonics_Inc_MAX		0x80B3
+
+/** DCA Data Exchange Cluster ethernet protocol type.
+ */
+#define ETH_P_DCA_Data_Exchange_Cluster_MIN		0x80C0
+
+/** DCA Data Exchange Cluster ethernet protocol type.
+ */
+#define ETH_P_DCA_Data_Exchange_Cluster_MAX		0x80C3
+
+/** Banyan Systems ethernet protocol type.
+ */
+#define ETH_P_Banyan_Systems		0x80C4
+
+/** Banyan Systems ethernet protocol type.
+ */
+#define ETH_P_Banyan_Systems2		0x80C5
+
+/** Pacer Software ethernet protocol type.
+ */
+#define ETH_P_Pacer_Software		0x80C6
+
+/** Applitek Corporation ethernet protocol type.
+ */
+#define ETH_P_Applitek_Corporation		0x80C7
+
+/** Intergraph Corporation ethernet protocol type.
+ */
+#define ETH_P_Intergraph_Corporation_MIN		0x80C8
+
+/** Intergraph Corporation ethernet protocol type.
+ */
+#define ETH_P_Intergraph_Corporation_MAX		0x80CC
+
+/** Harris Corporation ethernet protocol type.
+ */
+#define ETH_P_Harris_Corporation_MIN		0x80CD
+
+/** Harris Corporation ethernet protocol type.
+ */
+#define ETH_P_Harris_Corporation_MAX		0x80CE
+
+/** Taylor Instrument ethernet protocol type.
+ */
+#define ETH_P_Taylor_Instrument_MIN		0x80CF
+
+/** Taylor Instrument ethernet protocol type.
+ */
+#define ETH_P_Taylor_Instrument_MAX		0x80D2
+
+/** Rosemount Corporation ethernet protocol type.
+ */
+#define ETH_P_Rosemount_Corporation_MIN		0x80D3
+
+/** Rosemount Corporation ethernet protocol type.
+ */
+#define ETH_P_Rosemount_Corporation_MAX		0x80D4
+
+/** IBM SNA Service on Ether ethernet protocol type.
+ */
+#define ETH_P_IBM_SNA_Service_on_Ether		0x80D5
+
+/** Varian Associates ethernet protocol type.
+ */
+#define ETH_P_Varian_Associates		0x80DD
+
+/** Integrated Solutions TRFS ethernet protocol type.
+ */
+#define ETH_P_Integrated_Solutions_TRFS_MIN		0x80DE
+
+/** Integrated Solutions TRFS ethernet protocol type.
+ */
+#define ETH_P_Integrated_Solutions_TRFS_MAX		0x80DF
+
+/** Allen-Bradley ethernet protocol type.
+ */
+#define ETH_P_Allen_Bradley_MIN		0x80E0
+
+/** Allen-Bradley ethernet protocol type.
+ */
+#define ETH_P_Allen_Bradley_MAX		0x80E3
+
+/** Datability ethernet protocol type.
+ */
+#define ETH_P_Datability_MIN2		0x80E4
+
+/** Datability ethernet protocol type.
+ */
+#define ETH_P_Datability_MAX2		0x80F0
+
+/** Retix ethernet protocol type.
+ */
+#define ETH_P_Retix		0x80F2
+
+/** AppleTalk AARP (Kinetics) ethernet protocol type.
+ */
+#define ETH_P_AARP		0x80F3
+
+/** Kinetics ethernet protocol type.
+ */
+#define ETH_P_Kinetics_MIN		0x80F4
+
+/** Kinetics ethernet protocol type.
+ */
+#define ETH_P_Kinetics_MAX		0x80F5
+
+/** Apollo Computer ethernet protocol type.
+ */
+#define ETH_P_Apollo_Computer		0x80F7
+
+/** Wellfleet Communications ethernet protocol type.
+ */
+#define ETH_P_Wellfleet_Communications		0x80FF
+
+/** IEEE 802.1Q VLAN-tagged frames (initially Wellfleet) ethernet protocol type.
+ */
+#define ETH_P_8021Q		0x8100
+
+/** Wellfleet Communications ethernet protocol type.
+ */
+#define ETH_P_Wellfleet_Communications_MIN		0x8101
+
+/** Wellfleet Communications ethernet protocol type.
+ */
+#define ETH_P_Wellfleet_Communications_MAX		0x8103
+
+/** Symbolics Private ethernet protocol type.
+ */
+#define ETH_P_Symbolics_Private_MIN		0x8107
+
+/** Symbolics Private ethernet protocol type.
+ */
+#define ETH_P_Symbolics_Private_MAX		0x8109
+
+/** Hayes Microcomputers ethernet protocol type.
+ */
+#define ETH_P_Hayes_Microcomputers		0x8130
+
+/** VG Laboratory Systems ethernet protocol type.
+ */
+#define ETH_P_VG_Laboratory_Systems		0x8131
+
+/** Bridge Communications ethernet protocol type.
+ */
+#define ETH_P_Bridge_Communications_MIN		0x8132
+
+/** Bridge Communications ethernet protocol type.
+ */
+#define ETH_P_Bridge_Communications_MAX		0x8136
+
+/** Novell, Inc. ethernet protocol type.
+ */
+#define ETH_P_Novell_Inc_MIN		0x8137
+
+/** Novell, Inc. ethernet protocol type.
+ */
+#define ETH_P_Novell_Inc_MAX		0x8138
+
+/** KTI ethernet protocol type.
+ */
+#define ETH_P_KTI_MIN		0x8139
+
+/** KTI ethernet protocol type.
+ */
+#define ETH_P_KTI_MAX		0x813D
+
+/** Logicraft ethernet protocol type.
+ */
+#define ETH_P_Logicraft		0x8148
+
+/** Network Computing Devices ethernet protocol type.
+ */
+#define ETH_P_Network_Computing_Devices		0x8149
+
+/** Alpha Micro ethernet protocol type.
+ */
+#define ETH_P_Alpha_Micro		0x814A
+
+/** SNMP ethernet protocol type.
+ */
+#define ETH_P_SNMP		0x814C
+
+/** BIIN ethernet protocol type.
+ */
+#define ETH_P_BIIN		0x814D
+
+/** BIIN ethernet protocol type.
+ */
+#define ETH_P_BIIN2		0x814E
+
+/** Technically Elite Concept ethernet protocol type.
+ */
+#define ETH_P_Technically_Elite_Concept		0x814F
+
+/** Rational Corp ethernet protocol type.
+ */
+#define ETH_P_Rational_Corp		0x8150
+
+/** Qualcomm ethernet protocol type.
+ */
+#define ETH_P_Qualcomm_MIN		0x8151
+
+/** Qualcomm ethernet protocol type.
+ */
+#define ETH_P_Qualcomm_MAX		0x8153
+
+/** Computer Protocol Pty Ltd ethernet protocol type.
+ */
+#define ETH_P_Computer_Protocol_Pty_Ltd_MIN		0x815C
+
+/** Computer Protocol Pty Ltd ethernet protocol type.
+ */
+#define ETH_P_Computer_Protocol_Pty_Ltd_MAX		0x815E
+
+/** Charles River Data System ethernet protocol type.
+ */
+#define ETH_P_Charles_River_Data_System_MIN		0x8164
+
+/** Charles River Data System ethernet protocol type.
+ */
+#define ETH_P_Charles_River_Data_System_MAX		0x8166
+
+/** XTP ethernet protocol type.
+ */
+#define ETH_P_XTP		0x817D
+
+/** SGI/Time Warner prop. ethernet protocol type.
+ */
+#define ETH_P_SGITime_Warner_prop		0x817E
+
+/** HIPPI-FP encapsulation ethernet protocol type.
+ */
+#define ETH_P_HIPPI_FP_encapsulation		0x8180
+
+/** STP, HIPPI-ST ethernet protocol type.
+ */
+#define ETH_P_STP_HIPPI_ST		0x8181
+
+/** Reserved for HIPPI-6400 ethernet protocol type.
+ */
+#define ETH_P_Reserved_for_HIPPI_6400		0x8182
+
+/** Reserved for HIPPI-6400 ethernet protocol type.
+ */
+#define ETH_P_Reserved_for_HIPPI_64002		0x8183
+
+/** Silicon Graphics prop. ethernet protocol type.
+ */
+#define ETH_P_Silicon_Graphics_prop_MIN		0x8184
+
+/** Silicon Graphics prop. ethernet protocol type.
+ */
+#define ETH_P_Silicon_Graphics_prop_MAX		0x818C
+
+/** Motorola Computer ethernet protocol type.
+ */
+#define ETH_P_Motorola_Computer		0x818D
+
+/** Qualcomm ethernet protocol type.
+ */
+#define ETH_P_Qualcomm_MIN2		0x819A
+
+/** Qualcomm ethernet protocol type.
+ */
+#define ETH_P_Qualcomm_MAX2		0x81A3
+
+/** ARAI Bunkichi ethernet protocol type.
+ */
+#define ETH_P_ARAI_Bunkichi		0x81A4
+
+/** RAD Network Devices ethernet protocol type.
+ */
+#define ETH_P_RAD_Network_Devices_MIN		0x81A5
+
+/** RAD Network Devices ethernet protocol type.
+ */
+#define ETH_P_RAD_Network_Devices_MAX		0x81AE
+
+/** Xyplex ethernet protocol type.
+ */
+#define ETH_P_Xyplex_MIN2		0x81B7
+
+/** Xyplex ethernet protocol type.
+ */
+#define ETH_P_Xyplex_MAX2		0x81B9
+
+/** Apricot Computers ethernet protocol type.
+ */
+#define ETH_P_Apricot_Computers_MIN		0x81CC
+
+/** Apricot Computers ethernet protocol type.
+ */
+#define ETH_P_Apricot_Computers_MAX		0x81D5
+
+/** Artisoft ethernet protocol type.
+ */
+#define ETH_P_Artisoft_MIN		0x81D6
+
+/** Artisoft ethernet protocol type.
+ */
+#define ETH_P_Artisoft_MAX		0x81DD
+
+/** Polygon ethernet protocol type.
+ */
+#define ETH_P_Polygon_MIN		0x81E6
+
+/** Polygon ethernet protocol type.
+ */
+#define ETH_P_Polygon_MAX		0x81EF
+
+/** Comsat Labs ethernet protocol type.
+ */
+#define ETH_P_Comsat_Labs_MIN		0x81F0
+
+/** Comsat Labs ethernet protocol type.
+ */
+#define ETH_P_Comsat_Labs_MAX		0x81F2
+
+/** SAIC ethernet protocol type.
+ */
+#define ETH_P_SAIC_MIN		0x81F3
+
+/** SAIC ethernet protocol type.
+ */
+#define ETH_P_SAIC_MAX		0x81F5
+
+/** VG Analytical ethernet protocol type.
+ */
+#define ETH_P_VG_Analytical_MIN		0x81F6
+
+/** VG Analytical ethernet protocol type.
+ */
+#define ETH_P_VG_Analytical_MAX		0x81F8
+
+/** Quantum Software ethernet protocol type.
+ */
+#define ETH_P_Quantum_Software_MIN		0x8203
+
+/** Quantum Software ethernet protocol type.
+ */
+#define ETH_P_Quantum_Software_MAX		0x8205
+
+/** Ascom Banking Systems ethernet protocol type.
+ */
+#define ETH_P_Ascom_Banking_Systems_MIN		0x8221
+
+/** Ascom Banking Systems ethernet protocol type.
+ */
+#define ETH_P_Ascom_Banking_Systems_MAX		0x8222
+
+/** Advanced Encryption Syste ethernet protocol type.
+ */
+#define ETH_P_Advanced_Encryption_Syste_MIN		0x823E
+
+/** Advanced Encryption Syste ethernet protocol type.
+ */
+#define ETH_P_Advanced_Encryption_Syste_MAX		0x8240
+
+/** Athena Programming ethernet protocol type.
+ */
+#define ETH_P_Athena_Programming_MIN		0x827F
+
+/** Athena Programming ethernet protocol type.
+ */
+#define ETH_P_Athena_Programming_MAX		0x8282
+
+/** Charles River Data System ethernet protocol type.
+ */
+#define ETH_P_Charles_River_Data_System_MIN2		0x8263
+
+/** Charles River Data System ethernet protocol type.
+ */
+#define ETH_P_Charles_River_Data_System_MAX2		0x826A
+
+/** Inst Ind Info Tech ethernet protocol type.
+ */
+#define ETH_P_Inst_Ind_Info_Tech_MIN		0x829A
+
+/** Inst Ind Info Tech ethernet protocol type.
+ */
+#define ETH_P_Inst_Ind_Info_Tech_MAX		0x829B
+
+/** Taurus Controls ethernet protocol type.
+ */
+#define ETH_P_Taurus_Controls_MIN		0x829C
+
+/** Taurus Controls ethernet protocol type.
+ */
+#define ETH_P_Taurus_Controls_MAX		0x82AB
+
+/** Walker Richer & Quinn ethernet protocol type.
+ */
+#define ETH_P_Walker_Richer_Quinn_MIN		0x82AC
+
+/** Walker Richer & Quinn ethernet protocol type.
+ */
+#define ETH_P_Walker_Richer_Quinn_MAX		0x8693
+
+/** Idea Courier ethernet protocol type.
+ */
+#define ETH_P_Idea_Courier_MIN		0x8694
+
+/** Idea Courier ethernet protocol type.
+ */
+#define ETH_P_Idea_Courier_MAX		0x869D
+
+/** Computer Network Tech ethernet protocol type.
+ */
+#define ETH_P_Computer_Network_Tech_MIN		0x869E
+
+/** Computer Network Tech ethernet protocol type.
+ */
+#define ETH_P_Computer_Network_Tech_MAX		0x86A1
+
+/** Gateway Communications ethernet protocol type.
+ */
+#define ETH_P_Gateway_Communications_MIN		0x86A3
+
+/** Gateway Communications ethernet protocol type.
+ */
+#define ETH_P_Gateway_Communications_MAX		0x86AC
+
+/** SECTRA ethernet protocol type.
+ */
+#define ETH_P_SECTRA		0x86DB
+
+/** Delta Controls ethernet protocol type.
+ */
+#define ETH_P_Delta_Controls		0x86DE
+
+/** IPv6 ethernet protocol type.
+ */
+#define ETH_P_IPV6		0x86DD
+
+/** ATOMIC ethernet protocol type.
+ */
+#define ETH_P_ATOMIC		0x86DF
+
+/** Landis & Gyr Powers ethernet protocol type.
+ */
+#define ETH_P_Landis_Gyr_Powers_MIN		0x86E0
+
+/** Landis & Gyr Powers ethernet protocol type.
+ */
+#define ETH_P_Landis_Gyr_Powers_MAX		0x86EF
+
+/** Motorola ethernet protocol type.
+ */
+#define ETH_P_Motorola_MIN		0x8700
+
+/** Motorola ethernet protocol type.
+ */
+#define ETH_P_Motorola_MAX		0x8710
+
+/** TCP/IP Compression ethernet protocol type.
+ */
+#define ETH_P_TCPIP_Compression		0x876B
+
+/** IP Autonomous Systems ethernet protocol type.
+ */
+#define ETH_P_IP_Autonomous_Systems		0x876C
+
+/** Secure Data ethernet protocol type.
+ */
+#define ETH_P_Secure_Data		0x876D
+
+/** PPP ethernet protocol type.
+ */
+#define ETH_P_PPP		0x880B
+
+/** MPLS ethernet protocol type.
+ */
+#define ETH_P_MPLS_UC		0x8847
+
+/** MPLS with upstream-assigned label ethernet protocol type.
+ */
+#define ETH_P_MPLS_MC		0x8848
+
+/** Invisible Software ethernet protocol type.
+ */
+#define ETH_P_Invisible_Software_MIN		0x8A96
+
+/** Invisible Software ethernet protocol type.
+ */
+#define ETH_P_Invisible_Software_MAX		0x8A97
+
+/** PPPoE Discovery Stage ethernet protocol type.
+ */
+#define ETH_P_PPP_DISC		0x8863
+
+/** PPPoE Session Stage ethernet protocol type.
+ */
+#define ETH_P_PPP_SES		0x8864
+
+/** Loopback ethernet protocol type.
+ */
+#define ETH_P_Loopback		0x9000
+
+/** Com(Bridge) XNS Sys Mgmt ethernet protocol type.
+ */
+#define ETH_P_Com_XNS_Sys_Mgmt		0x9001
+
+/** Com(Bridge) TCP-IP Sys ethernet protocol type.
+ */
+#define ETH_P_Com_TCP_IP_Sys		0x9002
+
+/** Com(Bridge) loop detect ethernet protocol type.
+ */
+#define ETH_P_Com_loop_detect		0x9003
+
+/** BBN VITAL-LanBridge cache ethernet protocol type.
+ */
+#define ETH_P_BBN_VITAL_LanBridge_cache		0xFF00
+
+/** ISC Bunker Ramo ethernet protocol type.
+ */
+#define ETH_P_ISC_Bunker_Ramo_MIN		0xFF00
+
+/** ISC Bunker Ramo ethernet protocol type.
+ */
+#define ETH_P_ISC_Bunker_Ramo_MAX		0xFF0F
+
+/*@}*/
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/include/hardware.h
===================================================================
--- uspace/srv/net/include/hardware.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/include/hardware.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup net_nil
+ *  @{
+ */
+
+/** @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 __NET_HW_TYPES_H__
+#define __NET_HW_TYPES_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
+
+/** Experimental Ethernet (3Mb) hardware type.
+ */
+#define HW_EETHER		2
+
+/** Amateur Radio AX.25 hardware type.
+ */
+#define HW_AX25		3
+
+/** Proteon ProNET Token Ring hardware type.
+ */
+#define HW_PRONET		4
+
+/** Chaos hardware type.
+ */
+#define HW_CHAOS		5
+
+/** IEEE 802 Networks hardware type.
+ */
+#define HW_IEEE802		6
+
+/** ARCNET hardware type.
+ */
+#define HW_ARCNET		7
+
+/** Hyperchannel hardware type.
+ */
+#define HW_Hyperchannel		8
+
+/** Lanstar hardware type.
+ */
+#define HW_Lanstar		9
+
+/** Autonet Short Address hardware type.
+ */
+#define HW_ASA		10
+
+/** LocalTalk hardware type.
+ */
+#define HW_LocalTalk		11
+
+/** LocalNet (IBM PCNet or SYTEK LocalNET) hardware type.
+ */
+#define HW_LocalNet		12
+
+/** Ultra link hardware type.
+ */
+#define HW_Ultra_link		13
+
+/** SMDS hardware type.
+ */
+#define HW_SMDS		14
+
+/** Frame Relay DLCI hardware type.
+ */
+#define HW_DLCI		15
+
+/** Asynchronous Transmission Mode (ATM) hardware type.
+ */
+#define HW_ATM		16
+
+/** HDLC hardware type.
+ */
+#define HW_HDLC		17
+
+/** Fibre Channel hardware type.
+ */
+#define HW_Fibre_Channel		18
+
+/** Asynchronous Transmission Mode (ATM) hardware type.
+ */
+#define HW_ATM2		19
+
+/** Serial Line hardware type.
+ */
+#define HW_Serial_Line		20
+
+/** Asynchronous Transmission Mode (ATM) hardware type.
+ */
+#define HW_ATM3		21
+
+/** MIL-STD-188-220 hardware type.
+ */
+#define HW_MIL_STD_188_220		22
+
+/** Metricom hardware type.
+ */
+#define HW_METRICOM		23
+
+/** IEEE 1394.1995 hardware type.
+ */
+#define HW_IEEE1394		24
+
+/** MAPOS hardware type.
+ */
+#define HW_MAPOS		25
+
+/** Twinaxial hardware type.
+ */
+#define HW_Twinaxial		26
+
+/** EUI-64 hardware type.
+ */
+#define HW_EUI64		27
+
+/** HIPARP hardware type.
+ */
+#define HW_HIPARP		28
+
+/** IP and ARP over ISO 7816-3 hardware type.
+ */
+#define HW_ISO_7816_3		29
+
+/** ARPSec hardware type.
+ */
+#define HW_ARPSec		30
+
+/** IPsec tunnel hardware type.
+ */
+#define HW_IPsec_tunnel		31
+
+/** InfiniBand (TM) hardware type.
+ */
+#define HW_INFINIBAND		32
+
+/** TIA-102 Project 25 Common Air Interface (CAI) hardware type.
+ */
+#define HW_CAI		33
+
+/** Wiegand Interface hardware type.
+ */
+#define HW_Wiegand		34
+
+/** Pure IP hardware type.
+ */
+#define HW_Pure_IP		35
+
+/*@}*/
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/include/icmp_api.h
===================================================================
--- uspace/srv/net/include/icmp_api.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/include/icmp_api.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,88 @@
+/*
+ * 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 icmp
+ *  @{
+ */
+
+/** @file
+ *  ICMP module application interface.
+ */
+
+#ifndef __NET_ICMP_API_H__
+#define __NET_ICMP_API_H__
+
+#include <sys/types.h>
+
+#include "device.h"
+
+#include "../structures/measured_strings.h"
+#include "../structures/packet/packet.h"
+
+#include "inet.h"
+#include "ip_codes.h"
+#include "socket_codes.h"
+
+#include "icmp_codes.h"
+#include "icmp_common.h"
+
+/** Miliseconds type definition.
+ */
+typedef size_t	mseconds_t;
+
+/** @name ICMP module application interface
+ *  This interface is used by other application modules.
+ */
+/*@{*/
+
+/** 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 occurres.
+ *  @param[in] icmp_phone The ICMP module phone used for (semi)remote calls.
+ *  @param[in] size The message data length in bytes.
+ *  @param[in] timeout The timeout in miliseconds.
+ *  @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.
+ *  @returns ICMP_ECHO on success.
+ *  @returns ETIMEOUT if the reply has not arrived before the timeout.
+ *  @returns ICMP type of the received error notification. 
+ *  @returns EINVAL if the addrlen parameter is less or equal to zero (<=0).
+ *  @returns ENOMEM if there is not enough memory left.
+ *  @returns EPARTY if there was an internal error.
+ */
+int	icmp_echo_msg( int icmp_phone, size_t size, mseconds_t timeout, ip_ttl_t ttl, ip_tos_t tos, int dont_fragment, const struct sockaddr * addr, socklen_t addrlen );
+
+/*@}*/
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/include/icmp_client.h
===================================================================
--- uspace/srv/net/include/icmp_client.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/include/icmp_client.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,63 @@
+/*
+ * 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 icmp
+ *  @{
+ */
+
+/** @file
+ *  ICMP client interface.
+ */
+
+#ifndef __NET_ICMP_CLIENT_H__
+#define __NET_ICMP_CLIENT_H__
+
+#include "icmp_codes.h"
+#include "../structures/packet/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.
+ *  @returns The ICMP header length.
+ *  @returns Zero (0) 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 );
+
+/** Returns the ICMP header length.
+ *  @param[in] packet The packet.
+ *  @returns The ICMP header length in bytes.
+ */
+size_t	icmp_client_header_length( packet_t packet );
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/include/icmp_codes.h
===================================================================
--- uspace/srv/net/include/icmp_codes.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/include/icmp_codes.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,347 @@
+/*
+ * 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 icmp
+ *  @{
+ */
+
+/** @file
+ *  ICMP types and codes according to the on-line IANA - ICMP Type Numbers - <http://http://www.iana.org/assignments/icmp-parameters>, cited September 14 2009.
+ */
+
+#ifndef __NET_ICMP_CODES_H__
+#define __NET_ICMP_CODES_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: uspace/srv/net/include/icmp_common.h
===================================================================
--- uspace/srv/net/include/icmp_common.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/include/icmp_common.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,60 @@
+/*
+ * 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 icmp
+ *  @{
+ */
+
+/** @file
+ *  ICMP module common interface.
+ */
+
+#ifndef __NET_ICMP_COMMON_H__
+#define __NET_ICMP_COMMON_H__
+
+#include <ipc/services.h>
+
+#include <sys/time.h>
+
+/** Default timeout for incoming connections in microseconds.
+ */
+#define ICMP_CONNECT_TIMEOUT	( 1 * 1000 * 1000 )
+
+/** Connects to the ICMP module.
+ *  @param service The ICMP module service. Ignored parameter.
+ *  @param[in] timeout The connection timeout in microseconds. No timeout if set to zero (0).
+ *  @returns The ICMP module phone on success.
+ *  @returns The ICMP socket identifier if called by the bundle module.
+ *  @returns ETIMEOUT if the connection timeouted.
+ */
+int	icmp_connect_module( services_t service, suseconds_t timeout );
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/include/icmp_interface.h
===================================================================
--- uspace/srv/net/include/icmp_interface.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/include/icmp_interface.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,116 @@
+/*
+ * 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 icmp
+ *  @{
+ */
+
+/** @file
+ *  ICMP module interface.
+ *  The same interface is used for standalone remote modules as well as for bundle modules.
+ *  The standalone remote modules have to be compiled with the icmp_remote.c source file.
+ *  The bundle modules with the icmp.c source file.
+ */
+
+#ifndef __NET_ICMP_INTERFACE_H__
+#define __NET_ICMP_INTERFACE_H__
+
+#include <sys/types.h>
+
+#include "device.h"
+
+#include "../structures/measured_strings.h"
+#include "../structures/packet/packet.h"
+
+#include "inet.h"
+#include "ip_codes.h"
+#include "socket_codes.h"
+
+#include "icmp_codes.h"
+#include "icmp_common.h"
+
+/** @name ICMP module interface
+ *  This interface is used by other modules.
+ */
+/*@{*/
+
+/** Sends 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] icmp_phone The ICMP module phone used for (semi)remote calls.
+ *  @param[in] code The error specific code.
+ *  @param[in] mtu The error MTU value.
+ *  @param[in] packet The original packet.
+ *  @returns EOK on success.
+ *  @returns EPERM if the ICMP error notifications are disabled.
+ *  @returns ENOMEM if there is not enough memory left.
+ */
+int icmp_destination_unreachable_msg( int icmp_phone, icmp_code_t code, icmp_param_t mtu, packet_t packet );
+
+/** Sends 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] icmp_phone The ICMP module phone used for (semi)remote calls.
+ *  @param[in] packet The original packet.
+ *  @returns EOK on success.
+ *  @returns EPERM if the ICMP error notifications are disabled.
+ *  @returns ENOMEM if there is not enough memory left.
+ */
+int icmp_source_quench_msg( int icmp_phone, packet_t packet );
+
+/** Sends 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] icmp_phone The ICMP module phone used for (semi)remote calls.
+ *  @param[in] code The error specific code.
+ *  @param[in] packet The original packet.
+ *  @returns EOK on success.
+ *  @returns EPERM if the ICMP error notifications are disabled.
+ *  @returns ENOMEM if there is not enough memory left.
+ */
+int icmp_time_exceeded_msg( int icmp_phone, icmp_code_t code, packet_t packet );
+
+/** Sends 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] icmp_phone The ICMP module phone used for (semi)remote calls.
+ *  @param[in] code The error specific code.
+ *  @param[in] pointer The problematic parameter offset.
+ *  @param[in] packet The original packet.
+ *  @returns EOK on success.
+ *  @returns EPERM if the ICMP error notifications are disabled.
+ *  @returns ENOMEM if there is not enough memory left.
+ */
+int icmp_parameter_problem_msg( int icmp_phone, icmp_code_t code, icmp_param_t pointer, packet_t packet );
+
+/*@}*/
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/include/il_interface.h
===================================================================
--- uspace/srv/net/include/il_interface.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/include/il_interface.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup net_il
+ *  @{
+ */
+
+/** @file
+ *  Internetwork layer module interface for the underlying network interface layer.
+ *  This interface is always called by the standalone remote modules.
+ */
+
+#ifndef __NET_IL_INTERFACE_H__
+#define __NET_IL_INTERFACE_H__
+
+#include <async.h>
+
+#include <ipc/services.h>
+
+#include "../messages.h"
+
+#include "../include/device.h"
+
+#include "../structures/packet/packet.h"
+#include "../structures/packet/packet_client.h"
+
+#include "../il/il_messages.h"
+
+/** @name Internetwork layer module interface
+ *  This interface is used by other modules.
+ */
+/*@{*/
+
+/** Notifies the internetwork layer modules about the device state change.
+ *  @param[in] il_phone The internetwork layer module phone used for (semi)remote calls.
+ *  @param[in] device_id The device identifier.
+ *  @param[in] state The new device state.
+ *  @param[in] target The target internetwork module service to be delivered to.
+ *  @returns EOK on success.
+ */
+static inline int	il_device_state_msg( int il_phone, device_id_t device_id, device_state_t state, services_t target ){
+	return generic_device_state_msg( il_phone, NET_IL_DEVICE_STATE, device_id, state, target );
+}
+
+/** Notifies the internetwork layer modules about the received packet/s.
+ *  @param[in] il_phone The internetwork layer module phone used for (semi)remote calls.
+ *  @param[in] device_id The device identifier.
+ *  @param[in] packet The received packet or the received packet queue.
+ *  @param[in] target The target internetwork module service to be delivered to.
+ *  @returns EOK on success.
+ */
+inline static int	il_received_msg( int il_phone, device_id_t device_id, packet_t packet, services_t target ){
+	return generic_received_msg( il_phone, NET_IL_RECEIVED, device_id, packet_get_id( packet ), target, 0 );
+}
+
+/** Notifies the internetwork layer modules about the mtu change.
+ *  @param[in] il_phone The internetwork layer module phone used for (semi)remote calls.
+ *  @param[in] device_id The device identifier.
+ *  @param[in] mtu The new mtu value.
+ *  @param[in] target The target internetwork module service to be delivered to.
+ *  @returns EOK on success.
+ */
+inline static int	il_mtu_changed_msg( int il_phone, device_id_t device_id, size_t mtu, services_t target ){
+	return generic_device_state_msg( il_phone, NET_IL_MTU_CHANGED, device_id, ( int ) mtu, target );
+}
+
+/*@}*/
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/include/in.h
===================================================================
--- uspace/srv/net/include/in.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/include/in.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup net
+ *  @{
+ */
+
+/** @file
+ *  INET family common definitions.
+ */
+
+#ifndef __NET_IN_H__
+#define __NET_IN_H__
+
+#include <sys/types.h>
+
+#include "ip_protocols.h"
+#include "inet.h"
+
+/** INET string address maximum length.
+ */
+#define INET_ADDRSTRLEN		( 4 * 3 + 3 + 1 )
+
+/** Type definition of the INET address.
+ *  @see in_addr
+ */
+typedef struct in_addr		in_addr_t;
+
+/** Type definition of the INET socket address.
+ *  @see sockaddr_in
+ */
+typedef struct sockaddr_in	sockaddr_in_t;
+
+/** INET address.
+ */
+struct in_addr{
+	/** 4 byte IP address.
+	 */
+	uint32_t		s_addr;
+};
+
+/** INET socket address.
+ *  @see sockaddr
+ */
+struct sockaddr_in{
+	/** Address family.
+	 *  Should be AF_INET.
+	 */
+	uint16_t		sin_family;
+	/** Port number.
+	 */
+	uint16_t		sin_port;
+	/** Internet address.
+	 */
+	struct in_addr	sin_addr;
+	/** Padding to meet the sockaddr size.
+	 */
+	uint8_t			sin_zero[ 8 ];
+};
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/include/in6.h
===================================================================
--- uspace/srv/net/include/in6.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/include/in6.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup net
+ *  @{
+ */
+
+/** @file
+ *  INET6 family common definitions.
+ */
+
+#ifndef __NET_IN6_H__
+#define __NET_IN6_H__
+
+#include <sys/types.h>
+
+#include "ip_protocols.h"
+#include "inet.h"
+
+/** INET6 string address maximum length.
+ */
+#define INET6_ADDRSTRLEN	( 8 * 4 + 7 + 1 )
+
+/** Type definition of the INET6 address.
+ *  @see in6_addr
+ */
+typedef struct in6_addr	in6_addr_t;
+
+/** Type definition of the INET6 socket address.
+ *  @see sockaddr_in6
+ */
+typedef struct sockaddr_in6	sockaddr_in6_t;
+
+/** INET6 address.
+ */
+struct in6_addr{
+	/** 16 byte IPv6 address.
+	 */
+	unsigned char	s6_addr[ 16 ];
+};
+
+/** INET6 socket address.
+ *  @see sockaddr
+ */
+struct sockaddr_in6{
+	/** Address family.
+	 *  Should be AF_INET6.
+	 */
+	uint16_t		sin6_family;
+	/** Port number.
+	 */
+	uint16_t		sin6_port;
+	/** IPv6 flow information.
+	 */
+	uint32_t		sin6_flowinfo;
+	/** IPv6 address.
+	 */
+	struct in6_addr	sin6_addr;
+	/** Scope identifier.
+	 */
+	uint32_t		sin6_scope_id;
+};
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/include/inet.h
===================================================================
--- uspace/srv/net/include/inet.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/include/inet.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup net
+ *  @{
+ */
+
+/** @file
+ *  Internet common definitions.
+ */
+
+#ifndef __NET_INET_H__
+#define __NET_INET_H__
+
+#include <sys/types.h>
+
+#include "byteorder.h"
+
+/** Type definition of the socket address.
+ *  @see sockaddr
+ */
+typedef struct sockaddr		sockaddr_t;
+
+/** Type definition of the address information.
+ *  @see addrinfo
+ */
+typedef struct addrinfo		addrinfo_t;
+
+/** Prints the address into the character buffer.
+ *  @param[in] family The address family.
+ *  @param[in] data The address data.
+ *  @param[out] address The character buffer to be filled.
+ *  @param[in] length The buffer length.
+ *  @returns EOK on success.
+ *  @returns EINVAL if the data or address parameter is NULL.
+ *  @returns ENOMEM if the character buffer is not long enough.
+ *  @returns ENOTSUP if the address family is not supported.
+ */
+int	inet_ntop( uint16_t family, const uint8_t * data, char * address, size_t length );
+
+/** Parses the character string into the address.
+ *  If the string is shorter than the full address, zero bytes are added.
+ *  @param[in] family The address family.
+ *  @param[in] address The character buffer to be parsed.
+ *  @param[out] data The address data to be filled.
+ *  @returns EOK on success.
+ *  @returns EINVAL if the data parameter is NULL.
+ *  @returns ENOENT if the address parameter is NULL.
+ *  @returns ENOTSUP if the address family is not supported.
+ */
+int	inet_pton( uint16_t family, const char * address, uint8_t * data );
+
+/** Socket address.
+ */
+struct sockaddr{
+	/** Address family.
+	 *  @see socket.h
+	 */
+	uint16_t		sa_family;
+	/** 14 byte protocol address.
+	 */
+	uint8_t			sa_data[ 14 ];
+};
+
+// TODO define address information
+// /** Address information.
+// * \todo
+// */
+//struct addrinfo{
+//	int				ai_flags;		// AI_PASSIVE, AI_CANONNAME, etc.
+//	uint16_t		ai_family;		// AF_INET, AF_INET6, AF_UNSPEC
+//	int				ai_socktype;	// SOCK_STREAM, SOCK_DGRAM
+//	int				ai_protocol;	// use 0 for "any"
+//	size_t			ai_addrlen;		// size of ai_addr in bytes
+//	struct sockaddr *	ai_addr;	// struct sockaddr_in or _in6
+//	char *			ai_canonname;	// full canonical hostname
+//	struct addrinfo *	ai_next;	// linked list, next node
+//};
+
+/*int getaddrinfo(const char *node, // e.g. "www.example.com" or IP
+const char *service, // e.g. "http" or port number
+const struct addrinfo *hints,
+struct addrinfo **res);
+getnameinfo
+*/
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/include/ip_client.h
===================================================================
--- uspace/srv/net/include/ip_client.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/include/ip_client.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,117 @@
+/*
+ * 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 client interface.
+ */
+
+#ifndef __NET_IP_CLIENT_H__
+#define __NET_IP_CLIENT_H__
+
+#include <sys/types.h>
+
+#include "../structures/packet/packet.h"
+
+#include "ip_codes.h"
+#include "ip_interface.h"
+#include "socket_codes.h"
+
+/** 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 (0).
+ *  @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.
+ *  @returns EOK on success.
+ *  @returns 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 );
+
+/** 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.
+ *  @returns The prefixed IP header length in bytes on success.
+ *  @returns 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 );
+
+/** Returns the IP header length.
+ *  @param[in] packet The packet.
+ *  @returns The IP header length in bytes.
+ *  @returns Zero (0) if there is no IP header.
+ */
+size_t	ip_client_header_length( packet_t packet );
+
+/** 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.
+ *  @returns EOK on success.
+ *  @returns EBADMEM if the header parameter is NULL.
+ *  @returns EINVAL if the headerlen parameter is not IPv4 pseudo header length.
+ */
+int	ip_client_set_pseudo_header_data_length( ip_pseudo_header_ref header, size_t headerlen, size_t data_length );
+
+/** 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.
+ *  @returns EOK on success.
+ *  @returns EBADMEM if the header and/or the headerlen parameter is NULL.
+ *  @returns EINVAL if the source address and/or the destination address parameter is NULL.
+ *  @returns EINVAL if the source address length is less than struct sockaddr length.
+ *  @returns EINVAL if the source address length differs from the destination address length.
+ *  @returns EINVAL if the source address family differs from the destination family.
+ *  @returns EAFNOSUPPORT if the address family is not supported.
+ *  @returns 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, ip_pseudo_header_ref * header, size_t * headerlen );
+
+// TODO ipopt manipulation
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/include/ip_codes.h
===================================================================
--- uspace/srv/net/include/ip_codes.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/include/ip_codes.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,374 @@
+/*
+ * 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 codes and definitions.
+ */
+
+#ifndef __NET_IP_CODES_H__
+#define __NET_IP_CODES_H__
+
+#include <sys/types.h>
+
+/** IP time to live counter type definition.
+ */
+typedef uint8_t	ip_ttl_t;
+
+/** IP type of service type definition.
+ */
+typedef uint8_t	ip_tos_t;
+
+/** IP transport protocol type definition.
+ */
+typedef uint8_t	ip_protocol_t;
+
+/** Default IPVERSION.
+ */
+#define IPVERSION	4
+
+/** Maximum time to live counter.
+ */
+#define MAXTTL		255
+
+/** Default time to live counter.
+ */
+#define IPDEFTTL	64
+
+/** @name IP type of service definitions
+ */
+/*@{*/
+
+/** IP TOS mask.
+ */
+#define IPTOS_TOS_MASK				0x1E
+
+/** Precedence shift.
+ */
+#define IPTOS_PRECEDENCE_SHIFT		5
+
+/** Delay shift.
+ */
+#define IPTOS_DELAY_SHIFT			4
+
+/** Throughput shift.
+ */
+#define IPTOS_THROUGHPUT_SHIFT		3
+
+/** Reliability shift.
+ */
+#define IPTOS_RELIABILITY_SHIFT		2
+
+/** Cost shift.
+ */
+#define IPTOS_COST_SHIFT			1
+
+/** Normal delay.
+ */
+#define IPTOS_NORMALDELAY			( 0x0 << IPTOS_DELAY_SHIFT )
+
+/** Low delay.
+ */
+#define IPTOS_LOWDELAY				( 0x1 << IPTOS_DELAY_SHIFT )
+
+/** Normal throughput.
+ */
+#define IPTOS_NORMALTHROUGHPUT		( 0x0 << IPTOS_THROUGHPUT_SHIFT )
+
+/** Throughput.
+ */
+#define IPTOS_THROUGHPUT			( 0x1 << IPTOS_THROUGHPUT_SHIFT )
+
+/** Normal reliability.
+ */
+#define IPTOS_NORMALRELIABILITY		( 0x0 << IPTOS_RELIABILITY_SHIFT )
+
+/** Reliability.
+ */
+#define IPTOS_RELIABILITY			( 0x1 << IPTOS_RELIABILITY_SHIFT )
+
+/** Normal cost.
+ */
+#define IPTOS_NORMALCOST			( 0x0 << IPTOS_COST_SHIFT )
+
+/** Minimum cost.
+ */
+#define IPTOS_MICNCOST				( 0x1 << IPTOS_COST_SHIFT )
+
+/*@}*/
+
+/** @name IP TOS precedence definitions
+ */
+/*@{*/
+
+
+/** Precedence mask.
+ */
+#define IPTOS_PREC_MASK				0xE0
+
+/** Routine precedence.
+ */
+#define IPTOS_PREC_ROUTINE			( 0x0 << IPTOS_PRECEDENCE_SHIFT )
+
+/** Priority precedence.
+ */
+#define IPTOS_PREC_PRIORITY			( 0x1 << IPTOS_PRECEDENCE_SHIFT )
+
+/** Immediate precedence.
+ */
+#define IPTOS_PREC_IMMEDIATE		( 0x2 << IPTOS_PRECEDENCE_SHIFT )
+
+/** Flash precedence.
+ */
+#define IPTOS_PREC_FLASH			( 0x3 << IPTOS_PRECEDENCE_SHIFT )
+
+/** Flash override precedence.
+ */
+#define IPTOS_PREC_FLASHOVERRIDE	( 0x4 << IPTOS_PRECEDENCE_SHIFT )
+
+/** Critical precedence.
+ */
+#define IPTOS_PREC_CRITIC_ECP		( 0x5 << IPTOS_PRECEDENCE_SHIFT )
+
+/** Inter-network control precedence.
+ */
+#define IPTOS_PREC_INTERNETCONTROL	( 0x6 << IPTOS_PRECEDENCE_SHIFT )
+
+/** Network control precedence.
+ */
+#define IPTOS_PREC_NETCONTROL		( 0x7 << IPTOS_PRECEDENCE_SHIFT )
+
+/*@}*/
+
+/** @name IP options definitions
+ */
+/*@{*/
+
+/** Copy shift.
+ */
+#define IPOPT_COPY_SHIFT			7
+
+/** Class shift.
+ */
+#define IPOPT_CLASS_SHIFT			5
+
+/** Number shift.
+ */
+#define IPOPT_NUMBER_SHIFT			0
+
+/** Class mask.
+ */
+#define IPOPT_CLASS_MASK			0x60
+
+/** Number mask.
+ */
+#define IPOPT_NUMBER_MASK			0x1F
+
+/** Copy flag.
+ */
+#define IPOPT_COPY					( 1 << IPOPT_COPY_SHIFT )
+
+/** Returns IP option type.
+ *  @param[in] copy The value indication whether the IP option should be copied.
+ *  @param[in] class The IP option class.
+ *  @param[in] number The IP option number.
+ */
+#define IPOPT_TYPE( copy, class, number )	((( copy ) & IPOPT_COPY ) | (( class ) & IPOPT_CLASS_MASK ) | (( number << IPOPT_NUMBER_SHIFT ) & IPOPT_NUMBER_MASK ))
+
+/** Returns a value indicating whether the IP option should be copied.
+ *  @param[in] o The IP option.
+ */
+#define	IPOPT_COPIED( o )			(( o ) & IPOPT_COPY )
+
+/** Returns an IP option class.
+ *  @param[in] o The IP option.
+ */
+#define	IPOPT_CLASS( o )			(( o ) & IPOPT_CLASS_MASK )
+
+/** Returns an IP option number.
+ *  @param[in] o The IP option.
+ */
+#define	IPOPT_NUMBER( o )			(( o ) & IPOPT_NUMBER_MASK )
+
+/*@}*/
+
+/** @name IP option class definitions
+ */
+/*@{*/
+
+/** Control class.
+ */
+#define	IPOPT_CONTROL				( 0 << IPOPT_CLASS_SHIFT )
+
+/** Reserved class 1.
+ */
+#define	IPOPT_RESERVED1				( 1 << IPOPT_CLASS_SHIFT )
+
+/** Measurement class.
+ */
+#define	IPOPT_MEASUREMENT			( 2 << IPOPT_CLASS_SHIFT )
+
+/** Reserved class 2.
+ */
+#define	IPOPT_RESERVED2				( 3 << IPOPT_CLASS_SHIFT )
+
+/*@}*/
+
+/** @name IP option type definitions
+ */
+/*@{*/
+
+/** End of list.
+ */
+//#define IPOPT_END_OF_LIST			0x0
+#define IPOPT_END					IPOPT_TYPE( 0, IPOPT_CONTROL, 0 )
+
+/** No operation.
+ */
+//#define IPOPT_NO_OPERATION		0x1
+#define IPOPT_NOOP					IPOPT_TYPE( 0, IPOPT_CONTROL, 1 )
+
+/** Security.
+ */
+//#define IPOPT_SECURITY			0x82
+#define IPOPT_SEC					IPOPT_TYPE( IPOPT_COPY, IPOPT_CONTROL, 2 )
+
+/** Loose source.
+ */
+//#define IPOPT_LOOSE_SOURCE		0x83
+#define IPOPT_LSRR					IPOPT_TYPE( IPOPT_COPY, IPOPT_CONTROL, 3 )
+
+/** Strict route.
+ */
+//#define IPOPT_STRICT_SOURCE		0x89
+#define IPOPT_SSRR					IPOPT_TYPE( IPOPT_COPY, IPOPT_CONTROL, 9 )
+
+/** Record route.
+ */
+//#define IPOPT_RECORD_ROUTE		0x07
+#define IPOPT_RR					IPOPT_TYPE( IPOPT_COPY, IPOPT_CONTROL, 7 )
+
+/** Stream identifier.
+ */
+//#define IPOPT_STREAM_IDENTIFIER	0x88
+#define IPOPT_SID					IPOPT_TYPE( IPOPT_COPY, IPOPT_CONTROL, 8 )
+
+/** Stream identifier length.
+ */
+#define IPOPT_SID_LENGTH			4
+
+/** Internet timestamp.
+ */
+//#define IPOPT_INTERNET_TIMESTAMP	0x44
+#define IPOPT_TIMESTAMP				IPOPT_TYPE( IPOPT_COPY, IPOPT_MEASUREMENT, 4 )
+
+/** Commercial IP security option.
+ */
+#define IPOPT_CIPSO					IPOPT_TYPE( IPOPT_COPY, IPOPT_CONTROL, 5 )
+
+/** No operation variant.
+ */
+#define IPOPT_NOP IPOPT_NOOP
+
+/** End of list variant.
+ */
+#define IPOPT_EOL IPOPT_END
+
+/** Timestamp variant.
+ */
+#define IPOPT_TS  IPOPT_TIMESTAMP
+
+/*@}*/
+
+/** @name IP security option definitions
+ */
+/*@{*/
+
+/** Security length.
+ */
+#define IPOPT_SEC_LENGTH			11
+
+/** Unclasified.
+ */
+#define IPOPT_SEC_UNCLASIFIED		0x0
+
+/** Confidential.
+ */
+#define IPOPT_SEC_CONFIDENTIAL		0xF035
+
+/** EFTO.
+ */
+#define IPOPT_SEC_EFTO				0x789A
+
+/** MMMM.
+ */
+#define IPOPT_SEC_MMMM				0xBC4D
+
+/** PROG.
+ */
+#define IPOPT_SEC_PROG				0x5E26
+
+/** Restricted.
+ */
+#define IPOPT_SEC_RESTRICTED		0xAF13
+
+/** Secret.
+ */
+#define IPOPT_SEC_SECRET			0xD788
+
+/** Top secret.
+ */
+#define IPOPT_SEC_TOP_SECRET		0x6BC5
+
+/*@}*/
+
+/** @name IP timestamp option definitions
+ */
+/*@{*/
+
+/** Tiemstamp only.
+ */
+#define	IPOPT_TS_TSONLY		0
+
+/** Timestamps and addresses.
+ */
+#define	IPOPT_TS_TSANDADDR	1
+
+/** Specified modules only.
+ */
+#define	IPOPT_TS_PRESPEC	3
+
+/*@}*/
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/include/ip_interface.h
===================================================================
--- uspace/srv/net/include/ip_interface.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/include/ip_interface.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,179 @@
+/*
+ * 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 interface.
+ *  The same interface is used for standalone remote modules as well as for bundle modules.
+ *  The standalone remote modules have to be compiled with the ip_remote.c source file.
+ *  The bundle modules with the ip.c source file.
+ */
+
+#ifndef __NET_IP_INTERFACE_H__
+#define __NET_IP_INTERFACE_H__
+
+#include <async.h>
+
+#include <ipc/services.h>
+
+#include "../include/device.h"
+
+#include "../structures/packet/packet.h"
+
+#include "in.h"
+#include "ip_codes.h"
+#include "socket_codes.h"
+
+/** @name IP module interface
+ *  This interface is used by other modules.
+ */
+/*@{*/
+
+/** Type definition of the internet pseudo header pointer.
+ */
+typedef void *		ip_pseudo_header_ref;
+
+/** The transport layer notification function type definition.
+ *  Notifies the transport layer modules about the received packet/s.
+ *  @param[in] device_id The device identifier.
+ *  @param[in] packet The received packet or the received packet queue.
+ *  @param[in] receiver The receiving module service.
+ *  @param[in] error The packet error reporting service. Prefixes the received packet.
+ *  @returns EOK on success.
+ */
+typedef int	( * tl_received_msg_t )( device_id_t device_id, packet_t packet, services_t receiver, services_t error );
+
+/** Creates bidirectional connection with the ip module service and registers the message receiver.
+ *  @param[in] service The IP module service.
+ *  @param[in] protocol The transport layer protocol.
+ *  @param[in] me The requesting module service.
+ *  @param[in] receiver The message receiver. Used for remote connection.
+ *  @param[in] tl_received_msg The message processing function. Used if bundled together.
+ *  @returns The phone of the needed service.
+ *  @returns EOK on success.
+ *  @returns Other error codes as defined for the bind_service() function.
+ */
+int	ip_bind_service( services_t service, int protocol, services_t me, async_client_conn_t receiver, tl_received_msg_t tl_received_msg );
+
+/** Registers the new device.
+ *  Registers itself as the ip packet receiver.
+ *  If the device uses ARP registers also the new ARP device.
+ *  @param[in] ip_phone The IP module phone used for (semi)remote calls.
+ *  @param[in] device_id The new device identifier.
+ *  @param[in] netif The underlying device network interface layer service.
+ *  @returns EOK on success.
+ *  @returns ENOMEM if there is not enough memory left.
+ *  @returns EINVAL if the device configuration is invalid.
+ *  @returns ENOTSUP if the device uses IPv6.
+ *  @returns ENOTSUP if the device uses DHCP.
+ *  @returns Other error codes as defined for the net_get_device_conf_req() function.
+ *  @returns Other error codes as defined for the arp_device_req() function.
+ */
+int	ip_device_req( int ip_phone, device_id_t device_id, services_t netif );
+
+/** Sends the packet queue.
+ *  The packets may get fragmented if needed.
+ *  @param[in] ip_phone The IP module phone used for (semi)remote calls.
+ *  @param[in] device_id The device identifier.
+ *  @param[in] packet The packet fragments as a~packet queue. All the packets have to have the same destination address.
+ *  @param[in] sender The sending module service.
+ *  @param[in] error The packet error reporting service. Prefixes the received packet.
+ *  @returns EOK on success.
+ *  @returns Other error codes as defined for the generic_send_msg() function.
+ */
+int	ip_send_msg( int ip_phone, device_id_t device_id, packet_t packet, services_t sender, services_t error );
+
+/** Connects to the IP module.
+ *  @param service The IP module service. Ignored parameter.
+ *  @returns The IP module phone on success.
+ *  @returns 0 if called by the bundle module.
+ */
+int	ip_connect_module( services_t service );
+
+/** Adds a route to the device routing table.
+ *  The target network is routed using this device.
+ *  @param[in] ip_phone The IP module phone used for (semi)remote calls.
+ *  @param[in] device_id The device identifier.
+ *  @param[in] address The target network address.
+ *  @param[in] netmask The target network mask.
+ *  @param[in] gateway The target network gateway. Not used if zero.
+ */
+int	ip_add_route_req( int ip_phone, device_id_t device_id, in_addr_t address, in_addr_t netmask, in_addr_t gateway );
+
+/** Sets the default gateway.
+ *  This gateway is used if no other route is found.
+ *  @param[in] ip_phone The IP module phone used for (semi)remote calls.
+ *  @param[in] device_id The device identifier.
+ *  @param[in] gateway The default gateway.
+ */
+int	ip_set_gateway_req( int ip_phone, device_id_t device_id, in_addr_t gateway );
+
+/** Returns the device packet dimensions for sending.
+ *  @param[in] ip_phone The IP module phone used for (semi)remote calls.
+ *  @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.
+ *  @returns EOK on success.
+ *  @returns EBADMEM if either one of the parameters is NULL.
+ *  @returns ENOENT if there is no such device.
+ *  @returns Other error codes as defined for the generic_packet_size_req() function.
+ */
+int	ip_packet_size_req( int ip_phone, device_id_t device_id, size_t * addr_len, size_t * prefix, size_t * content, size_t * suffix );
+
+/** Notifies the IP module about the received error notification packet.
+ *  @param[in] ip_phone The IP module phone used for (semi)remote calls.
+ *  @param[in] device_id The device identifier.
+ *  @param[in] packet The received packet or the received packet queue.
+ *  @param[in] target The target internetwork module service to be delivered to.
+ *  @param[in] error The packet error reporting service. Prefixes the received packet.
+ *  @returns EOK on success.
+ */
+int	ip_received_error_msg( int ip_phone, device_id_t device_id, packet_t packet, services_t target, services_t error );
+
+/** Returns the device identifier and the IP pseudo header based on the destination address.
+ *  @param[in] ip_phone The IP module phone used for (semi)remote calls.
+ *  @param[in] protocol The transport protocol.
+ *  @param[in] destination The destination address.
+ *  @param[in] addrlen The destination address length.
+ *  @param[out] device_id The device identifier.
+ *  @param[out] header The constructed IP pseudo header.
+ *  @param[out] headerlen The IP pseudo header length.
+ */
+int	ip_get_route_req( int ip_phone, ip_protocol_t protocol, const struct sockaddr * destination, socklen_t addrlen, device_id_t * device_id, ip_pseudo_header_ref * header, size_t * headerlen );
+
+/*@}*/
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/include/ip_protocols.h
===================================================================
--- uspace/srv/net/include/ip_protocols.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/include/ip_protocols.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,619 @@
+/*
+ * 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
+ *  Internet protocol numbers according to the on-line IANA - Assigned Protocol numbers - <http://www.iana.org/assignments/protocol-numbers/protocol-numbers.xml>, cited January 14 2009.
+ */
+
+#ifndef __NET_IPPROTOCOLS_H__
+#define __NET_IPPROTOCOLS_H__
+
+/** @name IP protocols definitions
+ */
+/*@{*/
+
+/** IPv6 Hop-by-Hop Option internet protocol number.
+ */
+#define IPPROTO_HOPOPT		0
+
+/** Internet Control Message internet protocol number.
+ */
+#define IPPROTO_ICMP		1
+
+/** Internet Group Management internet protocol number.
+ */
+#define IPPROTO_IGMP		2
+
+/** Gateway-to-Gateway internet protocol number.
+ */
+#define IPPROTO_GGP		3
+
+/** IP in IP (encapsulation) internet protocol number.
+ */
+#define IPPROTO_IP		4
+
+/** Stream internet protocol number.
+ */
+#define IPPROTO_ST		5
+
+/** Transmission Control internet protocol number.
+ */
+#define IPPROTO_TCP		6
+
+/** CBT internet protocol number.
+ */
+#define IPPROTO_CBT		7
+
+/** Exterior Gateway Protocol internet protocol number.
+ */
+#define IPPROTO_EGP		8
+
+/** any private interior gateway             
+(used by Cisco for their IGRP) internet protocol number.
+ */
+#define IPPROTO_IGP		9
+
+/** BBN RCC Monitoring internet protocol number.
+ */
+#define IPPROTO_BBN_RCC_MON		10
+
+/** Network Voice Protocol internet protocol number.
+ */
+#define IPPROTO_NVP_II		11
+
+/** PUP internet protocol number.
+ */
+#define IPPROTO_PUP		12
+
+/** ARGUS internet protocol number.
+ */
+#define IPPROTO_ARGUS		13
+
+/** EMCON internet protocol number.
+ */
+#define IPPROTO_EMCON		14
+
+/** Cross Net Debugger internet protocol number.
+ */
+#define IPPROTO_XNET		15
+
+/** Chaos internet protocol number.
+ */
+#define IPPROTO_CHAOS		16
+
+/** User Datagram internet protocol number.
+ */
+#define IPPROTO_UDP		17
+
+/** Multiplexing internet protocol number.
+ */
+#define IPPROTO_MUX		18
+
+/** DCN Measurement Subsystems internet protocol number.
+ */
+#define IPPROTO_DCN_MEAS		19
+
+/** Host Monitoring internet protocol number.
+ */
+#define IPPROTO_HMP		20
+
+/** Packet Radio Measurement internet protocol number.
+ */
+#define IPPROTO_PRM		21
+
+/** XEROX NS IDP internet protocol number.
+ */
+#define IPPROTO_XNS_IDP		22
+
+/** Trunk-1 internet protocol number.
+ */
+#define IPPROTO_TRUNK_1		23
+
+/** Trunk-2 internet protocol number.
+ */
+#define IPPROTO_TRUNK_2		24
+
+/** Leaf-1 internet protocol number.
+ */
+#define IPPROTO_LEAF_1		25
+
+/** Leaf-2 internet protocol number.
+ */
+#define IPPROTO_LEAF_2		26
+
+/** Reliable Data Protocol internet protocol number.
+ */
+#define IPPROTO_RDP		27
+
+/** Internet Reliable Transaction internet protocol number.
+ */
+#define IPPROTO_IRTP		28
+
+/** ISO Transport Protocol Class 4 internet protocol number.
+ */
+#define IPPROTO_ISO_TP4		29
+
+/** Bulk Data Transfer Protocol internet protocol number.
+ */
+#define IPPROTO_NETBLT		30
+
+/** MFE Network Services Protocol internet protocol number.
+ */
+#define IPPROTO_MFE_NSP		31
+
+/** MERIT Internodal Protocol internet protocol number.
+ */
+#define IPPROTO_MERIT_INP		32
+
+/** Datagram Congestion Control Protocol internet protocol number.
+ */
+#define IPPROTO_DCCP		33
+
+/** Third Party Connect Protocol internet protocol number.
+ */
+#define IPPROTO_3PC		34
+
+/** Inter-Domain Policy Routing Protocol internet protocol number.
+ */
+#define IPPROTO_IDPR		35
+
+/** XTP internet protocol number.
+ */
+#define IPPROTO_XTP		36
+
+/** Datagram Delivery Protocol internet protocol number.
+ */
+#define IPPROTO_DDP		37
+
+/** IDPR Control Message Transport Proto internet protocol number.
+ */
+#define IPPROTO_IDPR_CMTP		38
+
+/** TP++ Transport Protocol internet protocol number.
+ */
+#define IPPROTO_TP		39
+
+/** IL Transport Protocol internet protocol number.
+ */
+#define IPPROTO_IL		40
+
+/** Ipv6 internet protocol number.
+ */
+#define IPPROTO_IPV6		41
+
+/** Source Demand Routing Protocol internet protocol number.
+ */
+#define IPPROTO_SDRP		42
+
+/** Routing Header for IPv6 internet protocol number.
+ */
+#define IPPROTO_IPv6_Route		43
+
+/** Fragment Header for IPv6 internet protocol number.
+ */
+#define IPPROTO_IPv6_Frag		44
+
+/** Inter-Domain Routing Protocol internet protocol number.
+ */
+#define IPPROTO_IDRP		45
+
+/** Reservation Protocol internet protocol number.
+ */
+#define IPPROTO_RSVP		46
+
+/** General Routing Encapsulation internet protocol number.
+ */
+#define IPPROTO_GRE		47
+
+/** Dynamic Source Routing Protocol internet protocol number.
+ */
+#define IPPROTO_DSR		48
+
+/** BNA internet protocol number.
+ */
+#define IPPROTO_BNA		49
+
+/** Encap Security Payload internet protocol number.
+ */
+#define IPPROTO_ESP		50
+
+/** Authentication Header internet protocol number.
+ */
+#define IPPROTO_AH		51
+
+/** Integrated Net Layer Security  TUBA internet protocol number.
+ */
+#define IPPROTO_I_NLSP		52
+
+/** IP with Encryption internet protocol number.
+ */
+#define IPPROTO_SWIPE		53
+
+/** NBMA Address Resolution Protocol internet protocol number.
+ */
+#define IPPROTO_NARP		54
+
+/** IP Mobility internet protocol number.
+ */
+#define IPPROTO_MOBILE		55
+
+/** Transport Layer Security Protocol        
+using Kryptonet key management internet protocol number.
+ */
+#define IPPROTO_TLSP		56
+
+/** SKIP internet protocol number.
+ */
+#define IPPROTO_SKIP		57
+
+/** ICMP for IPv6 internet protocol number.
+ */
+#define IPPROTO_IPv6_ICMP		58
+
+/** No Next Header for IPv6 internet protocol number.
+ */
+#define IPPROTO_IPv6_NoNxt		59
+
+/** Destination Options for IPv6 internet protocol number.
+ */
+#define IPPROTO_IPv6_Opts		60
+
+/** Any host internal protocol internet protocol number.
+ */
+#define IPPROTO_AHIP		61
+
+/** CFTP internet protocol number.
+ */
+#define IPPROTO_CFTP		62
+
+/** Any local network internet protocol number.
+ */
+#define IPPROTO_ALN		63
+
+/** SATNET and Backroom EXPAK internet protocol number.
+ */
+#define IPPROTO_SAT_EXPAK		64
+
+/** Kryptolan internet protocol number.
+ */
+#define IPPROTO_KRYPTOLAN		65
+
+/** MIT Remote Virtual Disk Protocol internet protocol number.
+ */
+#define IPPROTO_RVD		66
+
+/** Internet Pluribus Packet Core internet protocol number.
+ */
+#define IPPROTO_IPPC		67
+
+/** Any distributed file system internet protocol number.
+ */
+#define IPPROTO_ADFS		68
+
+/** SATNET Monitoring internet protocol number.
+ */
+#define IPPROTO_SAT_MON		69
+
+/** VISA Protocol internet protocol number.
+ */
+#define IPPROTO_VISA		70
+
+/** Internet Packet Core Utility internet protocol number.
+ */
+#define IPPROTO_IPCV		71
+
+/** Computer Protocol Network Executive internet protocol number.
+ */
+#define IPPROTO_CPNX		72
+
+/** Computer Protocol Heart Beat internet protocol number.
+ */
+#define IPPROTO_CPHB		73
+
+/** Wang Span Network internet protocol number.
+ */
+#define IPPROTO_WSN		74
+
+/** Packet Video Protocol internet protocol number.
+ */
+#define IPPROTO_PVP		75
+
+/** Backroom SATNET Monitoring internet protocol number.
+ */
+#define IPPROTO_BR_SAT_MON		76
+
+/** SUN ND IPPROTOCOL_Temporary internet protocol number.
+ */
+#define IPPROTO_SUN_ND		77
+
+/** WIDEBAND Monitoring internet protocol number.
+ */
+#define IPPROTO_WB_MON		78
+
+/** WIDEBAND EXPAK internet protocol number.
+ */
+#define IPPROTO_WB_EXPAK		79
+
+/** ISO Internet Protocol internet protocol number.
+ */
+#define IPPROTO_ISO_IP		80
+
+/** VMTP internet protocol number.
+ */
+#define IPPROTO_VMTP		81
+
+/** SECURE-VMTP internet protocol number.
+ */
+#define IPPROTO_SECURE_VMTP		82
+
+/** VINES internet protocol number.
+ */
+#define IPPROTO_VINES		83
+
+/** TTP internet protocol number.
+ */
+#define IPPROTO_TTP		84
+
+/** NSFNET-IGP internet protocol number.
+ */
+#define IPPROTO_NSFNET_IGP		85
+
+/** Dissimilar Gateway Protocol internet protocol number.
+ */
+#define IPPROTO_DGP		86
+
+/** TCF internet protocol number.
+ */
+#define IPPROTO_TCF		87
+
+/** EIGRP internet protocol number.
+ */
+#define IPPROTO_EIGRP		88
+
+/** OSPFIGP internet protocol number.
+ */
+#define IPPROTO_OSPFIGP		89
+
+/** Sprite RPC Protocol internet protocol number.
+ */
+#define IPPROTO_Sprite_RPC		90
+
+/** Locus Address Resolution Protocol internet protocol number.
+ */
+#define IPPROTO_LARP		91
+
+/** Multicast Transport Protocol internet protocol number.
+ */
+#define IPPROTO_MTP		92
+
+/** AX.25 Frames internet protocol number.
+ */
+#define IPPROTO_AX25		93
+
+/** IP-within-IP Encapsulation Protocol internet protocol number.
+ */
+#define IPPROTO_IPIP		94
+
+/** Mobile Internetworking Control Pro. internet protocol number.
+ */
+#define IPPROTO_MICP		95
+
+/** Semaphore Communications Sec. Pro. internet protocol number.
+ */
+#define IPPROTO_SCC_SP		96
+
+/** Ethernet-within-IP Encapsulation internet protocol number.
+ */
+#define IPPROTO_ETHERIP		97
+
+/** Encapsulation Header internet protocol number.
+ */
+#define IPPROTO_ENCAP		98
+
+/** Any private encryption scheme internet protocol number.
+ */
+#define IPPROTO_APES		99
+
+/** GMTP internet protocol number.
+ */
+#define IPPROTO_GMTP		100
+
+/** Ipsilon Flow Management Protocol internet protocol number.
+ */
+#define IPPROTO_IFMP		101
+
+/** PNNI over IP internet protocol number.
+ */
+#define IPPROTO_PNNI		102
+
+/** Protocol Independent Multicast internet protocol number.
+ */
+#define IPPROTO_PIM		103
+
+/** ARIS internet protocol number.
+ */
+#define IPPROTO_ARIS		104
+
+/** SCPS internet protocol number.
+ */
+#define IPPROTO_SCPS		105
+
+/** QNX internet protocol number.
+ */
+#define IPPROTO_QNX		106
+
+/** Active Networks internet protocol number.
+ */
+#define IPPROTO_AN		107
+
+/** IP Payload Compression Protocol internet protocol number.
+ */
+#define IPPROTO_IPComp		108
+
+/** Sitara Networks Protocol internet protocol number.
+ */
+#define IPPROTO_SNP		109
+
+/** Compaq Peer Protocol internet protocol number.
+ */
+#define IPPROTO_Compaq_Peer		110
+
+/** IPX in IP internet protocol number.
+ */
+#define IPPROTO_IPX_in_IP		111
+
+/** Virtual Router Redundancy Protocol internet protocol number.
+ */
+#define IPPROTO_VRRP		112
+
+/** PGM Reliable Transport Protocol internet protocol number.
+ */
+#define IPPROTO_PGM		113
+
+/** Any 0-hop protocol internet protocol number.
+ */
+#define IPPROTO_A0HP		114
+
+/** Layer Two Tunneling Protocol internet protocol number.
+ */
+#define IPPROTO_L2TP		115
+
+/** D-II Data Exchange (DDX) internet protocol number.
+ */
+#define IPPROTO_DDX		116
+
+/** Interactive Agent Transfer Protocol internet protocol number.
+ */
+#define IPPROTO_IATP		117
+
+/** Schedule Transfer Protocol internet protocol number.
+ */
+#define IPPROTO_STP		118
+
+/** SpectraLink Radio Protocol internet protocol number.
+ */
+#define IPPROTO_SRP		119
+
+/** UTI internet protocol number.
+ */
+#define IPPROTO_UTI		120
+
+/** Simple Message Protocol internet protocol number.
+ */
+#define IPPROTO_SMP		121
+
+/** SM internet protocol number.
+ */
+#define IPPROTO_SM		122
+
+/** Performance Transparency Protocol internet protocol number.
+ */
+#define IPPROTO_PTP		123
+
+/** ISIS over IPv4 internet protocol number.
+ */
+#define IPPROTO_ISIS		124
+
+/** FIRE internet protocol number.
+ */
+#define IPPROTO_FIRE		125
+
+/** Combat Radio Transport Protocol internet protocol number.
+ */
+#define IPPROTO_CRTP		126
+
+/** Combat Radio User Datagram internet protocol number.
+ */
+#define IPPROTO_CRUDP		127
+
+/** SSCOPMCE internet protocol number.
+ */
+#define IPPROTO_SSCOPMCE		128
+
+/** IPLT internet protocol number.
+ */
+#define IPPROTO_IPLT		129
+
+/** Secure Packet Shield internet protocol number.
+ */
+#define IPPROTO_SPS		130
+
+/** Private IP Encapsulation within IP internet protocol number.
+ */
+#define IPPROTO_PIPE		131
+
+/** Stream Control Transmission Protocol internet protocol number.
+ */
+#define IPPROTO_SCTP		132
+
+/** Fibre Channel internet protocol number.
+ */
+#define IPPROTO_FC		133
+
+/** RSVP-E2E-IGNORE internet protocol number.
+ */
+#define IPPROTO_RSVP_E2E_IGNORE		134
+
+/** Mobility Header internet protocol number.
+ */
+#define IPPROTO_MH		135
+
+/** UDPLite internet protocol number.
+ */
+#define IPPROTO_UDPLITE		136
+
+/** MPLS-in-IP internet protocol number.
+ */
+#define IPPROTO_MPLS_in_IP		137
+
+/** MANET Protocols internet protocol number.
+ */
+#define IPPROTO_manet		138
+
+/** Host Identity Protocol internet protocol number.
+ */
+#define IPPROTO_HIP		139
+
+/** Raw internet protocol number.
+ */
+#define IPPROTO_RAW		255
+
+/** Maximum internet protocol number.
+ */
+#define IPPROTO_MAX		( IPPROTO_RAW + 1 )
+
+/*@}*/
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/include/net_interface.h
===================================================================
--- uspace/srv/net/include/net_interface.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/include/net_interface.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup net
+ *  @{
+ */
+
+/** @file
+ *  Networking module interface.
+ *  The same interface is used for standalone remote modules as well as for bundle modules.
+ *  The standalone remote modules have to be compiled with the net_remote.c source file.
+ *  The bundle networking module is compiled with the net_bundle.c source file and the choosen bundle module implementation source files.
+ */
+
+#ifndef __NET_NET_INTERFACE_H__
+#define __NET_NET_INTERFACE_H__
+
+#include <ipc/services.h>
+
+#include "../include/device.h"
+
+#include "../structures/measured_strings.h"
+
+/** @name Networking module interface
+ *  This interface is used by other modules.
+ */
+/*@{*/
+
+/** Returns the device specific configuration.
+ *  Returns 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] net_phone The networking module phone.
+ *  @param[in] device_id The device identifier.
+ *  @param[in,out] configuration The requested device configuration. The names are read and the appropriate settings are set instead.
+ *  @param[in] count The configuration entries count.
+ *  @param[in,out] data The configuration and settings data.
+ *  @returns EOK on success.
+ *  @returns EINVAL if the configuration is NULL.
+ *  @returns EINVAL if the count is zero (0).
+ *  @returns Other error codes as defined for the generic_translate_req() function.
+ */
+int	net_get_device_conf_req( int net_phone, device_id_t device_id, measured_string_ref * configuration, size_t count, char ** data );
+
+/** Returns 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] net_phone The networking module phone.
+ *  @param[in,out] configuration The requested configuration. The names are read and the appropriate settings are set instead.
+ *  @param[in] count The configuration entries count.
+ *  @param[in,out] data The configuration and settings data.
+ *  @returns EOK on success.
+ *  @returns EINVAL if the configuration is NULL.
+ *  @returns EINVAL if the count is zero (0).
+ *  @returns Other error codes as defined for the generic_translate_req() function.
+ */
+int	net_get_conf_req( int net_phone, measured_string_ref * configuration, size_t count, char ** data );
+
+/** Frees the received settings.
+ *  @param[in] settings The received settings.
+ *  @param[in] data The received settings data.
+ *  @see net_get_device_conf_req()
+ *  @see net_get_conf_req()
+ */
+void	net_free_settings( measured_string_ref settings, char * data );
+
+/** Connects to the networking module.
+ *  @param service The networking module service. Ignored parameter.
+ *  @returns The networking module phone on success.
+ *  @returns 0 if called by the bundle module.
+ */
+int	net_connect_module( services_t service );
+
+/*@}*/
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/include/netdb.h
===================================================================
--- uspace/srv/net/include/netdb.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/include/netdb.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,109 @@
+/*
+ * 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 netdb
+ *  @{
+ */
+
+/** @file
+ *  Structures and interfaces according to the BSD netdb.h file.
+ */
+
+#ifndef __NET_NETDB_H__
+#define __NET_NETDB_H__
+
+#include <sys/types.h>
+
+/** Structure returned by network data base library.
+ *  All addresses are supplied in host order, and returned in network order (suitable for use in system calls).
+ */
+struct	hostent {
+	/** Official host name.
+	 */
+	char *	h_name;
+	/** Alias list.
+	 */
+	char **	h_aliases;
+	/** Host address type.
+	 */
+	int		h_addrtype;
+	/** Address length.
+	 */
+	int		h_length;
+	/** List of addresses from name server.
+	 */
+	char **	h_addr_list;
+	/** Address, for backward compatiblity.
+	 */
+#define	h_addr	h_addr_list[ 0 ]
+};
+
+/** @name Host entry address types definitions.
+ */
+/*@{*/
+
+/** Authoritative Answer Host not found address type.
+ */
+#define	HOST_NOT_FOUND	1
+
+/** Non-Authoritive Host not found, or SERVERFAIL address type.
+ */
+#define	TRY_AGAIN	2
+
+/** Non recoverable errors, FORMERR, REFUSED, NOTIMP address type.
+ */
+#define	NO_RECOVERY	3
+
+/** Valid name, no data record of requested type address type.
+ */
+#define	NO_DATA		4
+
+/** No address, look for MX record address type.
+ */
+#define	NO_ADDRESS	NO_DATA
+
+/*@}*/
+
+/** Returns host entry by the host address.
+ *  @param[in] address The host address.
+ *  @param[in] len The address length.
+ *  @param[in] type The address type.
+ *  @returns Host entry information.
+ */
+//struct hostent *	gethostbyaddr( const void * address, int len, int type );
+
+/** Returns host entry by the host name.
+ *  @param[in] name The host name.
+ *  @returns Host entry information.
+ */
+//struct hostent *	gethostbyname( const char * name );
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/include/netif_interface.h
===================================================================
--- uspace/srv/net/include/netif_interface.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/include/netif_interface.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,131 @@
+/*
+ * 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
+ *  @{
+ */
+
+/** @file
+ *  Network interface module interface.
+ *  The same interface is used for standalone remote modules as well as for bundle network interface layer modules.
+ *  The standalone remote modules have to be compiled with the netif_remote.c source file.
+ *  The bundle network interface layer modules are compiled with the netif_nil_bundle.c source file and the choosen network interface layer implementation source file.
+ */
+
+#ifndef __NET_NETIF_INTERFACE_H__
+#define __NET_NETIF_INTERFACE_H__
+
+#include <ipc/services.h>
+
+#include "../messages.h"
+
+#include "../structures/measured_strings.h"
+#include "../structures/packet/packet.h"
+
+#include "device.h"
+
+/** @name Network interface module interface
+ *  This interface is used by other modules.
+ */
+/*@{*/
+
+/** Returns the device local hardware address.
+ *  @param[in] netif_phone The network interface phone.
+ *  @param[in] device_id The device identifier.
+ *  @param[out] address The device local hardware address.
+ *  @param[out] data The address data.
+ *  @returns EOK on success.
+ *  @returns EBADMEM if the address parameter is NULL.
+ *  @returns ENOENT if there no such device.
+ *  @returns Other error codes as defined for the netif_get_addr_message() function.
+ */
+int	netif_get_addr_req( int netif_phone, device_id_t device_id, measured_string_ref * address, char ** data );
+
+/** Probes the existence of the device.
+ *  @param[in] netif_phone The network interface phone.
+ *  @param[in] device_id The device identifier.
+ *  @param[in] irq The device interrupt number.
+ *  @param[in] io The device input/output address.
+ *  @returns EOK on success.
+ *  @returns Other errro codes as defined for the netif_probe_message().
+ */
+int	netif_probe_req( int netif_phone, device_id_t device_id, int irq, int io );
+
+/** Sends the packet queue.
+ *  @param[in] netif_phone The network interface phone.
+ *  @param[in] device_id The device identifier.
+ *  @param[in] packet The packet queue.
+ *  @param[in] sender The sending module service.
+ *  @returns EOK on success.
+ *  @returns Other error codes as defined for the generic_send_msg() function.
+ */
+int	netif_send_msg( int netif_phone, device_id_t device_id, packet_t packet, services_t sender );
+
+/** Starts the device.
+ *  @param[in] netif_phone The network interface phone.
+ *  @param[in] device_id The device identifier.
+ *  @returns EOK on success.
+ *  @returns Other error codes as defined for the find_device() function.
+ *  @returns Other error codes as defined for the netif_start_message() function.
+ */
+int	netif_start_req( int netif_phone, device_id_t device_id );
+
+/** Stops the device.
+ *  @param[in] netif_phone The network interface phone.
+ *  @param[in] device_id The device identifier.
+ *  @returns EOK on success.
+ *  @returns Other error codes as defined for the find_device() function.
+ *  @returns Other error codes as defined for the netif_stop_message() function.
+ */
+int	netif_stop_req( int netif_phone, device_id_t device_id );
+
+/** Returns the device usage statistics.
+ *  @param[in] netif_phone The network interface phone.
+ *  @param[in] device_id The device identifier.
+ *  @param[out] stats The device usage statistics.
+ *  @returns EOK on success.
+ */
+int	netif_stats_req( int netif_phone, device_id_t device_id, device_stats_ref stats );
+
+/** Creates bidirectional connection with the network interface module and registers the message receiver.
+ *  @param[in] service The network interface module service.
+ *  @param[in] device_id The device identifier.
+ *  @param[in] me The requesting module service.
+ *  @param[in] receiver The message receiver.
+ *  @returns The phone of the needed service.
+ *  @returns EOK on success.
+ *  @returns Other error codes as defined for the bind_service() function.
+ */
+int	netif_bind_service( services_t service, device_id_t device_id, services_t me, async_client_conn_t receiver );
+
+/*@}*/
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/include/nil_interface.h
===================================================================
--- uspace/srv/net/include/nil_interface.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/include/nil_interface.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup net_nil
+ *  @{
+ */
+
+/** @file
+ *  Network interface layer module interface.
+ *  The same interface is used for standalone remote device modules as well as for bundle device modules.
+ *  The standalone remote device modules have to be compiled with the nil_remote.c source file.
+ *  The bundle device modules with the appropriate network interface layer source file (eth.c etc.).
+ *  The upper layers cannot be bundled with the network interface layer.
+ */
+
+#ifndef __NET_NIL_INTERFACE_H__
+#define __NET_NIL_INTERFACE_H__
+
+#include <async.h>
+#include <errno.h>
+
+#include <ipc/ipc.h>
+
+#include "../messages.h"
+
+#include "../structures/measured_strings.h"
+#include "../structures/packet/packet.h"
+
+#include "../nil/nil_messages.h"
+
+#include "device.h"
+
+/** @name Network interface layer module interface
+ *  This interface is used by other modules.
+ */
+/*@{*/
+
+/** Returns the device local hardware address.
+ *  @param[in] nil_phone The network interface layer phone.
+ *  @param[in] device_id The device identifier.
+ *  @param[out] address The device local hardware address.
+ *  @param[out] data The address data.
+ *  @returns EOK on success.
+ *  @returns EBADMEM if the address parameter and/or the data parameter is NULL.
+ *  @returns ENOENT if there no such device.
+ *  @returns Other error codes as defined for the generic_get_addr_req() function.
+ */
+#define nil_get_addr_req( nil_phone, device_id, address, data )	\
+	generic_get_addr_req( nil_phone, NET_NIL_ADDR, device_id, address, data )
+
+/** Returns the device broadcast hardware address.
+ *  @param[in] nil_phone The network interface layer phone.
+ *  @param[in] device_id The device identifier.
+ *  @param[out] address The device broadcast hardware address.
+ *  @param[out] data The address data.
+ *  @returns EOK on success.
+ *  @returns EBADMEM if the address parameter is NULL.
+ *  @returns ENOENT if there no such device.
+ *  @returns Other error codes as defined for the generic_get_addr_req() function.
+ */
+#define nil_get_broadcast_addr_req( nil_phone, device_id, address, data )	\
+	generic_get_addr_req( nil_phone, NET_NIL_BROADCAST_ADDR, device_id, address, data )
+
+/** Sends the packet queue.
+ *  @param[in] nil_phone The network interface layer phone.
+ *  @param[in] device_id The device identifier.
+ *  @param[in] packet The packet queue.
+ *  @param[in] sender The sending module service.
+ *  @returns EOK on success.
+ *  @returns Other error codes as defined for the generic_send_msg() function.
+ */
+#define nil_send_msg( nil_phone, device_id, packet, sender )	\
+	generic_send_msg( nil_phone, NET_NIL_SEND, device_id, packet_get_id( packet ), sender, 0 )
+
+/** Returns the device packet dimensions for sending.
+ *  @param[in] nil_phone The network interface layer phone.
+ *  @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.
+ *  @returns EOK on success.
+ *  @returns EBADMEM if either one of the parameters is NULL.
+ *  @returns ENOENT if there is no such device.
+ *  @returns Other error codes as defined for the generic_packet_size_req() function.
+ */
+#define nil_packet_size_req( nil_phone, device_id, addr_len, prefix, content, suffix )	\
+	generic_packet_size_req( nil_phone, NET_NIL_PACKET_SPACE, device_id, addr_len, prefix, content, suffix )
+
+/** Registers new device or updates the MTU of an existing one.
+ *  @param[in] nil_phone The network interface layer phone.
+ *  @param[in] device_id The new device identifier.
+ *  @param[in] mtu The device maximum transmission unit.
+ *  @param[in] netif_service The device driver service.
+ *  @returns EOK on success.
+ *  @returns EEXIST if the device with the different service exists.
+ *  @returns ENOMEM if there is not enough memory left.
+ *  @returns Other error codes as defined for the generic_device_req() function.
+ */
+#define nil_device_req( nil_phone, device_id, mtu, netif_service )	\
+	generic_device_req( nil_phone, NET_NIL_DEVICE, device_id, mtu, netif_service )
+
+/** Notifies the network interface layer about the device state change.
+ *  @param[in] nil_phone The network interface layer phone.
+ *  @param[in] device_id The device identifier.
+ *  @param[in] state The new device state.
+ *  @returns EOK on success.
+ *  @returns Other error codes as defined for each specific module device state function.
+ */
+int nil_device_state_msg( int nil_phone, device_id_t device_id, int state );
+
+/** Passes the packet queue to the network interface layer.
+ *  Processes and redistributes the received packet queue to the registered upper layers.
+ *  @param[in] nil_phone The network interface layer phone.
+ *  @param[in] device_id The source device identifier.
+ *  @param[in] packet The received packet or the received packet queue.
+ *  @param target The target service. Ignored parameter.
+ *  @returns EOK on success.
+ *  @returns Other error codes as defined for each specific module received function.
+ */
+int nil_received_msg( int nil_phone, device_id_t device_id, packet_t packet, services_t target );
+
+/** Creates bidirectional connection with the network interface layer module and registers the message receiver.
+ *  @param[in] service The network interface layer module service.
+ *  @param[in] device_id The device identifier.
+ *  @param[in] me The requesting module service.
+ *  @param[in] receiver The message receiver.
+ *  @returns The phone of the needed service.
+ *  @returns EOK on success.
+ *  @returns Other error codes as defined for the bind_service() function.
+ */
+#define	nil_bind_service( service, device_id, me, receiver )	\
+	bind_service( service, device_id, me, 0, receiver );
+/*@}*/
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/include/protocol_map.h
===================================================================
--- uspace/srv/net/include/protocol_map.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/include/protocol_map.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup net_nil
+ *  @{
+ */
+
+/** @file
+ *  Internetwork layer services - network interface layer service type translation.
+ */
+
+#ifndef __NET_PROTOCOL_MAP_H__
+#define __NET_PROTOCOL_MAP_H__
+
+#include <ipc/services.h>
+
+#include "ethernet_lsap.h"
+#include "ethernet_protocols.h"
+#include "hardware.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.
+ *  @returns Network interface layer type of the internetworking layer service.
+ *  @returns 0 if mapping is not found.
+ */
+static inline eth_type_t protocol_map( services_t nil, services_t il ){
+	switch( nil ){
+		case SERVICE_ETHERNET:
+		case SERVICE_DP8390:
+			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.
+ *  @returns Internetwork layer service of the network interface layer type.
+ *  @returns 0 if mapping is not found.
+ */
+static inline services_t protocol_unmap( services_t nil, int protocol ){
+	switch( nil ){
+		case SERVICE_ETHERNET:
+		case SERVICE_DP8390:
+			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.
+ *  @returns Ethernet protocol identifier of the link service access point identifier.
+ *  @returns ETH_LSAP_NULL if mapping is not found.
+ */
+static inline 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.
+ *  @returns Link service access point identifier.
+ *  @returns 0 if mapping is not found.
+ */
+static inline 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.
+ *  @returns The hardware type of the network interface service.
+ *  @returns 0 if mapping is not found.
+ */
+static inline hw_type_t hardware_map( services_t nil ){
+	switch( nil ){
+		case SERVICE_ETHERNET:
+		case SERVICE_DP8390:
+			return HW_ETHER;
+		default:
+			return 0;
+	}
+}
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/include/socket.h
===================================================================
--- uspace/srv/net/include/socket.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/include/socket.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,214 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup socket
+ *  @{
+ */
+
+/** @file
+ *  Socket application program interface (API).
+ *  This is a part of the network application library.
+ *  Based on the BSD socket interface.
+ */
+
+#ifndef __NET_SOCKET_H__
+#define __NET_SOCKET_H__
+
+#include "byteorder.h"
+#include "in.h"
+#include "in6.h"
+#include "inet.h"
+
+#include "socket_codes.h"
+#include "socket_errno.h"
+
+/** @name Socket application programming interface
+ */
+/*@{*/
+
+/** Creates a new socket.
+ *  @param[in] domain The socket protocol family.
+ *  @param[in] type Socket type.
+ *  @param[in] protocol Socket protocol.
+ *  @returns The socket identifier on success.
+ *  @returns EPFNOTSUPPORT if the protocol family is not supported.
+ *  @returns ESOCKNOTSUPPORT if the socket type is not supported.
+ *  @returns EPROTONOSUPPORT if the protocol is not supported.
+ *  @returns ENOMEM if there is not enough memory left.
+ *  @returns Other error codes as defined for the NET_SOCKET message.
+ *  @returns Other error codes as defined for the bind_service_timeout() function.
+ */
+int	socket( int domain, int type, int protocol );
+
+/** Binds the socket to a port address.
+ *  @param[in] socket_id Socket identifier.
+ *  @param[in] my_addr The port address.
+ *  @param[in] addrlen The address length.
+ *  @returns EOK on success.
+ *  @returns ENOTSOCK if the socket is not found.
+ *  @returns EBADMEM if the my_addr parameter is NULL.
+ *  @returns NO_DATA if the addlen parameter is zero (0).
+ *  @returns Other error codes as defined for the NET_SOCKET_BIND message.
+ */
+int	bind( int socket_id, const struct sockaddr * my_addr, socklen_t addrlen );
+
+/** Sets the number of connections waiting to be accepted.
+ *  @param[in] socket_id Socket identifier.
+ *  @param[in] backlog The maximum number of waiting sockets to be accepted.
+ *  @returns EOK on success.
+ *  @returns EINVAL if the backlog parameter is not positive (<=0).
+ *  @returns ENOTSOCK if the socket is not found.
+ *  @returns Other error codes as defined for the NET_SOCKET_LISTEN message.
+ */
+int	listen( int socket_id, int backlog );
+
+/** Accepts waiting socket.
+ *  Blocks until such a socket exists.
+ *  @param[in] socket_id Socket identifier.
+ *  @param[out] cliaddr The remote client address.
+ *  @param[in] addrlen The address length.
+ *  @returns EOK on success.
+ *  @returns EBADMEM if the cliaddr or addrlen parameter is NULL.
+ *  @returns EINVAL if the backlog parameter is not positive (<=0).
+ *  @returns ENOTSOCK if the socket is not found.
+ *  @returns Other error codes as defined for the NET_SOCKET_ACCEPT message.
+ */
+int	accept( int socket_id, struct sockaddr * cliaddr, socklen_t * addrlen );
+
+/** Connects socket to the remote server.
+ *  @param[in] socket_id Socket identifier.
+ *  @param[in] serv_addr The remote server address.
+ *  @param[in] addrlen The address length.
+ *  @returns EOK on success.
+ *  @returns EBADMEM if the serv_addr parameter is NULL.
+ *  @returns NO_DATA if the addlen parameter is zero (0).
+ *  @returns ENOTSOCK if the socket is not found.
+ *  @returns Other error codes as defined for the NET_SOCKET_CONNECT message.
+ */
+int	connect( int socket_id, const struct sockaddr * serv_addr, socklen_t addrlen );
+
+/** Closes the socket.
+ *  @param[in] socket_id Socket identifier.
+ *  @returns EOK on success.
+ *  @returns ENOTSOCK if the socket is not found.
+ *  @returns EINPROGRESS if there is another blocking function in progress.
+ *  @returns Other error codes as defined for the NET_SOCKET_CLOSE message.
+ */
+int	closesocket( int socket_id );
+
+/** Sends data via the socket.
+ *  @param[in] socket_id Socket identifier.
+ *  @param[in] data The data to be sent.
+ *  @param[in] datalength The data length.
+ *  @param[in] flags Various send flags.
+ *  @returns EOK on success.
+ *  @returns ENOTSOCK if the socket is not found.
+ *  @returns EBADMEM if the data parameter is NULL.
+ *  @returns NO_DATA if the datalength parameter is zero (0).
+ *  @returns Other error codes as defined for the NET_SOCKET_SEND message.
+ */
+int send( int socket_id, void * data, size_t datalength, int flags );
+
+/** Sends data via the socket to the remote address.
+ *  Binds the socket to a free port if not already connected/bound.
+ *  @param[in] socket_id Socket identifier.
+ *  @param[in] data The data to be sent.
+ *  @param[in] datalength The data length.
+ *  @param[in] flags Various send flags.
+ *  @param[in] toaddr The destination address.
+ *  @param[in] addrlen The address length.
+ *  @returns EOK on success.
+ *  @returns ENOTSOCK if the socket is not found.
+ *  @returns EBADMEM if the data or toaddr parameter is NULL.
+ *  @returns NO_DATA if the datalength or the addrlen parameter is zero (0).
+ *  @returns Other error codes as defined for the NET_SOCKET_SENDTO message.
+ */
+int sendto( int socket_id, const void * data, size_t datalength, int flags, const struct sockaddr * toaddr, socklen_t addrlen );
+
+/** Receives data via the socket.
+ *  @param[in] socket_id Socket identifier.
+ *  @param[out] data The data buffer to be filled.
+ *  @param[in] datalength The data length.
+ *  @param[in] flags Various receive flags.
+ *  @returns EOK on success.
+ *  @returns ENOTSOCK if the socket is not found.
+ *  @returns EBADMEM if the data parameter is NULL.
+ *  @returns NO_DATA if the datalength parameter is zero (0).
+ *  @returns Other error codes as defined for the NET_SOCKET_RECV message.
+ */
+int recv( int socket_id, void * data, size_t datalength, int flags );
+
+/** Receives data via the socket.
+ *  @param[in] socket_id Socket identifier.
+ *  @param[out] data The data buffer to be filled.
+ *  @param[in] datalength The data length.
+ *  @param[in] flags Various receive flags.
+ *  @param[out] fromaddr The source address.
+ *  @param[in,out] addrlen The address length. The maximum address length is read. The actual address length is set.
+ *  @returns EOK on success.
+ *  @returns ENOTSOCK if the socket is not found.
+ *  @returns EBADMEM if the data or fromaddr parameter is NULL.
+ *  @returns NO_DATA if the datalength or addrlen parameter is zero (0).
+ *  @returns Other error codes as defined for the NET_SOCKET_RECVFROM message.
+ */
+int recvfrom( int socket_id, void * data, size_t datalength, int flags, struct sockaddr * fromaddr, socklen_t * addrlen );
+
+/** Gets socket option.
+ *  @param[in] socket_id Socket identifier.
+ *  @param[in] level The socket options level.
+ *  @param[in] optname The socket option to be get.
+ *  @param[out] value The value buffer to be filled.
+ *  @param[in,out] optlen The value buffer length. The maximum length is read. The actual length is set.
+ *  @returns EOK on success.
+ *  @returns ENOTSOCK if the socket is not found.
+ *  @returns EBADMEM if the value or optlen parameter is NULL.
+ *  @returns NO_DATA if the optlen parameter is zero (0).
+ *  @returns Other error codes as defined for the NET_SOCKET_GETSOCKOPT message.
+ */
+int	getsockopt( int socket_id, int level, int optname, void * value, size_t * optlen );
+
+/** Sets socket option.
+ *  @param[in] socket_id Socket identifier.
+ *  @param[in] level The socket options level.
+ *  @param[in] optname The socket option to be set.
+ *  @param[in] value The value to be set.
+ *  @param[in] optlen The value length.
+ *  @returns EOK on success.
+ *  @returns ENOTSOCK if the socket is not found.
+ *  @returns EBADMEM if the value parameter is NULL.
+ *  @returns NO_DATA if the optlen parameter is zero (0).
+ *  @returns Other error codes as defined for the NET_SOCKET_SETSOCKOPT message.
+ */
+int	setsockopt( int socket_id, int level, int optname, const void * value, size_t optlen );
+
+/*@}*/
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/include/socket_codes.h
===================================================================
--- uspace/srv/net/include/socket_codes.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/include/socket_codes.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,460 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup socket
+ *  @{
+ */
+
+/** @file
+ *  Socket codes and definitions.
+ *  This is a part of the network application library.
+ */
+
+#ifndef __NET_SOCKET_CODES_H__
+#define __NET_SOCKET_CODES_H__
+
+#include <sys/types.h>
+
+/** @name Address families definitions
+ */
+/*@{*/
+
+/** Unspecified address family.
+ */
+#define AF_UNSPEC	0
+
+/** Unix domain sockets address family.
+ */
+#define AF_UNIXL	1
+
+/** POSIX name for AF_UNIX address family.
+ */
+#define AF_LOCAL	1
+
+/** Internet IP Protocol address family.
+ */
+#define AF_INET		2
+
+/** Amateur Radio AX.25 address family.
+ */
+#define AF_AX25		3
+
+/** Novell IPX address family.
+ */
+#define AF_IPX		4
+
+/** AppleTalk DDP address family.
+ */
+#define AF_APPLETALK	5
+
+/** Amateur Radio NET/ROM address family.
+ */
+#define AF_NETROM	6
+
+/** Multiprotocol bridge address family.
+ */
+#define AF_BRIDGE	7
+
+/** ATM PVCs address family.
+ */
+#define AF_ATMPVC	8
+
+/** Reserved for X.25 project address family.
+ */
+#define AF_X25		9
+
+/** IP version 6 address family.
+ */
+#define AF_INET6	10
+
+/** Amateur Radio X.25 PLP address family.
+ */
+#define AF_ROSE		11
+
+/** Reserved for DECnet project address family.
+ */
+#define AF_DECnet	12
+
+/** Reserved for 802.2LLC project address family.
+ */
+#define AF_NETBEUI	13
+
+/** Security callback pseudo AF address family.
+ */
+#define AF_SECURITY	14
+
+/** PF_KEY key management API address family.
+ */
+#define AF_KEY		15
+
+/** Alias to emulate 4.4BSD address family.
+ */
+#define AF_NETLINK	16
+
+/** Packet family address family.
+ */
+#define AF_PACKET	17
+
+/** Ash address family.
+ */
+#define AF_ASH		18
+
+/** Acorn Econet address family.
+ */
+#define AF_ECONET	19
+
+/** ATM SVCs address family.
+ */
+#define AF_ATMSVC	20
+
+/** Linux SNA Project (nutters!) address family.
+ */
+#define AF_SNA		22
+
+/** IRDA sockets address family.
+ */
+#define AF_IRDA		23
+
+/** PPPoX sockets address family.
+ */
+#define AF_PPPOX	24
+
+/** Wanpipe API Sockets address family.
+ */
+#define AF_WANPIPE	25
+
+/** Linux LLC address family.
+ */
+#define AF_LLC		26
+
+/** Controller Area Network address family.
+ */
+#define AF_CAN		29
+
+/** TIPC sockets address family.
+ */
+#define AF_TIPC		30
+
+/** Bluetooth sockets address family.
+ */
+#define AF_BLUETOOTH	31
+
+/** IUCV sockets address family.
+ */
+#define AF_IUCV		32
+
+/** RxRPC sockets address family.
+ */
+#define AF_RXRPC	33
+
+/** Maximum address family.
+ */
+#define AF_MAX		34
+
+/*@}*/
+
+/** @name Protocol families definitions
+ *  Same as address families.
+ */
+/*@{*/
+
+/** Unspecified protocol family.
+ */
+#define PF_UNSPEC	AF_UNSPEC
+
+/** Unix domain sockets protocol family.
+ */
+#define PF_UNIXL	AF_UNIXL
+
+/** POSIX name for AF_UNIX protocol family.
+ */
+#define PF_LOCAL	AF_LOCAL
+
+/** Internet IP Protocol protocol family.
+ */
+#define PF_INET		AF_INET
+
+/** Amateur Radio AX.25 protocol family.
+ */
+#define PF_AX25		AF_AX25
+
+/** Novell IPX protocol family.
+ */
+#define PF_IPX		AF_IPX
+
+/** AppleTalk DDP protocol family.
+ */
+#define PF_APPLETALK	AF_APPLETALK
+
+/** Amateur Radio NET/ROM protocol family.
+ */
+#define PF_NETROM	AF_NETROM
+
+/** Multiprotocol bridge protocol family.
+ */
+#define PF_BRIDGE	AF_BRIDGE
+
+/** ATM PVCs protocol family.
+ */
+#define PF_ATMPVC	AF_ATMPVC
+
+/** Reserved for X.25 project protocol family.
+ */
+#define PF_X25		AF_X25
+
+/** IP version 6 protocol family.
+ */
+#define PF_INET6	AF_INET6
+
+/** Amateur Radio X.25 PLP protocol family.
+ */
+#define PF_ROSE		AF_ROSE
+
+/** Reserved for DECnet project protocol family.
+ */
+#define PF_DECnet	AF_DECnet
+
+/** Reserved for 802.2LLC project protocol family.
+ */
+#define PF_NETBEUI	AF_NETBEUI
+
+/** Security callback pseudo AF protocol family.
+ */
+#define PF_SECURITY	AF_SECURITY
+
+/** PF_KEY key management API protocol family.
+ */
+#define PF_KEY		AF_KEY
+
+/** Alias to emulate 4.4BSD protocol family.
+ */
+#define PF_NETLINK	AF_NETLINK
+
+/** Packet family protocol family.
+ */
+#define PF_PACKET	AF_PACKET
+
+/** Ash protocol family.
+ */
+#define PF_ASH		AF_ASH
+
+/** Acorn Econet protocol family.
+ */
+#define PF_ECONET	AF_ECONET
+
+/** ATM SVCs protocol family.
+ */
+#define PF_ATMSVC	AF_ATMSVC
+
+/** Linux SNA Project (nutters!) protocol family.
+ */
+#define PF_SNA		AF_SNA
+
+/** IRDA sockets protocol family.
+ */
+#define PF_IRDA		AF_IRDA
+
+/** PPPoX sockets protocol family.
+ */
+#define PF_PPPOX	AF_PPPOX
+
+/** Wanpipe API Sockets protocol family.
+ */
+#define PF_WANPIPE	AF_WANPIPE
+
+/** Linux LLC protocol family.
+ */
+#define PF_LLC		AF_LLC
+
+/** Controller Area Network protocol family.
+ */
+#define PF_CAN		AF_CAN
+
+/** TIPC sockets protocol family.
+ */
+#define PF_TIPC		AF_TIPC
+
+/** Bluetooth sockets protocol family.
+ */
+#define PF_BLUETOOTH	AF_BLUETOOTH
+
+/** IUCV sockets protocol family.
+ */
+#define PF_IUCV		AF_IUCV
+
+/** RxRPC sockets protocol family.
+ */
+#define PF_RXRPC	AF_RXRPC
+
+/** Maximum protocol family.
+ */
+#define PF_MAX		AF_MAX
+
+/*@}*/
+
+/** @name Socket option levels definitions
+ *  Thanks to BSD these must match IPPROTO_xxx
+ */
+/*@{*/
+
+/** IP socket option level.
+ */
+#define SOL_IP		0
+
+/** ICMP socket option level.
+ */
+#define SOL_ICMP	1
+
+/** TCP socket option level.
+ */
+#define SOL_TCP		6
+
+/** UDP socket option level.
+ */
+#define SOL_UDP		17
+
+/** IPV socket option level.
+ */
+#define SOL_IPV6	41
+
+/** ICMPV socket option level.
+ */
+#define SOL_ICMPV6	58
+
+/** SCTP socket option level.
+ */
+#define SOL_SCTP	132
+
+/** UDP-Lite (RFC 3828) socket option level.
+ */
+#define SOL_UDPLITE	136
+
+/** RAW socket option level.
+ */
+#define SOL_RAW		255
+
+/** IPX socket option level.
+ */
+#define SOL_IPX		256
+
+/** AX socket option level.
+ */
+#define SOL_AX25	257
+
+/** ATALK socket option level.
+ */
+#define SOL_ATALK	258
+
+/** NETROM socket option level.
+ */
+#define SOL_NETROM	259
+
+/** ROSE socket option level.
+ */
+#define SOL_ROSE	260
+
+/** DECNET socket option level.
+ */
+#define SOL_DECNET	261
+
+/** X25 socket option level.
+ */
+#define	SOL_X25		262
+
+/** PACKET socket option level.
+ */
+#define SOL_PACKET	263
+
+/** ATM layer (cell level) socket option level.
+ */
+#define SOL_ATM		264
+
+/** ATM Adaption Layer (packet level) socket option level.
+ */
+#define SOL_AAL		265
+
+/** IRDA socket option level.
+ */
+#define SOL_IRDA	266
+
+/** NETBEUI socket option level.
+ */
+#define SOL_NETBEUI	267
+
+/** LLC socket option level.
+ */
+#define SOL_LLC		268
+
+/** DCCP socket option level.
+ */
+#define SOL_DCCP	269
+
+/** NETLINK socket option level.
+ */
+#define SOL_NETLINK	270
+
+/** TIPC socket option level.
+ */
+#define SOL_TIPC	271
+
+/** RXRPC socket option level.
+ */
+#define SOL_RXRPC	272
+
+/** PPPOL socket option level.
+ */
+#define SOL_PPPOL2TP	273
+
+/** BLUETOOTH socket option level.
+ */
+#define SOL_BLUETOOTH	274
+
+/*@}*/
+
+/** Socket types.
+ */
+typedef enum sock_type{
+	/** Stream (connection oriented) socket.
+	 */
+	SOCK_STREAM	= 1,
+	/** Datagram (connectionless oriented) socket.
+	 */
+	SOCK_DGRAM	= 2,
+	/** Raw socket.
+	 */
+	SOCK_RAW	= 3
+} sock_type_t;
+
+/** Type definition of the socket length.
+ */
+typedef int32_t	socklen_t;
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/include/socket_errno.h
===================================================================
--- uspace/srv/net/include/socket_errno.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/include/socket_errno.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup net
+ *  @{
+ */
+
+/** @file
+ *  Socket error codes.
+ *  Based on BSD.
+ */
+
+#ifndef __NET_SOCKET_ERR_H__
+#define __NET_SOCKET_ERR_H__
+
+#include <errno.h>
+
+/** @name Socket error codes definitions
+ */
+/*@{*/
+
+////#define EINTR			(-10004)
+////#define EBADF			(-10009)
+//#define EACCES			(-10013)
+//#define EFAULT			(-10014)
+////#define EINVAL			(-10022)
+////#define EMFILE			(-10024)
+//#define EWOULDBLOCK		(-10035)
+
+/** An API function is called while another blocking function is in progress.
+ */
+#define EINPROGRESS		(-10036)
+
+//#define EALREADY		(-10037)
+
+/** The socket identifier is not valid.
+ */
+#define ENOTSOCK		(-10038)
+
+/** The destination address required.
+ */
+#define EDESTADDRREQ	(-10039)
+
+//#define EMSGSIZE		(-10040)
+//#define EPROTOTYPE		(-10041)
+//#define ENOPROTOOPT		(-10042)
+
+/** Protocol is not supported.
+ */
+#define EPROTONOSUPPORT	(-10043)
+
+/** Socket type is not supported.
+ */
+#define ESOCKTNOSUPPORT	(-10044)
+
+//#define EOPNOTSUPP		(-10045)
+
+/** Protocol family is not supported.
+ */
+#define EPFNOSUPPORT	(-10046)
+
+/** Address family is not supported.
+ */
+#define EAFNOSUPPORT	(-10047)
+
+/** Address is already in use.
+ */
+#define EADDRINUSE		(-10048)
+
+//#define EADDRNOTAVAIL	(-10049)
+/* May be reported at any time if the implementation detects an underlying failure.
+ */
+//#define ENETDOWN		(-10050)
+//#define ENETUNREACH		(-10051)
+//#define ENETRESET		(-10052)
+//#define ECONNABORTED	(-10053)
+//#define ECONNRESET		(-10054)
+//#define ENOBUFS			(-10055)
+//#define EISCONN			(-10056)
+
+/** The socket is not connected or bound.
+ */
+#define ENOTCONN		(-10057)
+
+//#define ESHUTDOWN		(-10058)
+//#define ETOOMANYREFS	(-10059)
+//#define ETIMEDOUT		(-10060)
+//#define ECONNREFUSED	(-10061)
+//#define ELOOP			(-10062)
+////#define ENAMETOOLONG	(-10063)
+//#define EHOSTDOWN		(-10064)
+//#define EHOSTUNREACH	(-10065)
+//#define HOST_NOT_FOUND	(-11001)
+
+/** The requested operation was not performed.
+ *  Try again later.
+ */
+#define TRY_AGAIN		(-11002)
+
+//#define NO_RECOVERY		(-11003)
+
+/** No data.
+ */
+#define NO_DATA			(-11004)
+
+/*@}*/
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/include/tcp_codes.h
===================================================================
--- uspace/srv/net/include/tcp_codes.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/include/tcp_codes.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,88 @@
+/*
+ * 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 tcp
+ *  @{
+ */
+
+/** @file
+ *  TCP options definitions.
+ */
+
+#ifndef __NET_TCP_CODES_H__
+#define __NET_TCP_CODES_H__
+
+/** End of list TCP option.
+ */
+#define TCPOPT_END_OF_LIST				0x0
+
+/** No operation TCP option.
+ */
+#define TCPOPT_NO_OPERATION				0x1
+
+/** Maximum segment size TCP option.
+ */
+#define TCPOPT_MAX_SEGMENT_SIZE			0x2
+
+/** Maximum segment size TCP option length.
+ */
+#define TCPOPT_MAX_SEGMENT_SIZE_LENGTH	4
+
+/** Window scale TCP option.
+ */
+#define TCPOPT_WINDOW_SCALE				0x3
+
+/** Window scale TCP option length.
+ */
+#define TCPOPT_WINDOW_SCALE_LENGTH		3
+
+/** Selective acknowledgement permitted TCP option.
+ */
+#define TCPOPT_SACK_PERMITTED			0x4
+
+/** Selective acknowledgement permitted TCP option length.
+ */
+#define TCPOPT_SACK_PERMITTED_LENGTH	2
+
+/** Selective acknowledgement TCP option.
+ *  Has variable length.
+ */
+#define TCPOPT_SACK						0x5
+
+/** Timestamp TCP option.
+ */
+#define TCPOPT_TIMESTAMP				0x8
+
+/** Timestamp TCP option length.
+ */
+#define TCPOPT_TIMESTAMP_LENGTH			10
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/include/tl_interface.h
===================================================================
--- uspace/srv/net/include/tl_interface.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/include/tl_interface.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup net_tl
+ *  @{
+ */
+
+/** @file
+ *  Transport layer module interface for the underlying internetwork layer.
+ */
+
+#ifndef __NET_TL_INTERFACE_H__
+#define __NET_TL_INTERFACE_H__
+
+#include <async.h>
+
+#include <ipc/services.h>
+
+#include "../messages.h"
+
+#include "../include/device.h"
+
+#include "../structures/packet/packet.h"
+#include "../structures/packet/packet_client.h"
+
+#include "../tl/tl_messages.h"
+
+/** @name Transport layer module interface
+ *  This interface is used by other modules.
+ */
+/*@{*/
+
+/** Notifies the remote transport layer modules about the received packet/s.
+ *  @param[in] tl_phone The transport layer module phone used for remote calls.
+ *  @param[in] device_id The device identifier.
+ *  @param[in] packet The 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 The target transport layer module service to be delivered to.
+ *  @param[in] error The packet error reporting service. Prefixes the received packet.
+ *  @returns EOK on success.
+ */
+inline static int	tl_received_msg( int tl_phone, device_id_t device_id, packet_t packet, services_t target, services_t error ){
+	return generic_received_msg( tl_phone, NET_TL_RECEIVED, device_id, packet_get_id( packet ), target, error );
+}
+
+/*@}*/
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/inet.c
===================================================================
--- uspace/srv/net/inet.c	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/inet.c	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup net
+ *  @{
+ */
+
+/** @file
+ *  Internet protocol address conversion functions implementation.
+ */
+
+#include <errno.h>
+#include <mem.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "include/in.h"
+#include "include/in6.h"
+#include "include/inet.h"
+#include "include/socket_codes.h"
+
+int inet_pton( uint16_t family, const char * address, uint8_t * data ){
+	const char *	next;
+	char *			last;
+	int				index;
+	int				count;
+	int				base;
+	size_t			bytes;
+	size_t			shift;
+	unsigned long	value;
+
+	if( ! data ) return EINVAL;
+	switch( family ){
+		case AF_INET:
+			count = 4;
+			base = 10;
+			bytes = 1;
+			break;
+		case AF_INET6:
+			count = 16;
+			base = 16;
+			bytes = 4;
+			break;
+		default:
+			return ENOTSUP;
+	}
+	if( ! address ){
+		bzero( data, count );
+		return ENOENT;
+	}
+	next = address;
+	index = 0;
+	do{
+		if( next && ( * next )){
+			if( index ) ++ next;
+			value = strtoul( next, & last, base );
+			next = last;
+			shift = bytes - 1;
+			do{
+				// like little endian
+				data[ index + shift ] = value;
+				value >>= 8;
+			}while( shift -- );
+			index += bytes;
+		}else{
+			bzero( data + index, count - index );
+			return EOK;
+		}
+	}while( index < count );
+	return EOK;
+}
+
+int inet_ntop( uint16_t family, const uint8_t * data, char * address, size_t length ){
+	if(( ! data ) || ( ! address ))	return EINVAL;
+	switch( family ){
+		case AF_INET:	if( length < INET_ADDRSTRLEN ) return ENOMEM;
+						snprintf( address, length, "%hhu.%hhu.%hhu.%hhu", data[ 0 ], data[ 1 ], data[ 2 ], data[ 3 ] );
+						return EOK;
+		case AF_INET6:	if( length < INET6_ADDRSTRLEN ) return ENOMEM;
+						snprintf( address, length, "%hhx%hhx:%hhx%hhx:%hhx%hhx:%hhx%hhx:%hhx%hhx:%hhx%hhx:%hhx%hhx:%hhx%hhx", data[ 0 ], data[ 1 ], data[ 2 ], data[ 3 ], data[ 4 ], data[ 5 ], data[ 6 ], data[ 7 ], data[ 8 ], data[ 9 ], data[ 10 ], data[ 11 ], data[ 12 ], data[ 13 ], data[ 14 ], data[ 15 ] );
+						return EOK;
+		default:		return ENOTSUP;
+	}
+}
+
+/** @}
+ */
Index: uspace/srv/net/messages.h
===================================================================
--- uspace/srv/net/messages.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/messages.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,523 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup net
+ *  @{
+ */
+
+/** @file
+ *  Networking common message definitions.
+ */
+
+#ifndef __NET_MESSAGES_H__
+#define __NET_MESSAGES_H__
+
+#include <async.h>
+
+#include <ipc/ipc.h>
+#include <ipc/services.h>
+
+#include "include/device.h"
+
+#include "structures/measured_strings.h"
+#include "structures/packet/packet.h"
+
+/** @name Networking message counts
+ */
+/*@{*/
+
+/** The number of network interface driver messages.
+ */
+#define NET_NETIF_COUNT		6
+
+/** The number of general networking messages.
+ */
+#define NET_NET_COUNT		3
+
+/** The number of network interface layer messages.
+ */
+#define NET_NIL_COUNT		7
+
+/** The number of Ethernet messages.
+ */
+#define NET_ETH_COUNT		0
+
+/** The number of inter-network messages.
+ */
+#define NET_IL_COUNT		6
+
+/** The number of IP messages.
+ */
+#define NET_IP_COUNT		4
+
+/** The number of ARP messages.
+ */
+#define NET_ARP_COUNT		5
+
+/** The number of ICMP messages.
+ */
+#define NET_ICMP_COUNT		6
+
+/** The number of transport layer messages.
+ */
+#define NET_TL_COUNT		1
+
+/** The number of UDP messages.
+ */
+#define NET_UDP_COUNT		0
+
+/** The number of TCP messages.
+ */
+#define NET_TCP_COUNT		0
+
+/** The number of packet management system messages.
+ */
+#define NET_PACKET_COUNT	5
+
+/** The number of socket messages.
+ */
+#define NET_SOCKET_COUNT	14
+
+/*@}*/
+
+/** @name Networking message intervals
+ */
+/*@{*/
+
+/** The first networking message.
+ */
+#define NET_FIRST			2000
+
+/** The first network interface layer message.
+ */
+#define NET_NETIF_FIRST		NET_FIRST
+
+/** The last network interface layer message.
+ */
+#define NET_NETIF_LAST		( NET_NETIF_FIRST + NET_NETIF_COUNT )
+
+/** The first general networking message.
+ */
+#define NET_NET_FIRST		( NET_NETIF_LAST + 0 )
+
+/** The last general networking message.
+ */
+#define NET_NET_LAST		( NET_NET_FIRST + NET_NET_COUNT )
+
+/** The first network interface layer message.
+ */
+#define NET_NIL_FIRST		( NET_NET_LAST + 0 )
+
+/** The last network interface layer message.
+ */
+#define NET_NIL_LAST		( NET_NIL_FIRST + NET_NIL_COUNT )
+
+/** The first Ethernet message.
+ */
+#define NET_ETH_FIRST		( NET_NIL_LAST + 0 )
+
+/** The last Ethernet message.
+ */
+#define NET_ETH_LAST		( NET_ETH_FIRST + NET_ETH_COUNT )
+
+/** The first inter-network message.
+ */
+#define NET_IL_FIRST		( NET_ETH_LAST + 0 )
+
+/** The last inter-network message.
+ */
+#define NET_IL_LAST			( NET_IL_FIRST + NET_IL_COUNT )
+
+/** The first IP message.
+ */
+#define NET_IP_FIRST		( NET_IL_LAST + 0 )
+
+/** The last IP message.
+ */
+#define NET_IP_LAST			( NET_IP_FIRST + NET_IP_COUNT )
+
+/** The first ARP message.
+ */
+#define NET_ARP_FIRST		( NET_IP_LAST + 0 )
+
+/** The last ARP message.
+ */
+#define NET_ARP_LAST		( NET_ARP_FIRST + NET_ARP_COUNT )
+
+/** The first ICMP message.
+ */
+#define NET_ICMP_FIRST		( NET_ARP_LAST + 0 )
+
+/** The last ICMP message.
+ */
+#define NET_ICMP_LAST		( NET_ICMP_FIRST + NET_ICMP_COUNT )
+
+/** The first ICMP message.
+ */
+#define NET_TL_FIRST		( NET_ICMP_LAST + 0 )
+
+/** The last ICMP message.
+ */
+#define NET_TL_LAST			( NET_TL_FIRST + NET_TL_COUNT )
+
+/** The first UDP message.
+ */
+#define NET_UDP_FIRST		( NET_TL_LAST + 0 )
+
+/** The last UDP message.
+ */
+#define NET_UDP_LAST		( NET_UDP_FIRST + NET_UDP_COUNT )
+
+/** The first TCP message.
+ */
+#define NET_TCP_FIRST		( NET_UDP_LAST + 0 )
+
+/** The last TCP message.
+ */
+#define NET_TCP_LAST		( NET_TCP_FIRST + NET_TCP_COUNT )
+
+/** The first socket message.
+ */
+#define NET_SOCKET_FIRST	( NET_TCP_LAST + 0 )
+
+/** The last socket message.
+ */
+#define NET_SOCKET_LAST		( NET_SOCKET_FIRST + NET_SOCKET_COUNT )
+
+/** The first packet management system message.
+ */
+#define NET_PACKET_FIRST	( NET_SOCKET_LAST + 0 )
+
+/** The last packet management system message.
+ */
+#define NET_PACKET_LAST		( NET_PACKET_FIRST + NET_PACKET_COUNT )
+
+/** The last networking message.
+ */
+#define NET_LAST			NET_PACKET_LAST
+
+/** The number of networking messages.
+ */
+#define NET_COUNT			( NET_LAST - NET_FIRST )
+
+/** Returns a value indicating whether the value is in the interval.
+ *  @param[in] item The value to be checked.
+ *  @param[in] first_inclusive The first value in the interval inclusive.
+ *  @param[in] last_exclusive The first value after the interval.
+ */
+#define IS_IN_INTERVAL( item, first_inclusive, last_exclusive )	((( item ) >= ( first_inclusive )) && (( item ) < ( last_exclusive )))
+
+/** Returns a value indicating whether the IPC call is a generic networking message.
+ *  @param[in] call The IPC call to be checked.
+ */
+#define IS_NET_MESSAGE( call )			IS_IN_INTERVAL( IPC_GET_METHOD( * call ), NET_FIRST, NET_LAST )
+
+/** Returns a value indicating whether the IPC call is a generic networking message.
+ *  @param[in] call The IPC call to be checked.
+ */
+#define IS_NET_NET_MESSAGE( call )		IS_IN_INTERVAL( IPC_GET_METHOD( * call ), NET_NET_FIRST, NET_NET_LAST )
+
+/** Returns a value indicating whether the IPC call is a network interface layer message.
+ *  @param[in] call The IPC call to be checked.
+ */
+#define IS_NET_NIL_MESSAGE( call )		IS_IN_INTERVAL( IPC_GET_METHOD( * call ), NET_NIL_FIRST, NET_NIL_LAST )
+
+/** Returns a value indicating whether the IPC call is an Ethernet message.
+ *  @param[in] call The IPC call to be checked.
+ */
+#define IS_NET_ETH_MESSAGE( call )		IS_IN_INTERVAL( IPC_GET_METHOD( * call ), NET_ETH_FIRST, NET_ETH_LAST )
+
+/** Returns a value indicating whether the IPC call is an inter-network layer message.
+ *  @param[in] call The IPC call to be checked.
+ */
+#define IS_NET_IL_MESSAGE( call )		IS_IN_INTERVAL( IPC_GET_METHOD( * call ), NET_IL_FIRST, NET_IL_LAST )
+
+/** Returns a value indicating whether the IPC call is an IP message.
+ *  @param[in] call The IPC call to be checked.
+ */
+#define IS_NET_IP_MESSAGE( call )		IS_IN_INTERVAL( IPC_GET_METHOD( * call ), NET_IP_FIRST, NET_IP_LAST )
+
+/** Returns a value indicating whether the IPC call is an ARP message.
+ *  @param[in] call The IPC call to be checked.
+ */
+#define IS_NET_ARP_MESSAGE( call )		IS_IN_INTERVAL( IPC_GET_METHOD( * call ), NET_ARP_FIRST, NET_ARP_LAST )
+
+/** Returns a value indicating whether the IPC call is an ICMP message.
+ *  @param[in] call The IPC call to be checked.
+ */
+#define IS_NET_ICMP_MESSAGE( call )		IS_IN_INTERVAL( IPC_GET_METHOD( * call ), NET_ICMP_FIRST, NET_ICMP_LAST )
+
+/** Returns a value indicating whether the IPC call is a transport layer message.
+ *  @param[in] call The IPC call to be checked.
+ */
+#define IS_NET_TL_MESSAGE( call )		IS_IN_INTERVAL( IPC_GET_METHOD( * call ), NET_TL_FIRST, NET_TL_LAST )
+
+/** Returns a value indicating whether the IPC call is a UDP message.
+ *  @param[in] call The IPC call to be checked.
+ */
+#define IS_NET_UDP_MESSAGE( call )		IS_IN_INTERVAL( IPC_GET_METHOD( * call ), NET_UDP_FIRST, NET_UDP_LAST )
+
+/** Returns a value indicating whether the IPC call is a TCP message.
+ *  @param[in] call The IPC call to be checked.
+ */
+#define IS_NET_TCP_MESSAGE( call )		IS_IN_INTERVAL( IPC_GET_METHOD( * call ), NET_TCP_FIRST, NET_TCP_LAST )
+
+/** Returns a value indicating whether the IPC call is a socket message.
+ *  @param[in] call The IPC call to be checked.
+ */
+#define IS_NET_SOCKET_MESSAGE( call )	IS_IN_INTERVAL( IPC_GET_METHOD( * call ), NET_SOCKET_FIRST, NET_SOCKET_LAST )
+
+/** Returns a value indicating whether the IPC call is a packet manaagement system message.
+ *  @param[in] call The IPC call to be checked.
+ */
+#define IS_NET_PACKET_MESSAGE( call )	IS_IN_INTERVAL( IPC_GET_METHOD( * call ), NET_PACKET_FIRST, NET_PACKET_LAST )
+
+/*@}*/
+
+/** @name Networking specific message parameters definitions
+ */
+/*@{*/
+
+/** Returns the device identifier message parameter.
+ *  @param[in] call The message call structure.
+ */
+#define IPC_GET_DEVICE( call )		( device_id_t ) IPC_GET_ARG1( * call )
+
+/** Returns the packet identifier message parameter.
+ *  @param[in] call The message call structure.
+ */
+#define IPC_GET_PACKET( call )		( packet_id_t ) IPC_GET_ARG2( * call )
+
+/** Returns the count message parameter.
+ *  @param[in] call The message call structure.
+ */
+#define IPC_GET_COUNT( call )		( size_t ) IPC_GET_ARG2( * call )
+
+/** Returns the device state message parameter.
+ *  @param[in] call The message call structure.
+ */
+#define IPC_GET_STATE( call )		( device_state_t ) IPC_GET_ARG2( * call )
+
+/** Returns the maximum transmission unit message parameter.
+ *  @param[in] call The message call structure.
+ */
+#define IPC_GET_MTU( call )			( size_t ) IPC_GET_ARG2( * call )
+
+/** Returns the device driver service message parameter.
+ *  @param[in] call The message call structure.
+ */
+#define IPC_GET_SERVICE( call )		( services_t ) IPC_GET_ARG3( * call )
+
+/** Returns the target service message parameter.
+ *  @param[in] call The message call structure.
+ */
+#define IPC_GET_TARGET( call )		( services_t ) IPC_GET_ARG3( * call )
+
+/** Returns the sender service message parameter.
+ *  @param[in] call The message call structure.
+ */
+#define IPC_GET_SENDER( call )		( services_t ) IPC_GET_ARG3( * call )
+
+/** Returns the error service message parameter.
+ *  @param[in] call The message call structure.
+ */
+#define IPC_GET_ERROR( call )		( services_t ) IPC_GET_ARG4( * call )
+
+/** Returns the phone message parameter.
+ *  @param[in] call The message call structure.
+ */
+#define IPC_GET_PHONE( call )		( int ) IPC_GET_ARG5( * call )
+
+/** Sets the device identifier in the message answer.
+ *  @param[out] answer The message answer structure.
+ */
+#define IPC_SET_DEVICE( answer )	(( device_id_t * ) & IPC_GET_ARG1( * answer ))
+
+/** Sets the minimum address length in the message answer.
+ *  @param[out] answer The message answer structure.
+ */
+#define IPC_SET_ADDR( answer )		(( size_t * ) & IPC_GET_ARG1( * answer ))
+
+/** Sets the minimum prefix size in the message answer.
+ *  @param[out] answer The message answer structure.
+ */
+#define IPC_SET_PREFIX( answer )	(( size_t * ) & IPC_GET_ARG2( * answer ))
+
+/** Sets the maximum content size in the message answer.
+ *  @param[out] answer The message answer structure.
+ */
+#define IPC_SET_CONTENT( answer )	(( size_t * ) & IPC_GET_ARG3( * answer ))
+
+/** Sets the minimum suffix size in the message answer.
+ *  @param[out] answer The message answer structure.
+ */
+#define IPC_SET_SUFFIX( answer )	(( size_t * ) & IPC_GET_ARG4( * answer ))
+
+/*@}*/
+
+/** Returns the address.
+ *  @param[in] phone The service module phone.
+ *  @param[in] message The service specific message.
+ *  @param[in] device_id The device identifier.
+ *  @param[out] address The desired address.
+ *  @param[out] data The address data container.
+ *  @returns EOK on success.
+ *  @returns EBADMEM if the address parameter and/or the data parameter is NULL.
+ *  @returns Other error codes as defined for the specific service message.
+ */
+static inline int generic_get_addr_req( int phone, int message, device_id_t device_id, measured_string_ref * address, char ** data ){
+	aid_t			message_id;
+	ipcarg_t		result;
+	int				string;
+
+	if( !( address && data )) return EBADMEM;
+	message_id = async_send_1( phone, ( ipcarg_t ) message, ( ipcarg_t ) device_id, NULL );
+	string = measured_strings_return( phone, address, data, 1 );
+	async_wait_for( message_id, & result );
+	if(( string == EOK ) && ( result != EOK )){
+		free( * address );
+		free( * data );
+	}
+	return ( int ) result;
+}
+
+/** Translates the given strings.
+ *  Allocates and returns the needed memory block as the data parameter.
+ *  @param[in] phone The service module phone.
+ *  @param[in] message The service specific message.
+ *  @param[in] device_id The device identifier.
+ *  @param[in] service The module service.
+ *  @param[in] configuration The key strings.
+ *  @param[in] count The number of configuration keys.
+ *  @param[out] translation The translated values.
+ *  @param[out] data The translation data container.
+ *  @returns EOK on success.
+ *  @returns EINVAL if the configuration parameter is NULL.
+ *  @returns EINVAL if the count parameter is zero (0).
+ *  @returns EBADMEM if the translation or the data parameters are NULL.
+ *  @returns Other error codes as defined for the specific service message.
+ */
+static inline int	generic_translate_req( int phone, int message, device_id_t device_id, services_t service, measured_string_ref configuration, size_t count, measured_string_ref * translation, char ** data ){
+	aid_t			message_id;
+	ipcarg_t		result;
+	int				string;
+
+	if( !( configuration && ( count > 0 ))) return EINVAL;
+	if( !( translation && data )) return EBADMEM;
+	message_id = async_send_3( phone, ( ipcarg_t ) message, ( ipcarg_t ) device_id, ( ipcarg_t ) count, ( ipcarg_t ) service, NULL );
+	measured_strings_send( phone, configuration, count );
+	string = measured_strings_return( phone, translation, data, count );
+	async_wait_for( message_id, & result );
+	if(( string == EOK ) && ( result != EOK )){
+		free( * translation );
+		free( * data );
+	}
+	return ( int ) result;
+}
+
+/** Sends the packet queue.
+ *  @param[in] phone The service module phone.
+ *  @param[in] message The service specific message.
+ *  @param[in] device_id The device identifier.
+ *  @param[in] packet_id The packet or the packet queue identifier.
+ *  @param[in] sender The sending module service.
+ *  @param[in] error The error module service.
+ *  @returns EOK on success.
+ */
+static inline int	generic_send_msg( int phone, int message, device_id_t device_id, packet_id_t packet_id, services_t sender, services_t error ){
+	if( error ){
+		async_msg_4( phone, ( ipcarg_t ) message, ( ipcarg_t ) device_id, ( ipcarg_t ) packet_id, ( ipcarg_t ) sender, ( ipcarg_t ) error );
+	}else{
+		async_msg_3( phone, ( ipcarg_t ) message, ( ipcarg_t ) device_id, ( ipcarg_t ) packet_id, ( ipcarg_t ) sender );
+	}
+	return EOK;
+}
+
+/** Returns the device packet dimensions for sending.
+ *  @param[in] phone The service module phone.
+ *  @param[in] message The service specific message.
+ *  @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.
+ *  @returns EOK on success.
+ *  @returns Other error codes as defined for the specific service message.
+ */
+static inline int	generic_packet_size_req( int phone, int message, device_id_t device_id, size_t * addr_len, size_t * prefix, size_t * content, size_t * suffix ){
+	return ( int ) async_req_1_4( phone, ( ipcarg_t ) message, ( ipcarg_t ) device_id, ( ipcarg_t * ) addr_len, ( ipcarg_t * ) prefix, ( ipcarg_t * ) content, ( ipcarg_t * ) suffix );
+}
+
+/** Notifies the module about the device state change.
+ *  @param[in] phone The service module phone.
+ *  @param[in] message The service specific message.
+ *  @param[in] device_id The device identifier.
+ *  @param[in] state The new device state.
+ *  @param[in] target The target module service.
+ *  @returns EOK on success.
+ */
+static inline int	generic_device_state_msg( int phone, int message, device_id_t device_id, int state, services_t target ){
+	async_msg_3( phone, ( ipcarg_t ) message, ( ipcarg_t ) device_id, ( ipcarg_t ) state, target );
+	return EOK;
+}
+
+/** Passes the packet queue to the module.
+ *  @param[in] phone The service module phone.
+ *  @param[in] message The service specific message.
+ *  @param[in] device_id The device identifier.
+ *  @param[in] packet_id The received packet or the received packet queue identifier.
+ *  @param[in] target The target module service.
+ *  @param[in] error The error module service.
+ *  @returns EOK on success.
+ */
+static inline int	generic_received_msg( int phone, int message, device_id_t device_id, packet_id_t packet_id, services_t target, services_t error ){
+	if( error ){
+		async_msg_4( phone, ( ipcarg_t ) message, ( ipcarg_t ) device_id, ( ipcarg_t ) packet_id, ( ipcarg_t ) target, ( ipcarg_t ) error );
+	}else{
+		async_msg_3( phone, ( ipcarg_t ) message, ( ipcarg_t ) device_id, ( ipcarg_t ) packet_id, ( ipcarg_t ) target );
+	}
+	return EOK;
+}
+
+/** Notifies a module about the device.
+ *  @param[in] phone The service module phone.
+ *  @param[in] message The service specific message.
+ *  @param[in] device_id The device identifier.
+ *  @param[in] arg2 The second argument of the message.
+ *  @param[in] service The device module service.
+ *  @returns EOK on success.
+ *  @returns Other error codes as defined for the specific service message.
+ */
+static inline int	generic_device_req( int phone, int message, device_id_t device_id, int arg2, services_t service ){
+	return ( int ) async_req_3_0( phone, ( ipcarg_t ) message, ( ipcarg_t ) device_id, ( ipcarg_t ) arg2, ( ipcarg_t ) service );
+}
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/module.c
===================================================================
--- uspace/srv/net/module.c	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/module.c	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup net
+ *  @{
+ */
+
+/** @file
+ *  Generic module skeleton implementation.
+ */
+
+#include <async.h>
+#include <stdio.h>
+#include <task.h>
+
+#include <ipc/ipc.h>
+
+#include "err.h"
+#include "modules.h"
+
+/** @name External module functions.
+ *  This functions have to be implemented in every module.
+ */
+/*@{*/
+
+/** External message processing function.
+ *  Should process the messages.
+ *  The function has to be defined in each module.
+ *  @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.
+ *  @returns EOK on success.
+ *  @returns ENOTSUP if the message is not known.
+ *  @returns Other error codes as defined for each specific module message function.
+ */
+extern int	module_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count );
+
+/** External function to print the module name.
+ *  Should print the module name.
+ *  The function has to be defined in each module.
+ */
+extern void	module_print_name( void );
+
+/** External module startup function.
+ *  Should start and initialize the module and register the given client connection function.
+ *  The function has to be defined in each module.
+ *  @param[in] client_connection The client connection function to be registered.
+ */
+extern int	module_start( async_client_conn_t client_connection );
+
+/*@}*/
+
+/** Default thread for new connections.
+ *  @param[in] iid The initial message identifier.
+ *  @param[in] icall The initial message call structure.
+ */
+void	client_connection( ipc_callid_t iid, ipc_call_t * icall );
+
+/**	Starts the module.
+ *  @param argc The count of the command line arguments. Ignored parameter.
+ *  @param argv The command line parameters. Ignored parameter.
+ *  @returns EOK on success.
+ *  @returns Other error codes as defined for each specific module start function.
+ */
+int	main( int argc, char * argv[] );
+
+void client_connection( ipc_callid_t iid, ipc_call_t * icall ){
+	ipc_callid_t	callid;
+	ipc_call_t		call;
+	ipc_call_t		answer;
+	int				answer_count;
+	int				res;
+
+	/*
+	 * Accept the connection
+	 *  - Answer the first IPC_M_CONNECT_ME_TO call.
+	 */
+	ipc_answer_0( iid, EOK );
+
+	while( true ){
+		refresh_answer( & answer, & answer_count );
+
+		callid = async_get_call( & call );
+		res = module_message( callid, & call, & answer, & answer_count );
+
+		if( IPC_GET_METHOD( call ) == IPC_M_PHONE_HUNGUP ) return;
+
+		answer_call( callid, res, & answer, answer_count );
+	}
+}
+
+int main( int argc, char * argv[] ){
+	ERROR_DECLARE;
+
+	printf("Task %d - ", task_get_id());
+	module_print_name();
+	printf( "\n" );
+	if( ERROR_OCCURRED( module_start( client_connection ))){
+		printf( " - ERROR %i\n", ERROR_CODE );
+		return ERROR_CODE;
+	}
+	return EOK;
+}
+
+/** @}
+ */
Index: uspace/srv/net/modules.c
===================================================================
--- uspace/srv/net/modules.c	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/modules.c	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup net
+ *  @{
+ */
+
+/** @file
+ *  Generic module functions implementation.
+ */
+
+#include <async.h>
+#include <malloc.h>
+
+#include <ipc/ipc.h>
+#include <ipc/services.h>
+
+#include <sys/time.h>
+
+#include "err.h"
+#include "modules.h"
+
+/** The time between connect requests in microseconds.
+ */
+#define MODULE_WAIT_TIME	( 10 * 1000 )
+
+int connect_to_service( services_t need ){
+	return connect_to_service_timeout( need, 0 );
+}
+
+int connect_to_service_timeout( services_t need, suseconds_t timeout ){
+	int	phone;
+	int	res;
+
+	while( true ){
+		res = async_req_3_5( PHONE_NS, IPC_M_CONNECT_ME_TO, need, 0, 0, NULL, NULL, NULL, NULL, ( ipcarg_t * ) & phone );
+		if(( res >= 0 ) && ( phone >= 0 )){
+			return phone;
+		}
+		if( timeout > 0 ){
+			timeout -= MODULE_WAIT_TIME;
+			if( timeout <= 0 ) return ETIMEOUT;
+		}
+		usleep( MODULE_WAIT_TIME );
+	}
+}
+
+int bind_service( services_t need, ipcarg_t arg1, ipcarg_t arg2, ipcarg_t arg3, async_client_conn_t client_receiver ){
+	return bind_service_timeout( need, arg1, arg2, arg3, client_receiver, 0 );
+}
+
+int bind_service_timeout( services_t need, ipcarg_t arg1, ipcarg_t arg2, ipcarg_t arg3, async_client_conn_t client_receiver, suseconds_t timeout ){
+	ERROR_DECLARE;
+
+	int			phone;
+	ipcarg_t	phonehash;
+
+	phone = connect_to_service_timeout( need, timeout );
+	if( phone >= 0 ){
+		if( ERROR_OCCURRED( ipc_connect_to_me( phone, arg1, arg2, arg3, & phonehash ))){
+			async_msg_0( phone, IPC_M_PHONE_HUNGUP );
+			return ERROR_CODE;
+		}
+		async_new_connection( phonehash, 0, NULL, client_receiver );
+	}
+	return phone;
+}
+
+void answer_call( ipc_callid_t callid, int result, ipc_call_t * answer, int answer_count ){
+	if( answer || ( ! answer_count )){
+		switch( answer_count ){
+			case 0:
+				ipc_answer_0( callid, ( ipcarg_t ) result );
+				break;
+			case 1:
+				ipc_answer_1( callid, ( ipcarg_t ) result, IPC_GET_ARG1( * answer ));
+				break;
+			case 2:
+				ipc_answer_2( callid, ( ipcarg_t ) result, IPC_GET_ARG1( * answer ), IPC_GET_ARG2( * answer ));
+				break;
+			case 3:
+				ipc_answer_3( callid, ( ipcarg_t ) result, IPC_GET_ARG1( * answer ), IPC_GET_ARG2( * answer ), IPC_GET_ARG3( * answer ));
+				break;
+			case 4:
+				ipc_answer_4( callid, ( ipcarg_t ) result, IPC_GET_ARG1( * answer ), IPC_GET_ARG2( * answer ), IPC_GET_ARG3( * answer ), IPC_GET_ARG4( * answer ));
+				break;
+			case 5:
+			default:
+				ipc_answer_5( callid, ( ipcarg_t ) result, IPC_GET_ARG1( * answer ), IPC_GET_ARG2( * answer ), IPC_GET_ARG3( * answer ), IPC_GET_ARG4( * answer ), IPC_GET_ARG5( * answer ));
+				break;
+		}
+	}
+}
+
+void refresh_answer( ipc_call_t * answer, int * answer_count ){
+	if( answer_count ){
+		* answer_count = 0;
+	}
+	if( answer ){
+		IPC_SET_RETVAL( * answer, 0 );
+		// just to be precize
+		IPC_SET_METHOD( * answer, 0 );
+		IPC_SET_ARG1( * answer, 0 );
+		IPC_SET_ARG2( * answer, 0 );
+		IPC_SET_ARG3( * answer, 0 );
+		IPC_SET_ARG4( * answer, 0 );
+		IPC_SET_ARG5( * answer, 0 );
+	}
+}
+
+int data_receive( void ** data, size_t * length ){
+	ERROR_DECLARE;
+
+	ipc_callid_t	callid;
+
+	if( !( data && length )) return EBADMEM;
+	if( ! async_data_write_receive( & callid, length )) return EINVAL;
+	* data = malloc( * length );
+	if( !( * data )) return ENOMEM;
+	if( ERROR_OCCURRED( async_data_write_finalize( callid, * data, * length ))){
+		free( data );
+		return ERROR_CODE;
+	}
+	return EOK;
+}
+
+int data_reply( void * data, size_t data_length ){
+	size_t			length;
+	ipc_callid_t	callid;
+
+	if( ! async_data_read_receive( & callid, & length )){
+		return EINVAL;
+	}
+	if( length < data_length ){
+		async_data_read_finalize( callid, data, length );
+		return EOVERFLOW;
+	}
+	return async_data_read_finalize( callid, data, data_length );
+}
+
+/** @}
+ */
Index: uspace/srv/net/modules.h
===================================================================
--- uspace/srv/net/modules.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/modules.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup net
+ *  @{
+ */
+
+/** @file
+ *  Generic module functions.
+ */
+
+#ifndef __NET_MODULES_H__
+#define __NET_MODULES_H__
+ 
+#include <async.h>
+
+#include <ipc/ipc.h>
+#include <ipc/services.h>
+
+#include <sys/time.h>
+
+/** Converts the data length between different types.
+ *	@param[in] type_from The source type.
+ *  @param[in] type_to The destination type.
+ *  @param[in] count The number units of the source type size.
+ */
+#define CONVERT_SIZE( type_from, type_to, count )	(( sizeof( type_from ) / sizeof( type_to )) * ( count ))
+
+/** Registers the module service at the name server.
+ *  @param[in] me The module service.
+ *  @param[out] phonehash The created phone hash.
+ */
+#define REGISTER_ME( me, phonehash )	ipc_connect_to_me( PHONE_NS, ( me ), 0, 0, ( phonehash ))
+
+/** Connect to the needed module function type definition.
+ *  @param[in] need The needed module service.
+ *  @returns The phone of the needed service.
+ */
+typedef int connect_module_t( services_t need );
+
+/** Connects to the needed module.
+ *  @param[in] need The needed module service.
+ *  @returns The phone of the needed service.
+ */
+int connect_to_service( services_t need );
+
+/** Connects to the needed module.
+ *  @param[in] need The needed module service.
+ *  @param[in] timeout The connection timeout in microseconds. No timeout if set to zero (0).
+ *  @returns The phone of the needed service.
+ *  @returns ETIMEOUT if the connection timeouted.
+ */
+int connect_to_service_timeout( services_t need, suseconds_t timeout );
+
+/** Creates bidirectional connection with the needed module service and registers the message receiver.
+ *  @param[in] need The needed module service.
+ *  @param[in] arg1 The first parameter.
+ *  @param[in] arg2 The second parameter.
+ *  @param[in] arg3 The third parameter.
+ *  @param[in] client_receiver The message receiver.
+ *  @returns The phone of the needed service.
+ *  @returns Other error codes as defined for the ipc_connect_to_me() function.
+ */
+int	bind_service( services_t need, ipcarg_t arg1, ipcarg_t arg2, ipcarg_t arg3, async_client_conn_t client_receiver );
+
+/** Creates bidirectional connection with the needed module service and registers the message receiver.
+ *  @param[in] need The needed module service.
+ *  @param[in] arg1 The first parameter.
+ *  @param[in] arg2 The second parameter.
+ *  @param[in] arg3 The third parameter.
+ *  @param[in] client_receiver The message receiver.
+ *  @param[in] timeout The connection timeout in microseconds. No timeout if set to zero (0).
+ *  @returns The phone of the needed service.
+ *  @returns ETIMEOUT if the connection timeouted.
+ *  @returns Other error codes as defined for the ipc_connect_to_me() function.
+ */
+int	bind_service_timeout( services_t need, ipcarg_t arg1, ipcarg_t arg2, ipcarg_t arg3, async_client_conn_t client_receiver, suseconds_t timeout );
+
+/** Answers the call.
+ *  @param[in] callid The call identifier.
+ *  @param[in] result The message processing result.
+ *  @param[in] answer The message processing answer.
+ *  @param[in] answer_count The number of answer parameters.
+ */
+void	answer_call( ipc_callid_t callid, int result, ipc_call_t * answer, int answer_count );
+
+/** Refreshes answer structure and parameters count.
+ *  Erases all attributes.
+ *  @param[in,out] answer The message processing answer structure.
+ *  @param[in,out] answer_count The number of answer parameters.
+ */
+void	refresh_answer( ipc_call_t * answer, int * answer_count );
+
+/** Receives data from the other party.
+ *  The received data buffer is allocated and returned.
+ *  @param[out] data The data buffer to be filled.
+ *  @param[out] length The buffer length.
+ *  @returns EOK on success.
+ *  @returns EBADMEM if the data or the length parameter is NULL.
+ *  @returns EINVAL if the client does not send data.
+ *  @returns ENOMEM if there is not enough memory left.
+ *  @returns Other error codes as defined for the async_data_write_finalize() function.
+ */
+int data_receive( void ** data, size_t * length );
+
+/** Replies the data to the other party.
+ *  @param[in] data The data buffer to be sent.
+ *  @param[in] data_length The buffer length.
+ *  @returns EOK on success.
+ *  @returns EINVAL if the client does not expect the data.
+ *  @returns EOVERFLOW if the client does not expect all the data. Only partial data are transfered.
+ *  @returns Other error codes as defined for the async_data_read_finalize() function.
+ */
+int data_reply( void * data, size_t data_length );
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/net/Makefile
===================================================================
--- uspace/srv/net/net/Makefile	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/net/Makefile	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,75 @@
+#
+# 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.
+#
+
+NAME = net
+
+NET_BASE = ../
+STRUCTURES = $(NET_BASE)structures/
+
+include $(NET_BASE)../../../Makefile.config
+
+## Sources
+#
+
+OUTPUT = $(NAME)
+SOURCES = \
+	$(NAME).c \
+	$(NET_BASE)module.c \
+	$(NET_BASE)modules.c \
+	$(NET_BASE)netif/netif_remote.c \
+	$(STRUCTURES)char_map.c \
+	$(STRUCTURES)measured_strings.c \
+	$(STRUCTURES)module_map.c \
+	$(STRUCTURES)packet/packet.c \
+	$(STRUCTURES)packet/packet_client.c \
+	$(STRUCTURES)packet/packet_server.c
+
+ifeq ($(NETWORKING), module)
+
+	SOURCES +=	$(NAME)_bundle.c \
+				$(NET_BASE)checksum.c \
+				$(NET_BASE)inet.c \
+				$(NET_BASE)il/arp/arp.c \
+				$(NET_BASE)il/ip/ip.c \
+				$(NET_BASE)il/ip/ip_client.c \
+				$(NET_BASE)socket/socket_core.c \
+				$(NET_BASE)tl/icmp/icmp.c \
+				$(NET_BASE)tl/icmp/icmp_client.c \
+				$(NET_BASE)tl/tcp/tcp.c \
+				$(NET_BASE)tl/tl_common.c \
+				$(NET_BASE)tl/udp/udp.c \
+				$(STRUCTURES)dynamic_fifo.c
+
+else
+
+	SOURCES +=	$(NAME)_standalone.c \
+				$(NET_BASE)il/ip/ip_remote.c
+
+endif
+
+include $(NET_BASE)Makefile.module
Index: uspace/srv/net/net/net.c
===================================================================
--- uspace/srv/net/net/net.c	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/net/net.c	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,545 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup net
+ *  @{
+ */
+
+/** @file
+ *  Networking subsystem central module implementation.
+ */
+
+#include <async.h>
+#include <ctype.h>
+#include <ddi.h>
+#include <errno.h>
+#include <malloc.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <ipc/ipc.h>
+#include <ipc/services.h>
+
+#include "../err.h"
+#include "../messages.h"
+#include "../modules.h"
+
+#include "../structures/char_map.h"
+#include "../structures/generic_char_map.h"
+#include "../structures/measured_strings.h"
+#include "../structures/module_map.h"
+#include "../structures/packet/packet.h"
+
+#include "../il/il_messages.h"
+#include "../include/device.h"
+#include "../include/netif_interface.h"
+#include "../include/nil_interface.h"
+#include "../include/net_interface.h"
+#include "../include/ip_interface.h"
+
+#include "net.h"
+#include "net_messages.h"
+
+/** Networking module name.
+ */
+#define NAME	"Networking"
+
+/** File read buffer size.
+ */
+#define BUFFER_SIZE	256
+
+/** Prints the module name.
+ *  @see NAME
+ */
+void	module_print_name( void );
+
+/** Starts the networking module.
+ *  Initializes the client connection serving function, initializes the module, registers the module service and starts the async manager, processing IPC messages in an infinite loop.
+ *  @param[in] client_connection The client connection processing function. The module skeleton propagates its own one.
+ *  @returns EOK on successful module termination.
+ *  @returns Other error codes as defined for the net_initialize() function.
+ *  @returns Other error codes as defined for the REGISTER_ME() macro function.
+ */
+int module_start( async_client_conn_t client_connection );
+
+/** \todo
+ */
+int	read_configuration_file( const char * directory, const char * filename, measured_strings_ref configuration );
+
+/** \todo
+ */
+int	parse_line( measured_strings_ref configuration, char * line );
+
+/** Reads the networking subsystem global configuration.
+ *  @returns EOK on success.
+ *  @returns Other error codes as defined for the add_configuration() function.
+ */
+int		read_configuration( void );
+
+/** Starts the network interface according to its configuration.
+ *  Registers the network interface with the subsystem modules.
+ *  Starts the needed subsystem modules.
+ *  @param[in] netif The network interface specific data.
+ *  @returns EOK on success.
+ *  @returns EINVAL if there are some settings missing.
+ *  @returns ENOENT if the internet protocol module is not known.
+ *  @returns Other error codes as defined for the netif_probe_req() function.
+ *  @returns Other error codes as defined for the nil_device_req() function.
+ *  @returns Other error codes as defined for the needed internet layer registering function.
+ */
+int		start_device( netif_ref netif );
+
+/** Reads the configuration and starts all network interfaces.
+ *  @returns EOK on success.
+ *  @returns EXDEV if there is no available system-unique device identifier.
+ *  @returns EINVAL if any of the network interface names are not configured.
+ *  @returns ENOMEM if there is not enough memory left.
+ *  @returns Other error codes as defined for the read_configuration() function.
+ *  @returns Other error codes as defined for the read_netif_configuration() function.
+ *  @returns Other error codes as defined for the start_device() function.
+ */
+int		startup( void );
+
+/** Generates new system-unique device identifier.
+ *  @returns The system-unique devic identifier.
+ */
+device_id_t	generate_new_device_id( void );
+
+/** Returns 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.
+ *  @returns EOK.
+ */
+int	net_get_conf( measured_strings_ref netif_conf, measured_string_ref configuration, size_t count, char ** data );
+
+/** Initializes the networking module.
+ *  @param[in] client_connection The client connection processing function. The module skeleton propagates its own one.
+ *  @returns EOK on success.
+ *  @returns ENOMEM if there is not enough memory left.
+ */
+int	net_initialize( async_client_conn_t client_connection );
+
+/** Reads the network interface specific configuration.
+ *  @param[in] name The network interface name.
+ *  @param[in,out] netif The network interface structure.
+ *  @returns EOK on success.
+ *  @returns Other error codes as defined for the add_configuration() function.
+ */
+int	read_netif_configuration( char * name, netif_ref netif );
+
+/** Networking module global data.
+ */
+net_globals_t	net_globals;
+
+DEVICE_MAP_IMPLEMENT( netifs, netif_t )
+
+GENERIC_CHAR_MAP_IMPLEMENT( measured_strings, measured_string_t )
+
+void module_print_name( void ){
+	printf( "%s", NAME );
+}
+
+int module_start( async_client_conn_t client_connection ){
+	ERROR_DECLARE;
+
+	ipcarg_t	phonehash;
+
+	async_set_client_connection( client_connection );
+	ERROR_PROPAGATE( pm_init());
+	if( ERROR_OCCURRED( net_initialize( client_connection ))
+	|| ERROR_OCCURRED( REGISTER_ME( SERVICE_NETWORKING, & phonehash ))){
+		pm_destroy();
+		return ERROR_CODE;
+	}
+
+	async_manager();
+
+	pm_destroy();
+	return EOK;
+}
+
+int net_initialize( async_client_conn_t client_connection ){
+	ERROR_DECLARE;
+
+	netifs_initialize( & net_globals.netifs );
+	char_map_initialize( & net_globals.netif_names );
+	modules_initialize( & net_globals.modules );
+	measured_strings_initialize( & net_globals.configuration );
+
+	// TODO dynamic configuration
+	ERROR_PROPAGATE( read_configuration());
+
+	ERROR_PROPAGATE( add_module( NULL, & net_globals.modules, LO_NAME, LO_FILENAME, SERVICE_LO, 0, connect_to_service ));
+	ERROR_PROPAGATE( add_module( NULL, & net_globals.modules, DP8390_NAME, DP8390_FILENAME, SERVICE_DP8390, 0, connect_to_service ));
+	ERROR_PROPAGATE( add_module( NULL, & net_globals.modules, ETHERNET_NAME, ETHERNET_FILENAME, SERVICE_ETHERNET, 0, connect_to_service ));
+	ERROR_PROPAGATE( add_module( NULL, & net_globals.modules, NILDUMMY_NAME, NILDUMMY_FILENAME, SERVICE_NILDUMMY, 0, connect_to_service ));
+
+	// build specific initialization
+	return net_initialize_build( client_connection );
+}
+
+int	net_get_device_conf_req( int net_phone, device_id_t device_id, measured_string_ref * configuration, size_t count, char ** data ){
+	netif_ref	netif;
+
+	if( !( configuration && ( count > 0 ))) return EINVAL;
+	netif = netifs_find( & net_globals.netifs, device_id );
+	if( netif ){
+		return net_get_conf( & netif->configuration, * configuration, count, data );
+	}else{
+		return net_get_conf( NULL, * configuration, count, data );
+	}
+}
+
+int	net_get_conf_req( int net_phone, measured_string_ref * configuration, size_t count, char ** data ){
+	if( !( configuration && ( count > 0 ))) return EINVAL;
+	return net_get_conf( NULL, * configuration, count, data );
+}
+
+int	net_get_conf( measured_strings_ref netif_conf, measured_string_ref configuration, size_t count, char ** data ){
+	measured_string_ref	setting;
+	size_t				index;
+
+	if( data ) * data = NULL;
+	for( index = 0; index < count; ++ index ){
+		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;
+}
+
+void net_free_settings( measured_string_ref settings, char * data ){
+}
+
+int net_connect_module( services_t service ){
+	return EOK;
+}
+
+int net_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){
+	ERROR_DECLARE;
+
+	measured_string_ref	strings;
+	char *				data;
+
+	* answer_count = 0;
+	switch( IPC_GET_METHOD( * call )){
+		case IPC_M_PHONE_HUNGUP:
+			return EOK;
+		case NET_NET_GET_DEVICE_CONF:
+			ERROR_PROPAGATE( measured_strings_receive( & strings, & data, IPC_GET_COUNT( call )));
+			net_get_device_conf_req( 0, IPC_GET_DEVICE( call ), & strings, IPC_GET_COUNT( call ), NULL );
+			// strings should not contain received data anymore
+			free( data );
+			ERROR_CODE = measured_strings_reply( strings, IPC_GET_COUNT( call ));
+			free( strings );
+			return ERROR_CODE;
+		case NET_NET_GET_CONF:
+			ERROR_PROPAGATE( measured_strings_receive( & strings, & data, IPC_GET_COUNT( call )));
+			net_get_conf_req( 0, & strings, IPC_GET_COUNT( call ), NULL );
+			// strings should not contain received data anymore
+			free( data );
+			ERROR_CODE = measured_strings_reply( strings, IPC_GET_COUNT( call ));
+			free( strings );
+			return ERROR_CODE;
+		case NET_NET_STARTUP:
+			return startup();
+	}
+	return ENOTSUP;
+}
+
+int read_configuration_file( const char * directory, const char * filename, measured_strings_ref configuration ){
+	ERROR_DECLARE;
+
+	size_t	index = 0;
+	char	line[ BUFFER_SIZE ];
+	FILE *	cfg;
+	int		read;
+	int		line_number = 0;
+
+	// construct the full filename
+	printf( "Reading file %s/%s\n", directory, filename );
+	if( snprintf( line, BUFFER_SIZE, "%s/%s", directory, filename ) > BUFFER_SIZE ){
+		return EOVERFLOW;
+	}
+	// open the file
+	cfg = fopen( line, "r" );
+	if( ! cfg ){
+		return ENOENT;
+	}
+
+	// read the configuration line by line
+	// until an error or the end of file
+	while(( ! ferror( cfg )) && ( ! feof( cfg ))){
+		read = fgetc( cfg );
+		if(( read > 0 ) && ( read != '\n' ) && ( read != '\r' )){
+			if( index >= BUFFER_SIZE ){
+				line[ BUFFER_SIZE - 1 ] = '\0';
+				printf( "line %d too long: %s\n", line_number, line );
+				// no space left in the line buffer
+				return EOVERFLOW;
+			}else{
+				// append the character
+				line[ index ] = (char) read;
+				++ index;
+			}
+		}else{
+			// on error or new line
+			line[ index ] = '\0';
+			++ line_number;
+			if( ERROR_OCCURRED( parse_line( configuration, line ))){
+				printf( "error on line %d: %s\n", line_number, line );
+				//fclose( cfg );
+				//return ERROR_CODE;
+			}
+			index = 0;
+		}
+	}
+	fclose( cfg );
+	return EOK;
+}
+
+int parse_line( measured_strings_ref configuration, char * line ){
+	ERROR_DECLARE;
+
+	measured_string_ref	setting;
+	char *				name;
+	char *				value;
+
+	// from the beginning
+	name = line;
+
+	// skip comments and blank lines
+	if(( * name == '#' ) || ( * name == '\0' )){
+		return EOK;
+	}
+	// skip spaces
+	while( isspace( * name )) ++ name;
+
+	// remember the name start
+	value = name;
+	// skip the name
+	while( isalnum( * value ) || ( * value == '_' )){
+		// make uppercase
+//		* value = toupper( * value );
+		++ value;
+	}
+
+	if( * value == '=' ){
+		// terminate the name
+		* value = '\0';
+	}else{
+		// terminate the name
+		* value = '\0';
+		// skip until '='
+		++ value;
+		while(( * value ) && ( * value != '=' )) ++ value;
+		// not found?
+		if( * value != '=' ) return EINVAL;
+	}
+
+	++ value;
+	// skip spaces
+	while( isspace( * value )) ++ value;
+	// create a bulk measured string till the end
+	setting = measured_string_create_bulk( value, 0 );
+	if( ! setting ) return ENOMEM;
+
+	// add the configuration setting
+	if( ERROR_OCCURRED( measured_strings_add( configuration, name, 0, setting ))){
+		free( setting );
+		return ERROR_CODE;
+	}
+	return EOK;
+}
+
+int add_configuration( measured_strings_ref configuration, const char * name, const char * value ){
+	ERROR_DECLARE;
+
+	measured_string_ref	setting;
+
+	setting = measured_string_create_bulk( value, 0 );
+	if( ! setting ) return ENOMEM;
+	// add the configuration setting
+	if( ERROR_OCCURRED( measured_strings_add( configuration, name, 0, setting ))){
+		free( setting );
+		return ERROR_CODE;
+	}
+	return EOK;
+}
+
+device_id_t generate_new_device_id( void ){
+	return device_assign_devno();
+}
+
+int read_configuration( void ){
+	// read the general configuration file
+	return read_configuration_file( CONF_DIR, CONF_GENERAL_FILE, & net_globals.configuration );
+}
+
+int read_netif_configuration( char * name, netif_ref netif ){
+	// read the netif configuration file
+	return read_configuration_file( CONF_DIR, name, & netif->configuration );
+}
+
+int start_device( netif_ref netif ){
+	ERROR_DECLARE;
+
+	measured_string_ref	setting;
+	services_t			internet_service;
+	int					irq;
+	int					io;
+	int					mtu;
+
+	// mandatory netif
+	setting = measured_strings_find( & netif->configuration, CONF_NETIF, 0 );
+	netif->driver = get_running_module( & net_globals.modules, setting->value );
+	if( ! netif->driver ){
+		printf( "Failed to start the network interface driver %s\n", setting->value );
+		return EINVAL;
+	}
+	// optional network interface layer
+	setting = measured_strings_find( & netif->configuration, CONF_NIL, 0 );
+	if( setting ){
+		netif->nil = get_running_module( & net_globals.modules, setting->value );
+		if( ! netif->nil ){
+			printf( "Failed to start the network interface layer %s\n", setting->value );
+			return EINVAL;
+		}
+	}else{
+		netif->nil = NULL;
+	}
+	// mandatory internet layer
+	setting = measured_strings_find( & netif->configuration, CONF_IL, 0 );
+	netif->il = get_running_module( & net_globals.modules, setting->value );
+	if( ! netif->il ){
+		printf( "Failed to start the internet layer %s\n", setting->value );
+		return EINVAL;
+	}
+	// end of the static loopback initialization
+	// startup the loopback interface
+	setting = measured_strings_find( & netif->configuration, CONF_IRQ, 0 );
+	irq = setting ? strtol( setting->value, NULL, 10 ) : 0;
+	setting = measured_strings_find( & netif->configuration, CONF_IO, 0 );
+	io = setting ? strtol( setting->value, NULL, 16 ) : 0;
+	ERROR_PROPAGATE( netif_probe_req( netif->driver->phone, netif->id, irq, io ));
+	if( netif->nil ){
+		setting = measured_strings_find( & netif->configuration, CONF_MTU, 0 );
+		if( ! setting ){
+			setting = measured_strings_find( & net_globals.configuration, CONF_MTU, 0 );
+		}
+		mtu = setting ? strtol( setting->value, NULL, 10 ) : 0;
+		ERROR_PROPAGATE( nil_device_req( netif->nil->phone, netif->id, mtu, netif->driver->service ));
+		internet_service = netif->nil->service;
+	}else{
+		internet_service = netif->driver->service;
+	}
+	switch( netif->il->service ){
+		case SERVICE_IP:
+			ERROR_PROPAGATE( ip_device_req( netif->il->phone, netif->id, internet_service ));
+			break;
+		default:
+			return ENOENT;
+	}
+	ERROR_PROPAGATE( netif_start_req( netif->driver->phone, netif->id ));
+	return EOK;
+}
+
+int startup( void ){
+	ERROR_DECLARE;
+
+#ifdef CONFIG_NETIF_DP8390
+	char *		conf_files[] = { "lo", "ne2k" };
+#else
+	char *		conf_files[] = { "lo" };
+#endif
+
+	int			count = sizeof( conf_files ) / sizeof( char * );
+	int			index;
+	netif_ref	netif;
+	int			i;
+	measured_string_ref	setting;
+
+	for( i = 0; i < count; ++ i ){
+		netif = ( netif_ref ) malloc( sizeof( netif_t ));
+		if( ! netif ) return ENOMEM;
+
+		netif->id = generate_new_device_id();
+		if( ! netif->id ) return EXDEV;
+		ERROR_PROPAGATE( measured_strings_initialize( & netif->configuration ));
+		// read configuration files
+		if( ERROR_OCCURRED( read_netif_configuration( conf_files[ i ], netif ))){
+			measured_strings_destroy( & netif->configuration );
+			free( netif );
+			return ERROR_CODE;
+		}
+		// mandatory name
+		setting = measured_strings_find( & netif->configuration, CONF_NAME, 0 );
+		if( ! setting ){
+			printf( "The name is missing\n" );
+			measured_strings_destroy( & netif->configuration );
+			free( netif );
+			return EINVAL;
+		}
+		netif->name = setting->value;
+		// add to the netifs map
+		index = netifs_add( & net_globals.netifs, netif->id, netif );
+		if( index < 0 ){
+			measured_strings_destroy( & netif->configuration );
+			free( netif );
+			return index;
+		}
+		// add to the netif names map
+		if( ERROR_OCCURRED( char_map_add( & net_globals.netif_names, netif->name, 0, index ))
+		// start network interfaces and needed modules
+		|| ERROR_OCCURRED( start_device( netif ))){
+			measured_strings_destroy( & netif->configuration );
+			netifs_exclude_index( & net_globals.netifs, index );
+			return ERROR_CODE;
+		}
+		// increment modules' usage
+		++ netif->driver->usage;
+		if( netif->nil ) ++ netif->nil->usage;
+		++ netif->il->usage;
+		printf( "New network interface started:\n\tname\t= %s\n\tid\t= %d\n\tdriver\t= %s\n\tnil\t= %s\n\til\t= %s\n", netif->name, netif->id, netif->driver->name, netif->nil ? netif->nil->name : NULL, netif->il->name );
+	}
+	return EOK;
+}
+
+/** @}
+ */
Index: uspace/srv/net/net/net.h
===================================================================
--- uspace/srv/net/net/net.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/net/net.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,248 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup net
+ *  @{
+ */
+
+/** @file
+ *  Networking subsystem central module.
+ */
+
+#ifndef __NET_NET_H__
+#define __NET_NET_H__
+
+#include <ipc/ipc.h>
+
+#include "../include/device.h"
+
+#include "../structures/char_map.h"
+#include "../structures/generic_char_map.h"
+#include "../structures/measured_strings.h"
+#include "../structures/module_map.h"
+#include "../structures/packet/packet.h"
+
+/** @name Modules definitions
+ */
+/*@{*/
+
+/** Loopback network interface module name.
+ */
+#define LO_NAME				"lo"
+
+/** Loopback network interface module full path filename.
+ */
+#define LO_FILENAME			"/srv/lo"
+
+/** DP8390 network interface module name.
+ */
+#define DP8390_NAME			"dp8390"
+
+/** DP8390 network interface module full path filename.
+ */
+#define DP8390_FILENAME		"/srv/dp8390"
+
+/** Ethernet module name.
+ */
+#define ETHERNET_NAME		"ethernet"
+
+/** Ethernet module full path filename.
+ */
+#define ETHERNET_FILENAME	"/srv/eth"
+
+/** Ethernet module name.
+ */
+#define NILDUMMY_NAME		"nildummy"
+
+/** Ethernet module full path filename.
+ */
+#define NILDUMMY_FILENAME	"/srv/nildummy"
+
+/** IP module name.
+ */
+#define IP_NAME				"ip"
+
+/** IP module full path filename.
+ */
+#define IP_FILENAME			"/srv/ip"
+
+/*@}*/
+
+/** @name Configuration setting names definitions
+ */
+/*@{*/
+
+/** Network interface name configuration label.
+ */
+#define CONF_NAME			"NAME"
+
+/** Network interface module name configuration label.
+ */
+#define CONF_NETIF			"NETIF"
+
+/** Network interface layer module name configuration label.
+ */
+#define CONF_NIL			"NIL"
+
+/** Internet protocol module name configuration label.
+ */
+#define CONF_IL				"IL"
+
+/** Interrupt number configuration label.
+ */
+#define CONF_IRQ			"IRQ"
+
+/** Device input/output address configuration label.
+ */
+#define CONF_IO				"IO"
+
+/** Maximum transmission unit configuration label.
+ */
+#define CONF_MTU			"MTU"
+
+/*@}*/
+
+/** Configuration directory.
+ */
+#define CONF_DIR			"/cfg/net"
+
+/** General configuration file.
+ */
+#define CONF_GENERAL_FILE	"general"
+
+/** Type definition of the network interface specific data.
+ *  @see netif
+ */
+typedef struct netif	netif_t;
+
+/** Type definition of the network interface specific data pointer.
+ *  @see netif
+ */
+typedef netif_t *		netif_ref;
+
+/** Type definition of the networking module global data.
+ *  @see net_globals
+ */
+typedef struct net_globals	net_globals_t;
+
+/** Present network interfaces.
+ *  Maps devices to the networking device specific data.
+ *  @see device.h
+ */
+DEVICE_MAP_DECLARE( netifs, netif_t )
+
+/** 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.
+ */
+struct netif{
+	/** System-unique network interface identifier.
+	 */
+	device_id_t		id;
+	/** Serving network interface driver module index.
+	 */
+	module_ref		driver;
+	/** Serving link layer module index.
+	 */
+	module_ref		nil;
+	/** Serving internet layer module index.
+	 */
+	module_ref		il;
+	/** System-unique network interface name.
+	 */
+	char *			name;
+	/** Configuration.
+	 */
+	measured_strings_t	configuration;
+};
+
+/** Networking module global variables.
+ */
+struct net_globals{
+	/** Present network interfaces.
+	 */
+	netifs_t		netifs;
+	/** Network interface structure indices by names.
+	 */
+	char_map_t		netif_names;
+	/** Available modules.
+	 */
+	modules_t		modules;
+	/** Global configuration.
+	 */
+	measured_strings_t	configuration;
+};
+
+/** Adds 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.
+ *  @returns EOK on success.
+ *  @returns ENOMEM if there is not enough memory left.
+ */
+int	add_configuration( measured_strings_ref configuration, const char * name, const char * value );
+
+/** Processes 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.
+ *  @returns EOK on success.
+ *  @returns ENOTSUP if the message is not known.
+ *  @see net_interface.h
+ *  @see IS_NET_NET_MESSAGE()
+ */
+int net_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count );
+
+/** Initializes the networking module for the chosen subsystem build type.
+ *  @param[in] client_connection The client connection processing function. The module skeleton propagates its own one.
+ *  @returns EOK on success.
+ *  @returns ENOMEM if there is not enough memory left.
+ */
+int	net_initialize_build( async_client_conn_t client_connection );
+
+/** Processes the module message.
+ *  Distributes the message to the right bundled module.
+ *  @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.
+ *  @returns EOK on success.
+ *  @returns ENOTSUP if the message is not known.
+ *  @returns Other error codes as defined for each bundled module message function.
+ */
+int	module_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count );
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/net/net_bundle.c
===================================================================
--- uspace/srv/net/net/net_bundle.c	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/net/net_bundle.c	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup net
+ *  @{
+ */
+
+/** @file
+ *  Wrapper for the bundled networking and TCP/IP stact modules.
+ *  Distributes messages and initializes all module parts.
+ */
+
+#include <string.h>
+
+#include <ipc/ipc.h>
+
+#include "../messages.h"
+
+#include "../include/ip_interface.h"
+
+#include "../structures/measured_strings.h"
+#include "../structures/module_map.h"
+#include "../structures/packet/packet_server.h"
+
+#include "../il/arp/arp_module.h"
+#include "../il/ip/ip_module.h"
+#include "../tl/icmp/icmp_module.h"
+#include "../tl/udp/udp_module.h"
+#include "../tl/tcp/tcp_module.h"
+
+#include "net.h"
+
+/** Networking module global data.
+ */
+extern net_globals_t	net_globals;
+
+int module_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){
+	if(( IPC_GET_METHOD( * call ) == IPC_M_CONNECT_TO_ME )
+	|| IS_NET_IL_MESSAGE( call )
+	|| IS_NET_TL_MESSAGE( call )
+	|| IS_NET_SOCKET_MESSAGE( call )){
+		switch( IPC_GET_TARGET( call )){
+			case SERVICE_IP:
+				return ip_message( callid, call, answer, answer_count );
+			case SERVICE_ARP:
+				return arp_message( callid, call, answer, answer_count );
+			case SERVICE_ICMP:
+				return icmp_message( callid, call, answer, answer_count );
+			case SERVICE_UDP:
+				return udp_message( callid, call, answer, answer_count );
+			case SERVICE_TCP:
+				return tcp_message( callid, call, answer, answer_count );
+			default:
+				return EINVAL;
+		}
+	}else if( IS_NET_IP_MESSAGE( call )){
+		return ip_message( callid, call, answer, answer_count );
+	}else if( IS_NET_ARP_MESSAGE( call )){
+		return arp_message( callid, call, answer, answer_count );
+	}else if( IS_NET_ICMP_MESSAGE( call )){
+		return icmp_message( callid, call, answer, answer_count );
+	}else if( IS_NET_UDP_MESSAGE( call )){
+		return udp_message( callid, call, answer, answer_count );
+	}else if( IS_NET_TCP_MESSAGE( call )){
+		return tcp_message( callid, call, answer, answer_count );
+	}else{
+		if( IS_NET_PACKET_MESSAGE( call )){
+			return packet_server_message( callid, call, answer, answer_count );
+		}else{
+			return net_message( callid, call, answer, answer_count );
+		}
+	}
+}
+
+int net_initialize_build( async_client_conn_t client_connection ){
+	ERROR_DECLARE;
+
+	ipcarg_t	phonehash;
+
+	ERROR_PROPAGATE( REGISTER_ME( SERVICE_IP, & phonehash ));
+	ERROR_PROPAGATE( add_module( NULL, & net_globals.modules, IP_NAME, IP_FILENAME, SERVICE_IP, task_get_id(), ip_connect_module ));
+	ERROR_PROPAGATE( ip_initialize( client_connection ));
+	ERROR_PROPAGATE( REGISTER_ME( SERVICE_ARP, & phonehash ));
+	ERROR_PROPAGATE( arp_initialize( client_connection ));
+	ERROR_PROPAGATE( REGISTER_ME( SERVICE_ICMP, & phonehash ));
+	ERROR_PROPAGATE( icmp_initialize( client_connection ));
+	ERROR_PROPAGATE( REGISTER_ME( SERVICE_UDP, & phonehash ));
+	ERROR_PROPAGATE( udp_initialize( client_connection ));
+	ERROR_PROPAGATE( REGISTER_ME( SERVICE_TCP, & phonehash ));
+	ERROR_PROPAGATE( tcp_initialize( client_connection ));
+	return EOK;
+}
+
+/** @}
+ */
Index: uspace/srv/net/net/net_messages.h
===================================================================
--- uspace/srv/net/net/net_messages.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/net/net_messages.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup net
+ *  @{
+ */
+
+/** @file
+ *  Networking subsystem central module messages.
+ *  @see net_interface.h
+ */
+
+#ifndef __NET_NET_MESSAGES_H__
+#define __NET_NET_MESSAGES_H__
+
+#include <ipc/ipc.h>
+
+#include "../messages.h"
+
+/** Networking subsystem central module messages.
+ */
+typedef enum{
+	/** Returns the general configuration
+	 *  @see net_get_conf_req()
+	 */
+	NET_NET_GET_CONF = NET_FIRST,
+	/** Returns the device specific configuration
+	 *  @see net_get_device_conf_req()
+	 */
+	NET_NET_GET_DEVICE_CONF,
+	/** Starts the networking stack.
+	 */
+	NET_NET_STARTUP,
+} net_messages;
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/net/net_remote.c
===================================================================
--- uspace/srv/net/net/net_remote.c	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/net/net_remote.c	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup net
+ *  @{
+ */
+
+/** @file
+ *  Networking interface implementation for standalone remote modules.
+ *  @see net_interface.h
+ */
+
+#include <ipc/services.h>
+
+#include <malloc.h>
+
+#include "../messages.h"
+#include "../modules.h"
+
+#include "../include/device.h"
+#include "../include/net_interface.h"
+
+#include "../structures/measured_strings.h"
+
+#include "net_messages.h"
+
+int	net_get_device_conf_req( int net_phone, device_id_t device_id, measured_string_ref * configuration, size_t count, char ** data ){
+	return generic_translate_req( net_phone, NET_NET_GET_DEVICE_CONF, device_id, 0, * configuration, count, configuration, data );
+}
+
+int	net_get_conf_req( int net_phone, measured_string_ref * configuration, size_t count, char ** data ){
+	return generic_translate_req( net_phone, NET_NET_GET_DEVICE_CONF, 0, 0, * configuration, count, configuration, data );
+}
+
+void net_free_settings( measured_string_ref settings, char * data ){
+	if( settings ) free( settings );
+	if( data ) free( data );
+}
+
+int net_connect_module( services_t service ){
+	return connect_to_service( SERVICE_NETWORKING );
+}
+
+/** @}
+ */
Index: uspace/srv/net/net/net_standalone.c
===================================================================
--- uspace/srv/net/net/net_standalone.c	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/net/net_standalone.c	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup net
+ *  @{
+ */
+
+/** @file
+ *  Wrapper for the standalone networking module.
+ */
+
+#include <string.h>
+
+#include <ipc/ipc.h>
+
+#include "../messages.h"
+
+#include "../include/ip_interface.h"
+
+#include "../structures/measured_strings.h"
+#include "../structures/module_map.h"
+#include "../structures/packet/packet_server.h"
+
+#include "net.h"
+
+/** Networking module global data.
+ */
+extern net_globals_t	net_globals;
+
+int module_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){
+	if( IS_NET_PACKET_MESSAGE( call )){
+		return packet_server_message( callid, call, answer, answer_count );
+	}else{
+		return net_message( callid, call, answer, answer_count );
+	}
+}
+
+int net_initialize_build( async_client_conn_t client_connection ){
+	ERROR_DECLARE;
+
+	task_id_t	task_id;
+
+	task_id = spawn( "/srv/ip" );
+	if( ! task_id ) return EINVAL;
+	ERROR_PROPAGATE( add_module( NULL, & net_globals.modules, IP_NAME, IP_FILENAME, SERVICE_IP, task_id, ip_connect_module ));
+	if( ! spawn( "/srv/icmp" )) return EINVAL;
+	if( ! spawn( "/srv/udp" )) return EINVAL;
+	if( ! spawn( "/srv/tcp" )) return EINVAL;
+	return EOK;
+}
+
+/** @}
+ */
Index: uspace/srv/net/net/start/Makefile
===================================================================
--- uspace/srv/net/net/start/Makefile	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/net/start/Makefile	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,49 @@
+#
+# 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.
+#
+
+NAME = netstart
+
+NET_BASE = ../../
+STRUCTURES = $(NET_BASE)structures/
+
+include ../../../../../Makefile.config
+
+## Sources
+#
+
+OUTPUT = $(NAME)
+SOURCES = \
+	$(NAME).c \
+	$(NET_BASE)checksum.c \
+	$(NET_BASE)modules.c \
+	$(NET_BASE)self_test.c \
+	$(STRUCTURES)char_map.c \
+	$(STRUCTURES)dynamic_fifo.c \
+	$(STRUCTURES)measured_strings.c
+
+include $(NET_BASE)Makefile.module
Index: uspace/srv/net/net/start/netstart.c
===================================================================
--- uspace/srv/net/net/start/netstart.c	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/net/start/netstart.c	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup net
+ *  @{
+ */
+
+/** @file
+ *  Starts the networking subsystem.
+ *  Performs self test if configured to.
+ *  @see configuration.h
+ */
+
+#include <async.h>
+#include <stdio.h>
+#include <task.h>
+
+#include <ipc/ipc.h>
+#include <ipc/services.h>
+
+#include "../../err.h"
+#include "../../modules.h"
+#include "../../self_test.h"
+
+#include "../net_messages.h"
+
+/** Networking startup module name.
+ */
+#define NAME	"Networking startup"
+
+/** Module entry point.
+ *  @param[in] argc The number of command line parameters.
+ *  @param[in] argv The command line parameters.
+ *  @returns EOK on success.
+ *  @returns EINVAL if the net module cannot be started.
+ *  @returns Other error codes as defined for the self_test() function.
+ *  @returns Other error codes as defined for the NET_NET_STARTUP message.
+ */
+int		main( int argc, char * argv[] );
+
+/** Starts the module.
+ *  @param[in] fname The module absolute name.
+ *  @returns The started module task identifier.
+ *  @returns Other error codes as defined for the task_spawn() function.
+ */
+task_id_t	spawn( char * fname );
+
+int main( int argc, char * argv[] ){
+	ERROR_DECLARE;
+
+	int		net_phone;
+
+	printf( "Task %d - ", task_get_id());
+	printf( "%s\n", NAME );
+	// run self tests
+	ERROR_PROPAGATE( self_test());
+	// start net service
+	if( ! spawn( "/srv/net" )){
+		fprintf( stderr, "Could not spawn net\n" );
+		return EINVAL;
+	}
+	// start net
+	net_phone = connect_to_service( SERVICE_NETWORKING );
+	if( ERROR_OCCURRED( ipc_call_sync_0_0( net_phone, NET_NET_STARTUP ))){
+		printf( "ERROR %d\n", ERROR_CODE );
+		return ERROR_CODE;
+	}else{
+		printf( "OK\n" );
+	}
+
+	return EOK;
+}
+
+task_id_t spawn( char * fname ){
+	char *	argv[ 2 ];
+	task_id_t	res;
+
+//	printf( "Spawning %s\n", fname );
+	argv[ 0 ] = fname;
+	argv[ 1 ] = NULL;
+	res = task_spawn( fname, argv );
+	if( res != 0 ){
+		/* Success */
+		usleep( 50000 );
+	}
+	return res;
+}
+
+/** @}
+ */
Index: uspace/srv/net/netif/dp8390/Makefile
===================================================================
--- uspace/srv/net/netif/dp8390/Makefile	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/netif/dp8390/Makefile	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,66 @@
+#
+# 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.
+#
+
+NAME = dp8390
+
+NET_BASE = ../../
+STRUCTURES = $(NET_BASE)structures/
+
+include $(NET_BASE)../../../Makefile.config
+
+## Sources
+#
+
+OUTPUT = $(NAME)
+SOURCES = \
+	$(NAME).c \
+	$(NAME)_module.c \
+	ne2000.c \
+	$(NET_BASE)module.c \
+	$(NET_BASE)modules.c \
+	$(NET_BASE)netif/netif.c \
+	$(STRUCTURES)measured_strings.c \
+	$(STRUCTURES)packet/packet.c \
+	$(STRUCTURES)packet/packet_client.c \
+	$(STRUCTURES)packet/packet_remote.c
+
+ifeq ($(NETWORKING), module)
+
+	SOURCES +=	$(NET_BASE)checksum.c \
+				$(NET_BASE)nil/eth/eth.c \
+				$(NET_BASE)net/net_remote.c \
+				$(NET_BASE)netif/netif_nil_bundle.c
+
+else
+
+	SOURCES += 	$(NET_BASE)nil/nil_remote.c \
+				$(NET_BASE)netif/netif_standalone.c
+
+endif
+
+include $(NET_BASE)Makefile.module
Index: uspace/srv/net/netif/dp8390/dp8390.c
===================================================================
--- uspace/srv/net/netif/dp8390/dp8390.c	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/netif/dp8390/dp8390.c	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,1675 @@
+/*
+ * Copyright (c) 1987,1997, 2006, Vrije Universiteit, Amsterdam, The Netherlands All rights reserved. Redistribution and use of the MINIX 3 operating system in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Vrije Universiteit nor the names of the software authors or contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+ * * Any deviations from these conditions require written permission from the copyright holder in advance
+ *
+ *
+ * Disclaimer
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS, AUTHORS, AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR ANY AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Changes:
+ *  2009 ported to HelenOS, Lukas Mejdrech
+ */
+
+/** @addtogroup dp8390
+ *  @{
+ */
+
+/** @file
+ *  DP8390 network interface core implementation.
+ */
+
+#include <assert.h>
+#include <errno.h>
+
+#include "../../include/byteorder.h"
+
+#include "../../structures/packet/packet.h"
+#include "../../structures/packet/packet_client.h"
+
+#include "../netif.h"
+
+#include "dp8390_drv.h"
+#include "dp8390_port.h"
+
+/*
+ * dp8390.c
+ *
+ * Created:	before Dec 28, 1992 by Philip Homburg <philip@f-mnx.phicoh.com>
+ *
+ * Modified Mar 10 1994 by Philip Homburg
+ *	Become a generic dp8390 driver.
+ *
+ * Modified Dec 20 1996 by G. Falzoni <falzoni@marina.scn.de>
+ *	Added support for 3c503 boards.
+ */
+
+#include "local.h"
+#include "dp8390.h"
+
+/** Queues the outgoing packet.
+ *  @param[in] dep The network interface structure.
+ *  @param[in] packet The outgoing packet.
+ *  @returns EOK on success.
+ *  @returns EINVAL 
+ */
+int	queue_packet( dpeth_t * dep, packet_t packet );
+
+/** Reads a memory block byte by byte.
+ *  @param[in] port The source address.
+ *  @param[out] buf The destination buffer.
+ *  @param[in] size The memory block size in bytes.
+ */
+static void outsb( port_t port, void * buf, size_t size );
+
+/** Reads a memory block word by word.
+ *  @param[in] port The source address.
+ *  @param[out] buf The destination buffer.
+ *  @param[in] size The memory block size in bytes.
+ */
+static void outsw( port_t port, void * buf, size_t size );
+
+//static u16_t eth_ign_proto;
+//static char *progname;
+
+/* Configuration */
+/*typedef struct dp_conf
+{
+	port_t dpc_port;
+	int dpc_irq;
+	phys_bytes dpc_mem;
+	char *dpc_envvar;
+} dp_conf_t;
+*/
+//dp_conf_t dp_conf[]=	/* Card addresses */
+//{
+	/* I/O port, IRQ,  Buffer address,  Env. var. */
+/*	{  0x280,     3,    0xD0000,        "DPETH0"	},
+	{  0x300,     5,    0xC8000,        "DPETH1"	},
+	{  0x380,    10,    0xD8000,        "DPETH2"	},
+};
+*/
+/* Test if dp_conf has exactly DE_PORT_NR entries.  If not then you will see
+ * the error: "array size is negative".
+ */
+//extern int ___dummy[DE_PORT_NR == sizeof(dp_conf)/sizeof(dp_conf[0]) ? 1 : -1];
+
+/* Card inits configured out? */
+#if !ENABLE_WDETH
+#define wdeth_probe(dep)	(0)
+#endif
+#if !ENABLE_NE2000
+#define ne_probe(dep)		(0)
+#endif
+#if !ENABLE_3C503
+#define el2_probe(dep)		(0)
+#endif
+
+/* Some clones of the dp8390 and the PC emulator 'Bochs' require the CR_STA
+ * on writes to the CR register. Additional CR_STAs do not appear to hurt
+ * genuine dp8390s
+ */
+#define CR_EXTRA	CR_STA
+
+//#if ENABLE_PCI
+//_PROTOTYPE( static void pci_conf, (void)				);
+//#endif
+//_PROTOTYPE( static void do_vwrite, (message *mp, int from_int,
+//							int vectored)	);
+//_PROTOTYPE( static void do_vwrite_s, (message *mp, int from_int)	);
+//_PROTOTYPE( static void do_vread, (message *mp, int vectored)		);
+//_PROTOTYPE( static void do_vread_s, (message *mp)			);
+//_PROTOTYPE( static void do_init, (message *mp)				);
+//_PROTOTYPE( static void do_int, (dpeth_t *dep)				);
+//_PROTOTYPE( static void do_getstat, (message *mp)			);
+//_PROTOTYPE( static void do_getstat_s, (message *mp)			);
+//_PROTOTYPE( static void do_getname, (message *mp)			);
+//_PROTOTYPE( static void do_stop, (message *mp)				);
+_PROTOTYPE( static void dp_init, (dpeth_t *dep)				);
+//_PROTOTYPE( static void dp_confaddr, (dpeth_t *dep)			);
+_PROTOTYPE( static void dp_reinit, (dpeth_t *dep)			);
+_PROTOTYPE( static void dp_reset, (dpeth_t *dep)			);
+//_PROTOTYPE( static void dp_check_ints, (dpeth_t *dep)			);
+_PROTOTYPE( static void dp_recv, (dpeth_t *dep)				);
+_PROTOTYPE( static void dp_send, (dpeth_t *dep)				);
+//_PROTOTYPE( static void dp8390_stop, (void)				);
+_PROTOTYPE( static void dp_getblock, (dpeth_t *dep, int page,
+				size_t offset, size_t size, void *dst)	);
+_PROTOTYPE( static void dp_pio8_getblock, (dpeth_t *dep, int page,
+				size_t offset, size_t size, void *dst)	);
+_PROTOTYPE( static void dp_pio16_getblock, (dpeth_t *dep, int page,
+				size_t offset, size_t size, void *dst)	);
+_PROTOTYPE( static int dp_pkt2user, (dpeth_t *dep, int page,
+							int length)	);
+//_PROTOTYPE( static int dp_pkt2user_s, (dpeth_t *dep, int page,
+//							int length)	);
+_PROTOTYPE( static void dp_user2nic, (dpeth_t *dep, iovec_dat_t *iovp, 
+		vir_bytes offset, int nic_addr, vir_bytes count)	);
+//_PROTOTYPE( static void dp_user2nic_s, (dpeth_t *dep, iovec_dat_s_t *iovp, 
+//		vir_bytes offset, int nic_addr, vir_bytes count)	);
+_PROTOTYPE( static void dp_pio8_user2nic, (dpeth_t *dep,
+				iovec_dat_t *iovp, vir_bytes offset,
+				int nic_addr, vir_bytes count)		);
+//_PROTOTYPE( static void dp_pio8_user2nic_s, (dpeth_t *dep,
+//				iovec_dat_s_t *iovp, vir_bytes offset,
+//				int nic_addr, vir_bytes count)		);
+_PROTOTYPE( static void dp_pio16_user2nic, (dpeth_t *dep,
+				iovec_dat_t *iovp, vir_bytes offset,
+				int nic_addr, vir_bytes count)		);
+//_PROTOTYPE( static void dp_pio16_user2nic_s, (dpeth_t *dep,
+//				iovec_dat_s_t *iovp, vir_bytes offset,
+//				int nic_addr, vir_bytes count)		);
+_PROTOTYPE( static void dp_nic2user, (dpeth_t *dep, int nic_addr, 
+		iovec_dat_t *iovp, vir_bytes offset, vir_bytes count)	);
+//_PROTOTYPE( static void dp_nic2user_s, (dpeth_t *dep, int nic_addr, 
+//		iovec_dat_s_t *iovp, vir_bytes offset, vir_bytes count)	);
+_PROTOTYPE( static void dp_pio8_nic2user, (dpeth_t *dep, int nic_addr, 
+		iovec_dat_t *iovp, vir_bytes offset, vir_bytes count)	);
+//_PROTOTYPE( static void dp_pio8_nic2user_s, (dpeth_t *dep, int nic_addr, 
+//		iovec_dat_s_t *iovp, vir_bytes offset, vir_bytes count)	);
+_PROTOTYPE( static void dp_pio16_nic2user, (dpeth_t *dep, int nic_addr, 
+		iovec_dat_t *iovp, vir_bytes offset, vir_bytes count)	);
+//_PROTOTYPE( static void dp_pio16_nic2user_s, (dpeth_t *dep, int nic_addr, 
+//		iovec_dat_s_t *iovp, vir_bytes offset, vir_bytes count)	);
+_PROTOTYPE( static void dp_next_iovec, (iovec_dat_t *iovp)		);
+//_PROTOTYPE( static void dp_next_iovec_s, (iovec_dat_s_t *iovp)		);
+_PROTOTYPE( static void conf_hw, (dpeth_t *dep)				);
+//_PROTOTYPE( static void update_conf, (dpeth_t *dep, dp_conf_t *dcp)	);
+_PROTOTYPE( static void map_hw_buffer, (dpeth_t *dep)			);
+//_PROTOTYPE( static int calc_iovec_size, (iovec_dat_t *iovp)		);
+//_PROTOTYPE( static int calc_iovec_size_s, (iovec_dat_s_t *iovp)		);
+_PROTOTYPE( static void reply, (dpeth_t *dep, int err, int may_block)	);
+//_PROTOTYPE( static void mess_reply, (message *req, message *reply)	);
+_PROTOTYPE( static void get_userdata, (int user_proc,
+		vir_bytes user_addr, vir_bytes count, void *loc_addr)	);
+//_PROTOTYPE( static void get_userdata_s, (int user_proc,
+//		cp_grant_id_t grant, vir_bytes offset, vir_bytes count,
+//		void *loc_addr)	);
+//_PROTOTYPE( static void put_userdata, (int user_proc,
+//		vir_bytes user_addr, vir_bytes count, void *loc_addr)	);
+//_PROTOTYPE( static void put_userdata_s, (int user_proc,
+//		cp_grant_id_t grant, size_t count, void *loc_addr)	);
+_PROTOTYPE( static void insb, (port_t port, void *buf, size_t size)				);
+_PROTOTYPE( static void insw, (port_t port, void *buf, size_t size)				);
+//_PROTOTYPE( static void do_vir_insb, (port_t port, int proc,
+//					vir_bytes buf, size_t size)	);
+//_PROTOTYPE( static void do_vir_insw, (port_t port, int proc,
+//					vir_bytes buf, size_t size)	);
+//_PROTOTYPE( static void do_vir_outsb, (port_t port, int proc,
+//					vir_bytes buf, size_t size)	);
+//_PROTOTYPE( static void do_vir_outsw, (port_t port, int proc,
+//					vir_bytes buf, size_t size)	);
+
+int do_probe( dpeth_t * dep ){
+	/* This is the default, try to (re)locate the device. */
+	conf_hw(dep);
+	if (dep->de_mode == DEM_DISABLED)
+	{
+		/* Probe failed, or the device is configured off. */
+		return EXDEV;//ENXIO;
+	}
+	if (dep->de_mode == DEM_ENABLED)
+		dp_init(dep);
+	return EOK;
+}
+
+/*===========================================================================*
+ *				dp8390_dump				     *
+ *===========================================================================*/
+void dp8390_dump( dpeth_t * dep )
+{
+//	dpeth_t *dep;
+	int /*i,*/ isr;
+
+//	printf("\n");
+//	for (i= 0, dep = &de_table[0]; i<DE_PORT_NR; i++, dep++)
+//	{
+#if XXX
+		if (dep->de_mode == DEM_DISABLED)
+			printf("dp8390 port %d is disabled\n", i);
+		else if (dep->de_mode == DEM_SINK)
+			printf("dp8390 port %d is in sink mode\n", i);
+#endif
+
+		if (dep->de_mode != DEM_ENABLED)
+//			continue;
+			return;
+
+//		printf("dp8390 statistics of port %d:\n", i);
+
+		printf("recvErr    :%8ld\t", dep->de_stat.ets_recvErr);
+		printf("sendErr    :%8ld\t", dep->de_stat.ets_sendErr);
+		printf("OVW        :%8ld\n", dep->de_stat.ets_OVW);
+
+		printf("CRCerr     :%8ld\t", dep->de_stat.ets_CRCerr);
+		printf("frameAll   :%8ld\t", dep->de_stat.ets_frameAll);
+		printf("missedP    :%8ld\n", dep->de_stat.ets_missedP);
+
+		printf("packetR    :%8ld\t", dep->de_stat.ets_packetR);
+		printf("packetT    :%8ld\t", dep->de_stat.ets_packetT);
+		printf("transDef   :%8ld\n", dep->de_stat.ets_transDef);
+
+		printf("collision  :%8ld\t", dep->de_stat.ets_collision);
+		printf("transAb    :%8ld\t", dep->de_stat.ets_transAb);
+		printf("carrSense  :%8ld\n", dep->de_stat.ets_carrSense);
+
+		printf("fifoUnder  :%8ld\t", dep->de_stat.ets_fifoUnder);
+		printf("fifoOver   :%8ld\t", dep->de_stat.ets_fifoOver);
+		printf("CDheartbeat:%8ld\n", dep->de_stat.ets_CDheartbeat);
+
+		printf("OWC        :%8ld\t", dep->de_stat.ets_OWC);
+
+		isr= inb_reg0(dep, DP_ISR);
+		printf("dp_isr = 0x%x + 0x%x, de_flags = 0x%x\n", isr,
+					inb_reg0(dep, DP_ISR), dep->de_flags);
+//	}
+}
+
+/*===========================================================================*
+ *				do_init					     *
+ *===========================================================================*/
+int do_init( dpeth_t * dep, int mode ){
+	if (dep->de_mode == DEM_DISABLED)
+	{
+		// might call do_probe()
+		return EXDEV;
+	}
+
+	if (dep->de_mode == DEM_SINK)
+	{
+//		strncpy((char *) dep->de_address.ea_addr, "ZDP", 6);
+//		dep->de_address.ea_addr[5] = port;
+//		dp_confaddr(dep);
+//		reply_mess.m_type = DL_CONF_REPLY;
+//		reply_mess.m3_i1 = mp->DL_PORT;
+//		reply_mess.m3_i2 = DE_PORT_NR;
+//		*(ether_addr_t *) reply_mess.m3_ca1 = dep->de_address;
+//		mess_reply(mp, &reply_mess);
+//		return;
+		return EOK;
+	}
+	assert(dep->de_mode == DEM_ENABLED);
+	assert(dep->de_flags & DEF_ENABLED);
+
+	dep->de_flags &= ~(DEF_PROMISC | DEF_MULTI | DEF_BROAD);
+
+	if (mode & DL_PROMISC_REQ)
+		dep->de_flags |= DEF_PROMISC | DEF_MULTI | DEF_BROAD;
+	if (mode & DL_MULTI_REQ)
+		dep->de_flags |= DEF_MULTI;
+	if (mode & DL_BROAD_REQ)
+		dep->de_flags |= DEF_BROAD;
+
+//	dep->de_client = mp->m_source;
+	dp_reinit(dep);
+
+//	reply_mess.m_type = DL_CONF_REPLY;
+//	reply_mess.m3_i1 = mp->DL_PORT;
+//	reply_mess.m3_i2 = DE_PORT_NR;
+//	*(ether_addr_t *) reply_mess.m3_ca1 = dep->de_address;
+
+//	mess_reply(mp, &reply_mess);
+	return EOK;
+}
+
+/*===========================================================================*
+ *				do_stop					     *
+ *===========================================================================*/
+void do_stop( dpeth_t * dep ){
+	if(( dep->de_mode != DEM_SINK ) && ( dep->de_mode == DEM_ENABLED ) && ( dep->de_flags & DEF_ENABLED )){
+		outb_reg0( dep, DP_CR, CR_STP | CR_DM_ABORT );
+		( dep->de_stopf )( dep );
+
+		dep->de_flags = DEF_EMPTY;
+	}
+}
+
+int queue_packet( dpeth_t * dep, packet_t packet ){
+	packet_t	tmp;
+
+	if( dep->packet_count >= MAX_PACKETS ){
+		netif_pq_release( packet_get_id( packet ));
+		return ELIMIT;
+	}
+
+	tmp = dep->packet_queue;
+	while( pq_next( tmp )){
+		tmp = pq_next( tmp );
+	}
+	if( ! pq_add( tmp, packet, 0, 0 )){
+		return EINVAL;
+	}
+	if( ! dep->packet_count ){
+		dep->packet_queue = packet;
+	}
+	++ dep->packet_count;
+	return EBUSY;
+}
+
+/*===========================================================================*
+ *			based on	do_vwrite				     *
+ *===========================================================================*/
+int do_pwrite( dpeth_t * dep, packet_t packet, int from_int )
+{
+//	int port, count, size;
+	int size;
+	int sendq_head;
+/*	dpeth_t *dep;
+
+	port = mp->DL_PORT;
+	count = mp->DL_COUNT;
+	if (port < 0 || port >= DE_PORT_NR)
+		panic("", "dp8390: illegal port", port);
+	dep= &de_table[port];
+	dep->de_client= mp->DL_PROC;
+*/
+	if (dep->de_mode == DEM_SINK)
+	{
+		assert(!from_int);
+//		dep->de_flags |= DEF_PACK_SEND;
+		reply(dep, OK, FALSE);
+//		return;
+		return EOK;
+	}
+	assert(dep->de_mode == DEM_ENABLED);
+	assert(dep->de_flags & DEF_ENABLED);
+	if( dep->packet_queue && ( ! from_int )){
+//	if (dep->de_flags & DEF_SEND_AVAIL){
+//		panic("", "dp8390: send already in progress", NO_NUM);
+		return queue_packet( dep, packet );
+	}
+
+	sendq_head= dep->de_sendq_head;
+//	if (dep->de_sendq[sendq_head].sq_filled)
+//	{
+//		if (from_int)
+//			panic("", "dp8390: should not be sending\n", NO_NUM);
+//		dep->de_sendmsg= *mp;
+//		dep->de_flags |= DEF_SEND_AVAIL;
+//		reply(dep, OK, FALSE);
+//		return;
+//		return queue_packet( dep, packet );
+//	}
+//	assert(!(dep->de_flags & DEF_PACK_SEND));
+
+/*	if (vectored)
+	{
+		get_userdata(mp->DL_PROC, (vir_bytes) mp->DL_ADDR,
+			(count > IOVEC_NR ? IOVEC_NR : count) *
+			sizeof(iovec_t), dep->de_write_iovec.iod_iovec);
+		dep->de_write_iovec.iod_iovec_s = count;
+		dep->de_write_iovec.iod_proc_nr = mp->DL_PROC;
+		dep->de_write_iovec.iod_iovec_addr = (vir_bytes) mp->DL_ADDR;
+
+		dep->de_tmp_iovec = dep->de_write_iovec;
+		size = calc_iovec_size(&dep->de_tmp_iovec);
+	}
+	else
+	{  
+		dep->de_write_iovec.iod_iovec[0].iov_addr =
+			(vir_bytes) mp->DL_ADDR;
+		dep->de_write_iovec.iod_iovec[0].iov_size =
+			mp->DL_COUNT;
+		dep->de_write_iovec.iod_iovec_s = 1;
+		dep->de_write_iovec.iod_proc_nr = mp->DL_PROC;
+		dep->de_write_iovec.iod_iovec_addr = 0;
+		size= mp->DL_COUNT;
+	}
+*/
+	size = packet_get_data_length( packet );
+	dep->de_write_iovec.iod_iovec[0].iov_addr = ( vir_bytes ) packet_get_data( packet );
+	dep->de_write_iovec.iod_iovec[0].iov_size = size;
+	dep->de_write_iovec.iod_iovec_s = 1;
+	dep->de_write_iovec.iod_iovec_addr = NULL;
+
+	if (size < ETH_MIN_PACK_SIZE || size > ETH_MAX_PACK_SIZE_TAGGED)
+	{
+		panic("", "dp8390: invalid packet size", size);
+		return EINVAL;
+	}
+	(dep->de_user2nicf)(dep, &dep->de_write_iovec, 0,
+		dep->de_sendq[sendq_head].sq_sendpage * DP_PAGESIZE,
+		size);
+	dep->de_sendq[sendq_head].sq_filled= TRUE;
+	if (dep->de_sendq_tail == sendq_head)
+	{
+		outb_reg0(dep, DP_TPSR, dep->de_sendq[sendq_head].sq_sendpage);
+		outb_reg0(dep, DP_TBCR1, size >> 8);
+		outb_reg0(dep, DP_TBCR0, size & 0xff);
+		outb_reg0(dep, DP_CR, CR_TXP | CR_EXTRA);/* there it goes.. */
+	}
+	else
+		dep->de_sendq[sendq_head].sq_size= size;
+	
+	if (++sendq_head == dep->de_sendq_nr)
+		sendq_head= 0;
+	assert(sendq_head < SENDQ_NR);
+	dep->de_sendq_head= sendq_head;
+
+//	dep->de_flags |= DEF_PACK_SEND;
+
+	/* If the interrupt handler called, don't send a reply. The reply
+	 * will be sent after all interrupts are handled. 
+	 */
+	if (from_int)
+		return EOK;
+	reply(dep, OK, FALSE);
+
+	assert(dep->de_mode == DEM_ENABLED);
+	assert(dep->de_flags & DEF_ENABLED);
+	return EOK;
+}
+
+/*===========================================================================*
+ *				dp_init					     *
+ *===========================================================================*/
+void dp_init(dep)
+dpeth_t *dep;
+{
+	int dp_rcr_reg;
+	int i;//, r;
+
+	/* General initialization */
+	dep->de_flags = DEF_EMPTY;
+	(*dep->de_initf)(dep);
+
+//	dp_confaddr(dep);
+
+	if (debug)
+	{
+		printf("%s: Ethernet address ", dep->de_name);
+		for (i= 0; i < 6; i++)
+			printf("%x%c", dep->de_address.ea_addr[i],
+							i < 5 ? ':' : '\n');
+	}
+
+	/* Map buffer */
+	map_hw_buffer(dep);
+
+	/* Initialization of the dp8390 following the mandatory procedure
+	 * in reference manual ("DP8390D/NS32490D NIC Network Interface
+	 * Controller", National Semiconductor, July 1995, Page 29).
+	 */
+	/* Step 1: */
+	outb_reg0(dep, DP_CR, CR_PS_P0 | CR_STP | CR_DM_ABORT);
+	/* Step 2: */
+	if (dep->de_16bit)
+		outb_reg0(dep, DP_DCR, DCR_WORDWIDE | DCR_8BYTES | DCR_BMS);
+	else
+		outb_reg0(dep, DP_DCR, DCR_BYTEWIDE | DCR_8BYTES | DCR_BMS);
+	/* Step 3: */
+	outb_reg0(dep, DP_RBCR0, 0);
+	outb_reg0(dep, DP_RBCR1, 0);
+	/* Step 4: */
+	dp_rcr_reg = 0;
+	if (dep->de_flags & DEF_PROMISC)
+		dp_rcr_reg |= RCR_AB | RCR_PRO | RCR_AM;
+	if (dep->de_flags & DEF_BROAD)
+		dp_rcr_reg |= RCR_AB;
+	if (dep->de_flags & DEF_MULTI)
+		dp_rcr_reg |= RCR_AM;
+	outb_reg0(dep, DP_RCR, dp_rcr_reg);
+	/* Step 5: */
+	outb_reg0(dep, DP_TCR, TCR_INTERNAL);
+	/* Step 6: */
+	outb_reg0(dep, DP_BNRY, dep->de_startpage);
+	outb_reg0(dep, DP_PSTART, dep->de_startpage);
+	outb_reg0(dep, DP_PSTOP, dep->de_stoppage);
+	/* Step 7: */
+	outb_reg0(dep, DP_ISR, 0xFF);
+	/* Step 8: */
+	outb_reg0(dep, DP_IMR, IMR_PRXE | IMR_PTXE | IMR_RXEE | IMR_TXEE |
+		IMR_OVWE | IMR_CNTE);
+	/* Step 9: */
+	outb_reg0(dep, DP_CR, CR_PS_P1 | CR_DM_ABORT | CR_STP);
+
+	outb_reg1(dep, DP_PAR0, dep->de_address.ea_addr[0]);
+	outb_reg1(dep, DP_PAR1, dep->de_address.ea_addr[1]);
+	outb_reg1(dep, DP_PAR2, dep->de_address.ea_addr[2]);
+	outb_reg1(dep, DP_PAR3, dep->de_address.ea_addr[3]);
+	outb_reg1(dep, DP_PAR4, dep->de_address.ea_addr[4]);
+	outb_reg1(dep, DP_PAR5, dep->de_address.ea_addr[5]);
+
+	outb_reg1(dep, DP_MAR0, 0xff);
+	outb_reg1(dep, DP_MAR1, 0xff);
+	outb_reg1(dep, DP_MAR2, 0xff);
+	outb_reg1(dep, DP_MAR3, 0xff);
+	outb_reg1(dep, DP_MAR4, 0xff);
+	outb_reg1(dep, DP_MAR5, 0xff);
+	outb_reg1(dep, DP_MAR6, 0xff);
+	outb_reg1(dep, DP_MAR7, 0xff);
+
+	outb_reg1(dep, DP_CURR, dep->de_startpage + 1);
+	/* Step 10: */
+	outb_reg0(dep, DP_CR, CR_DM_ABORT | CR_STA);
+	/* Step 11: */
+	outb_reg0(dep, DP_TCR, TCR_NORMAL);
+
+	inb_reg0(dep, DP_CNTR0);		/* reset counters by reading */
+	inb_reg0(dep, DP_CNTR1);
+	inb_reg0(dep, DP_CNTR2);
+
+	/* Finish the initialization. */
+	dep->de_flags |= DEF_ENABLED;
+	for (i= 0; i<dep->de_sendq_nr; i++)
+		dep->de_sendq[i].sq_filled= 0;
+	dep->de_sendq_head= 0;
+	dep->de_sendq_tail= 0;
+	if (!dep->de_prog_IO)
+	{
+		dep->de_user2nicf= dp_user2nic;
+//		dep->de_user2nicf_s= dp_user2nic_s;
+		dep->de_nic2userf= dp_nic2user;
+//		dep->de_nic2userf_s= dp_nic2user_s;
+		dep->de_getblockf= dp_getblock;
+	}
+	else if (dep->de_16bit)
+	{
+		dep->de_user2nicf= dp_pio16_user2nic;
+//		dep->de_user2nicf_s= dp_pio16_user2nic_s;
+		dep->de_nic2userf= dp_pio16_nic2user;
+//		dep->de_nic2userf_s= dp_pio16_nic2user_s;
+		dep->de_getblockf= dp_pio16_getblock;
+	}
+	else
+	{
+		dep->de_user2nicf= dp_pio8_user2nic;
+//		dep->de_user2nicf_s= dp_pio8_user2nic_s;
+		dep->de_nic2userf= dp_pio8_nic2user;
+//		dep->de_nic2userf_s= dp_pio8_nic2user_s;
+		dep->de_getblockf= dp_pio8_getblock;
+	}
+
+	/* Set the interrupt handler and policy. Do not automatically 
+	 * reenable interrupts. Return the IRQ line number on interrupts.
+ 	 */
+/* 	dep->de_hook = dep->de_irq;
+	r= sys_irqsetpolicy(dep->de_irq, 0, &dep->de_hook);
+	if (r != OK)
+		panic("DP8390", "sys_irqsetpolicy failed", r);
+
+	r= sys_irqenable(&dep->de_hook);
+	if (r != OK)
+	{
+		panic("DP8390", "unable enable interrupts", r);
+	}
+*/
+}
+
+/*===========================================================================*
+ *				dp_reinit				     *
+ *===========================================================================*/
+static void dp_reinit(dep)
+dpeth_t *dep;
+{
+	int dp_rcr_reg;
+
+	outb_reg0(dep, DP_CR, CR_PS_P0 | CR_EXTRA);
+
+	dp_rcr_reg = 0;
+	if (dep->de_flags & DEF_PROMISC)
+		dp_rcr_reg |= RCR_AB | RCR_PRO | RCR_AM;
+	if (dep->de_flags & DEF_BROAD)
+		dp_rcr_reg |= RCR_AB;
+	if (dep->de_flags & DEF_MULTI)
+		dp_rcr_reg |= RCR_AM;
+	outb_reg0(dep, DP_RCR, dp_rcr_reg);
+}
+
+/*===========================================================================*
+ *				dp_reset				     *
+ *===========================================================================*/
+static void dp_reset(dep)
+dpeth_t *dep;
+{
+	int i;
+
+	/* Stop chip */
+	outb_reg0(dep, DP_CR, CR_STP | CR_DM_ABORT);
+	outb_reg0(dep, DP_RBCR0, 0);
+	outb_reg0(dep, DP_RBCR1, 0);
+	for (i= 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) & ISR_RST) == 0); i++)
+		; /* Do nothing */
+	outb_reg0(dep, DP_TCR, TCR_1EXTERNAL|TCR_OFST);
+	outb_reg0(dep, DP_CR, CR_STA|CR_DM_ABORT);
+	outb_reg0(dep, DP_TCR, TCR_NORMAL);
+
+	/* Acknowledge the ISR_RDC (remote dma) interrupt. */
+	for (i= 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) & ISR_RDC) == 0); i++)
+		; /* Do nothing */
+	outb_reg0(dep, DP_ISR, inb_reg0(dep, DP_ISR) & ~ISR_RDC);
+
+	/* Reset the transmit ring. If we were transmitting a packet, we
+	 * pretend that the packet is processed. Higher layers will
+	 * retransmit if the packet wasn't actually sent.
+	 */
+	dep->de_sendq_head= dep->de_sendq_tail= 0;
+	for (i= 0; i<dep->de_sendq_nr; i++)
+		dep->de_sendq[i].sq_filled= 0;
+	dp_send(dep);
+	dep->de_flags &= ~DEF_STOPPED;
+}
+
+/*===========================================================================*
+ *				dp_check_ints				     *
+ *===========================================================================*/
+void dp_check_ints(dep, isr)
+dpeth_t *dep;
+int isr;
+{
+	int /*isr,*/ tsr;
+	int size, sendq_tail;
+
+	if (!(dep->de_flags & DEF_ENABLED))
+		panic("", "dp8390: got premature interrupt", NO_NUM);
+
+	for(;;)
+	{
+//		isr = inb_reg0(dep, DP_ISR);
+		if (!isr)
+			break;
+		outb_reg0(dep, DP_ISR, isr);
+		if (isr & (ISR_PTX|ISR_TXE))
+		{
+			if (isr & ISR_TXE)
+			{
+#if DEBUG
+ { printf("%s: got send Error\n", dep->de_name); }
+#endif
+				dep->de_stat.ets_sendErr++;
+			}
+			else
+			{
+				tsr = inb_reg0(dep, DP_TSR);
+
+				if (tsr & TSR_PTX) dep->de_stat.ets_packetT++;
+#if 0	/* Reserved in later manuals, should be ignored */
+				if (!(tsr & TSR_DFR))
+				{
+					/* In most (all?) implementations of
+					 * the dp8390, this bit is set
+					 * when the packet is not deferred
+					 */
+					dep->de_stat.ets_transDef++;
+				}
+#endif
+				if (tsr & TSR_COL) dep->de_stat.ets_collision++;
+				if (tsr & TSR_ABT) dep->de_stat.ets_transAb++;
+				if (tsr & TSR_CRS) dep->de_stat.ets_carrSense++;
+				if (tsr & TSR_FU
+					&& ++dep->de_stat.ets_fifoUnder <= 10)
+				{
+					printf("%s: fifo underrun\n",
+						dep->de_name);
+				}
+				if (tsr & TSR_CDH
+					&& ++dep->de_stat.ets_CDheartbeat <= 10)
+				{
+					printf("%s: CD heart beat failure\n",
+						dep->de_name);
+				}
+				if (tsr & TSR_OWC) dep->de_stat.ets_OWC++;
+			}
+			sendq_tail= dep->de_sendq_tail;
+
+			if (!(dep->de_sendq[sendq_tail].sq_filled))
+			{
+				/* Software bug? */
+				assert(!debug);
+
+				/* Or hardware bug? */
+				printf(
+				"%s: transmit interrupt, but not sending\n",
+					dep->de_name);
+				continue;
+			}
+			dep->de_sendq[sendq_tail].sq_filled= 0;
+			if (++sendq_tail == dep->de_sendq_nr)
+				sendq_tail= 0;
+			dep->de_sendq_tail= sendq_tail;
+			if (dep->de_sendq[sendq_tail].sq_filled)
+			{
+				size= dep->de_sendq[sendq_tail].sq_size;
+				outb_reg0(dep, DP_TPSR,
+					dep->de_sendq[sendq_tail].sq_sendpage);
+				outb_reg0(dep, DP_TBCR1, size >> 8);
+				outb_reg0(dep, DP_TBCR0, size & 0xff);
+				outb_reg0(dep, DP_CR, CR_TXP | CR_EXTRA);
+			}
+//			if (dep->de_flags & DEF_SEND_AVAIL)
+				dp_send(dep);
+		}
+
+		if (isr & ISR_PRX)
+		{
+			/* Only call dp_recv if there is a read request */
+//			if (dep->de_flags) & DEF_READING)
+				dp_recv(dep);
+		}
+		
+		if (isr & ISR_RXE) dep->de_stat.ets_recvErr++;
+		if (isr & ISR_CNT)
+		{
+			dep->de_stat.ets_CRCerr += inb_reg0(dep, DP_CNTR0);
+			dep->de_stat.ets_frameAll += inb_reg0(dep, DP_CNTR1);
+			dep->de_stat.ets_missedP += inb_reg0(dep, DP_CNTR2);
+		}
+		if (isr & ISR_OVW)
+		{
+			dep->de_stat.ets_OVW++;
+#if 0
+			{ printW(); printf(
+				"%s: got overwrite warning\n", dep->de_name); }
+#endif
+/*			if (dep->de_flags & DEF_READING)
+			{
+				printf(
+"dp_check_ints: strange: overwrite warning and pending read request\n");
+				dp_recv(dep);
+			}
+*/		}
+		if (isr & ISR_RDC)
+		{
+			/* Nothing to do */
+		}
+		if (isr & ISR_RST)
+		{
+			/* this means we got an interrupt but the ethernet 
+			 * chip is shutdown. We set the flag DEF_STOPPED,
+			 * and continue processing arrived packets. When the
+			 * receive buffer is empty, we reset the dp8390.
+			 */
+#if 0
+			 { printW(); printf(
+				"%s: NIC stopped\n", dep->de_name); }
+#endif
+			dep->de_flags |= DEF_STOPPED;
+			break;
+		}
+		isr = inb_reg0(dep, DP_ISR);
+	}
+//	if ((dep->de_flags & (DEF_READING|DEF_STOPPED)) == 
+//						(DEF_READING|DEF_STOPPED))
+	if ((dep->de_flags & DEF_STOPPED) == DEF_STOPPED )
+	{
+		/* The chip is stopped, and all arrived packets are 
+		 * delivered.
+		 */
+		dp_reset(dep);
+	}
+}
+
+/*===========================================================================*
+ *				dp_recv					     *
+ *===========================================================================*/
+static void dp_recv(dep)
+dpeth_t *dep;
+{
+	dp_rcvhdr_t header;
+	//unsigned pageno, curr, next;
+	int pageno, curr, next;
+	vir_bytes length;
+	int packet_processed, r;
+	u16_t eth_type;
+
+	packet_processed = FALSE;
+	pageno = inb_reg0(dep, DP_BNRY) + 1;
+	if (pageno == dep->de_stoppage) pageno = dep->de_startpage;
+
+	do
+	{
+		outb_reg0(dep, DP_CR, CR_PS_P1 | CR_EXTRA);
+		curr = inb_reg1(dep, DP_CURR);
+		outb_reg0(dep, DP_CR, CR_PS_P0 | CR_EXTRA);
+
+		if (curr == pageno) break;
+
+		(dep->de_getblockf)(dep, pageno, (size_t)0, sizeof(header),
+			&header);
+		(dep->de_getblockf)(dep, pageno, sizeof(header) +
+			2*sizeof(ether_addr_t), sizeof(eth_type), &eth_type);
+
+		length = (header.dr_rbcl | (header.dr_rbch << 8)) -
+			sizeof(dp_rcvhdr_t);
+		next = header.dr_next;
+		if (length < ETH_MIN_PACK_SIZE ||
+			length > ETH_MAX_PACK_SIZE_TAGGED)
+		{
+			printf("%s: packet with strange length arrived: %d\n",
+				dep->de_name, (int) length);
+			next= curr;
+		}
+		else if (next < dep->de_startpage || next >= dep->de_stoppage)
+		{
+			printf("%s: strange next page\n", dep->de_name);
+			next= curr;
+		}
+/*		else if (eth_type == eth_ign_proto)
+		{
+*/			/* Hack: ignore packets of a given protocol, useful
+			 * if you share a net with 80 computers sending
+			 * Amoeba FLIP broadcasts.  (Protocol 0x8146.)
+			 */
+/*			static int first= 1;
+			if (first)
+			{
+				first= 0;
+				printf("%s: dropping proto 0x%04x packets\n",
+					dep->de_name,
+					ntohs(eth_ign_proto));
+			}
+			dep->de_stat.ets_packetR++;
+		}
+*/		else if (header.dr_status & RSR_FO)
+		{
+			/* This is very serious, so we issue a warning and
+			 * reset the buffers */
+			printf("%s: fifo overrun, resetting receive buffer\n",
+				dep->de_name);
+			dep->de_stat.ets_fifoOver++;
+			next = curr;
+		}
+		else if ((header.dr_status & RSR_PRX) &&
+					   (dep->de_flags & DEF_ENABLED))
+		{
+//			if (dep->de_safecopy_read)
+//				r = dp_pkt2user_s(dep, pageno, length);
+//			else
+				r = dp_pkt2user(dep, pageno, length);
+			if (r != OK)
+				return;
+
+			packet_processed = TRUE;
+			dep->de_stat.ets_packetR++;
+		}
+		if (next == dep->de_startpage)
+			outb_reg0(dep, DP_BNRY, dep->de_stoppage - 1);
+		else
+			outb_reg0(dep, DP_BNRY, next - 1);
+
+		pageno = next;
+	}
+	while (!packet_processed);
+}
+
+/*===========================================================================*
+ *				dp_send					     *
+ *===========================================================================*/
+static void dp_send(dep)
+dpeth_t *dep;
+{
+	packet_t packet;
+
+//	if (!(dep->de_flags & DEF_SEND_AVAIL))
+//		return;
+
+	if( dep->packet_queue ){
+		packet = dep->packet_queue;
+		dep->packet_queue = pq_detach( packet );
+		do_pwrite( dep, packet, TRUE );
+		netif_pq_release( packet_get_id( packet ));
+		-- dep->packet_count;
+	}
+//	if( ! dep->packet_queue ){
+//		dep->de_flags &= ~DEF_SEND_AVAIL;
+//	}
+/*	switch(dep->de_sendmsg.m_type)
+	{
+	case DL_WRITE:	do_vwrite(&dep->de_sendmsg, TRUE, FALSE);	break;
+	case DL_WRITEV:	do_vwrite(&dep->de_sendmsg, TRUE, TRUE);	break;
+	case DL_WRITEV_S: do_vwrite_s(&dep->de_sendmsg, TRUE);	break;
+	default:
+		panic("", "dp8390: wrong type", dep->de_sendmsg.m_type);
+		break;
+	}
+*/
+}
+
+/*===========================================================================*
+ *				dp_getblock				     *
+ *===========================================================================*/
+static void dp_getblock(dep, page, offset, size, dst)
+dpeth_t *dep;
+int page;
+size_t offset;
+size_t size;
+void *dst;
+{
+//	int r;
+
+	offset = page * DP_PAGESIZE + offset;
+
+	memcpy(dst, dep->de_locmem + offset, size);
+}
+
+/*===========================================================================*
+ *				dp_pio8_getblock			     *
+ *===========================================================================*/
+static void dp_pio8_getblock(dep, page, offset, size, dst)
+dpeth_t *dep;
+int page;
+size_t offset;
+size_t size;
+void *dst;
+{
+	offset = page * DP_PAGESIZE + offset;
+	outb_reg0(dep, DP_RBCR0, size & 0xFF);
+	outb_reg0(dep, DP_RBCR1, size >> 8);
+	outb_reg0(dep, DP_RSAR0, offset & 0xFF);
+	outb_reg0(dep, DP_RSAR1, offset >> 8);
+	outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
+
+	insb(dep->de_data_port, dst, size);
+}
+
+/*===========================================================================*
+ *				dp_pio16_getblock			     *
+ *===========================================================================*/
+static void dp_pio16_getblock(dep, page, offset, size, dst)
+dpeth_t *dep;
+int page;
+size_t offset;
+size_t size;
+void *dst;
+{
+	offset = page * DP_PAGESIZE + offset;
+	outb_reg0(dep, DP_RBCR0, size & 0xFF);
+	outb_reg0(dep, DP_RBCR1, size >> 8);
+	outb_reg0(dep, DP_RSAR0, offset & 0xFF);
+	outb_reg0(dep, DP_RSAR1, offset >> 8);
+	outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
+
+	assert (!(size & 1));
+	insw(dep->de_data_port, dst, size);
+}
+
+/*===========================================================================*
+ *				dp_pkt2user				     *
+ *===========================================================================*/
+static int dp_pkt2user(dep, page, length)
+dpeth_t *dep;
+int page, length;
+{
+	int last, count;
+	packet_t	packet;
+	packet_t	queue;
+
+//	if (!(dep->de_flags & DEF_READING))
+//		return EGENERIC;
+
+	packet = netif_packet_get_1( length );
+	if( ! packet ) return ENOMEM;
+	dep->de_read_iovec.iod_iovec[0].iov_addr = ( vir_bytes ) packet_suffix( packet, length );
+	dep->de_read_iovec.iod_iovec[0].iov_size = length;
+	dep->de_read_iovec.iod_iovec_s = 1;
+	dep->de_read_iovec.iod_iovec_addr = NULL;
+
+	last = page + (length - 1) / DP_PAGESIZE;
+	if (last >= dep->de_stoppage)
+	{
+		count = (dep->de_stoppage - page) * DP_PAGESIZE -
+			sizeof(dp_rcvhdr_t);
+
+		/* Save read_iovec since we need it twice. */
+		dep->de_tmp_iovec = dep->de_read_iovec;
+		(dep->de_nic2userf)(dep, page * DP_PAGESIZE +
+			sizeof(dp_rcvhdr_t), &dep->de_tmp_iovec, 0, count);
+		(dep->de_nic2userf)(dep, dep->de_startpage * DP_PAGESIZE, 
+				&dep->de_read_iovec, count, length - count);
+	}
+	else
+	{
+		(dep->de_nic2userf)(dep, page * DP_PAGESIZE +
+			sizeof(dp_rcvhdr_t), &dep->de_read_iovec, 0, length);
+	}
+
+	dep->de_read_s = length;
+	dep->de_flags |= DEF_PACK_RECV;
+//	dep->de_flags &= ~DEF_READING;
+
+	if( dep->received_count >= MAX_PACKETS ){
+		netif_pq_release( packet_get_id( packet ));
+		return ELIMIT;
+	}else{
+		queue = pq_add( dep->received_queue, packet, 0, 0 );
+		if( queue ){
+			dep->received_queue = queue;
+			++ dep->received_count;
+		}else{
+			netif_pq_release( packet_get_id( packet ));
+		}
+	}
+	return OK;
+}
+
+/*===========================================================================*
+ *				dp_user2nic				     *
+ *===========================================================================*/
+static void dp_user2nic(dep, iovp, offset, nic_addr, count)
+dpeth_t *dep;
+iovec_dat_t *iovp;
+vir_bytes offset;
+int nic_addr;
+vir_bytes count;
+{
+	vir_bytes vir_hw;//, vir_user;
+	//int bytes, i, r;
+	int i, r;
+	vir_bytes bytes;
+
+	vir_hw = (vir_bytes)dep->de_locmem + nic_addr;
+
+	i= 0;
+	while (count > 0)
+	{
+		if (i >= IOVEC_NR)
+		{
+			dp_next_iovec(iovp);
+			i= 0;
+			continue;
+		}
+		assert(i < iovp->iod_iovec_s);
+		if (offset >= iovp->iod_iovec[i].iov_size)
+		{
+			offset -= iovp->iod_iovec[i].iov_size;
+			i++;
+			continue;
+		}
+		bytes = iovp->iod_iovec[i].iov_size - offset;
+		if (bytes > count)
+			bytes = count;
+
+		r= sys_vircopy(iovp->iod_proc_nr, D,
+			iovp->iod_iovec[i].iov_addr + offset,
+			SELF, D, vir_hw, bytes);
+		if (r != OK)
+			panic("DP8390", "dp_user2nic: sys_vircopy failed", r);
+
+		count -= bytes;
+		vir_hw += bytes;
+		offset += bytes;
+	}
+	assert(count == 0);
+}
+
+/*===========================================================================*
+ *				dp_pio8_user2nic			     *
+ *===========================================================================*/
+static void dp_pio8_user2nic(dep, iovp, offset, nic_addr, count)
+dpeth_t *dep;
+iovec_dat_t *iovp;
+vir_bytes offset;
+int nic_addr;
+vir_bytes count;
+{
+//	phys_bytes phys_user;
+	int i;
+	vir_bytes bytes;
+
+	outb_reg0(dep, DP_ISR, ISR_RDC);
+
+	outb_reg0(dep, DP_RBCR0, count & 0xFF);
+	outb_reg0(dep, DP_RBCR1, count >> 8);
+	outb_reg0(dep, DP_RSAR0, nic_addr & 0xFF);
+	outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
+	outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
+
+	i= 0;
+	while (count > 0)
+	{
+		if (i >= IOVEC_NR)
+		{
+			dp_next_iovec(iovp);
+			i= 0;
+			continue;
+		}
+		assert(i < iovp->iod_iovec_s);
+		if (offset >= iovp->iod_iovec[i].iov_size)
+		{
+			offset -= iovp->iod_iovec[i].iov_size;
+			i++;
+			continue;
+		}
+		bytes = iovp->iod_iovec[i].iov_size - offset;
+		if (bytes > count)
+			bytes = count;
+
+		do_vir_outsb(dep->de_data_port, iovp->iod_proc_nr,
+			iovp->iod_iovec[i].iov_addr + offset, bytes);
+		count -= bytes;
+		offset += bytes;
+	}
+	assert(count == 0);
+
+	for (i= 0; i<100; i++)
+	{
+		if (inb_reg0(dep, DP_ISR) & ISR_RDC)
+			break;
+	}
+	if (i == 100)
+	{
+		panic("", "dp8390: remote dma failed to complete", NO_NUM);
+	}
+}
+
+/*===========================================================================*
+ *				dp_pio16_user2nic			     *
+ *===========================================================================*/
+static void dp_pio16_user2nic(dep, iovp, offset, nic_addr, count)
+dpeth_t *dep;
+iovec_dat_t *iovp;
+vir_bytes offset;
+int nic_addr;
+vir_bytes count;
+{
+	vir_bytes vir_user;
+	vir_bytes ecount;
+	int i, r, user_proc;
+	vir_bytes bytes;
+	//u8_t two_bytes[2];
+	u16_t two_bytes;
+	int odd_byte;
+
+	ecount= (count+1) & ~1;
+	odd_byte= 0;
+
+	outb_reg0(dep, DP_ISR, ISR_RDC);
+	outb_reg0(dep, DP_RBCR0, ecount & 0xFF);
+	outb_reg0(dep, DP_RBCR1, ecount >> 8);
+	outb_reg0(dep, DP_RSAR0, nic_addr & 0xFF);
+	outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
+	outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
+
+	i= 0;
+	while (count > 0)
+	{
+		if (i >= IOVEC_NR)
+		{
+			dp_next_iovec(iovp);
+			i= 0;
+			continue;
+		}
+		assert(i < iovp->iod_iovec_s);
+		if (offset >= iovp->iod_iovec[i].iov_size)
+		{
+			offset -= iovp->iod_iovec[i].iov_size;
+			i++;
+			continue;
+		}
+		bytes = iovp->iod_iovec[i].iov_size - offset;
+		if (bytes > count)
+			bytes = count;
+
+		user_proc= iovp->iod_proc_nr;
+		vir_user= iovp->iod_iovec[i].iov_addr + offset;
+		if (odd_byte)
+		{
+			r= sys_vircopy(user_proc, D, vir_user, 
+			//	SELF, D, (vir_bytes)&two_bytes[1], 1);
+				SELF, D, (vir_bytes)&(((u8_t *)&two_bytes)[1]), 1);
+			if (r != OK)
+			{
+				panic("DP8390",
+					"dp_pio16_user2nic: sys_vircopy failed",
+					r);
+			}
+			//outw(dep->de_data_port, *(u16_t *)two_bytes);
+			outw(dep->de_data_port, two_bytes);
+			count--;
+			offset++;
+			bytes--;
+			vir_user++;
+			odd_byte= 0;
+			if (!bytes)
+				continue;
+		}
+		ecount= bytes & ~1;
+		if (ecount != 0)
+		{
+			do_vir_outsw(dep->de_data_port, user_proc, vir_user,
+				ecount);
+			count -= ecount;
+			offset += ecount;
+			bytes -= ecount;
+			vir_user += ecount;
+		}
+		if (bytes)
+		{
+			assert(bytes == 1);
+			r= sys_vircopy(user_proc, D, vir_user, 
+			//	SELF, D, (vir_bytes)&two_bytes[0], 1);
+				SELF, D, (vir_bytes)&(((u8_t *)&two_bytes)[0]), 1);
+			if (r != OK)
+			{
+				panic("DP8390",
+					"dp_pio16_user2nic: sys_vircopy failed",
+					r);
+			}
+			count--;
+			offset++;
+			bytes--;
+			vir_user++;
+			odd_byte= 1;
+		}
+	}
+	assert(count == 0);
+
+	if (odd_byte)
+		//outw(dep->de_data_port, *(u16_t *)two_bytes);
+		outw(dep->de_data_port, two_bytes);
+
+	for (i= 0; i<100; i++)
+	{
+		if (inb_reg0(dep, DP_ISR) & ISR_RDC)
+			break;
+	}
+	if (i == 100)
+	{
+		panic("", "dp8390: remote dma failed to complete", NO_NUM);
+	}
+}
+
+/*===========================================================================*
+ *				dp_nic2user				     *
+ *===========================================================================*/
+static void dp_nic2user(dep, nic_addr, iovp, offset, count)
+dpeth_t *dep;
+int nic_addr;
+iovec_dat_t *iovp;
+vir_bytes offset;
+vir_bytes count;
+{
+	vir_bytes vir_hw;//, vir_user;
+	vir_bytes bytes;
+	int i, r;
+
+	vir_hw = (vir_bytes)dep->de_locmem + nic_addr;
+
+	i= 0;
+	while (count > 0)
+	{
+		if (i >= IOVEC_NR)
+		{
+			dp_next_iovec(iovp);
+			i= 0;
+			continue;
+		}
+		assert(i < iovp->iod_iovec_s);
+		if (offset >= iovp->iod_iovec[i].iov_size)
+		{
+			offset -= iovp->iod_iovec[i].iov_size;
+			i++;
+			continue;
+		}
+		bytes = iovp->iod_iovec[i].iov_size - offset;
+		if (bytes > count)
+			bytes = count;
+
+		r= sys_vircopy(SELF, D, vir_hw,
+			iovp->iod_proc_nr, D,
+			iovp->iod_iovec[i].iov_addr + offset, bytes);
+		if (r != OK)
+			panic("DP8390", "dp_nic2user: sys_vircopy failed", r);
+
+		count -= bytes;
+		vir_hw += bytes;
+		offset += bytes;
+	}
+	assert(count == 0);
+}
+
+/*===========================================================================*
+ *				dp_pio8_nic2user			     *
+ *===========================================================================*/
+static void dp_pio8_nic2user(dep, nic_addr, iovp, offset, count)
+dpeth_t *dep;
+int nic_addr;
+iovec_dat_t *iovp;
+vir_bytes offset;
+vir_bytes count;
+{
+//	phys_bytes phys_user;
+	int i;
+	vir_bytes bytes;
+
+	outb_reg0(dep, DP_RBCR0, count & 0xFF);
+	outb_reg0(dep, DP_RBCR1, count >> 8);
+	outb_reg0(dep, DP_RSAR0, nic_addr & 0xFF);
+	outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
+	outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
+
+	i= 0;
+	while (count > 0)
+	{
+		if (i >= IOVEC_NR)
+		{
+			dp_next_iovec(iovp);
+			i= 0;
+			continue;
+		}
+		assert(i < iovp->iod_iovec_s);
+		if (offset >= iovp->iod_iovec[i].iov_size)
+		{
+			offset -= iovp->iod_iovec[i].iov_size;
+			i++;
+			continue;
+		}
+		bytes = iovp->iod_iovec[i].iov_size - offset;
+		if (bytes > count)
+			bytes = count;
+
+		do_vir_insb(dep->de_data_port, iovp->iod_proc_nr,
+			iovp->iod_iovec[i].iov_addr + offset, bytes);
+		count -= bytes;
+		offset += bytes;
+	}
+	assert(count == 0);
+}
+
+/*===========================================================================*
+ *				dp_pio16_nic2user			     *
+ *===========================================================================*/
+static void dp_pio16_nic2user(dep, nic_addr, iovp, offset, count)
+dpeth_t *dep;
+int nic_addr;
+iovec_dat_t *iovp;
+vir_bytes offset;
+vir_bytes count;
+{
+	vir_bytes vir_user;
+	vir_bytes ecount;
+	int i, r, user_proc;
+	vir_bytes bytes;
+	//u8_t two_bytes[2];
+	u16_t two_bytes;
+	int odd_byte;
+
+	ecount= (count+1) & ~1;
+	odd_byte= 0;
+
+	outb_reg0(dep, DP_RBCR0, ecount & 0xFF);
+	outb_reg0(dep, DP_RBCR1, ecount >> 8);
+	outb_reg0(dep, DP_RSAR0, nic_addr & 0xFF);
+	outb_reg0(dep, DP_RSAR1, nic_addr >> 8);
+	outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
+
+	i= 0;
+	while (count > 0)
+	{
+		if (i >= IOVEC_NR)
+		{
+			dp_next_iovec(iovp);
+			i= 0;
+			continue;
+		}
+		assert(i < iovp->iod_iovec_s);
+		if (offset >= iovp->iod_iovec[i].iov_size)
+		{
+			offset -= iovp->iod_iovec[i].iov_size;
+			i++;
+			continue;
+		}
+		bytes = iovp->iod_iovec[i].iov_size - offset;
+		if (bytes > count)
+			bytes = count;
+
+		user_proc= iovp->iod_proc_nr;
+		vir_user= iovp->iod_iovec[i].iov_addr + offset;
+		if (odd_byte)
+		{
+			//r= sys_vircopy(SELF, D, (vir_bytes)&two_bytes[1],
+			r= sys_vircopy(SELF, D, (vir_bytes)&(((u8_t *)&two_bytes)[1]),
+				user_proc, D, vir_user,  1);
+			if (r != OK)
+			{
+				panic("DP8390",
+					"dp_pio16_nic2user: sys_vircopy failed",
+					r);
+			}
+			count--;
+			offset++;
+			bytes--;
+			vir_user++;
+			odd_byte= 0;
+			if (!bytes)
+				continue;
+		}
+		ecount= bytes & ~1;
+		if (ecount != 0)
+		{
+			do_vir_insw(dep->de_data_port, user_proc, vir_user,
+				ecount);
+			count -= ecount;
+			offset += ecount;
+			bytes -= ecount;
+			vir_user += ecount;
+		}
+		if (bytes)
+		{
+			assert(bytes == 1);
+			//*(u16_t *)two_bytes= inw(dep->de_data_port);
+			two_bytes= inw(dep->de_data_port);
+			//r= sys_vircopy(SELF, D, (vir_bytes)&two_bytes[0],
+			r= sys_vircopy(SELF, D, (vir_bytes)&(((u8_t *)&two_bytes)[0]),
+				user_proc, D, vir_user,  1);
+			if (r != OK)
+			{
+				panic("DP8390",
+					"dp_pio16_nic2user: sys_vircopy failed",
+					r);
+			}
+			count--;
+			offset++;
+			bytes--;
+			vir_user++;
+			odd_byte= 1;
+		}
+	}
+	assert(count == 0);
+}
+
+/*===========================================================================*
+ *				dp_next_iovec				     *
+ *===========================================================================*/
+static void dp_next_iovec(iovp)
+iovec_dat_t *iovp;
+{
+	assert(iovp->iod_iovec_s > IOVEC_NR);
+
+	iovp->iod_iovec_s -= IOVEC_NR;
+
+	iovp->iod_iovec_addr += IOVEC_NR * sizeof(iovec_t);
+
+	get_userdata(iovp->iod_proc_nr, iovp->iod_iovec_addr, 
+		(iovp->iod_iovec_s > IOVEC_NR ? IOVEC_NR : iovp->iod_iovec_s) *
+		sizeof(iovec_t), iovp->iod_iovec); 
+}
+
+/*===========================================================================*
+ *				conf_hw					     *
+ *===========================================================================*/
+static void conf_hw(dep)
+dpeth_t *dep;
+{
+//	static eth_stat_t empty_stat = {0, 0, 0, 0, 0, 0 	/* ,... */ };
+
+//	int ifnr;
+//	dp_conf_t *dcp;
+
+//	dep->de_mode= DEM_DISABLED;	/* Superfluous */
+//	ifnr= dep-de_table;
+
+//	dcp= &dp_conf[ifnr];
+//	update_conf(dep, dcp);
+//	if (dep->de_mode != DEM_ENABLED)
+//		return;
+	if (!wdeth_probe(dep) && !ne_probe(dep) && !el2_probe(dep))
+	{
+		printf("%s: No ethernet card found at 0x%x\n", 
+			dep->de_name, dep->de_base_port);
+		dep->de_mode= DEM_DISABLED;
+		return;
+	}
+
+/* XXX */ if (dep->de_linmem == 0) dep->de_linmem= 0xFFFF0000;
+
+	dep->de_mode = DEM_ENABLED;
+
+	dep->de_flags = DEF_EMPTY;
+//	dep->de_stat = empty_stat;
+}
+
+/*===========================================================================*
+ *				map_hw_buffer				     *
+ *===========================================================================*/
+static void map_hw_buffer(dep)
+dpeth_t *dep;
+{
+//	int r;
+//	size_t o, size;
+//	char *buf, *abuf;
+
+	if (dep->de_prog_IO)
+	{
+#if 0
+		if(debug){
+			printf(
+			"map_hw_buffer: programmed I/O, no need to map buffer\n");
+		}
+#endif
+		dep->de_locmem = (char *)-dep->de_ramsize; /* trap errors */
+		return;
+	}else{
+		printf( "map_hw_buffer: no buffer!\n" );
+	}
+
+//	size = dep->de_ramsize + PAGE_SIZE;	/* Add PAGE_SIZE for
+//						 * alignment
+//						 */
+//	buf= malloc(size);
+//	if (buf == NULL)
+//		panic(__FILE__, "map_hw_buffer: cannot malloc size", size);
+//	o= PAGE_SIZE - ((vir_bytes)buf % PAGE_SIZE);
+//	abuf= buf + o;
+//	printf("buf at 0x%x, abuf at 0x%x\n", buf, abuf);
+
+//	r= sys_vm_map(SELF, 1 /* map */, (vir_bytes)abuf,
+//			dep->de_ramsize, (phys_bytes)dep->de_linmem);
+//	if (r != OK)
+//		panic(__FILE__, "map_hw_buffer: sys_vm_map failed", r);
+//	dep->de_locmem = abuf;
+}
+
+/*===========================================================================*
+ *				reply					     *
+ *===========================================================================*/
+static void reply(dep, err, may_block)
+dpeth_t *dep;
+int err;
+int may_block;
+{
+/*	message reply;
+	int status;
+	int r;
+
+	status = 0;
+	if (dep->de_flags & DEF_PACK_SEND)
+		status |= DL_PACK_SEND;
+	if (dep->de_flags & DEF_PACK_RECV)
+		status |= DL_PACK_RECV;
+
+	reply.m_type = DL_TASK_REPLY;
+	reply.DL_PORT = dep - de_table;
+	reply.DL_PROC = dep->de_client;
+	reply.DL_STAT = status | ((u32_t) err << 16);
+	reply.DL_COUNT = dep->de_read_s;
+	reply.DL_CLCK = 0;	*//* Don't know */
+/*	r= send(dep->de_client, &reply);
+
+	if (r == ELOCKED && may_block)
+	{
+#if 0
+		printf("send locked\n");
+#endif
+		return;
+	}
+
+	if (r < 0)
+		panic("", "dp8390: send failed:", r);
+	
+*/	dep->de_read_s = 0;
+//	dep->de_flags &= ~(DEF_PACK_SEND | DEF_PACK_RECV);
+}
+
+/*===========================================================================*
+ *				get_userdata				     *
+ *===========================================================================*/
+static void get_userdata(user_proc, user_addr, count, loc_addr)
+int user_proc;
+vir_bytes user_addr;
+vir_bytes count;
+void *loc_addr;
+{
+	int r;
+
+	r= sys_vircopy(user_proc, D, user_addr,
+		SELF, D, (vir_bytes)loc_addr, count);
+	if (r != OK)
+		panic("DP8390", "get_userdata: sys_vircopy failed", r);
+}
+
+static void insb(port_t port, void *buf, size_t size)
+{
+	size_t i;
+
+	for( i = 0; i < size; ++ i ){
+		*(( uint8_t * ) buf + i ) = inb( port );
+	}
+}
+
+static void insw(port_t port, void *buf, size_t size)
+{
+	size_t i;
+
+	for( i = 0; i * 2 < size; ++ i ){
+		*(( uint16_t * ) buf + i ) = inw( port );
+	}
+}
+
+static void outsb(port_t port, void *buf, size_t size)
+{
+	size_t i;
+
+	for( i = 0; i < size; ++ i ){
+		outb( port, *(( uint8_t * ) buf + i ));
+	}
+}
+
+static void outsw(port_t port, void *buf, size_t size)
+{
+	size_t i;
+
+	for( i = 0; i * 2 < size; ++ i ){
+		outw( port, *(( uint16_t * ) buf + i ));
+	}
+}
+
+/*
+ * $PchId: dp8390.c,v 1.25 2005/02/10 17:32:07 philip Exp $
+ */
+
+/** @}
+ */
Index: uspace/srv/net/netif/dp8390/dp8390.h
===================================================================
--- uspace/srv/net/netif/dp8390/dp8390.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/netif/dp8390/dp8390.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,431 @@
+/*
+ * Copyright (c) 1987,1997, 2006, Vrije Universiteit, Amsterdam, The Netherlands All rights reserved. Redistribution and use of the MINIX 3 operating system in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Vrije Universiteit nor the names of the software authors or contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+ * * Any deviations from these conditions require written permission from the copyright holder in advance
+ *
+ *
+ * Disclaimer
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS, AUTHORS, AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR ANY AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Changes:
+ *  2009 ported to HelenOS, Lukas Mejdrech
+ */
+
+/** @addtogroup dp8390
+ *  @{
+ */
+
+/** @file
+ *  DP8390 network interface definitions.
+ */
+
+#ifndef __NET_NETIF_DP8390_H__
+#define __NET_NETIF_DP8390_H__
+
+#include "../../structures/packet/packet.h"
+
+#include "dp8390_port.h"
+#include "local.h"
+
+/** Input/output size.
+ */
+#define DP8390_IO_SIZE	0x01f
+
+/*
+dp8390.h
+
+Created:	before Dec 28, 1992 by Philip Homburg
+*/
+
+/* National Semiconductor DP8390 Network Interface Controller. */
+
+				/* Page 0, for reading ------------- */
+#define	DP_CR		0x0	/* Read side of Command Register     */
+#define	DP_CLDA0	0x1	/* Current Local Dma Address 0       */
+#define	DP_CLDA1	0x2	/* Current Local Dma Address 1       */
+#define	DP_BNRY		0x3	/* Boundary Pointer                  */
+#define	DP_TSR		0x4	/* Transmit Status Register          */
+#define	DP_NCR		0x5	/* Number of Collisions Register     */
+#define	DP_FIFO		0x6	/* Fifo ??                           */
+#define	DP_ISR		0x7	/* Interrupt Status Register         */
+#define	DP_CRDA0	0x8	/* Current Remote Dma Address 0      */
+#define	DP_CRDA1	0x9	/* Current Remote Dma Address 1      */
+#define	DP_DUM1		0xA	/* unused                            */
+#define	DP_DUM2		0xB	/* unused                            */
+#define	DP_RSR		0xC	/* Receive Status Register           */
+#define	DP_CNTR0	0xD	/* Tally Counter 0                   */
+#define	DP_CNTR1	0xE	/* Tally Counter 1                   */
+#define	DP_CNTR2	0xF	/* Tally Counter 2                   */
+
+				/* Page 0, for writing ------------- */
+#define	DP_CR		0x0	/* Write side of Command Register    */
+#define	DP_PSTART	0x1	/* Page Start Register               */
+#define	DP_PSTOP	0x2	/* Page Stop Register                */
+#define	DP_BNRY		0x3	/* Boundary Pointer                  */
+#define	DP_TPSR		0x4	/* Transmit Page Start Register      */
+#define	DP_TBCR0	0x5	/* Transmit Byte Count Register 0    */
+#define	DP_TBCR1	0x6	/* Transmit Byte Count Register 1    */
+#define	DP_ISR		0x7	/* Interrupt Status Register         */
+#define	DP_RSAR0	0x8	/* Remote Start Address Register 0   */
+#define	DP_RSAR1	0x9	/* Remote Start Address Register 1   */
+#define	DP_RBCR0	0xA	/* Remote Byte Count Register 0      */
+#define	DP_RBCR1	0xB	/* Remote Byte Count Register 1      */
+#define	DP_RCR		0xC	/* Receive Configuration Register    */
+#define	DP_TCR		0xD	/* Transmit Configuration Register   */
+#define	DP_DCR		0xE	/* Data Configuration Register       */
+#define	DP_IMR		0xF	/* Interrupt Mask Register           */
+
+				/* Page 1, read/write -------------- */
+#define	DP_CR		0x0	/* Command Register                  */
+#define	DP_PAR0		0x1	/* Physical Address Register 0       */
+#define	DP_PAR1		0x2	/* Physical Address Register 1       */
+#define	DP_PAR2		0x3	/* Physical Address Register 2       */
+#define	DP_PAR3		0x4	/* Physical Address Register 3       */
+#define	DP_PAR4		0x5	/* Physical Address Register 4       */
+#define	DP_PAR5		0x6	/* Physical Address Register 5       */
+#define	DP_CURR		0x7	/* Current Page Register             */
+#define	DP_MAR0		0x8	/* Multicast Address Register 0      */
+#define	DP_MAR1		0x9	/* Multicast Address Register 1      */
+#define	DP_MAR2		0xA	/* Multicast Address Register 2      */
+#define	DP_MAR3		0xB	/* Multicast Address Register 3      */
+#define	DP_MAR4		0xC	/* Multicast Address Register 4      */
+#define	DP_MAR5		0xD	/* Multicast Address Register 5      */
+#define	DP_MAR6		0xE	/* Multicast Address Register 6      */
+#define	DP_MAR7		0xF	/* Multicast Address Register 7      */
+
+/* Bits in dp_cr */
+#define CR_STP		0x01	/* Stop: software reset              */
+#define CR_STA		0x02	/* Start: activate NIC               */
+#define CR_TXP		0x04	/* Transmit Packet                   */
+#define CR_DMA		0x38	/* Mask for DMA control              */
+#define CR_DM_NOP	0x00	/* DMA: No Operation                 */
+#define CR_DM_RR	0x08	/* DMA: Remote Read                  */
+#define CR_DM_RW	0x10	/* DMA: Remote Write                 */
+#define CR_DM_SP	0x18	/* DMA: Send Packet                  */
+#define CR_DM_ABORT	0x20	/* DMA: Abort Remote DMA Operation   */
+#define CR_PS		0xC0	/* Mask for Page Select              */
+#define CR_PS_P0	0x00	/* Register Page 0                   */
+#define CR_PS_P1	0x40	/* Register Page 1                   */
+#define CR_PS_P2	0x80	/* Register Page 2                   */
+#define CR_PS_T1	0xC0	/* Test Mode Register Map            */
+
+/* Bits in dp_isr */
+#define ISR_PRX		0x01	/* Packet Received with no errors    */
+#define ISR_PTX		0x02	/* Packet Transmitted with no errors */
+#define ISR_RXE		0x04	/* Receive Error                     */
+#define ISR_TXE		0x08	/* Transmit Error                    */
+#define ISR_OVW		0x10	/* Overwrite Warning                 */
+#define ISR_CNT		0x20	/* Counter Overflow                  */
+#define ISR_RDC		0x40	/* Remote DMA Complete               */
+#define ISR_RST		0x80	/* Reset Status                      */
+
+/* Bits in dp_imr */
+#define IMR_PRXE	0x01	/* Packet Received iEnable           */
+#define IMR_PTXE	0x02	/* Packet Transmitted iEnable        */
+#define IMR_RXEE	0x04	/* Receive Error iEnable             */
+#define IMR_TXEE	0x08	/* Transmit Error iEnable            */
+#define IMR_OVWE	0x10	/* Overwrite Warning iEnable         */
+#define IMR_CNTE	0x20	/* Counter Overflow iEnable          */
+#define IMR_RDCE	0x40	/* DMA Complete iEnable              */
+
+/* Bits in dp_dcr */
+#define DCR_WTS		0x01	/* Word Transfer Select              */
+#define DCR_BYTEWIDE	0x00	/* WTS: byte wide transfers          */
+#define DCR_WORDWIDE	0x01	/* WTS: word wide transfers          */
+#define DCR_BOS		0x02	/* Byte Order Select                 */
+#define DCR_LTLENDIAN	0x00	/* BOS: Little Endian                */
+#define DCR_BIGENDIAN	0x02	/* BOS: Big Endian                   */
+#define DCR_LAS		0x04	/* Long Address Select               */
+#define DCR_BMS		0x08	/* Burst Mode Select
+				 * Called Loopback Select (LS) in 
+				 * later manuals. Should be set.     */
+#define DCR_AR		0x10	/* Autoinitialize Remote             */
+#define DCR_FTS		0x60	/* Fifo Threshold Select             */
+#define DCR_2BYTES	0x00	/* 2 bytes                           */
+#define DCR_4BYTES	0x40	/* 4 bytes                           */
+#define DCR_8BYTES	0x20	/* 8 bytes                           */
+#define DCR_12BYTES	0x60	/* 12 bytes                          */
+
+/* Bits in dp_tcr */
+#define TCR_CRC		0x01	/* Inhibit CRC                       */
+#define TCR_ELC		0x06	/* Encoded Loopback Control          */
+#define TCR_NORMAL	0x00	/* ELC: Normal Operation             */
+#define TCR_INTERNAL	0x02	/* ELC: Internal Loopback            */
+#define TCR_0EXTERNAL	0x04	/* ELC: External Loopback LPBK=0     */
+#define TCR_1EXTERNAL	0x06	/* ELC: External Loopback LPBK=1     */
+#define TCR_ATD		0x08	/* Auto Transmit Disable             */
+#define TCR_OFST	0x10	/* Collision Offset Enable (be nice) */
+
+/* Bits in dp_tsr */
+#define TSR_PTX		0x01	/* Packet Transmitted (without error)*/
+#define TSR_DFR		0x02	/* Transmit Deferred, reserved in
+				 * later manuals.		     */
+#define TSR_COL		0x04	/* Transmit Collided                 */
+#define TSR_ABT		0x08	/* Transmit Aborted                  */
+#define TSR_CRS		0x10	/* Carrier Sense Lost                */
+#define TSR_FU		0x20	/* FIFO Underrun                     */
+#define TSR_CDH		0x40	/* CD Heartbeat                      */
+#define TSR_OWC		0x80	/* Out of Window Collision           */
+
+/* Bits in tp_rcr */
+#define RCR_SEP		0x01	/* Save Errored Packets              */
+#define RCR_AR		0x02	/* Accept Runt Packets               */
+#define RCR_AB		0x04	/* Accept Broadcast                  */
+#define RCR_AM		0x08	/* Accept Multicast                  */
+#define RCR_PRO		0x10	/* Physical Promiscuous              */
+#define RCR_MON		0x20	/* Monitor Mode                      */
+
+/* Bits in dp_rsr */
+#define RSR_PRX		0x01	/* Packet Received Intact            */
+#define RSR_CRC		0x02	/* CRC Error                         */
+#define RSR_FAE		0x04	/* Frame Alignment Error             */
+#define RSR_FO		0x08	/* FIFO Overrun                      */
+#define RSR_MPA		0x10	/* Missed Packet                     */
+#define RSR_PHY		0x20	/* Multicast Address Match           */
+#define RSR_DIS		0x40	/* Receiver Disabled                 */
+#define RSR_DFR		0x80	/* In later manuals: Deferring       */
+
+/** Type definition of the receive header.
+ */
+typedef struct dp_rcvhdr
+{
+	/** Copy of rsr.
+	 */
+	u8_t dr_status;
+	/** Pointer to next packet.
+	 */
+	u8_t dr_next;
+	/** Receive Byte Count Low.
+	 */
+	u8_t dr_rbcl;
+	/** Receive Byte Count High.
+	 */
+	u8_t dr_rbch;
+} dp_rcvhdr_t;
+
+/** Page size.
+ */
+#define DP_PAGESIZE	256
+
+/* Some macros to simplify accessing the dp8390 */
+/** Reads 1 byte from the zero page register.
+ *  @param[in] dep The network interface structure.
+ *  @param[in] reg The register offset.
+ *  @returns The read value.
+ */
+#define inb_reg0(dep, reg)		(inb(dep->de_dp8390_port+reg))
+
+/** Writes 1 byte zero page register.
+ *  @param[in] dep The network interface structure.
+ *  @param[in] reg The register offset.
+ *  @param[in] data The value to be written.
+ */
+#define outb_reg0(dep, reg, data)	(outb(dep->de_dp8390_port+reg, data))
+
+/** Reads 1 byte from the first page register.
+ *  @param[in] dep The network interface structure.
+ *  @param[in] reg The register offset.
+ *  @returns The read value.
+ */
+#define inb_reg1(dep, reg)		(inb(dep->de_dp8390_port+reg))
+
+/** Writes 1 byte first page register.
+ *  @param[in] dep The network interface structure.
+ *  @param[in] reg The register offset.
+ *  @param[in] data The value to be written.
+ */
+#define outb_reg1(dep, reg, data)	(outb(dep->de_dp8390_port+reg, data))
+
+/* Software interface to the dp8390 driver */
+
+struct dpeth;
+struct iovec_dat;
+//struct iovec_dat_s;
+_PROTOTYPE( typedef void (*dp_initf_t), (struct dpeth *dep)		);
+_PROTOTYPE( typedef void (*dp_stopf_t), (struct dpeth *dep)		);
+_PROTOTYPE( typedef void (*dp_user2nicf_t), (struct dpeth *dep,
+			struct iovec_dat *iovp, vir_bytes offset,
+			int nic_addr, vir_bytes count)			);
+//_PROTOTYPE( typedef void (*dp_user2nicf_s_t), (struct dpeth *dep,
+//			struct iovec_dat_s *iovp, vir_bytes offset,
+//			int nic_addr, vir_bytes count)			);
+_PROTOTYPE( typedef void (*dp_nic2userf_t), (struct dpeth *dep,
+			int nic_addr, struct iovec_dat *iovp,
+			vir_bytes offset, vir_bytes count)		);
+//_PROTOTYPE( typedef void (*dp_nic2userf_s_t), (struct dpeth *dep,
+//			int nic_addr, struct iovec_dat_s *iovp,
+//			vir_bytes offset, vir_bytes count)		);
+//#if 0
+//_PROTOTYPE( typedef void (*dp_getheaderf_t), (struct dpeth *dep,
+//			int page, struct dp_rcvhdr *h, u16_t *eth_type)	);
+//#endif
+_PROTOTYPE( typedef void (*dp_getblock_t), (struct dpeth *dep,
+		int page, size_t offset, size_t size, void *dst)	);
+
+/* iovectors are handled IOVEC_NR entries at a time. */
+//#define IOVEC_NR	16
+// no vectors allowed
+#define IOVEC_NR	1
+
+/*
+typedef int irq_hook_t;
+*/
+typedef struct iovec_dat
+{
+  iovec_t iod_iovec[IOVEC_NR];
+  int iod_iovec_s;
+  // no direct process access
+  int iod_proc_nr;
+  vir_bytes iod_iovec_addr;
+} iovec_dat_t;
+/*
+typedef struct iovec_dat_s
+{
+  iovec_s_t iod_iovec[IOVEC_NR];
+  int iod_iovec_s;
+  int iod_proc_nr;
+  cp_grant_id_t iod_grant;
+  vir_bytes iod_iovec_offset;
+} iovec_dat_s_t;
+*/
+#define SENDQ_NR	1	/* Maximum size of the send queue */
+#define SENDQ_PAGES	6	/* 6 * DP_PAGESIZE >= 1514 bytes */
+
+/** Maximum number of waiting packets to be sent or received.
+ */
+#define MAX_PACKETS	4
+
+typedef struct dpeth
+{
+	/** Outgoing packets queue.
+	 */
+	packet_t	packet_queue;
+	/** Outgoing packets count.
+	 */
+	int			packet_count;
+
+	/** Received packets queue.
+	 */
+	packet_t	received_queue;
+	/** Received packets count.
+	 */
+	int			received_count;
+
+	/* The de_base_port field is the starting point of the probe.
+	 * The conf routine also fills de_linmem and de_irq. If the probe
+	 * routine knows the irq and/or memory address because they are
+	 * hardwired in the board, the probe should modify these fields.
+	 * Futhermore, the probe routine should also fill in de_initf and
+	 * de_stopf fields with the appropriate function pointers and set
+	 * de_prog_IO iff programmed I/O is to be used.
+	 */
+	port_t de_base_port;
+	phys_bytes de_linmem;
+	char *de_locmem;
+	int de_irq;
+	int de_int_pending;
+//	irq_hook_t de_hook;
+	dp_initf_t de_initf; 
+	dp_stopf_t de_stopf; 
+	int de_prog_IO;
+	char de_name[sizeof("dp8390#n")];
+
+	/* The initf function fills the following fields. Only cards that do
+	 * programmed I/O fill in the de_pata_port field.
+	 * In addition, the init routine has to fill in the sendq data
+	 * structures.
+	 */
+	ether_addr_t de_address;
+	port_t de_dp8390_port;
+	port_t de_data_port;
+	int de_16bit;
+	int de_ramsize;
+	int de_offset_page;
+	int de_startpage;
+	int de_stoppage;
+
+	/* should be here - read even for ne2k isa init... */
+	char de_pci;			/* TRUE iff PCI device */
+
+#if ENABLE_PCI
+	/* PCI config */
+//	char de_pci;			/* TRUE iff PCI device */
+//	u8_t de_pcibus;	
+//	u8_t de_pcidev;	
+//	u8_t de_pcifunc;	
+#endif
+
+	/* Do it yourself send queue */
+	struct sendq
+	{
+		int sq_filled;		/* this buffer contains a packet */
+		int sq_size;		/* with this size */
+		int sq_sendpage;	/* starting page of the buffer */
+	} de_sendq[SENDQ_NR];
+	int de_sendq_nr;
+	int de_sendq_head;		/* Enqueue at the head */
+	int de_sendq_tail;		/* Dequeue at the tail */
+
+	/* Fields for internal use by the dp8390 driver. */
+	int de_flags;
+	int de_mode;
+	eth_stat_t de_stat;
+	iovec_dat_t de_read_iovec;
+//	iovec_dat_s_t de_read_iovec_s;
+//	int de_safecopy_read;
+	iovec_dat_t de_write_iovec;
+//	iovec_dat_s_t de_write_iovec_s;
+	iovec_dat_t de_tmp_iovec;
+//	iovec_dat_s_t de_tmp_iovec_s;
+	vir_bytes de_read_s;
+//	int de_client;
+//	message de_sendmsg;
+	dp_user2nicf_t de_user2nicf; 
+//	dp_user2nicf_s_t de_user2nicf_s; 
+	dp_nic2userf_t de_nic2userf;
+//	dp_nic2userf_s_t de_nic2userf_s; 
+	dp_getblock_t de_getblockf;
+} dpeth_t;
+
+#define DEI_DEFAULT	0x8000
+
+#define DEF_EMPTY	0x000
+#define DEF_PACK_SEND	0x001
+#define DEF_PACK_RECV	0x002
+#define DEF_SEND_AVAIL	0x004
+#define DEF_READING	0x010
+#define DEF_PROMISC	0x040
+#define DEF_MULTI	0x080
+#define DEF_BROAD	0x100
+#define DEF_ENABLED	0x200
+#define DEF_STOPPED	0x400
+
+#define DEM_DISABLED	0x0
+#define DEM_SINK	0x1
+#define DEM_ENABLED	0x2
+
+//#if !__minix_vmd
+#define debug		1	/* Standard Minix lacks debug variable */
+//#endif
+
+/*
+ * $PchId: dp8390.h,v 1.10 2005/02/10 17:26:06 philip Exp $
+ */
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/netif/dp8390/dp8390_drv.h
===================================================================
--- uspace/srv/net/netif/dp8390/dp8390_drv.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/netif/dp8390/dp8390_drv.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,84 @@
+/*
+ * 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 dp8390
+ *  @{
+ */
+
+/** @file
+ *  DP8390 network interface driver interface.
+ */
+
+#ifndef __NET_NETIF_DP8390_DRIVER_H__
+#define __NET_NETIF_DP8390_DRIVER_H__
+
+#include "dp8390.h"
+
+/** Initializes and/or starts the network interface.
+ *  @param[in,out] dep The network interface structure.
+ *  @param[in] mode The state mode.
+ *  @returns EOK on success.
+ *  @returns EXDEV if the network interface is disabled.
+ */
+int do_init(dpeth_t *dep, int mode);
+
+/** Stops the network interface.
+ *  @param[in,out] dep The network interface structure.
+ */
+void do_stop(dpeth_t *dep);
+
+/** Processes the interrupt.
+ *  @param[in,out] dep The network interface structure.
+ *  @param[in] isr The interrupt status register.
+ */
+void dp_check_ints(dpeth_t *dep, int isr);
+
+/** Probes and initializes the network interface.
+ *  @param[in,out] dep The network interface structure.
+ *  @returns EOK on success.
+ *  @returns EXDEV if the network interface was not recognized.
+ */
+int	do_probe( dpeth_t * dep );
+
+/** Sends a packet.
+ *  @param[in,out] dep The network interface structure.
+ *  @param[in] packet The packet t be sent.
+ *  @param[in] from_int The value indicating whether the sending is initialized from the interrupt handler.
+ *  @returns 
+ */
+int	do_pwrite( dpeth_t * dep, packet_t packet, int from_int );
+
+/** Prints out network interface information.
+ *  @param[in] dep The network interface structure.
+ */
+void	dp8390_dump( dpeth_t * dep );
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/netif/dp8390/dp8390_module.c
===================================================================
--- uspace/srv/net/netif/dp8390/dp8390_module.c	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/netif/dp8390/dp8390_module.c	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,321 @@
+/*
+ * 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 dp8390
+ *  @{
+ */
+
+/** @file
+ *  DP8390 network interface implementation.
+ */
+
+#include <assert.h>
+#include <async.h>
+#include <ddi.h>
+#include <errno.h>
+#include <malloc.h>
+//#include <stdio.h>
+#include <ipc/ipc.h>
+#include <ipc/services.h>
+
+#include "../../err.h"
+#include "../../messages.h"
+#include "../../modules.h"
+
+#include "../../structures/packet/packet_client.h"
+#include "../../structures/measured_strings.h"
+
+#include "../../include/device.h"
+#include "../../include/nil_interface.h"
+
+#include "../netif.h"
+#include "../netif_module.h"
+
+#include "dp8390.h"
+#include "dp8390_drv.h"
+#include "dp8390_port.h"
+
+/** DP8390 module name.
+ */
+#define NAME	"dp8390 network interface"
+
+/** Returns the device from the interrupt call.
+ *  @param[in] call The interrupt call.
+ */
+#define IRQ_GET_DEVICE( call )			( device_id_t ) IPC_GET_METHOD( * call )
+
+/** Returns the interrupt status register from the interrupt call.
+ *  @param[in] call The interrupt call.
+ */
+#define IPC_GET_ISR( call )				( int ) IPC_GET_ARG2( * call )
+
+/** DP8390 kernel interrupt command sequence.
+ */
+static irq_cmd_t	dp8390_cmds[] = {
+	{ 	.cmd = CMD_PIO_READ_8,
+		.addr = NULL,
+		.dstarg = 2
+	},
+	{
+		.cmd = CMD_PREDICATE,
+		.value = 1,
+		.srcarg = 2
+	},
+	{
+		.cmd = CMD_ACCEPT
+	}
+};
+
+/** DP8390 kernel interrupt code.
+ */
+static irq_code_t	dp8390_code = {
+	sizeof( dp8390_cmds ) / sizeof( irq_cmd_t ),
+	dp8390_cmds
+};
+
+/** Network interface module global data.
+ */
+netif_globals_t netif_globals;
+
+/** Prints the module name.
+ *  @see NAME
+ */
+void	module_print_name( void );
+
+/** Handles the interrupt messages.
+ *  This is the interrupt handler callback function.
+ *  @param[in] iid The interrupt message identifier.
+ *  @param[in] call The interrupt message.
+ */
+void	irq_handler( ipc_callid_t iid, ipc_call_t * call );
+
+/** Changes the network interface state.
+ *  @param[in,out] device The network interface.
+ *  @param[in] state The new state.
+ *  @returns The new state.
+ */
+int	change_state( device_ref device, device_state_t state );
+
+int netif_specific_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){
+	return ENOTSUP;
+}
+
+int netif_get_device_stats( device_id_t device_id, device_stats_ref stats ){
+	ERROR_DECLARE;
+
+	device_ref		device;
+	eth_stat_t *	de_stat;
+
+	if( ! stats ) return EBADMEM;
+	ERROR_PROPAGATE( find_device( device_id, & device ));
+	de_stat = & (( dpeth_t * ) device->specific )->de_stat;
+	null_device_stats( stats );
+	stats->receive_errors = de_stat->ets_recvErr;
+	stats->send_errors = de_stat->ets_sendErr;
+	stats->receive_crc_errors = de_stat->ets_CRCerr;
+	stats->receive_frame_errors = de_stat->ets_frameAll;
+	stats->receive_missed_errors = de_stat->ets_missedP;
+	stats->receive_packets = de_stat->ets_packetR;
+	stats->send_packets = de_stat->ets_packetT;
+	stats->collisions = de_stat->ets_collision;
+	stats->send_aborted_errors = de_stat->ets_transAb;
+	stats->send_carrier_errors = de_stat->ets_carrSense;
+	stats->send_heartbeat_errors = de_stat->ets_CDheartbeat;
+	stats->send_window_errors = de_stat->ets_OWC;
+	return EOK;
+}
+
+void module_print_name( void ){
+	printf( "%s", NAME );
+}
+
+int netif_get_addr_message( device_id_t device_id, measured_string_ref address ){
+	ERROR_DECLARE;
+
+	device_ref	device;
+
+	if( ! address ) return EBADMEM;
+	ERROR_PROPAGATE( find_device( device_id, & device ));
+	address->value = ( char * ) ( & (( dpeth_t * ) device->specific )->de_address );
+	address->length = CONVERT_SIZE( ether_addr_t, char, 1 );
+	return EOK;
+}
+
+void irq_handler( ipc_callid_t iid, ipc_call_t * call )
+{
+	device_ref	device;
+	dpeth_t *	dep;
+	packet_t	received;
+	device_id_t	device_id;
+	int			phone;
+
+	device_id = IRQ_GET_DEVICE( call );
+	fibril_rwlock_write_lock( & netif_globals.lock );
+	if( find_device( device_id, & device ) != EOK ){
+		fibril_rwlock_write_unlock( & netif_globals.lock );
+		return;
+	}
+	dep = ( dpeth_t * ) device->specific;
+	if ( dep->de_mode != DEM_ENABLED){
+		fibril_rwlock_write_unlock( & netif_globals.lock );
+		return;
+	}
+	assert( dep->de_flags & DEF_ENABLED);
+	dep->de_int_pending = 0;
+//	remove debug print:
+	printf( "I%d: 0x%x\n", device_id, IPC_GET_ISR( call ));
+	dp_check_ints( dep, IPC_GET_ISR( call ));
+	if( dep->received_queue ){
+		received = dep->received_queue;
+		phone = device->nil_phone;
+		dep->received_queue = NULL;
+		dep->received_count = 0;
+		fibril_rwlock_write_unlock( & netif_globals.lock );
+//	remove debug dump:
+	uint8_t *	data;
+	data = packet_get_data( received );
+	printf( "Receiving packet:\n\tid\t= %d\n\tlength\t= %d\n\tdata\t= %.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX\n\t\t%.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX\n", packet_get_id( received ), packet_get_data_length( received ), data[ 0 ], data[ 1 ], data[ 2 ], data[ 3 ], data[ 4 ], data[ 5 ], data[ 6 ], data[ 7 ], data[ 8 ], data[ 9 ], data[ 10 ], data[ 11 ], data[ 12 ], data[ 13 ], data[ 14 ], data[ 15 ], data[ 16 ], data[ 17 ], data[ 18 ], data[ 19 ], data[ 20 ], data[ 21 ], data[ 22 ], data[ 23 ], data[ 24 ], data[ 25 ], data[ 26 ], data[ 27 ], data[ 28 ], data[ 29 ], data[ 30 ], data[ 31 ], data[ 32 ], data[ 33 ], data[ 34 ], data[ 35 ], data[ 36 ], data[ 37 ], data[ 38 ], data[ 39 ], data[ 40 ], data[ 41 ], data[ 42 ], data[ 43 ], data[ 44 ], data[ 45 ], data[ 46 ], data[ 47 ], data[ 48 ], data[ 49 ], data[ 50 ], data[ 51 ], data[ 52 ], data[ 53 ], data[ 54 ], data[ 55 ], data[ 56 ], data[ 57 ], data[ 58 ], data[ 59 ] );
+		nil_received_msg( phone, device_id, received, NULL );
+	}else{
+		fibril_rwlock_write_unlock( & netif_globals.lock );
+	}
+	ipc_answer_0( iid, EOK );
+}
+
+int netif_probe_message( device_id_t device_id, int irq, int io ){
+	ERROR_DECLARE;
+
+	device_ref	device;
+	dpeth_t *	dep;
+
+	device = ( device_ref ) malloc( sizeof( device_t ));
+	if( ! device ) return ENOMEM;
+	dep = ( dpeth_t * ) malloc( sizeof( dpeth_t ));
+	if( ! dep ){
+		free( device );
+		return ENOMEM;
+	}
+	bzero( device, sizeof( device_t ));
+	bzero( dep, sizeof( dpeth_t ));
+	device->device_id = device_id;
+	device->nil_phone = -1;
+	device->specific = ( void * ) dep;
+	device->state = NETIF_STOPPED;
+	dep->de_irq = irq;
+	dep->de_mode = DEM_DISABLED;
+	//TODO address?
+	if( ERROR_OCCURRED( pio_enable(( void * ) io, DP8390_IO_SIZE, ( void ** ) & dep->de_base_port ))
+	|| ERROR_OCCURRED( do_probe( dep ))){
+		free( dep );
+		free( device );
+		return ERROR_CODE;
+	}
+	if( ERROR_OCCURRED( device_map_add( & netif_globals.device_map, device->device_id, device ))){
+		free( dep );
+		free( device );
+		return ERROR_CODE;
+	}
+	return EOK;
+}
+
+int netif_send_message( device_id_t device_id, packet_t packet, services_t sender ){
+	ERROR_DECLARE;
+
+	device_ref	device;
+	dpeth_t *	dep;
+	packet_t	next;
+
+	ERROR_PROPAGATE( find_device( device_id, & device ));
+	if( device->state != NETIF_ACTIVE ){
+		netif_pq_release( packet_get_id( packet ));
+		return EFORWARD;
+	}
+	dep = ( dpeth_t * ) device->specific;
+	// process packet queue
+	do{
+		next = pq_detach( packet );
+//		remove debug dump:
+		uint8_t *	data;
+		data = packet_get_data( packet );
+		printf( "Sending packet:\n\tid\t= %d\n\tlength\t= %d\n\tdata\t= %.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX\n\t\t%.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX\n", packet_get_id( packet ), packet_get_data_length( packet ), data[ 0 ], data[ 1 ], data[ 2 ], data[ 3 ], data[ 4 ], data[ 5 ], data[ 6 ], data[ 7 ], data[ 8 ], data[ 9 ], data[ 10 ], data[ 11 ], data[ 12 ], data[ 13 ], data[ 14 ], data[ 15 ], data[ 16 ], data[ 17 ], data[ 18 ], data[ 19 ], data[ 20 ], data[ 21 ], data[ 22 ], data[ 23 ], data[ 24 ], data[ 25 ], data[ 26 ], data[ 27 ], data[ 28 ], data[ 29 ], data[ 30 ], data[ 31 ], data[ 32 ], data[ 33 ], data[ 34 ], data[ 35 ], data[ 36 ], data[ 37 ], data[ 38 ], data[ 39 ], data[ 40 ], data[ 41 ], data[ 42 ], data[ 43 ], data[ 44 ], data[ 45 ], data[ 46 ], data[ 47 ], data[ 48 ], data[ 49 ], data[ 50 ], data[ 51 ], data[ 52 ], data[ 53 ], data[ 54 ], data[ 55 ], data[ 56 ], data[ 57 ], data[ 58 ], data[ 59 ] );
+
+		if( do_pwrite( dep, packet, FALSE ) != EBUSY ){
+			netif_pq_release( packet_get_id( packet ));
+		}
+		packet = next;
+	}while( packet );
+	return EOK;
+}
+
+int	netif_start_message( device_ref device ){
+	ERROR_DECLARE;
+
+	dpeth_t *	dep;
+
+	if( device->state != NETIF_ACTIVE ){
+		dep = ( dpeth_t * ) device->specific;
+		dp8390_cmds[ 0 ].addr = ( void * ) ( uint32_t ) ( dep->de_dp8390_port + DP_ISR );
+		dp8390_cmds[ 2 ].addr = dp8390_cmds[ 0 ].addr;
+		ERROR_PROPAGATE( ipc_register_irq( dep->de_irq, device->device_id, device->device_id, & dp8390_code ));
+		if( ERROR_OCCURRED( do_init( dep, DL_BROAD_REQ ))){
+			ipc_unregister_irq( dep->de_irq, device->device_id );
+			return ERROR_CODE;
+		}
+		return change_state( device, NETIF_ACTIVE );
+	}
+	return EOK;
+}
+
+int	netif_stop_message( device_ref device ){
+	dpeth_t *	dep;
+
+	if( device->state != NETIF_STOPPED ){
+		dep = ( dpeth_t * ) device->specific;
+		do_stop( dep );
+		ipc_unregister_irq( dep->de_irq, device->device_id );
+		return change_state( device, NETIF_STOPPED );
+	}
+	return EOK;
+}
+
+int change_state( device_ref device, device_state_t state ){
+	device->state = state;
+	printf( "State changed to %s\n", ( state == NETIF_ACTIVE ) ? "ACTIVE" : "STOPPED" );
+	return state;
+}
+
+int netif_initialize( void ){
+	ipcarg_t	phonehash;
+
+	async_set_interrupt_received( irq_handler );
+
+	return REGISTER_ME( SERVICE_DP8390, & phonehash );
+}
+
+/** @}
+ */
Index: uspace/srv/net/netif/dp8390/dp8390_port.h
===================================================================
--- uspace/srv/net/netif/dp8390/dp8390_port.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/netif/dp8390/dp8390_port.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,274 @@
+/*
+ * 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 dp8390
+ *  @{
+ */
+
+/** @file
+ *  DP8390 network interface types and structures ports.
+ */
+
+#ifndef __NET_NETIF_DP8390_PORT_H__
+#define __NET_NETIF_DP8390_PORT_H__
+
+#include <errno.h>
+#include <mem.h>
+#include <stdio.h>
+#include <libarch/ddi.h>
+#include <sys/types.h>
+
+/** Macro for difining functions.
+ *  @param[in] function The function type and name definition.
+ *  @param[in] params The function parameters definition.
+ */
+#define _PROTOTYPE( function, params ) function params
+
+/** Success error code.
+ */
+#define OK	EOK
+
+/** Type definition of the unsigned byte.
+ */
+typedef uint8_t u8_t;
+
+/** Type definition of the unsigned short.
+ */
+typedef uint16_t u16_t;
+
+/** Compares two memory blocks.
+ *  @param[in] first The first memory block.
+ *  @param[in] second The second memory block.
+ *  @param[in] size The blocks size in bytes.
+ *  @returns 0 if equeal.
+ *  @returns -1 if the first is greater than the second.
+ *  @returns 1 if the second is greater than the first.
+ */
+#define memcmp( first, second, size )	bcmp(( char * ) ( first ), ( char * ) ( second ), ( size ))
+
+/** Reads 1 byte.
+ *  @param[in] port The address to be read.
+ *  @returns The read value.
+ */
+#define inb( port )	pio_read_8(( ioport8_t * ) ( port ))
+
+/** Reads 1 word (2 bytes).
+ *  @param[in] port The address to be read.
+ *  @returns The read value.
+ */
+#define inw( port )	pio_read_16(( ioport16_t * ) ( port ))
+
+/** Writes 1 byte.
+ *  @param[in] port The address to be written.
+ *  @param[in] value The value to be written.
+ */
+#define outb( port, value )	pio_write_8(( ioport8_t * ) ( port ), ( value ))
+
+/** Writes 1 word (2 bytes).
+ *  @param[in] port The address to be written.
+ *  @param[in] value The value to be written.
+ */
+#define outw( port, value )	pio_write_16(( ioport16_t * ) ( port ), ( value ))
+
+/** Prints out the driver critical error.
+ *  Does not call the system panic().
+ */
+#define panic( ... )	printf( "%s%s%d", __VA_ARGS__ )
+
+/** Copies a memory block.
+ *  @param proc The source process. Ignored parameter.
+ *  @param src_s Ignored parameter.
+ *  @param[in] src The source address.
+ *  @param me The current proces. Ignored parameter.
+ *  @param dst_s Ignored parameter.
+ *  @param[in] dst The destination address.
+ *  @param[in] bytes The block size in bytes.
+ *  @returns EOK.
+ */
+#define sys_vircopy( proc, src_s, src, me, dst_s, dst, bytes )	({ memcpy(( void * )( dst ), ( void * )( src ), ( bytes )); EOK; })
+
+/** Reads a memory block byte by byte.
+ *  @param[in] port The address to be written.
+ *  @param proc The source process. Ignored parameter.
+ *  @param[in] dst The destination address.
+ *  @param[in] bytes The block size in bytes.
+ */
+#define do_vir_insb( port, proc, dst, bytes )	insb(( port ), ( void * )( dst ), ( bytes ))
+
+/** Reads a memory block word by word (2 bytes).
+ *  @param[in] port The address to be written.
+ *  @param proc The source process. Ignored parameter.
+ *  @param[in] dst The destination address.
+ *  @param[in] bytes The block size in bytes.
+ */
+#define do_vir_insw( port, proc, dst, bytes )	insw(( port ), ( void * )( dst ), ( bytes ))
+
+/** Writes a memory block byte by byte.
+ *  @param[in] port The address to be written.
+ *  @param proc The source process. Ignored parameter.
+ *  @param[in] src The source address.
+ *  @param[in] bytes The block size in bytes.
+ */
+#define do_vir_outsb( port, proc, src, bytes )	outsb(( port ), ( void * )( src ), ( bytes ))
+
+/** Writes a memory block word by word (2 bytes).
+ *  @param[in] port The address to be written.
+ *  @param proc The source process. Ignored parameter.
+ *  @param[in] src The source address.
+ *  @param[in] bytes The block size in bytes.
+ */
+#define do_vir_outsw( port, proc, src, bytes )	outsw(( port ), ( void * )( src ), ( bytes ))
+
+/* com.h */
+/* Bits in 'DL_MODE' field of DL requests. */
+#  define DL_NOMODE		0x0
+#  define DL_PROMISC_REQ	0x2
+#  define DL_MULTI_REQ		0x4
+#  define DL_BROAD_REQ		0x8
+
+/* const.h */
+/** True value.
+ */
+#define TRUE               1	/* used for turning integers into Booleans */
+
+/** False value.
+ */
+#define FALSE              0	/* used for turning integers into Booleans */
+
+/** No number value.
+ */
+#define NO_NUM        0x8000	/* used as numerical argument to panic() */
+
+/* devio.h */
+//typedef u16_t port_t;
+/** Type definition of a port.
+ */
+typedef int port_t;
+
+/* dl_eth.h */
+/** Ethernet statistics.
+ */
+typedef struct eth_stat
+{
+	/** Number of receive errors.
+	 */
+	unsigned long ets_recvErr;
+	/** Number of send error.
+	 */
+	unsigned long ets_sendErr;
+	/** Number of buffer overwrite warnings.
+	 */
+	unsigned long ets_OVW;
+	/** Number of crc errors of read.
+	 */
+	unsigned long ets_CRCerr;
+	/** Number of frames not alligned (number of bits % 8 != 0).
+	 */
+	unsigned long ets_frameAll;
+	/** Number of packets missed due to slow processing.
+	 */
+	unsigned long ets_missedP;
+	/** Number of packets received.
+	 */
+	unsigned long ets_packetR;
+	/** Number of packets transmitted.
+	 */
+	unsigned long ets_packetT;
+	/** Number of transmission defered (Tx was busy).
+	 */
+	unsigned long ets_transDef;
+	/** Number of collissions.
+	 */
+	unsigned long ets_collision;
+	/** Number of Tx aborted due to excess collisions.
+	 */
+	unsigned long ets_transAb;
+	/** Number of carrier sense lost.
+	 */
+	unsigned long ets_carrSense;
+	/** Number of FIFO underruns (processor too busy).
+	 */
+	unsigned long ets_fifoUnder;
+	/** Number of FIFO overruns (processor too busy).
+	 */
+	unsigned long ets_fifoOver;
+	/** Number of times unable to transmit collision sig.
+	 */
+	unsigned long ets_CDheartbeat;
+	/** Number of times out of window collision.
+	 */
+	unsigned long ets_OWC;
+} eth_stat_t;
+
+/* errno.h */
+/** Generic error.
+ */
+#define EGENERIC     EINVAL
+
+/* ether.h */
+/** Minimum Ethernet packet size in bytes.
+ */
+#define ETH_MIN_PACK_SIZE		  60
+
+/** Maximum Ethernet packet size in bytes.
+ */
+#define ETH_MAX_PACK_SIZE_TAGGED	1518
+
+/** Ethernet address type definition.
+ */
+typedef struct ether_addr
+{
+	/** Address data.
+	 */
+	u8_t ea_addr[6];
+} ether_addr_t;
+
+/* type.h */
+/** Type definition of the physical addresses and lengths in bytes.
+ */
+typedef unsigned long phys_bytes;
+
+/** Type definition of the virtual addresses and lengths in bytes.
+ */
+typedef unsigned int vir_bytes;
+
+/** Type definition of the input/output vector.
+ */
+typedef struct {
+	/** Address of an I/O buffer.
+	 */
+	vir_bytes iov_addr;
+	/** Sizeof an I/O buffer.
+	 */
+	vir_bytes iov_size;
+} iovec_t;
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/netif/dp8390/local.h
===================================================================
--- uspace/srv/net/netif/dp8390/local.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/netif/dp8390/local.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 1987,1997, 2006, Vrije Universiteit, Amsterdam, The Netherlands All rights reserved. Redistribution and use of the MINIX 3 operating system in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Vrije Universiteit nor the names of the software authors or contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+ * * Any deviations from these conditions require written permission from the copyright holder in advance
+ *
+ *
+ * Disclaimer
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS, AUTHORS, AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR ANY AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Changes:
+ *  2009 ported to HelenOS, Lukas Mejdrech
+ */
+
+/** @addtogroup dp8390
+ *  @{
+ */
+
+/** @file
+ *  Network interface probe functions.
+ */
+
+#ifndef __NET_NETIF_DP8390_CONFIG_H__
+#define __NET_NETIF_DP8390_CONFIG_H__
+
+#include "dp8390_port.h"
+
+/*
+local.h
+*/
+
+/** WDETH switch.
+ */
+#define ENABLE_WDETH 0
+
+/** NE2000 switch.
+ */
+#define ENABLE_NE2000 1
+
+/** 3C503 switch.
+ */
+#define ENABLE_3C503 0
+
+/** PCI support switch.
+ */
+#define ENABLE_PCI 0
+
+struct dpeth;
+
+/* 3c503.c */
+/* * Probes a 3C503 network interface.
+ *  @param[in] dep The network interface structure.
+ *  @returns 1 if the NE2000 network interface is present.
+ *  @returns 0 otherwise.
+ */
+//_PROTOTYPE( int el2_probe, (struct dpeth* dep)				);
+
+/* ne2000.c */
+/** Probes a NE2000 or NE1000 network interface.
+ *  @param[in] dep The network interface structure.
+ *  @returns 1 if the NE2000 network interface is present.
+ *  @returns 0 otherwise.
+ */
+int	ne_probe( struct dpeth * dep );
+//_PROTOTYPE( int ne_probe, (struct dpeth *dep)				);
+//_PROTOTYPE( void ne_init, (struct dpeth *dep)				);
+
+/* rtl8029.c */
+/* * Probes a RTL8029 network interface.
+ *  @param[in] dep The network interface structure.
+ *  @returns 1 if the NE2000 network interface is present.
+ *  @returns 0 otherwise.
+ */
+//_PROTOTYPE( int rtl_probe, (struct dpeth *dep)				);
+
+/* wdeth.c */
+/* * Probes a WDETH network interface.
+ *  @param[in] dep The network interface structure.
+ *  @returns 1 if the NE2000 network interface is present.
+ *  @returns 0 otherwise.
+ */
+//_PROTOTYPE( int wdeth_probe, (struct dpeth* dep)				);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/netif/dp8390/ne2000.c
===================================================================
--- uspace/srv/net/netif/dp8390/ne2000.c	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/netif/dp8390/ne2000.c	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,416 @@
+/*
+ * Copyright (c) 1987,1997, 2006, Vrije Universiteit, Amsterdam, The Netherlands All rights reserved. Redistribution and use of the MINIX 3 operating system in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Vrije Universiteit nor the names of the software authors or contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+ * * Any deviations from these conditions require written permission from the copyright holder in advance
+ *
+ *
+ * Disclaimer
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS, AUTHORS, AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR ANY AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Changes:
+ *  2009 ported to HelenOS, Lukas Mejdrech
+ */
+
+/** @addtogroup ne2k
+ *  @{
+ */
+
+/** @file
+ *  NE1000 and NE2000 network interface initialization and probe functions implementation.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+
+#include "dp8390_port.h"
+
+/*
+ne2000.c
+
+Driver for the ne2000 ethernet cards. This file contains only the ne2000
+specific code, the rest is in dp8390.c
+
+Created:	March 15, 1994 by Philip Homburg <philip@f-mnx.phicoh.com>
+*/
+
+//#include "../drivers.h"
+
+//#include <net/gen/ether.h>
+//#include <net/gen/eth_io.h>
+//#if __minix_vmd
+//#include "config.h"
+//#endif
+
+#include "local.h"
+#include "dp8390.h"
+#include "ne2000.h"
+
+#if ENABLE_NE2000
+
+/** Number of bytes to transfer.
+ */
+#define N 100
+
+//#define MILLIS_TO_TICKS(m)  (((m)*HZ/1000)+1)
+
+/** Sleeps for the defined millicesonds.
+ *  @param[in] millis The number of milliseconds to sleep.
+ */
+#define milli_delay( millis )	usleep(( millis ) * 1000 )
+
+/** Type definition of the testing function.
+ */
+_PROTOTYPE( typedef int (*testf_t), (dpeth_t *dep, int pos, u8_t *pat)	);
+
+/** First data pattern.
+ */
+u8_t	pat0[]= { 0x00, 0x00, 0x00, 0x00 };
+
+/** Second data pattern.
+ */
+u8_t	pat1[]= { 0xFF, 0xFF, 0xFF, 0xFF };
+
+/** Third data pattern.
+ */
+u8_t	pat2[]= { 0xA5, 0x5A, 0x69, 0x96 };
+
+/** Fourth data pattern.
+ */
+u8_t	pat3[]= { 0x96, 0x69, 0x5A, 0xA5 };
+
+/** Tests 8 bit NE2000 network interface.
+ *  @param[in,out] dep The network interface structure.
+ *  @param[in] pos The starting position.
+ *  @param[in] pat The data pattern to be written.
+ *  @returns True on success.
+ *  @returns FALSE otherwise.
+ */
+static int test_8(dpeth_t *dep, int pos, u8_t *pat);
+
+/** Tests 16 bit NE2000 network interface.
+ *  @param[in,out] dep The network interface structure.
+ *  @param[in] pos The starting position.
+ *  @param[in] pat The data pattern to be written.
+ *  @returns True on success.
+ *  @returns FALSE otherwise.
+ */
+static int test_16(dpeth_t *dep, int pos, u8_t *pat);
+
+/** Stops the NE2000 network interface.
+ *  @param[in,out] dep The network interface structure.
+ */
+static void ne_stop(dpeth_t *dep);
+//_PROTOTYPE( static void milli_delay, (unsigned long millis)		);
+
+/** Initializes the NE2000 network interface.
+ *  @param[in,out] dep The network interface structure.
+ */
+void ne_init(struct dpeth *dep);
+
+/*===========================================================================*
+ *				ne_probe				     *
+ *===========================================================================*/
+int ne_probe(dep)
+dpeth_t *dep;
+{
+	int byte;
+	int i;
+	int loc1, loc2;
+	testf_t f;
+
+	dep->de_dp8390_port= dep->de_base_port + NE_DP8390;
+
+	/* We probe for an ne1000 or an ne2000 by testing whether the
+	 * on board is reachable through the dp8390. Note that the
+	 * ne1000 is an 8bit card and has a memory region distict from
+	 * the 16bit ne2000
+	 */
+
+	for (dep->de_16bit= 0; dep->de_16bit < 2; dep->de_16bit++)
+	{
+		/* Reset the ethernet card */
+		byte= inb_ne(dep, NE_RESET);
+		milli_delay(2);
+		outb_ne(dep, NE_RESET, byte);
+		milli_delay(2);
+
+		/* Reset the dp8390 */
+		outb_reg0(dep, DP_CR, CR_STP | CR_DM_ABORT);
+		for (i= 0; i < 0x1000 && ((inb_reg0(dep, DP_ISR) & ISR_RST) == 0); i++)
+			; /* Do nothing */
+
+		/* Check if the dp8390 is really there */
+		if ((inb_reg0(dep, DP_CR) & (CR_STP|CR_DM_ABORT)) !=
+			(CR_STP|CR_DM_ABORT))
+		{
+			return 0;
+		}
+
+		/* Disable the receiver and init TCR and DCR. */
+		outb_reg0(dep, DP_RCR, RCR_MON);
+		outb_reg0(dep, DP_TCR, TCR_NORMAL);
+		if (dep->de_16bit)
+		{
+			outb_reg0(dep, DP_DCR, DCR_WORDWIDE | DCR_8BYTES |
+				DCR_BMS);
+		}
+		else
+		{
+			outb_reg0(dep, DP_DCR, DCR_BYTEWIDE | DCR_8BYTES |
+				DCR_BMS);
+		}
+
+		if (dep->de_16bit)
+		{
+			loc1= NE2000_START;
+			loc2= NE2000_START + NE2000_SIZE - 4;
+			f= test_16;
+		}
+		else
+		{
+			loc1= NE1000_START;
+			loc2= NE1000_START + NE1000_SIZE - 4;
+			f= test_8;
+		}
+		if (f(dep, loc1, pat0) && f(dep, loc1, pat1) &&
+			f(dep, loc1, pat2) && f(dep, loc1, pat3) &&
+			f(dep, loc2, pat0) && f(dep, loc2, pat1) &&
+			f(dep, loc2, pat2) && f(dep, loc2, pat3))
+		{
+			/* We don't need a memory segment */
+			dep->de_linmem= 0;
+			if (!dep->de_pci)
+				dep->de_initf= ne_init;
+			dep->de_stopf= ne_stop;
+			dep->de_prog_IO= 1;
+			return 1;
+		}
+	}
+	return 0;
+}
+
+/*===========================================================================*
+ *				ne_init					     *
+ *===========================================================================*/
+void ne_init(dep)
+dpeth_t *dep;
+{
+	int i;
+	int word, sendq_nr;
+
+	/* Setup a transfer to get the ethernet address. */
+	if (dep->de_16bit)
+		outb_reg0(dep, DP_RBCR0, 6*2);
+	else
+		outb_reg0(dep, DP_RBCR0, 6);
+	outb_reg0(dep, DP_RBCR1, 0);
+	outb_reg0(dep, DP_RSAR0, 0);
+	outb_reg0(dep, DP_RSAR1, 0);
+	outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
+
+	for (i= 0; i<6; i++)
+	{
+		if (dep->de_16bit)
+		{
+			word= inw_ne(dep, NE_DATA);
+			dep->de_address.ea_addr[i]= word;
+		}
+		else
+		{
+			dep->de_address.ea_addr[i] = inb_ne(dep, NE_DATA);
+		}
+	}
+	dep->de_data_port= dep->de_base_port + NE_DATA;
+	if (dep->de_16bit)
+	{
+		dep->de_ramsize= NE2000_SIZE;
+		dep->de_offset_page= NE2000_START / DP_PAGESIZE;
+	}
+	else
+	{
+		dep->de_ramsize= NE1000_SIZE;
+		dep->de_offset_page= NE1000_START / DP_PAGESIZE;
+	}
+
+	/* Allocate one send buffer (1.5KB) per 8KB of on board memory. */
+	sendq_nr= dep->de_ramsize / 0x2000;
+	if (sendq_nr < 1)
+		sendq_nr= 1;
+	else if (sendq_nr > SENDQ_NR)
+		sendq_nr= SENDQ_NR;
+	dep->de_sendq_nr= sendq_nr;
+	for (i= 0; i<sendq_nr; i++)
+	{
+		dep->de_sendq[i].sq_sendpage= dep->de_offset_page +
+			i*SENDQ_PAGES;	
+	}
+
+	dep->de_startpage= dep->de_offset_page + i*SENDQ_PAGES;
+	dep->de_stoppage= dep->de_offset_page + dep->de_ramsize / DP_PAGESIZE;
+
+	/* Can't override the default IRQ. */
+	dep->de_irq &= ~DEI_DEFAULT;
+
+	if (!debug)
+	{
+		printf("%s: NE%d000 at %X:%d\n",
+			dep->de_name, dep->de_16bit ? 2 : 1,
+			dep->de_base_port, dep->de_irq);
+	}
+	else
+	{
+		printf("%s: Novell NE%d000 ethernet card at I/O address "
+			"0x%X, memory size 0x%X, irq %d\n",
+			dep->de_name, dep->de_16bit ? 2 : 1,
+			dep->de_base_port, dep->de_ramsize, dep->de_irq);
+	}
+}
+
+/*===========================================================================*
+ *				test_8					     *
+ *===========================================================================*/
+static int test_8(dep, pos, pat)
+dpeth_t *dep;
+int pos;
+u8_t *pat;
+{
+	u8_t buf[4];
+	int i;
+	int r;
+
+	outb_reg0(dep, DP_ISR, 0xFF);
+
+	/* Setup a transfer to put the pattern. */
+	outb_reg0(dep, DP_RBCR0, 4);
+	outb_reg0(dep, DP_RBCR1, 0);
+	outb_reg0(dep, DP_RSAR0, pos & 0xFF);
+	outb_reg0(dep, DP_RSAR1, pos >> 8);
+	outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
+
+	for (i= 0; i<4; i++)
+		outb_ne(dep, NE_DATA, pat[i]);
+
+	for (i= 0; i<N; i++)
+	{
+		if (inb_reg0(dep, DP_ISR) & ISR_RDC)
+			break;
+	}
+	if (i == N)
+	{
+		if (debug)
+		{
+			printf("%s: NE1000 remote DMA test failed\n",
+				dep->de_name);
+		}
+		return 0;
+	}
+
+	outb_reg0(dep, DP_RBCR0, 4);
+	outb_reg0(dep, DP_RBCR1, 0);
+	outb_reg0(dep, DP_RSAR0, pos & 0xFF);
+	outb_reg0(dep, DP_RSAR1, pos >> 8);
+	outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
+
+	for (i= 0; i<4; i++)
+		buf[i]= inb_ne(dep, NE_DATA);
+
+	r= (memcmp(buf, pat, 4) == 0);
+	return r;
+}
+
+/*===========================================================================*
+ *				test_16					     *
+ *===========================================================================*/
+static int test_16(dep, pos, pat)
+dpeth_t *dep;
+int pos;
+u8_t *pat;
+{
+	u8_t buf[4];
+	int i;
+	int r;
+
+	outb_reg0(dep, DP_ISR, 0xFF);
+
+	/* Setup a transfer to put the pattern. */
+	outb_reg0(dep, DP_RBCR0, 4);
+	outb_reg0(dep, DP_RBCR1, 0);
+	outb_reg0(dep, DP_RSAR0, pos & 0xFF);
+	outb_reg0(dep, DP_RSAR1, pos >> 8);
+	outb_reg0(dep, DP_CR, CR_DM_RW | CR_PS_P0 | CR_STA);
+
+	for (i= 0; i<4; i += 2)
+	{
+		outw_ne(dep, NE_DATA, *(u16_t *)(pat+i));
+	}
+
+	for (i= 0; i<N; i++)
+	{
+		if (inb_reg0(dep, DP_ISR) & ISR_RDC)
+			break;
+	}
+	if (i == N)
+	{
+		if (debug)
+		{
+			printf("%s: NE2000 remote DMA test failed\n",
+				dep->de_name);
+		}
+		return 0;
+	}
+
+	outb_reg0(dep, DP_RBCR0, 4);
+	outb_reg0(dep, DP_RBCR1, 0);
+	outb_reg0(dep, DP_RSAR0, pos & 0xFF);
+	outb_reg0(dep, DP_RSAR1, pos >> 8);
+	outb_reg0(dep, DP_CR, CR_DM_RR | CR_PS_P0 | CR_STA);
+
+	for (i= 0; i<4; i += 2)
+	{
+		*(u16_t *)(buf+i)= inw_ne(dep, NE_DATA);
+	}
+
+	r= (memcmp(buf, pat, 4) == 0);
+	return r;
+}
+
+/*===========================================================================*
+ *				ne_stop					     *
+ *===========================================================================*/
+static void ne_stop(dep)
+dpeth_t *dep;
+{
+	int byte;
+
+	/* Reset the ethernet card */
+	byte= inb_ne(dep, NE_RESET);
+	milli_delay(2);
+	outb_ne(dep, NE_RESET, byte);
+}
+/*
+static void milli_delay(unsigned long millis)
+{
+	tickdelay(MILLIS_TO_TICKS(millis));
+}
+*/
+#endif /* ENABLE_NE2000 */
+
+/*
+ * $PchId: ne2000.c,v 1.10 2004/08/03 12:03:00 philip Exp $
+ */
+
+/** @}
+ */
Index: uspace/srv/net/netif/dp8390/ne2000.h
===================================================================
--- uspace/srv/net/netif/dp8390/ne2000.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/netif/dp8390/ne2000.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 1987,1997, 2006, Vrije Universiteit, Amsterdam, The Netherlands All rights reserved. Redistribution and use of the MINIX 3 operating system in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+ * * Neither the name of the Vrije Universiteit nor the names of the software authors or contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+ * * Any deviations from these conditions require written permission from the copyright holder in advance
+ *
+ *
+ * Disclaimer
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS, AUTHORS, AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR ANY AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Changes:
+ *  2009 ported to HelenOS, Lukas Mejdrech
+ */
+
+/*
+ne2000.h
+
+Created:	March 15, 1994 by Philip Homburg <philip@f-mnx.phicoh.com>
+*/
+
+/** @addtogroup ne2k
+ *  @{
+ */
+
+/** @file
+ *  NE1000 and NE2000 network interface definitions.
+ */
+
+#ifndef __NET_NETIF_NE2000_H__
+#define __NET_NETIF_NE2000_H__
+
+#include <libarch/ddi.h>
+
+#include "dp8390_port.h"
+
+/** DP8390 register offset.
+ */
+#define NE_DP8390	0x00
+
+/** Data register.
+ */
+#define NE_DATA		0x10
+
+/** Reset register.
+ */
+#define NE_RESET	0x1F
+
+/** NE1000 data start.
+ */
+#define NE1000_START	0x2000
+
+/** NE1000 data size.
+ */
+#define NE1000_SIZE	0x2000
+
+/** NE2000 data start.
+ */
+#define NE2000_START	0x4000
+
+/** NE2000 data size.
+ */
+#define NE2000_SIZE	0x4000
+
+/** Reads 1 byte register.
+ *  @param[in] dep The network interface structure.
+ *  @param[in] reg The register offset.
+ *  @returns The read value.
+ */
+#define inb_ne(dep, reg)	(inb(dep->de_base_port+reg))
+
+/** Writes 1 byte register.
+ *  @param[in] dep The network interface structure.
+ *  @param[in] reg The register offset.
+ *  @param[in] data The value to be written.
+ */
+#define outb_ne(dep, reg, data)	(outb(dep->de_base_port+reg, data))
+
+/** Reads 1 word (2 bytes) register.
+ *  @param[in] dep The network interface structure.
+ *  @param[in] reg The register offset.
+ *  @returns The read value.
+ */
+#define inw_ne(dep, reg)	(inw(dep->de_base_port+reg))
+
+/** Writes 1 word (2 bytes) register.
+ *  @param[in] dep The network interface structure.
+ *  @param[in] reg The register offset.
+ *  @param[in] data The value to be written.
+ */
+#define outw_ne(dep, reg, data)	(outw(dep->de_base_port+reg, data))
+
+#endif /* __NET_NETIF_NE2000_H__ */
+
+/*
+ * $PchId: ne2000.h,v 1.4 2004/08/03 12:03:20 philip Exp $
+ */
+
+/** @}
+ */
Index: uspace/srv/net/netif/lo/Makefile
===================================================================
--- uspace/srv/net/netif/lo/Makefile	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/netif/lo/Makefile	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,63 @@
+#
+# 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.
+#
+
+NAME = lo
+
+NET_BASE = ../../
+STRUCTURES = $(NET_BASE)structures/
+
+include $(NET_BASE)../../../Makefile.config
+
+## Sources
+#
+
+OUTPUT = $(NAME)
+SOURCES = \
+	$(NAME).c \
+	$(NET_BASE)module.c \
+	$(NET_BASE)modules.c \
+	$(NET_BASE)net/net_remote.c \
+	$(NET_BASE)netif/netif.c \
+	$(STRUCTURES)measured_strings.c \
+	$(STRUCTURES)packet/packet.c \
+	$(STRUCTURES)packet/packet_client.c \
+	$(STRUCTURES)packet/packet_remote.c
+
+ifeq ($(NETWORKING), module)
+
+	SOURCES +=	$(NET_BASE)nil/nildummy/nildummy.c \
+				$(NET_BASE)netif/netif_nil_bundle.c
+
+else
+
+	SOURCES += 	$(NET_BASE)nil/nil_remote.c \
+				$(NET_BASE)netif/netif_standalone.c
+
+endif
+
+include $(NET_BASE)Makefile.module
Index: uspace/srv/net/netif/lo/lo.c
===================================================================
--- uspace/srv/net/netif/lo/lo.c	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/netif/lo/lo.c	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,217 @@
+/*
+ * 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 lo
+ *  @{
+ */
+
+/** @file
+ *  Loopback network interface implementation.
+ */
+
+#include <async.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <ipc/ipc.h>
+#include <ipc/services.h>
+
+#include "../../err.h"
+#include "../../messages.h"
+#include "../../modules.h"
+
+#include "../../structures/measured_strings.h"
+#include "../../structures/packet/packet_client.h"
+
+#include "../../include/device.h"
+#include "../../include/nil_interface.h"
+
+#include "../../nil/nil_messages.h"
+
+#include "../netif.h"
+#include "../netif_module.h"
+
+/** Default hardware address.
+ */
+#define DEFAULT_ADDR		"\0\0\0\0\0\0"
+
+/** Default address length.
+ */
+#define DEFAULT_ADDR_LEN	( sizeof( DEFAULT_ADDR ) / sizeof( char ))
+
+/** Loopback module name.
+ */
+#define NAME	"lo - loopback interface"
+
+/** Network interface global data.
+ */
+netif_globals_t	netif_globals;
+
+/** Changes the loopback state.
+ *  @param[in] device The device structure.
+ *  @param[in] state The new device state.
+ *  @returns The new state if changed.
+ *  @returns EOK otherwise.
+ */
+int	change_state_message( device_ref device, device_state_t state );
+
+/** Creates and returns the loopback network interface structure.
+ *  @param[in] device_id The new devce identifier.
+ *  @param[out] device The device structure.
+ *  @returns EOK on success.
+ *  @returns EXDEV if one loopback network interface already exists.
+ *  @returns ENOMEM if there is not enough memory left.
+ */
+int	create( device_id_t device_id, device_ref * device );
+
+/** Prints the module name.
+ *  @see NAME
+ */
+void	module_print_name( void );
+
+int netif_specific_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){
+	return ENOTSUP;
+}
+
+int netif_get_addr_message( device_id_t device_id, measured_string_ref address ){
+	if( ! address ) return EBADMEM;
+	address->value = DEFAULT_ADDR;
+	address->length = DEFAULT_ADDR_LEN;
+	return EOK;
+}
+
+int netif_get_device_stats( device_id_t device_id, device_stats_ref stats ){
+	ERROR_DECLARE;
+
+	device_ref	device;
+
+	if( ! stats ) return EBADMEM;
+	ERROR_PROPAGATE( find_device( device_id, & device ));
+	memcpy( stats, ( device_stats_ref ) device->specific, sizeof( device_stats_t ));
+	return EOK;
+}
+
+int change_state_message( device_ref device, device_state_t state ){
+	if( device->state != state ){
+		device->state = state;
+		printf( "State changed to %s\n", ( state == NETIF_ACTIVE ) ? "ACTIVE" : "STOPPED" );
+		return state;
+	}
+	return EOK;
+}
+
+int create( device_id_t device_id, device_ref * device ){
+	int	index;
+
+	if( device_map_count( & netif_globals.device_map ) > 0 ){
+		return EXDEV;
+	}else{
+		* device = ( device_ref ) malloc( sizeof( device_t ));
+		if( !( * device )) return ENOMEM;
+		( ** device ).specific = malloc( sizeof( device_stats_t ));
+		if( ! ( ** device ).specific ){
+			free( * device );
+			return ENOMEM;
+		}
+		null_device_stats(( device_stats_ref )( ** device ).specific );
+		( ** device ).device_id = device_id;
+		( ** device ).nil_phone = -1;
+		( ** device ).state = NETIF_STOPPED;
+		index = device_map_add( & netif_globals.device_map, ( ** device ).device_id, * device );
+		if( index < 0 ){
+			free( * device );
+			free(( ** device ).specific );
+			* device = NULL;
+			return index;
+		}
+	}
+	return EOK;
+}
+
+int netif_initialize( void ){
+	ipcarg_t	phonehash;
+
+	return REGISTER_ME( SERVICE_LO, & phonehash );
+}
+
+void module_print_name( void ){
+	printf( "%s", NAME );
+}
+
+int netif_probe_message( device_id_t device_id, int irq, int io ){
+	ERROR_DECLARE;
+
+	device_ref			device;
+
+	// create a new device
+	ERROR_PROPAGATE( create( device_id, & device ));
+	// print the settings
+	printf("New device created:\n\tid\t= %d\n", device->device_id );
+	return EOK;
+}
+
+int netif_send_message( device_id_t device_id, packet_t packet, services_t sender ){
+	ERROR_DECLARE;
+
+	device_ref	device;
+	size_t		length;
+	packet_t	next;
+	int			phone;
+
+	ERROR_PROPAGATE( find_device( device_id, & device ));
+	if( device->state != NETIF_ACTIVE ){
+		netif_pq_release( packet_get_id( packet ));
+		return EFORWARD;
+	}
+	next = packet;
+	do{
+		++ (( device_stats_ref ) device->specific )->send_packets;
+		++ (( device_stats_ref ) device->specific )->receive_packets;
+		length = packet_get_data_length( next );
+		(( device_stats_ref ) device->specific )->send_bytes += length;
+		(( device_stats_ref ) device->specific )->receive_bytes += length;
+		next = pq_next( next );
+	}while( next );
+	phone = device->nil_phone;
+	fibril_rwlock_write_unlock( & netif_globals.lock );
+	nil_received_msg( phone, device_id, packet, sender );
+	fibril_rwlock_write_lock( & netif_globals.lock );
+	return EOK;
+}
+
+int netif_start_message( device_ref device ){
+	return change_state_message( device, NETIF_ACTIVE );
+}
+
+int netif_stop_message( device_ref device ){
+	return change_state_message( device, NETIF_STOPPED );
+}
+
+/** @}
+ */
Index: uspace/srv/net/netif/netif.c
===================================================================
--- uspace/srv/net/netif/netif.c	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/netif/netif.c	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,284 @@
+/*
+ * 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
+ *  @{
+ */
+
+/** @file
+ *  Network interface module skeleton implementation.
+ *  @see netif.h
+ */
+
+#include <async.h>
+#include <mem.h>
+#include <fibril_synch.h>
+#include <stdio.h>
+
+#include <ipc/ipc.h>
+#include <ipc/services.h>
+
+#include "../err.h"
+#include "../messages.h"
+#include "../modules.h"
+
+#include "../structures/packet/packet.h"
+#include "../structures/packet/packet_client.h"
+#include "../structures/measured_strings.h"
+
+#include "../include/device.h"
+#include "../include/netif_interface.h"
+#include "../include/nil_interface.h"
+
+#include "netif.h"
+#include "netif_messages.h"
+#include "netif_module.h"
+
+/** Network interface module global data.
+ */
+extern netif_globals_t netif_globals;
+
+DEVICE_MAP_IMPLEMENT( device_map, device_t )
+
+/** @name Message processing functions
+ */
+/*@{*/
+
+/** Registers the device notification receiver, the network interface layer module.
+ *  @param[in] device_id The device identifier.
+ *  @param[in] phone The network interface layer module phone.
+ *  @returns EOK on success.
+ *  @returns ENOENT if there is no such device.
+ *  @returns ELIMIT if there is another module registered.
+ */
+int	register_message( device_id_t device_id, int phone );
+
+/*@}*/
+
+int	netif_probe_req( int netif_phone, device_id_t device_id, int irq, int io ){
+	int	result;
+
+	fibril_rwlock_write_lock( & netif_globals.lock );
+	result = netif_probe_message( device_id, irq, io );
+	fibril_rwlock_write_unlock( & netif_globals.lock );
+	return result;
+}
+
+int	netif_send_msg( int netif_phone, device_id_t device_id, packet_t packet, services_t sender ){
+	int	result;
+
+	fibril_rwlock_write_lock( & netif_globals.lock );
+	result = netif_send_message( device_id, packet, sender );
+	fibril_rwlock_write_unlock( & netif_globals.lock );
+	return result;
+}
+
+int	netif_start_req( int netif_phone, device_id_t device_id ){
+	ERROR_DECLARE;
+
+	device_ref	device;
+	int	result;
+	int	phone;
+
+	fibril_rwlock_write_lock( & netif_globals.lock );
+	if( ERROR_OCCURRED( find_device( device_id, & device ))){
+		fibril_rwlock_write_unlock( & netif_globals.lock );
+		return ERROR_CODE;
+	}
+	result = netif_start_message( device );
+	if( result > NETIF_NULL ){
+		phone = device->nil_phone;
+		fibril_rwlock_write_unlock( & netif_globals.lock );
+		nil_device_state_msg( phone, device_id, result );
+		return EOK;
+	}else{
+		fibril_rwlock_write_unlock( & netif_globals.lock );
+	}
+	return result;
+}
+
+int	netif_stop_req( int netif_phone, device_id_t device_id ){
+	ERROR_DECLARE;
+
+	device_ref	device;
+	int	result;
+	int	phone;
+
+	fibril_rwlock_write_lock( & netif_globals.lock );
+	if( ERROR_OCCURRED( find_device( device_id, & device ))){
+		fibril_rwlock_write_unlock( & netif_globals.lock );
+		return ERROR_CODE;
+	}
+	result = netif_stop_message( device );
+	if( result > NETIF_NULL ){
+		phone = device->nil_phone;
+		fibril_rwlock_write_unlock( & netif_globals.lock );
+		nil_device_state_msg( phone, device_id, result );
+		return EOK;
+	}else{
+		fibril_rwlock_write_unlock( & netif_globals.lock );
+	}
+	return result;
+}
+
+int	netif_stats_req( int netif_phone, device_id_t device_id, device_stats_ref stats ){
+	int res;
+
+	fibril_rwlock_read_lock( & netif_globals.lock );
+	res = netif_get_device_stats( device_id, stats );
+	fibril_rwlock_read_unlock( & netif_globals.lock );
+	return res;
+}
+
+int	netif_get_addr_req( int netif_phone, device_id_t device_id, measured_string_ref * address, char ** data ){
+	ERROR_DECLARE;
+
+	measured_string_t	translation;
+
+	if( !( address && data )) return EBADMEM;
+	fibril_rwlock_read_lock( & netif_globals.lock );
+	if( ! ERROR_OCCURRED( netif_get_addr_message( device_id, & translation ))){
+		* address = measured_string_copy( & translation );
+		ERROR_CODE = ( * address ) ? EOK : ENOMEM;
+	}
+	fibril_rwlock_read_unlock( & netif_globals.lock );
+	* data = ( ** address ).value;
+	return ERROR_CODE;
+}
+
+int netif_bind_service( services_t service, device_id_t device_id, services_t me, async_client_conn_t receiver ){
+	return EOK;
+}
+
+int find_device( device_id_t device_id, device_ref * device ){
+	if( ! device ) return EBADMEM;
+	* device = device_map_find( & netif_globals.device_map, device_id );
+	if( ! * device ) return ENOENT;
+	if(( ** device ).state == NETIF_NULL ) return EPERM;
+	return EOK;
+}
+
+void null_device_stats( device_stats_ref stats ){
+	bzero( stats, sizeof( device_stats_t ));
+}
+
+int register_message( device_id_t device_id, int phone ){
+	ERROR_DECLARE;
+
+	device_ref	device;
+
+	ERROR_PROPAGATE( find_device( device_id, & device ));
+	if( device->nil_phone > 0 ) return ELIMIT;
+	device->nil_phone = phone;
+	printf( "New receiver of the device %d registered:\n\tphone\t= %d\n", device->device_id, device->nil_phone );
+	return EOK;
+}
+
+int netif_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){
+	ERROR_DECLARE;
+
+	size_t				length;
+	device_stats_t		stats;
+	packet_t			packet;
+	measured_string_t	address;
+
+//	printf( "message %d - %d\n", IPC_GET_METHOD( * call ), NET_NETIF_FIRST );
+	* answer_count = 0;
+	switch( IPC_GET_METHOD( * call )){
+		case IPC_M_PHONE_HUNGUP:
+			return EOK;
+		case NET_NETIF_PROBE:
+			return netif_probe_req( 0, IPC_GET_DEVICE( call ), NETIF_GET_IRQ( call ), NETIF_GET_IO( call ));
+		case IPC_M_CONNECT_TO_ME:
+			fibril_rwlock_write_lock( & netif_globals.lock );
+			ERROR_CODE = register_message( IPC_GET_DEVICE( call ), IPC_GET_PHONE( call ));
+			fibril_rwlock_write_unlock( & netif_globals.lock );
+			return ERROR_CODE;
+		case NET_NETIF_SEND:
+			ERROR_PROPAGATE( packet_translate( netif_globals.net_phone, & packet, IPC_GET_PACKET( call )));
+			return netif_send_msg( 0, IPC_GET_DEVICE( call ), packet, IPC_GET_SENDER( call ));
+		case NET_NETIF_START:
+			return netif_start_req( 0, IPC_GET_DEVICE( call ));
+		case NET_NETIF_STATS:
+			fibril_rwlock_read_lock( & netif_globals.lock );
+			if( ! ERROR_OCCURRED( async_data_read_receive( & callid, & length ))){
+				if( length < sizeof( device_stats_t )){
+					ERROR_CODE = EOVERFLOW;
+				}else{
+					if( ! ERROR_OCCURRED( netif_get_device_stats( IPC_GET_DEVICE( call ), & stats ))){
+						ERROR_CODE = async_data_read_finalize( callid, & stats, sizeof( device_stats_t ));
+					}
+				}
+			}
+			fibril_rwlock_read_unlock( & netif_globals.lock );
+			return ERROR_CODE;
+		case NET_NETIF_STOP:
+			return netif_stop_req( 0, IPC_GET_DEVICE( call ));
+		case NET_NETIF_GET_ADDR:
+			fibril_rwlock_read_lock( & netif_globals.lock );
+			if( ! ERROR_OCCURRED( netif_get_addr_message( IPC_GET_DEVICE( call ), & address ))){
+				ERROR_CODE = measured_strings_reply( & address, 1 );
+			}
+			fibril_rwlock_read_unlock( & netif_globals.lock );
+			return ERROR_CODE;
+	}
+	return netif_specific_message( callid, call, answer, answer_count );
+}
+
+int netif_init_module( async_client_conn_t client_connection ){
+	ERROR_DECLARE;
+
+	async_set_client_connection( client_connection );
+	netif_globals.net_phone = connect_to_service( SERVICE_NETWORKING );
+	device_map_initialize( & netif_globals.device_map );
+	ERROR_PROPAGATE( pm_init());
+	fibril_rwlock_initialize( & netif_globals.lock );
+	if( ERROR_OCCURRED( netif_initialize())){
+		pm_destroy();
+		return ERROR_CODE;
+	}
+	return EOK;
+}
+
+int netif_run_module( void ){
+	async_manager();
+
+	pm_destroy();
+	return EOK;
+}
+
+void netif_pq_release( packet_id_t packet_id ){
+	pq_release( netif_globals.net_phone, packet_id );
+}
+
+packet_t netif_packet_get_1( size_t content ){
+	return packet_get_1( netif_globals.net_phone, content );
+}
+
+/** @}
+ */
Index: uspace/srv/net/netif/netif.h
===================================================================
--- uspace/srv/net/netif/netif.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/netif/netif.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,161 @@
+/*
+ * 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
+ *  @{
+ */
+
+/** @file
+ *  Network interface module skeleton.
+ *  The skeleton has to be part of each network interface module.
+ *  The skeleton can be also part of the module bundled with the network interface layer.
+ */
+
+#ifndef __NET_NETIF_H__
+#define __NET_NETIF_H__
+
+#include <async.h>
+#include <fibril_synch.h>
+
+#include <ipc/ipc.h>
+
+#include "../err.h"
+
+#include "../include/device.h"
+
+#include "../structures/packet/packet.h"
+
+/** Network interface module skeleton global data.
+ */
+typedef struct netif_globals	netif_globals_t;
+
+/** Type definition of the device specific data.
+ *  @see netif_device
+ */
+typedef struct netif_device	device_t;
+
+/** Type definition of the device specific data pointer.
+ *  @see netif_device
+ */
+typedef device_t *			device_ref;
+
+/** Device map.
+ *  Maps device identifiers to the network interface device specific data.
+ *  @see device.h
+ */
+DEVICE_MAP_DECLARE( device_map, device_t );
+
+/** Network interface device specific data.
+ */
+struct	netif_device{
+	/** Device identifier.
+	 */
+	device_id_t	device_id;
+	/** Receiving network interface layer phone.
+	 */
+	int		nil_phone;
+	/** Actual device state.
+	 */
+	device_state_t	state;
+	/** Driver specific data.
+	 */
+	void *		specific;
+};
+
+/** Network interface module skeleton global data.
+ */
+struct	netif_globals{
+	/** Networking module phone.
+	 */
+	int		net_phone;
+	/**	Device map.
+	 */
+	device_map_t	device_map;
+	/** Safety lock.
+	 */
+	fibril_rwlock_t	lock;
+};
+
+/**	Finds the device specific data.
+ *  @param[in] device_id The device identifier.
+ *  @param[out] device The device specific data.
+ *  @returns EOK on success.
+ *  @returns ENOENT if device is not found.
+ *  @returns EPERM if the device is not initialized.
+ */
+int	find_device( device_id_t device_id, device_ref * device );
+
+/** Clears the usage statistics.
+ *  @param[in] stats The usage statistics.
+ */
+void	null_device_stats( device_stats_ref stats );
+
+// prepared for future optimalizations
+/** Releases the given packet.
+ *  @param[in] packet_id The packet identifier.
+ */
+void	netif_pq_release( packet_id_t packet_id );
+
+/** Allocates new packet to handle the given content size.
+ *  @param[in] content The minimum content size.
+ *  @returns The allocated packet.
+ *  @returns NULL if there is an error.
+ */
+packet_t netif_packet_get_1( size_t content );
+
+/** Processes the netif module messages.
+ *  @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.
+ *  @returns EOK on success.
+ *  @returns ENOTSUP if the message is not known.
+ *  @returns Other error codes as defined for each specific module message function.
+ *  @see netif_interface.h
+ *  @see IS_NET_NETIF_MESSAGE()
+ */
+int	netif_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count );
+
+/** Initializes the netif module.
+ *  The function has to be defined in each module.
+ *  @param[in] client_connection The client connection functio to be registered.
+ *  @returns EOK on success.
+ *  @returns Other error codes as defined for each specific module message function.
+ */
+int	netif_init_module( async_client_conn_t client_connection );
+
+/** Starts and maintains the netif module until terminated.
+ *  @returns EOK after the module is terminated.
+ */
+int netif_run_module( void );
+
+#endif
+
+/** @}
+ */
+
Index: uspace/srv/net/netif/netif_messages.h
===================================================================
--- uspace/srv/net/netif/netif_messages.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/netif/netif_messages.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,93 @@
+/*
+ * 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
+ *  @{
+ */
+
+/** @file
+ *  Network interface common module messages.
+ *  @see netif_interface.h
+ */
+
+#ifndef __NET_NETIF_MESSAGES_H__
+#define __NET_NETIF_MESSAGES_H__
+
+#include <ipc/ipc.h>
+
+#include "../messages.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
+ */
+/*@{*/
+
+/** Returns the interrupt number message parameter.
+ *  @param[in] call The message call structure.
+ */
+#define NETIF_GET_IRQ( call )		( int )	IPC_GET_ARG2( * call )
+
+/** Returns the input/output address message parameter.
+ *  @param[in] call The message call structure.
+ */
+#define NETIF_GET_IO( call )		( int )	IPC_GET_ARG3( * call )
+
+/*@}*/
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/netif/netif_module.h
===================================================================
--- uspace/srv/net/netif/netif_module.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/netif/netif_module.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,126 @@
+/*
+ * 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
+ *  @{
+ */
+
+/** @file
+ *  Network interface module interface.
+ *  The interface has to be implemented by each network interface module.
+ *  The interface is used by the network interface module skeleton.
+ */
+
+#ifndef __NET_NETIF_MODULE_H__
+#define __NET_NETIF_MODULE_H__
+
+#include <ipc/ipc.h>
+#include <ipc/services.h>
+
+#include "../structures/measured_strings.h"
+#include "../structures/packet/packet.h"
+
+#include "../include/device.h"
+
+/** Initializes the specific module.
+ */
+int	netif_initialize( void );
+
+/** Probes the existence of the device.
+ *  @param[in] device_id The device identifier.
+ *  @param[in] irq The device interrupt number.
+ *  @param[in] io The device input/output address.
+ *  @returns EOK on success.
+ *  @returns Other error codes as defined for the find_device() function.
+ *  @returns Other error codes as defined for the specific module message implementation.
+ */
+int	netif_probe_message( device_id_t device_id, int irq, int io );
+
+/** Sends the packet queue.
+ *  @param[in] device_id The device identifier.
+ *  @param[in] packet The packet queue.
+ *  @param[in] sender The sending module service.
+ *  @returns EOK on success.
+ *  @returns EFORWARD if the device is not active (in the NETIF_ACTIVE state).
+ *  @returns Other error codes as defined for the find_device() function.
+ *  @returns Other error codes as defined for the specific module message implementation.
+ */
+int	netif_send_message( device_id_t device_id, packet_t packet, services_t sender );
+
+/** Starts the device.
+ *  @param[in] device The device structure.
+ *  @returns EOK on success.
+ *  @returns Other error codes as defined for the find_device() function.
+ *  @returns Other error codes as defined for the specific module message implementation.
+ */
+int	netif_start_message( device_ref device );
+
+/** Stops the device.
+ *  @param[in] device The device structure.
+ *  @returns EOK on success.
+ *  @returns Other error codes as defined for the find_device() function.
+ *  @returns Other error codes as defined for the specific module message implementation.
+ */
+int	netif_stop_message( device_ref device );
+
+/** Returns the device local hardware address.
+ *  @param[in] device_id The device identifier.
+ *  @param[out] address The device local hardware address.
+ *  @returns EOK on success.
+ *  @returns EBADMEM if the address parameter is NULL.
+ *  @returns ENOENT if there no such device.
+ *  @returns Other error codes as defined for the find_device() function.
+ *  @returns Other error codes as defined for the specific module message implementation.
+ */
+int	netif_get_addr_message( device_id_t device_id, measured_string_ref address );
+
+/** Processes the netif driver specific message.
+ *  This function is called for uncommon messages received by the netif skeleton.
+ *  @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.
+ *  @returns EOK on success.
+ *  @returns ENOTSUP if the message is not known.
+ *  @returns Other error codes as defined for the specific module message implementation.
+ */
+int	netif_specific_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count );
+
+/** Returns the device usage statistics.
+ *  @param[in] device_id The device identifier.
+ *  @param[out] stats The device usage statistics.
+ *  @returns EOK on success.
+ *  @returns Other error codes as defined for the find_device() function.
+ *  @returns Other error codes as defined for the specific module message implementation.
+ */
+int	netif_get_device_stats( device_id_t device_id, device_stats_ref stats );
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/netif/netif_nil_bundle.c
===================================================================
--- uspace/srv/net/netif/netif_nil_bundle.c	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/netif/netif_nil_bundle.c	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,93 @@
+/*
+ * 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
+ *  @{
+ */
+
+/** @file
+ *  Wrapper for the bundled network interface and network interface layer module.
+ *  Distributes messages and initializes both module parts.
+ */
+
+#include <async.h>
+
+#include <ipc/ipc.h>
+
+#include "../messages.h"
+
+#include "../structures/packet/packet.h"
+
+#include "../nil/nil_module.h"
+
+#include "netif.h"
+
+/** Network interface module global data.
+ */
+extern netif_globals_t netif_globals;
+
+/** Distributes the messages between the module parts.
+ *  @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.
+ *  @returns EOK on success.
+ *  @returns ENOTSUP if the message is not known.
+ *  @returns Other error codes as defined for each specific module message function.
+ */
+int	module_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count );
+
+/** Starts the bundle network interface module.
+ *  Initializes the client connection serving function, initializes both module parts, registers the module service and starts the async manager, processing IPC messages in an infinite loop.
+ *  @param[in] client_connection The client connection processing function. The module skeleton propagates its own one.
+ *  @returns EOK on success.
+ *  @returns Other error codes as defined for each specific module message function.
+ */
+int	module_start( async_client_conn_t client_connection );
+
+int	module_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){
+	if( IS_NET_NIL_MESSAGE( call ) || ( IPC_GET_METHOD( * call ) == IPC_M_CONNECT_TO_ME )){
+		return nil_message( callid, call, answer, answer_count );
+	}else{
+		return netif_message( callid, call, answer, answer_count );
+	}
+}
+
+int	module_start( async_client_conn_t client_connection ){
+	ERROR_DECLARE;
+
+	ERROR_PROPAGATE( netif_init_module( client_connection ));
+	if( ERROR_OCCURRED( nil_initialize( netif_globals.net_phone ))){
+		pm_destroy();
+		return ERROR_CODE;
+	}
+	return netif_run_module();
+}
+
+/** @}
+ */
Index: uspace/srv/net/netif/netif_remote.c
===================================================================
--- uspace/srv/net/netif/netif_remote.c	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/netif/netif_remote.c	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,87 @@
+/*
+ * 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
+ *  @{
+ */
+
+/** @file
+ *  Network interface module interface implementation for standalone remote modules.
+ *  @see netif_interface.h
+ */
+
+#include <ipc/services.h>
+
+#include "../modules.h"
+
+#include "../structures/measured_strings.h"
+#include "../structures/packet/packet.h"
+#include "../structures/packet/packet_client.h"
+
+#include "../include/device.h"
+#include "../include/netif_interface.h"
+
+#include "netif_messages.h"
+
+int	netif_get_addr_req( int netif_phone, device_id_t device_id, measured_string_ref * address, char ** data ){
+	return generic_get_addr_req( netif_phone, NET_NETIF_GET_ADDR, device_id, address, data );
+}
+
+int	netif_probe_req( int netif_phone, device_id_t device_id, int irq, int io ){
+	return async_req_3_0( netif_phone, NET_NETIF_PROBE, device_id, irq, io );
+}
+
+int	netif_send_msg( int netif_phone, device_id_t device_id, packet_t packet, services_t sender ){
+	return generic_send_msg( netif_phone, NET_NETIF_SEND, device_id, packet_get_id( packet ), sender, 0 );
+}
+
+int	netif_start_req( int netif_phone, device_id_t device_id ){
+	return async_req_1_0( netif_phone, NET_NETIF_START, device_id );
+}
+
+int	netif_stop_req( int netif_phone, device_id_t device_id ){
+	return async_req_1_0( netif_phone, NET_NETIF_STOP, device_id );
+}
+
+int	netif_stats_req( int netif_phone, device_id_t device_id, device_stats_ref stats ){
+	aid_t		message_id;
+	ipcarg_t	result;
+
+	if( ! stats ) return EBADMEM;
+	message_id = async_send_1( netif_phone, NET_NETIF_STATS, ( ipcarg_t ) device_id, NULL );
+	async_data_read_start( netif_phone, stats, sizeof( * stats ));
+	async_wait_for( message_id, & result );
+	return ( int ) result;
+}
+
+int netif_bind_service( services_t service, device_id_t device_id, services_t me, async_client_conn_t receiver ){
+	return bind_service( service, device_id, me, 0, receiver );
+}
+
+/** @}
+ */
Index: uspace/srv/net/netif/netif_standalone.c
===================================================================
--- uspace/srv/net/netif/netif_standalone.c	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/netif/netif_standalone.c	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,74 @@
+/*
+ * 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
+ *  @{
+ */
+
+/** @file
+ *  Wrapper for the standalone network interface module.
+ */
+
+#include <async.h>
+
+#include <ipc/ipc.h>
+
+#include "netif.h"
+
+/** Delegates the messages to the netif_message() function.
+ *  @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.
+ *  @returns EOK on success.
+ *  @returns ENOTSUP if the message is not known.
+ *  @returns Other error codes as defined for each specific module message function.
+ */
+int	module_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count );
+
+/** Starts the network interface module.
+ *  Initializes the client connection serving function, initializes the module, registers the module service and starts the async manager, processing IPC messages in an infinite loop.
+ *  @param[in] client_connection The client connection processing function. The module skeleton propagates its own one.
+ *  @returns EOK on success.
+ *  @returns Other error codes as defined for each specific module message function.
+ */
+int	module_start( async_client_conn_t client_connection );
+
+int	module_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){
+	return netif_message( callid, call, answer, answer_count );
+}
+
+int	module_start( async_client_conn_t client_connection ){
+	ERROR_DECLARE;
+
+	ERROR_PROPAGATE( netif_init_module( client_connection ));
+	return netif_run_module();
+}
+
+/** @}
+ */
Index: uspace/srv/net/nil/eth/Makefile
===================================================================
--- uspace/srv/net/nil/eth/Makefile	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/nil/eth/Makefile	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,48 @@
+#
+# 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.
+#
+
+NAME = eth
+
+NET_BASE = ../../
+STRUCTURES = $(NET_BASE)structures/
+
+OUTPUT = $(NAME)
+SOURCES = \
+	$(NAME).c \
+	$(NAME)_module.c \
+	$(NET_BASE)checksum.c \
+	$(NET_BASE)module.c \
+	$(NET_BASE)modules.c \
+	$(NET_BASE)net/net_remote.c \
+	$(NET_BASE)netif/netif_remote.c \
+	$(STRUCTURES)measured_strings.c \
+	$(STRUCTURES)packet/packet.c \
+	$(STRUCTURES)packet/packet_client.c \
+	$(STRUCTURES)packet/packet_remote.c
+
+include $(NET_BASE)Makefile.module
Index: uspace/srv/net/nil/eth/eth.c
===================================================================
--- uspace/srv/net/nil/eth/eth.c	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/nil/eth/eth.c	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,728 @@
+/*
+ * 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 eth
+ *  @{
+ */
+
+/** @file
+ *  Ethernet module implementation.
+ *  @see eth.h
+ */
+
+#include <async.h>
+#include <malloc.h>
+#include <mem.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <ipc/ipc.h>
+#include <ipc/services.h>
+
+#include "../../err.h"
+#include "../../messages.h"
+#include "../../modules.h"
+
+#include "../../include/byteorder.h"
+#include "../../include/checksum.h"
+#include "../../include/ethernet_lsap.h"
+#include "../../include/ethernet_protocols.h"
+#include "../../include/protocol_map.h"
+#include "../../include/device.h"
+#include "../../include/netif_interface.h"
+#include "../../include/net_interface.h"
+#include "../../include/nil_interface.h"
+#include "../../include/il_interface.h"
+
+#include "../../structures/measured_strings.h"
+#include "../../structures/packet/packet_client.h"
+
+#include "../nil_module.h"
+
+#include "eth.h"
+#include "eth_header.h"
+
+/** 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 )
+
+/** Returns whether the DIX Ethernet mode flag is set.
+ *  @param[in] flags The 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 )
+
+/** Returns whether the 802.3 + 802.2 + LSAP mode flag is set.
+ *  @param[in] flags The 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 )
+
+/** Returns whether the 802.3 + 802.2 + LSAP + SNAP mode flag is set.
+ *  @param[in] flags The 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;
+
+/** Type definition of the ethernet address type pointer.
+ *  @see eth_addr_type
+ */
+typedef eth_addr_type_t *	eth_addr_type_ref;
+
+/** 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;
+
+/** @name Message processing functions
+ */
+/*@{*/
+
+/** Processes IPC messages from the registered device driver modules in an infinite loop.
+ *  @param[in] iid The message identifier.
+ *  @param[in,out] icall The message parameters.
+ */
+void	eth_receiver( ipc_callid_t iid, ipc_call_t * icall );
+
+/** Registers new device or updates the MTU of an existing one.
+ *  Determines the device local hardware address.
+ *  @param[in] device_id The new device identifier.
+ *  @param[in] service The device driver service.
+ *  @param[in] mtu The device maximum transmission unit.
+ *  @returns EOK on success.
+ *  @returns EEXIST if the device with the different service exists.
+ *  @returns ENOMEM if there is not enough memory left.
+ *  @returns Other error codes as defined for the net_get_device_conf_req() function.
+ *  @returns Other error codes as defined for the netif_bind_service() function.
+ *  @returns Other error codes as defined for the netif_get_addr_req() function.
+ */
+int	eth_device_message( device_id_t device_id, services_t service, size_t mtu );
+
+/** Registers receiving module service.
+ *  Passes received packets for this service.
+ *  @param[in] service The module service.
+ *  @param[in] phone The service phone.
+ *  @returns EOK on success.
+ *  @returns ENOENT if the service is not known.
+ *  @returns ENOMEM if there is not enough memory left.
+ */
+int	eth_register_message( services_t service, int phone );
+
+/** 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.
+ *  @returns EOK on success.
+ *  @returns EBADMEM if either one of the parameters is NULL.
+ *  @returns ENOENT if there is no such device.
+ */
+int	eth_packet_space_message( device_id_t device_id, size_t * addr_len, size_t * prefix, size_t * content, size_t * suffix );
+
+/** Returns the device hardware address.
+ *  @param[in] device_id The device identifier.
+ *  @param[in] type Type of the desired address.
+ *  @param[out] address The device hardware address.
+ *  @returns EOK on success.
+ *  @returns EBADMEM if the address parameter is NULL.
+ *  @returns ENOENT if there no such device.
+ */
+int	eth_addr_message( device_id_t device_id, eth_addr_type_t type, measured_string_ref * address );
+
+/** 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.
+ *  @returns EOK on success.
+ *  @returns ENOENT if there no such device.
+ *  @returns EINVAL if the service parameter is not known.
+ */
+int	eth_send_message( device_id_t device_id, packet_t packet, services_t sender );
+
+/*@}*/
+
+/** Processes the received packet and chooses the target registered module.
+ *  @param[in] flags The device flags.
+ *  @param[in] packet The packet.
+ *  @returns The target registered module.
+ *  @returns NULL if the packet is not long enough.
+ *  @returns NULL if the packet is too long.
+ *  @returns NULL if the raw ethernet protocol is used.
+ *  @returns NULL if the dummy device FCS checksum is invalid.
+ *  @returns NULL if the packet address length is not big enough.
+ */
+eth_proto_ref	eth_process_packet( int flags, packet_t packet );
+
+/** 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.
+ *  @returns EOK on success.
+ *  @returns EINVAL if the packet addresses length is not long enough.
+ *  @returns EINVAL if the packet is bigger than the device MTU.
+ *  @returns ENOMEM if there is not enough memory in the packet.
+ */
+int	eth_prepare_packet( int flags, packet_t packet, uint8_t * src_addr, int ethertype, size_t mtu );
+
+DEVICE_MAP_IMPLEMENT( eth_devices, eth_device_t )
+
+INT_MAP_IMPLEMENT( eth_protos, eth_proto_t )
+
+int	nil_device_state_msg( int nil_phone, device_id_t device_id, int state ){
+	int				index;
+	eth_proto_ref	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->phone ) il_device_state_msg( proto->phone, device_id, state, proto->service );
+	}
+	fibril_rwlock_read_unlock( & eth_globals.protos_lock );
+	return EOK;
+}
+
+int nil_initialize( int net_phone ){
+	ERROR_DECLARE;
+
+	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_phone = net_phone;
+	eth_globals.broadcast_addr = measured_string_create_bulk( "\xFF\xFF\xFF\xFF\xFF\xFF", CONVERT_SIZE( uint8_t, char, ETH_ADDR ));
+	if( ! eth_globals.broadcast_addr ) return ENOMEM;
+	ERROR_PROPAGATE( eth_devices_initialize( & eth_globals.devices ));
+	if( ERROR_OCCURRED( eth_protos_initialize( & eth_globals.protos ))){
+		eth_devices_destroy( & eth_globals.devices );
+		return ERROR_CODE;
+	}
+	fibril_rwlock_write_unlock( & eth_globals.protos_lock );
+	fibril_rwlock_write_unlock( & eth_globals.devices_lock );
+	return EOK;
+}
+
+int eth_device_message( device_id_t device_id, services_t service, size_t mtu ){
+	ERROR_DECLARE;
+
+	eth_device_ref	device;
+	int				index;
+	measured_string_t	names[ 2 ] = {{ "ETH_MODE", 8 }, { "ETH_DUMMY", 9 }};
+	measured_string_ref	configuration;
+	size_t				count = sizeof( names ) / sizeof( measured_string_t );
+	char *				data;
+	eth_proto_ref		proto;
+
+	fibril_rwlock_write_lock( & eth_globals.devices_lock );
+	// an existing device?
+	device = eth_devices_find( & eth_globals.devices, device_id );
+	if( device ){
+		if( device->service != service ){
+			printf( "Device %d already exists\n", device->device_id );
+			fibril_rwlock_write_unlock( & eth_globals.devices_lock );
+			return EEXIST;
+		}else{
+			// 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= %d\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->phone ){
+					il_mtu_changed_msg( proto->phone, device->device_id, device->mtu, proto->service );
+				}
+			}
+			fibril_rwlock_read_unlock( & eth_globals.protos_lock );
+			return EOK;
+		}
+	}else{
+		// create a new device
+		device = ( eth_device_ref ) malloc( sizeof( eth_device_t ));
+		if( ! device ) return ENOMEM;
+		device->device_id = device_id;
+		device->service = service;
+		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 ];
+		if( ERROR_OCCURRED( net_get_device_conf_req( eth_globals.net_phone, device->device_id, & configuration, count, & data ))){
+			fibril_rwlock_write_unlock( & eth_globals.devices_lock );
+			free( device );
+			return ERROR_CODE;
+		}
+		if( configuration ){
+			if( ! str_lcmp( configuration[ 0 ].value, "DIX", configuration[ 0 ].length )){
+				device->flags |= ETH_DIX;
+			}else if( ! str_lcmp( 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->phone = netif_bind_service( device->service, device->device_id, SERVICE_ETHERNET, eth_receiver );
+		if( device->phone < 0 ){
+			fibril_rwlock_write_unlock( & eth_globals.devices_lock );
+			free( device );
+			return device->phone;
+		}
+		// get hardware address
+		if( ERROR_OCCURRED( netif_get_addr_req( device->phone, device->device_id, & device->addr, & device->addr_data ))){
+			fibril_rwlock_write_unlock( & eth_globals.devices_lock );
+			free( device );
+			return ERROR_CODE;
+		}
+		// 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->addr );
+			free( device->addr_data );
+			free( device );
+			return index;
+		}
+		printf( "New device registered:\n\tid\t= %d\n\tservice\t= %d\n\tMTU\t= %d\n\taddress\t= %X:%X:%X:%X:%X:%X\n\tflags\t= 0x%x\n", device->device_id, device->service, device->mtu, device->addr_data[ 0 ], device->addr_data[ 1 ], device->addr_data[ 2 ], device->addr_data[ 3 ], device->addr_data[ 4 ], device->addr_data[ 5 ], device->flags );
+	}
+	fibril_rwlock_write_unlock( & eth_globals.devices_lock );
+	return EOK;
+}
+
+eth_proto_ref eth_process_packet( int flags, packet_t packet ){
+	ERROR_DECLARE;
+
+	eth_header_snap_ref	header;
+	size_t				length;
+	eth_type_t			type;
+	size_t				prefix;
+	size_t				suffix;
+	eth_fcs_ref			fcs;
+	uint8_t *			data;
+
+	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_ref ) data;
+	type = ntohs( header->header.ethertype );
+	if( type >= ETH_MIN_PROTO ){
+		// DIX Ethernet
+		prefix = sizeof( eth_header_t );
+		suffix = 0;
+		fcs = ( eth_fcs_ref ) 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_ref ) data + prefix + type + suffix;
+		suffix += length - prefix - type;
+		length = prefix + type + suffix;
+	}else{
+		// invalid length/type, should not occurr
+		return NULL;
+	}
+	if( IS_DUMMY( flags )){
+		if(( ~ compute_crc32( ~ 0u, data, length * 8 )) != ntohl( * fcs )){
+			return NULL;
+		}
+		suffix += sizeof( eth_fcs_t );
+	}
+	if( ERROR_OCCURRED( packet_set_addr( packet, header->header.source_address, header->header.destination_address, ETH_ADDR ))
+	|| ERROR_OCCURRED( packet_trim( packet, prefix, suffix ))){
+		return NULL;
+	}
+	return eth_protos_find( & eth_globals.protos, type );
+}
+
+int nil_received_msg( int nil_phone, device_id_t device_id, packet_t packet, services_t target ){
+	eth_proto_ref	proto;
+	packet_t		next;
+	eth_device_ref	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->phone, device_id, packet, proto->service );
+		}else{
+			// drop invalid/unknown
+			pq_release( eth_globals.net_phone, packet_get_id( packet ));
+		}
+		packet = next;
+	}while( packet );
+	fibril_rwlock_read_unlock( & eth_globals.protos_lock );
+	return EOK;
+}
+
+int eth_packet_space_message( device_id_t device_id, size_t * addr_len, size_t * prefix, size_t * content, size_t * suffix ){
+	eth_device_ref	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;
+}
+
+int eth_addr_message( device_id_t device_id, eth_addr_type_t type, measured_string_ref * address ){
+	eth_device_ref	device;
+
+	if( ! address ) return EBADMEM;
+	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 = device->addr;
+		fibril_rwlock_read_unlock( & eth_globals.devices_lock );
+	}
+	return ( * address ) ? EOK : ENOENT;
+}
+
+int eth_register_message( services_t service, int phone ){
+	eth_proto_ref	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->phone = phone;
+		fibril_rwlock_write_unlock( & eth_globals.protos_lock );
+		return EOK;
+	}else{
+		proto = ( eth_proto_ref ) malloc( sizeof( eth_proto_t ));
+		if( ! proto ){
+			fibril_rwlock_write_unlock( & eth_globals.protos_lock );
+			return ENOMEM;
+		}
+		proto->service = service;
+		proto->protocol = protocol;
+		proto->phone = phone;
+		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( "New protocol registered:\n\tprotocol\t= 0x%x\n\tservice\t= %d\n\tphone\t= %d\n", proto->protocol, proto->service, proto->phone );
+	fibril_rwlock_write_unlock( & eth_globals.protos_lock );
+	return EOK;
+}
+
+int eth_prepare_packet( int flags, packet_t packet, uint8_t * src_addr, int ethertype, size_t mtu ){
+	eth_header_snap_ref	header;
+	eth_header_lsap_ref	header_lsap;
+	eth_header_ref		header_dix;
+	eth_fcs_ref			fcs;
+	uint8_t *			src;
+	uint8_t *			dest;
+	size_t				length;
+	int					i;
+	void *				padding;
+	eth_preamble_ref	preamble;
+
+	i = packet_get_addr( packet, & src, & dest );
+	if( i < 0 ) return i;
+	if( i != ETH_ADDR ) return EINVAL;
+	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;
+}
+
+int eth_send_message( device_id_t device_id, packet_t packet, services_t sender ){
+	ERROR_DECLARE;
+
+	eth_device_ref		device;
+	packet_t			next;
+	packet_t			tmp;
+	int					ethertype;
+
+	ethertype = htons( protocol_map( SERVICE_ETHERNET, sender ));
+	if( ! ethertype ){
+		pq_release( eth_globals.net_phone, 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{
+		if( ERROR_OCCURRED( eth_prepare_packet( device->flags, next, ( uint8_t * ) device->addr->value, ethertype, device->mtu ))){
+			// release invalid packet
+			tmp = pq_detach( next );
+			if( next == packet ) packet = tmp;
+			pq_release( eth_globals.net_phone, packet_get_id( next ));
+			next = tmp;
+		}else{
+			next = pq_next( next );
+		}
+	}while( next );
+	// send packet queue
+	if( packet ){
+		netif_send_msg( device->phone, device_id, packet, SERVICE_ETHERNET );
+	}
+	fibril_rwlock_read_unlock( & eth_globals.devices_lock );
+	return EOK;
+}
+
+int nil_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){
+	ERROR_DECLARE;
+
+	measured_string_ref	address;
+	packet_t			packet;
+
+//	printf( "message %d - %d\n", IPC_GET_METHOD( * call ), NET_NIL_FIRST );
+	* answer_count = 0;
+	switch( IPC_GET_METHOD( * call )){
+		case IPC_M_PHONE_HUNGUP:
+			return EOK;
+		case NET_NIL_DEVICE:
+			return eth_device_message( IPC_GET_DEVICE( call ), IPC_GET_SERVICE( call ), IPC_GET_MTU( call ));
+		case NET_NIL_SEND:
+			ERROR_PROPAGATE( packet_translate( eth_globals.net_phone, & packet, IPC_GET_PACKET( call )));
+			return eth_send_message( IPC_GET_DEVICE( call ), packet, IPC_GET_SERVICE( call ));
+		case NET_NIL_PACKET_SPACE:
+			ERROR_PROPAGATE( eth_packet_space_message( IPC_GET_DEVICE( call ), IPC_SET_ADDR( answer ), IPC_SET_PREFIX( answer ), IPC_SET_CONTENT( answer ), IPC_SET_SUFFIX( answer )));
+			* answer_count = 4;
+			return EOK;
+		case NET_NIL_ADDR:
+			ERROR_PROPAGATE( eth_addr_message( IPC_GET_DEVICE( call ), ETH_LOCAL_ADDR, & address ));
+			return measured_strings_reply( address, 1 );
+		case NET_NIL_BROADCAST_ADDR:
+			ERROR_PROPAGATE( eth_addr_message( IPC_GET_DEVICE( call ), ETH_BROADCAST_ADDR, & address ));
+			return measured_strings_reply( address, 1 );
+		case IPC_M_CONNECT_TO_ME:
+			return eth_register_message( NIL_GET_PROTO( call ), IPC_GET_PHONE( call ));
+	}
+	return ENOTSUP;
+}
+
+void eth_receiver( ipc_callid_t iid, ipc_call_t * icall ){
+	ERROR_DECLARE;
+
+	packet_t		packet;
+
+	while( true ){
+//		printf( "message %d - %d\n", IPC_GET_METHOD( * icall ), NET_NIL_FIRST );
+		switch( IPC_GET_METHOD( * icall )){
+			case NET_NIL_DEVICE_STATE:
+				nil_device_state_msg( 0, IPC_GET_DEVICE( icall ), IPC_GET_STATE( icall ));
+				ipc_answer_0( iid, EOK );
+				break;
+			case NET_NIL_RECEIVED:
+				if( ! ERROR_OCCURRED( packet_translate( eth_globals.net_phone, & packet, IPC_GET_PACKET( icall )))){
+					ERROR_CODE = nil_received_msg( 0, IPC_GET_DEVICE( icall ), packet, 0 );
+				}
+				ipc_answer_0( iid, ( ipcarg_t ) ERROR_CODE );
+				break;
+			default:
+				ipc_answer_0( iid, ( ipcarg_t ) ENOTSUP );
+		}
+		iid = async_get_call( icall );
+	}
+}
+
+/** @}
+ */
Index: uspace/srv/net/nil/eth/eth.h
===================================================================
--- uspace/srv/net/nil/eth/eth.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/nil/eth/eth.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,152 @@
+/*
+ * 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 eth
+ *  @{
+ */
+
+/** @file
+ *  Ethernet module.
+ */
+
+#ifndef __NET_ETH_H__
+#define __NET_ETH_H__
+
+#include <fibril_synch.h>
+#include <ipc/services.h>
+
+#include "../../include/device.h"
+#include "../../structures/measured_strings.h"
+
+/** 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 device specific data pointer.
+ *  @see eth_device
+ */
+typedef eth_device_t *		eth_device_ref;
+
+/** Type definition of the Ethernet protocol specific data.
+ *  @see eth_proto
+ */
+typedef struct eth_proto	eth_proto_t;
+
+/** Type definition of the Ethernet protocol specific data pointer.
+ *  @see eth_proto
+ */
+typedef eth_proto_t *		eth_proto_ref;
+
+/** 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.
+	 */
+	device_id_t			device_id;
+	/** Device driver service.
+	 */
+	services_t			service;
+	/** Driver phone.
+	 */
+	int					phone;
+	/** Maximal transmission unit.
+	 */
+	size_t				mtu;
+	/** Various device flags.
+	 *  @see ETH_DUMMY
+	 *  @see ETH_MODE_MASK
+	 */
+	int					flags;
+	/** Actual device hardware address.
+	 */
+	measured_string_ref	addr;
+	/** Actual device hardware address data.
+	 */
+	char *				addr_data;
+};
+
+/** Ethernet protocol specific data.
+ */
+struct eth_proto{
+	/** Protocol service.
+	 */
+	services_t	service;
+	/** Protocol identifier.
+	 */
+	int			protocol;
+	/** Protocol module phone.
+	 */
+	int			phone;
+};
+
+/** Ethernet global data.
+ */
+struct	eth_globals{
+	/** Networking module phone.
+	 */
+	int				net_phone;
+	/** 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 phone map for each protocol.
+	 */
+	eth_protos_t	protos;
+	/** Broadcast device hardware address.
+	 */
+	measured_string_ref	broadcast_addr;
+};
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/nil/eth/eth_header.h
===================================================================
--- uspace/srv/net/nil/eth/eth_header.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/nil/eth/eth_header.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,217 @@
+/*
+ * 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 eth
+ *  @{
+ */
+
+/** @file
+ *  Ethernet protocol header definitions.
+ *  Based on the IEEE~802.3-2005
+ */
+
+#ifndef __NET_ETH_HEADER_H__
+#define __NET_ETH_HEADER_H__
+
+#include <sys/types.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 pointer.
+ *  @see eth_header_snap
+ */
+typedef eth_header_snap_t *		eth_header_snap_ref;
+
+/** 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 IEEE 802.3 + 802.2 extension pointer.
+ *  @see eth_header_lsap
+ */
+typedef eth_header_lsap_t *		eth_header_lsap_ref;
+
+/** 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 LSAP extension pointer.
+ *  @see eth_ieee_lsap
+ */
+typedef eth_ieee_lsap_t *		eth_ieee_lsap_ref;
+
+/** Type definition of the Ethernet header SNAP extension.
+ *  @see eth_snap
+ */
+typedef struct eth_snap		eth_snap_t;
+
+/** Type definition of the Ethernet header SNAP extension pointer.
+ *  @see eth_snap
+ */
+typedef eth_snap_t *		eth_snap_ref;
+
+/** Type definition of the Ethernet header preamble.
+ *  @see preamble
+ */
+typedef struct eth_preamble	eth_preamble_t;
+
+/** Type definition of the Ethernet header preamble pointer.
+ *  @see eth_preamble
+ */
+typedef eth_preamble_t *	eth_preamble_ref;
+
+/** Type definition of the Ethernet header.
+ *  @see eth_header
+ */
+typedef struct eth_header	eth_header_t;
+
+/** Type definition of the Ethernet header pointer.
+ *  @see eth_header
+ */
+typedef eth_header_t *		eth_header_ref;
+
+/** 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;
+
+/** Ethernet Frame Check Sequence pointer.
+ */
+typedef eth_fcs_t *		eth_fcs_ref;
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/nil/eth/eth_module.c
===================================================================
--- uspace/srv/net/nil/eth/eth_module.c	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/nil/eth/eth_module.c	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,114 @@
+/*
+ * 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 eth
+ * @{
+ */
+
+/** @file
+ *  Ethernet module stub.
+ *  @see module.c
+ */
+
+#include <async.h>
+#include <stdio.h>
+
+#include <ipc/ipc.h>
+#include <ipc/services.h>
+
+#include "../../err.h"
+#include "../../modules.h"
+
+#include "../../include/net_interface.h"
+
+#include "../../structures/packet/packet.h"
+
+#include "../nil_module.h"
+
+#include "eth.h"
+
+/** The module name.
+ */
+#define NAME	"Ethernet protocol"
+
+/** Prints the module name.
+ */
+void	module_print_name( void );
+
+/** Starts the Ethernet module.
+ *  Initializes the client connection serving function, initializes the module, registers the module service and starts the async manager, processing IPC messages in an infinite loop.
+ *  @param[in] client_connection The client connection processing function. The module skeleton propagates its own one.
+ *  @returns EOK on success.
+ *  @returns Other error codes as defined for the pm_init() function.
+ *  @returns Other error codes as defined for the nil_initialize() function.
+ *  @returns Other error codes as defined for the REGISTER_ME() macro function.
+ */
+int	module_start( async_client_conn_t client_connection );
+
+/** Passes the parameters to the module specific nil_message() function.
+ *  @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.
+ *  @returns EOK on success.
+ *  @returns ENOTSUP if the message is not known.
+ *  @returns Other error codes as defined for each specific module message function.
+ */
+int	module_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count );
+
+void module_print_name( void ){
+	printf( "%s", NAME );
+}
+
+int module_start( async_client_conn_t client_connection ){
+	ERROR_DECLARE;
+
+	ipcarg_t	phonehash;
+	int			net_phone;
+
+	async_set_client_connection( client_connection );
+	net_phone = net_connect_module( SERVICE_NETWORKING );
+	ERROR_PROPAGATE( pm_init());
+	if( ERROR_OCCURRED( nil_initialize( net_phone ))
+	|| ERROR_OCCURRED( REGISTER_ME( SERVICE_ETHERNET, & phonehash ))){
+		pm_destroy();
+		return ERROR_CODE;
+	}
+
+	async_manager();
+
+	pm_destroy();
+	return EOK;
+}
+
+int	module_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){
+	return nil_message( callid, call, answer, answer_count );
+}
+
+/** @}
+ */
Index: uspace/srv/net/nil/nil_messages.h
===================================================================
--- uspace/srv/net/nil/nil_messages.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/nil/nil_messages.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup net_nil
+ *  @{
+ */
+
+/** @file
+ *  Network interface layer module messages.
+ *  @see nil_interface.h
+ */
+
+#ifndef __NET_NIL_MESSAGES_H__
+#define __NET_NIL_MESSAGES_H__
+
+#include <ipc/ipc.h>
+
+#include "../messages.h"
+
+/**  Network interface layer module messages.
+ */
+typedef enum {
+	/** New device or update MTU message.
+	 *  @see nil_device_req()
+	 */
+	NET_NIL_DEVICE = NET_NIL_FIRST,
+	/** New device state message.
+	 *  @see nil_device_state_msg()
+	 */
+	NET_NIL_DEVICE_STATE,
+	/** Received packet queue message.
+	 *  @see nil_received_msg()
+	 */
+	NET_NIL_RECEIVED,
+	/** 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
+ */
+/*@{*/
+
+/** Returns the protocol service message parameter.
+ */
+#define NIL_GET_PROTO( call )		( services_t ) IPC_GET_ARG2( * call )
+
+/*@}*/
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/nil/nil_module.h
===================================================================
--- uspace/srv/net/nil/nil_module.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/nil/nil_module.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup net_nil
+ *  @{
+ */
+
+/** @file
+ *  Network interface layer modules common skeleton.
+ *  All network interface layer modules have to implement this interface.
+ */
+
+#ifndef __NET_ETH_MODULE_H__
+#define __NET_ETH_MODULE_H__
+
+#include <ipc/ipc.h>
+
+/** Module initialization.
+ *  Is called by the module_start() function.
+ *  @param[in] net_phone The networking moduel phone.
+ *  @returns EOK on success.
+ *  @returns Other error codes as defined for each specific module initialize function.
+ */
+int	nil_initialize( int net_phone );
+
+/** Message processing function.
+ *  @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.
+ *  @returns EOK on success.
+ *  @returns ENOTSUP if the message is not known.
+ *  @returns Other error codes as defined for each specific module message function.
+ *  @see nil_interface.h
+ *  @see IS_NET_NIL_MESSAGE()
+ */
+int	nil_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count );
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/nil/nil_remote.c
===================================================================
--- uspace/srv/net/nil/nil_remote.c	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/nil/nil_remote.c	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup net_nil
+ *  @{
+ */
+
+/** @file
+ *  Network interface layer interface implementation for standalone remote modules.
+ *  @see nil_interface.h
+ */
+
+#include "../messages.h"
+
+#include "../include/device.h"
+#include "../include/nil_interface.h"
+
+#include "../structures/packet/packet.h"
+#include "../structures/packet/packet_client.h"
+
+#include "nil_messages.h"
+
+int nil_device_state_msg( int nil_phone, device_id_t device_id, int state ){
+	return generic_device_state_msg( nil_phone, NET_NIL_DEVICE_STATE, device_id, state, 0 );
+}
+
+int nil_received_msg( int nil_phone, device_id_t device_id, packet_t packet, services_t target ){
+	return generic_received_msg( nil_phone, NET_NIL_RECEIVED, device_id, packet_get_id( packet ), target, 0 );
+}
+
+/** @}
+ */
Index: uspace/srv/net/nil/nildummy/Makefile
===================================================================
--- uspace/srv/net/nil/nildummy/Makefile	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/nil/nildummy/Makefile	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,47 @@
+#
+# 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.
+#
+
+NAME = nildummy
+
+NET_BASE = ../../
+STRUCTURES = $(NET_BASE)structures/
+
+OUTPUT = $(NAME)
+SOURCES = \
+	$(NAME).c \
+	$(NAME)_module.c \
+	$(NET_BASE)module.c \
+	$(NET_BASE)modules.c \
+	$(NET_BASE)net/net_remote.c \
+	$(NET_BASE)netif/netif_remote.c \
+	$(STRUCTURES)measured_strings.c \
+	$(STRUCTURES)packet/packet.c \
+	$(STRUCTURES)packet/packet_client.c \
+	$(STRUCTURES)packet/packet_remote.c
+
+include $(NET_BASE)Makefile.module
Index: uspace/srv/net/nil/nildummy/nildummy.c
===================================================================
--- uspace/srv/net/nil/nildummy/nildummy.c	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/nil/nildummy/nildummy.c	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,360 @@
+/*
+ * 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 nildummy
+ *  @{
+ */
+
+/** @file
+ *  Dummy network interface layer module implementation.
+ *  @see nildummy.h
+ */
+
+#include <async.h>
+#include <malloc.h>
+#include <mem.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <ipc/ipc.h>
+#include <ipc/services.h>
+
+#include "../../err.h"
+#include "../../messages.h"
+#include "../../modules.h"
+
+#include "../../include/device.h"
+#include "../../include/netif_interface.h"
+#include "../../include/nil_interface.h"
+#include "../../include/il_interface.h"
+
+#include "../../structures/measured_strings.h"
+#include "../../structures/packet/packet.h"
+
+#include "../nil_module.h"
+
+#include "nildummy.h"
+
+/** Default maximum transmission unit.
+ */
+#define NET_DEFAULT_MTU	1500
+
+/** Network interface layer module global data.
+ */
+nildummy_globals_t	nildummy_globals;
+
+/** @name Message processing functions
+ */
+/*@{*/
+
+/** Processes IPC messages from the registered device driver modules in an infinite loop.
+ *  @param[in] iid The message identifier.
+ *  @param[in,out] icall The message parameters.
+ */
+void	nildummy_receiver( ipc_callid_t iid, ipc_call_t * icall );
+
+/** Registers new device or updates the MTU of an existing one.
+ *  Determines the device local hardware address.
+ *  @param[in] device_id The new device identifier.
+ *  @param[in] service The device driver service.
+ *  @param[in] mtu The device maximum transmission unit.
+ *  @returns EOK on success.
+ *  @returns EEXIST if the device with the different service exists.
+ *  @returns ENOMEM if there is not enough memory left.
+ *  @returns Other error codes as defined for the netif_bind_service() function.
+ *  @returns Other error codes as defined for the netif_get_addr_req() function.
+ */
+int	nildummy_device_message( device_id_t device_id, services_t service, size_t mtu );
+
+/** 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.
+ *  @returns EOK on success.
+ *  @returns EBADMEM if either one of the parameters is NULL.
+ *  @returns ENOENT if there is no such device.
+ */
+int	nildummy_packet_space_message( device_id_t device_id, size_t * addr_len, size_t * prefix, size_t * content, size_t * suffix );
+
+/** Registers receiving module service.
+ *  Passes received packets for this service.
+ *  @param[in] service The module service.
+ *  @param[in] phone The service phone.
+ *  @returns EOK on success.
+ *  @returns ENOENT if the service is not known.
+ *  @returns ENOMEM if there is not enough memory left.
+ */
+int	nildummy_register_message( services_t service, int phone );
+
+/** Sends the packet queue.
+ *  @param[in] device_id The device identifier.
+ *  @param[in] packet The packet queue.
+ *  @param[in] sender The sending module service.
+ *  @returns EOK on success.
+ *  @returns ENOENT if there no such device.
+ *  @returns EINVAL if the service parameter is not known.
+ */
+int	nildummy_send_message( device_id_t device_id, packet_t packet, services_t sender );
+
+/** Returns the device hardware address.
+ *  @param[in] device_id The device identifier.
+ *  @param[out] address The device hardware address.
+ *  @returns EOK on success.
+ *  @returns EBADMEM if the address parameter is NULL.
+ *  @returns ENOENT if there no such device.
+ */
+int	nildummy_addr_message( device_id_t device_id, measured_string_ref * address );
+
+/*@}*/
+
+DEVICE_MAP_IMPLEMENT( nildummy_devices, nildummy_device_t )
+
+int	nil_device_state_msg( int nil_phone, device_id_t device_id, int state ){
+	fibril_rwlock_read_lock( & nildummy_globals.protos_lock );
+	if( nildummy_globals.proto.phone ) il_device_state_msg( nildummy_globals.proto.phone, device_id, state, nildummy_globals.proto.service );
+	fibril_rwlock_read_unlock( & nildummy_globals.protos_lock );
+	return EOK;
+}
+
+int nil_initialize( int net_phone ){
+	ERROR_DECLARE;
+
+	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_phone = net_phone;
+	nildummy_globals.proto.phone = 0;
+	ERROR_PROPAGATE( nildummy_devices_initialize( & nildummy_globals.devices ));
+	fibril_rwlock_write_unlock( & nildummy_globals.protos_lock );
+	fibril_rwlock_write_unlock( & nildummy_globals.devices_lock );
+	return EOK;
+}
+
+int nildummy_device_message( device_id_t device_id, services_t service, size_t mtu ){
+	ERROR_DECLARE;
+
+	nildummy_device_ref	device;
+	int					index;
+
+	fibril_rwlock_write_lock( & nildummy_globals.devices_lock );
+	// an existing device?
+	device = nildummy_devices_find( & nildummy_globals.devices, device_id );
+	if( device ){
+		if( device->service != service ){
+			printf( "Device %d already exists\n", device->device_id );
+			fibril_rwlock_write_unlock( & nildummy_globals.devices_lock );
+			return EEXIST;
+		}else{
+			// update mtu
+			if( mtu > 0 ){
+				device->mtu = mtu;
+			}else{
+				device->mtu = NET_DEFAULT_MTU;
+			}
+			printf( "Device %d already exists:\tMTU\t= %d\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.phone ){
+				il_mtu_changed_msg( nildummy_globals.proto.phone, device->device_id, device->mtu, nildummy_globals.proto.service );
+			}
+			fibril_rwlock_read_unlock( & nildummy_globals.protos_lock );
+			return EOK;
+		}
+	}else{
+		// create a new device
+		device = ( nildummy_device_ref ) malloc( sizeof( nildummy_device_t ));
+		if( ! device ) return ENOMEM;
+		device->device_id = device_id;
+		device->service = service;
+		if( mtu > 0 ){
+			device->mtu = mtu;
+		}else{
+			device->mtu = NET_DEFAULT_MTU;
+		}
+		// bind the device driver
+		device->phone = netif_bind_service( device->service, device->device_id, SERVICE_ETHERNET, nildummy_receiver );
+		if( device->phone < 0 ){
+			fibril_rwlock_write_unlock( & nildummy_globals.devices_lock );
+			free( device );
+			return device->phone;
+		}
+		// get hardware address
+		if( ERROR_OCCURRED( netif_get_addr_req( device->phone, device->device_id, & device->addr, & device->addr_data ))){
+			fibril_rwlock_write_unlock( & nildummy_globals.devices_lock );
+			free( device );
+			return ERROR_CODE;
+		}
+		// add to the cache
+		index = nildummy_devices_add( & nildummy_globals.devices, device->device_id, device );
+		if( index < 0 ){
+			fibril_rwlock_write_unlock( & nildummy_globals.devices_lock );
+			free( device->addr );
+			free( device->addr_data );
+			free( device );
+			return index;
+		}
+		printf( "New device registered:\n\tid\t= %d\n\tservice\t= %d\n\tMTU\t= %d\n", device->device_id, device->service, device->mtu );
+	}
+	fibril_rwlock_write_unlock( & nildummy_globals.devices_lock );
+	return EOK;
+}
+
+int nildummy_addr_message( device_id_t device_id, measured_string_ref * address ){
+	nildummy_device_ref	device;
+
+	if( ! address ) return EBADMEM;
+	fibril_rwlock_read_lock( & nildummy_globals.devices_lock );
+	device = nildummy_devices_find( & nildummy_globals.devices, device_id );
+	if( ! device ){
+		fibril_rwlock_read_unlock( & nildummy_globals.devices_lock );
+		return ENOENT;
+	}
+	* address = device->addr;
+	fibril_rwlock_read_unlock( & nildummy_globals.devices_lock );
+	return ( * address ) ? EOK : ENOENT;
+}
+
+int nildummy_packet_space_message( device_id_t device_id, size_t * addr_len, size_t * prefix, size_t * content, size_t * suffix ){
+	nildummy_device_ref	device;
+
+	if( !( addr_len && prefix && content && suffix )) return EBADMEM;
+	fibril_rwlock_read_lock( & nildummy_globals.devices_lock );
+	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( int nil_phone, device_id_t device_id, packet_t packet, services_t target ){
+	packet_t		next;
+
+	fibril_rwlock_read_lock( & nildummy_globals.protos_lock );
+	if( nildummy_globals.proto.phone ){
+		do{
+			next = pq_detach( packet );
+			il_received_msg( nildummy_globals.proto.phone, device_id, packet, nildummy_globals.proto.service );
+			packet = next;
+		}while( packet );
+	}
+	fibril_rwlock_read_unlock( & nildummy_globals.protos_lock );
+	return EOK;
+}
+
+int nildummy_register_message( services_t service, int phone ){
+	fibril_rwlock_write_lock( & nildummy_globals.protos_lock );
+	nildummy_globals.proto.service = service;
+	nildummy_globals.proto.phone = phone;
+	printf( "New protocol registered:\n\tservice\t= %d\n\tphone\t= %d\n", nildummy_globals.proto.service, nildummy_globals.proto.phone );
+	fibril_rwlock_write_unlock( & nildummy_globals.protos_lock );
+	return EOK;
+}
+
+int nildummy_send_message( device_id_t device_id, packet_t packet, services_t sender ){
+	nildummy_device_ref		device;
+
+	fibril_rwlock_read_lock( & nildummy_globals.devices_lock );
+	device = nildummy_devices_find( & nildummy_globals.devices, device_id );
+	if( ! device ){
+		fibril_rwlock_read_unlock( & nildummy_globals.devices_lock );
+		return ENOENT;
+	}
+	// send packet queue
+	if( packet ){
+		netif_send_msg( device->phone, device_id, packet, SERVICE_NILDUMMY );
+	}
+	fibril_rwlock_read_unlock( & nildummy_globals.devices_lock );
+	return EOK;
+}
+
+int nil_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){
+	ERROR_DECLARE;
+
+	measured_string_ref	address;
+	packet_t			packet;
+
+//	printf( "message %d - %d\n", IPC_GET_METHOD( * call ), NET_NIL_FIRST );
+	* answer_count = 0;
+	switch( IPC_GET_METHOD( * call )){
+		case IPC_M_PHONE_HUNGUP:
+			return EOK;
+		case NET_NIL_DEVICE:
+			return nildummy_device_message( IPC_GET_DEVICE( call ), IPC_GET_SERVICE( call ), IPC_GET_MTU( call ));
+		case NET_NIL_SEND:
+			ERROR_PROPAGATE( packet_translate( nildummy_globals.net_phone, & packet, IPC_GET_PACKET( call )));
+			return nildummy_send_message( IPC_GET_DEVICE( call ), packet, IPC_GET_SERVICE( call ));
+		case NET_NIL_PACKET_SPACE:
+			ERROR_PROPAGATE( nildummy_packet_space_message( IPC_GET_DEVICE( call ), IPC_SET_ADDR( answer ), IPC_SET_PREFIX( answer ), IPC_SET_CONTENT( answer ), IPC_SET_SUFFIX( answer )));
+			* answer_count = 4;
+			return EOK;
+		case NET_NIL_ADDR:
+			ERROR_PROPAGATE( nildummy_addr_message( IPC_GET_DEVICE( call ), & address ));
+			return measured_strings_reply( address, 1 );
+		case IPC_M_CONNECT_TO_ME:
+			return nildummy_register_message( NIL_GET_PROTO( call ), IPC_GET_PHONE( call ));
+	}
+	return ENOTSUP;
+}
+
+void nildummy_receiver( ipc_callid_t iid, ipc_call_t * icall ){
+	ERROR_DECLARE;
+
+	packet_t		packet;
+
+	while( true ){
+//		printf( "message %d - %d\n", IPC_GET_METHOD( * icall ), NET_NIL_FIRST );
+		switch( IPC_GET_METHOD( * icall )){
+			case NET_NIL_DEVICE_STATE:
+				ERROR_CODE = nil_device_state_msg( 0, IPC_GET_DEVICE( icall ), IPC_GET_STATE( icall ));
+				ipc_answer_0( iid, ( ipcarg_t ) ERROR_CODE );
+				break;
+			case NET_NIL_RECEIVED:
+				if( ! ERROR_OCCURRED( packet_translate( nildummy_globals.net_phone, & packet, IPC_GET_PACKET( icall )))){
+					ERROR_CODE = nil_received_msg( 0, IPC_GET_DEVICE( icall ), packet, 0 );
+				}
+				ipc_answer_0( iid, ( ipcarg_t ) ERROR_CODE );
+				break;
+			default:
+				ipc_answer_0( iid, ( ipcarg_t ) ENOTSUP );
+		}
+		iid = async_get_call( icall );
+	}
+}
+
+/** @}
+ */
Index: uspace/srv/net/nil/nildummy/nildummy.h
===================================================================
--- uspace/srv/net/nil/nildummy/nildummy.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/nil/nildummy/nildummy.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,134 @@
+/*
+ * 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 nildummy
+ *  @{
+ */
+
+/** @file
+ *  Dummy network interface layer module.
+ */
+
+#ifndef __NET_NILDUMMY_H__
+#define __NET_NILDUMMY_H__
+
+#include <fibril_synch.h>
+#include <ipc/services.h>
+
+#include "../../include/device.h"
+#include "../../structures/measured_strings.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 device specific data pointer.
+ *  @see nildummy_device
+ */
+typedef nildummy_device_t *		nildummy_device_ref;
+
+/** Type definition of the dummy nil protocol specific data.
+ *  @see nildummy_proto
+ */
+typedef struct nildummy_proto	nildummy_proto_t;
+
+/** Type definition of the dummy nil protocol specific data pointer.
+ *  @see nildummy_proto
+ */
+typedef nildummy_proto_t *		nildummy_proto_ref;
+
+/** Dummy nil device map.
+ *  Maps 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.
+	 */
+	device_id_t			device_id;
+	/** Device driver service.
+	 */
+	services_t			service;
+	/** Driver phone.
+	 */
+	int					phone;
+	/** Maximal transmission unit.
+	 */
+	size_t				mtu;
+	/** Actual device hardware address.
+	 */
+	measured_string_ref	addr;
+	/** Actual device hardware address data.
+	 */
+	char *				addr_data;
+};
+
+/** Dummy nil protocol specific data.
+ */
+struct nildummy_proto{
+	/** Protocol service.
+	 */
+	services_t	service;
+	/** Protocol module phone.
+	 */
+	int			phone;
+};
+
+/** Dummy nil global data.
+ */
+struct	nildummy_globals{
+	/** Networking module phone.
+	 */
+	int				net_phone;
+	/** Safety 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/nil/nildummy/nildummy_module.c
===================================================================
--- uspace/srv/net/nil/nildummy/nildummy_module.c	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/nil/nildummy/nildummy_module.c	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,114 @@
+/*
+ * 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 nildummy
+ * @{
+ */
+
+/** @file
+ *  Dummy network interface layer module stub.
+ *  @see module.c
+ */
+
+#include <async.h>
+#include <stdio.h>
+
+#include <ipc/ipc.h>
+#include <ipc/services.h>
+
+#include "../../err.h"
+#include "../../modules.h"
+
+#include "../../include/net_interface.h"
+
+#include "../../structures/packet/packet.h"
+
+#include "../nil_module.h"
+
+#include "nildummy.h"
+
+/** The module name.
+ */
+#define NAME	"Dummy nil protocol"
+
+/** Prints the module name.
+ */
+void	module_print_name( void );
+
+/** Starts the dummy nil module.
+ *  Initializes the client connection serving function, initializes the module, registers the module service and starts the async manager, processing IPC messages in an infinite loop.
+ *  @param[in] client_connection The client connection processing function. The module skeleton propagates its own one.
+ *  @returns EOK on success.
+ *  @returns Other error codes as defined for the pm_init() function.
+ *  @returns Other error codes as defined for the nil_initialize() function.
+ *  @returns Other error codes as defined for the REGISTER_ME() macro function.
+ */
+int	module_start( async_client_conn_t client_connection );
+
+/** Passes the parameters to the module specific nil_message() function.
+ *  @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.
+ *  @returns EOK on success.
+ *  @returns ENOTSUP if the message is not known.
+ *  @returns Other error codes as defined for each specific module message function.
+ */
+int	module_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count );
+
+void module_print_name( void ){
+	printf( "%s", NAME );
+}
+
+int module_start( async_client_conn_t client_connection ){
+	ERROR_DECLARE;
+
+	ipcarg_t	phonehash;
+	int			net_phone;
+
+	async_set_client_connection( client_connection );
+	net_phone = net_connect_module( SERVICE_NETWORKING );
+	ERROR_PROPAGATE( pm_init());
+	if( ERROR_OCCURRED( nil_initialize( net_phone ))
+	|| ERROR_OCCURRED( REGISTER_ME( SERVICE_NILDUMMY, & phonehash ))){
+		pm_destroy();
+		return ERROR_CODE;
+	}
+
+	async_manager();
+
+	pm_destroy();
+	return EOK;
+}
+
+int	module_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){
+	return nil_message( callid, call, answer, answer_count );
+}
+
+/** @}
+ */
Index: uspace/srv/net/self_test.c
===================================================================
--- uspace/srv/net/self_test.c	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/self_test.c	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,381 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup net
+ *  @{
+ */
+
+/** @file
+ *  Self tests implementation.
+ */
+
+#include "configuration.h"
+
+#if NET_SELF_TEST
+
+#include <errno.h>
+#include <malloc.h>
+#include <stdio.h>
+
+#include "include/checksum.h"
+#include "structures/int_map.h"
+#include "structures/char_map.h"
+#include "structures/generic_char_map.h"
+#include "structures/measured_strings.h"
+#include "structures/dynamic_fifo.h"
+
+#include "self_test.h"
+
+/** Tests the function, compares the result and remembers if the result differs.
+ *  @param[in] name The test name.
+ *  @param[in] function_call The function to be called and checked.
+ *  @param[in] result The expected result.
+ */
+#define TEST( name, function_call, result );	{	\
+	printf( "\n\t%s", ( name )); 					\
+	if(( function_call ) != ( result )){			\
+		printf( "\tERROR\n" );						\
+		error = 1;									\
+	}else{											\
+		printf( "\tOK\n" );							\
+	}												\
+}
+
+#if NET_SELF_TEST_INT_MAP
+
+	INT_MAP_DECLARE( int_map, int );
+
+	INT_MAP_IMPLEMENT( int_map, int );
+
+#endif
+
+#if NET_SELF_TEST_GENERIC_FIELD
+
+	GENERIC_FIELD_DECLARE( int_field, int )
+
+	GENERIC_FIELD_IMPLEMENT( int_field, int )
+
+#endif
+
+#if NET_SELF_TEST_GENERIC_CHAR_MAP
+
+	GENERIC_CHAR_MAP_DECLARE( int_char_map, int )
+
+	GENERIC_CHAR_MAP_IMPLEMENT( int_char_map, int )
+
+#endif
+
+int self_test( void ){
+	int error = 0;
+	int * x, * y, * z, * u, * v, * w;
+
+#if NET_SELF_TEST_MEASURED_STRINGS
+	measured_string_ref	string;
+
+	printf( "\nMeasured strings test" );
+	string = measured_string_create_bulk( "I am a measured string!", 0 );
+	printf( "\n%x, %s at %x of %d", string, string->value, string->value, string->length );
+	printf( "\nOK" );
+#endif
+
+#if NET_SELF_TEST_CHAR_MAP
+	char_map_t	cm;
+
+	printf( "\nChar map test" );
+	TEST( "update ucho 3 einval", char_map_update( & cm, "ucho", 0, 3 ), EINVAL );
+	TEST( "initialize", char_map_initialize( & cm ), EOK );
+	TEST( "exclude bla null", char_map_exclude( & cm, "bla", 0 ), CHAR_MAP_NULL );
+	TEST( "find bla null", char_map_find( & cm, "bla", 0 ), CHAR_MAP_NULL );
+	TEST( "add bla 1 eok", char_map_add( & cm, "bla", 0, 1 ), EOK );
+	TEST( "find bla 1", char_map_find( & cm, "bla", 0 ), 1 );
+	TEST( "add bla 10 eexists", char_map_add( & cm, "bla", 0, 10 ), EEXISTS );
+	TEST( "update bla 2 eok", char_map_update( & cm, "bla", 0, 2 ), EOK );
+	TEST( "find bla 2", char_map_find( & cm, "bla", 0 ), 2 );
+	TEST( "update ucho 2 eok", char_map_update( & cm, "ucho", 0, 2 ), EOK );
+	TEST( "exclude bla 2", char_map_exclude( & cm, "bla", 0 ), 2 );
+	TEST( "exclude bla null", char_map_exclude( & cm, "bla", 0 ), CHAR_MAP_NULL );
+	TEST( "find ucho 2", char_map_find( & cm, "ucho", 0 ), 2 );
+	TEST( "update ucho 3 eok", char_map_update( & cm, "ucho", 0, 3 ), EOK );
+	TEST( "find ucho 3", char_map_find( & cm, "ucho", 0 ), 3 );
+	TEST( "add blabla 5 eok", char_map_add( & cm, "blabla", 0, 5 ), EOK );
+	TEST( "find blabla 5", char_map_find( & cm, "blabla", 0 ), 5 );
+	TEST( "add bla 6 eok", char_map_add( & cm, "bla", 0, 6 ), EOK );
+	TEST( "find bla 6", char_map_find( & cm, "bla", 0 ), 6 );
+	TEST( "exclude bla 6", char_map_exclude( & cm, "bla", 0 ), 6 );
+	TEST( "find bla null", char_map_find( & cm, "bla", 0 ), CHAR_MAP_NULL );
+	TEST( "find blabla 5", char_map_find( & cm, "blabla", 0 ), 5 );
+	TEST( "add auto 7 eok", char_map_add( & cm, "auto", 0, 7 ), EOK );
+	TEST( "find auto 7", char_map_find( & cm, "auto", 0 ), 7 );
+	TEST( "add kara 8 eok", char_map_add( & cm, "kara", 0, 8 ), EOK );
+	TEST( "find kara 8", char_map_find( & cm, "kara", 0 ), 8 );
+	TEST( "add nic 9 eok", char_map_add( & cm, "nic", 0, 9 ), EOK );
+	TEST( "find nic 9", char_map_find( & cm, "nic", 0 ), 9 );
+	TEST( "find blabla 5", char_map_find( & cm, "blabla", 0 ), 5 );
+	TEST( "add micnicnic 5 9 eok", char_map_add( & cm, "micnicnic", 5, 9 ), EOK );
+	TEST( "find micni 9", char_map_find( & cm, "micni", 0 ), 9 );
+	TEST( "find micnicn 5 9", char_map_find( & cm, "micnicn", 5 ), 9 );
+	TEST( "add 10.0.2.2 4 15 eok", char_map_add( & cm, "\x10\x0\x2\x2", 4, 15 ), EOK );
+	TEST( "find 10.0.2.2 4 15", char_map_find( & cm, "\x10\x0\x2\x2", 4 ), 15 );
+	printf( "\n\tdestroy" );
+	char_map_destroy( & cm );
+	TEST( "update ucho 3 einval", char_map_update( & cm, "ucho", 0, 3 ), EINVAL );
+	printf( "\nOK" );
+
+	if( error ) return EINVAL;
+
+#endif
+
+#if NET_SELF_TEST_INT_MAP
+	int_map_t	im;
+
+	x = ( int * ) malloc( sizeof( int ));
+	y = ( int * ) malloc( sizeof( int ));
+	z = ( int * ) malloc( sizeof( int ));
+	u = ( int * ) malloc( sizeof( int ));
+	v = ( int * ) malloc( sizeof( int ));
+	w = ( int * ) malloc( sizeof( int ));
+
+	im.magic = 0;
+	printf( "\nInt map test" );
+	TEST( "add 1 x einval", int_map_add( & im, 1, x ), EINVAL );
+	TEST( "count -1", int_map_count( & im ), -1 );
+	TEST( "initialize", int_map_initialize( & im ), EOK );
+	TEST( "count 0", int_map_count( & im ), 0 );
+	TEST( "find 1 null", int_map_find( & im, 1 ), NULL );
+	TEST( "add 1 x 0", int_map_add( & im, 1, x ), 0 );
+	TEST( "find 1 x", int_map_find( & im, 1 ), x );
+	int_map_exclude( & im, 1 );
+	TEST( "find 1 null", int_map_find( & im, 1 ), NULL );
+	TEST( "add 1 y 1", int_map_add( & im, 1, y ), 1 );
+	TEST( "find 1 y", int_map_find( & im, 1 ), y );
+	TEST( "add 4 z 2", int_map_add( & im, 4, z ), 2 );
+	TEST( "get 2 z", int_map_get_index( & im, 2 ), z );
+	TEST( "find 4 z", int_map_find( & im, 4 ), z );
+	TEST( "find 1 y", int_map_find( & im, 1 ), y );
+	TEST( "count 3", int_map_count( & im ), 3 );
+	TEST( "add 2 u 3", int_map_add( & im, 2, u ), 3 );
+	TEST( "find 2 u", int_map_find( & im, 2 ), u );
+	TEST( "add 3 v 4", int_map_add( & im, 3, v ), 4 );
+	TEST( "find 3 v", int_map_find( & im, 3 ), v );
+	TEST( "get 4 v", int_map_get_index( & im, 4 ), v );
+	TEST( "add 6 w 5", int_map_add( & im, 6, w ), 5 );
+	TEST( "find 6 w", int_map_find( & im, 6 ), w );
+	TEST( "count 6", int_map_count( & im ), 6 );
+	int_map_exclude( & im, 1 );
+	TEST( "find 1 null", int_map_find( & im, 1 ), NULL );
+	TEST( "find 2 u", int_map_find( & im, 2 ), u );
+	int_map_exclude( & im, 7 );
+	TEST( "find 2 u", int_map_find( & im, 2 ), u );
+	TEST( "find 6 w", int_map_find( & im, 6 ), w );
+	int_map_exclude_index( & im, 4 );
+	TEST( "get 4 null", int_map_get_index( & im, 4 ), NULL );
+	TEST( "find 3 null", int_map_find( & im, 3 ), NULL );
+	printf( "\n\tdestroy" );
+	int_map_destroy( & im );
+	TEST( "count -1", int_map_count( & im ), -1 );
+	printf( "\nOK" );
+
+	if( error ) return EINVAL;
+
+#endif
+
+#if NET_SELF_TEST_GENERIC_FIELD
+	int_field_t	gf;
+
+	x = ( int * ) malloc( sizeof( int ));
+	y = ( int * ) malloc( sizeof( int ));
+	z = ( int * ) malloc( sizeof( int ));
+	u = ( int * ) malloc( sizeof( int ));
+	v = ( int * ) malloc( sizeof( int ));
+	w = ( int * ) malloc( sizeof( int ));
+
+	gf.magic = 0;
+	printf( "\nGeneric field test" );
+	TEST( "add x einval", int_field_add( & gf, x ), EINVAL );
+	TEST( "count -1", int_field_count( & gf ), -1 );
+	TEST( "initialize", int_field_initialize( & gf ), EOK );
+	TEST( "count 0", int_field_count( & gf ), 0 );
+	TEST( "get 1 null", int_field_get_index( & gf, 1 ), NULL );
+	TEST( "add x 0", int_field_add( & gf, x ), 0 );
+	TEST( "get 0 x", int_field_get_index( & gf, 0 ), x );
+	int_field_exclude_index( & gf, 0 );
+	TEST( "get 0 null", int_field_get_index( & gf, 0 ), NULL );
+	TEST( "add y 1", int_field_add( & gf, y ), 1 );
+	TEST( "get 1 y", int_field_get_index( & gf, 1 ), y );
+	TEST( "add z 2", int_field_add( & gf, z ), 2 );
+	TEST( "get 2 z", int_field_get_index( & gf, 2 ), z );
+	TEST( "get 1 y", int_field_get_index( & gf, 1 ), y );
+	TEST( "count 3", int_field_count( & gf ), 3 );
+	TEST( "add u 3", int_field_add( & gf, u ), 3 );
+	TEST( "get 3 u", int_field_get_index( & gf, 3 ), u );
+	TEST( "add v 4", int_field_add( & gf, v ), 4 );
+	TEST( "get 4 v", int_field_get_index( & gf, 4 ), v );
+	TEST( "add w 5", int_field_add( & gf, w ), 5 );
+	TEST( "get 5 w", int_field_get_index( & gf, 5 ), w );
+	TEST( "count 6", int_field_count( & gf ), 6 );
+	int_field_exclude_index( & gf, 1 );
+	TEST( "get 1 null", int_field_get_index( & gf, 1 ), NULL );
+	TEST( "get 3 u", int_field_get_index( & gf, 3 ), u );
+	int_field_exclude_index( & gf, 7 );
+	TEST( "get 3 u", int_field_get_index( & gf, 3 ), u );
+	TEST( "get 5 w", int_field_get_index( & gf, 5 ), w );
+	int_field_exclude_index( & gf, 4 );
+	TEST( "get 4 null", int_field_get_index( & gf, 4 ), NULL );
+	printf( "\n\tdestroy" );
+	int_field_destroy( & gf );
+	TEST( "count -1", int_field_count( & gf ), -1 );
+	printf( "\nOK" );
+
+	if( error ) return EINVAL;
+
+#endif
+
+#if NET_SELF_TEST_GENERIC_CHAR_MAP
+	int_char_map_t	icm;
+
+	x = ( int * ) malloc( sizeof( int ));
+	y = ( int * ) malloc( sizeof( int ));
+	z = ( int * ) malloc( sizeof( int ));
+	u = ( int * ) malloc( sizeof( int ));
+	v = ( int * ) malloc( sizeof( int ));
+	w = ( int * ) malloc( sizeof( int ));
+
+	icm.magic = 0;
+	printf( "\nGeneric char map test" );
+	TEST( "add ucho z einval", int_char_map_add( & icm, "ucho", 0, z ), EINVAL );
+	TEST( "initialize", int_char_map_initialize( & icm ), EOK );
+	printf( "\n\texclude bla null" );
+	int_char_map_exclude( & icm, "bla", 0 );
+	TEST( "find bla null", int_char_map_find( & icm, "bla", 0 ), NULL );
+	TEST( "add bla x eok", int_char_map_add( & icm, "bla", 0, x ), EOK );
+	TEST( "find bla x", int_char_map_find( & icm, "bla", 0 ), x );
+	TEST( "add bla y eexists", int_char_map_add( & icm, "bla", 0, y ), EEXISTS );
+	printf( "\n\texclude bla y" );
+	int_char_map_exclude( & icm, "bla", 0 );
+	printf( "\n\texclude bla null" );
+	int_char_map_exclude( & icm, "bla", 0 );
+	TEST( "add blabla v eok", int_char_map_add( & icm, "blabla", 0, v ), EOK );
+	TEST( "find blabla v", int_char_map_find( & icm, "blabla", 0 ), v );
+	TEST( "add bla w eok", int_char_map_add( & icm, "bla", 0, w ), EOK );
+	TEST( "find bla w", int_char_map_find( & icm, "bla", 0 ), w );
+	printf( "\n\texclude bla" );
+	int_char_map_exclude( & icm, "bla", 0 );
+	TEST( "find bla null", int_char_map_find( & icm, "bla", 0 ), NULL );
+	TEST( "find blabla v", int_char_map_find( & icm, "blabla", 0 ), v );
+	TEST( "add auto u eok", int_char_map_add( & icm, "auto", 0, u ), EOK );
+	TEST( "find auto u", int_char_map_find( & icm, "auto", 0 ), u );
+	printf( "\n\tdestroy" );
+	int_char_map_destroy( & icm );
+	TEST( "add ucho z einval", int_char_map_add( & icm, "ucho", 0, z ), EINVAL );
+	printf( "\nOK" );
+
+	if( error ) return EINVAL;
+
+#endif
+
+#if NET_SELF_TEST_CRC
+	uint32_t	value;
+
+	printf( "\nCRC computation test" );
+	value = ~ compute_crc32( ~ 0, "123456789", 8 * 9 );
+	TEST( "123456789", value, 0xCBF43926 );
+	printf( "\t=> %X", value );
+	value = ~ compute_crc32( ~ 0, "1", 8 );
+	TEST( "1", value, 0x83DCEFB7 );
+	printf( "\t=> %X", value );
+	value = ~ compute_crc32( ~ 0, "12", 8 * 2 );
+	TEST( "12", value, 0x4F5344CD );
+	printf( "\t=> %X", value );
+	value = ~ compute_crc32( ~ 0, "123", 8 * 3 );
+	TEST( "123", value, 0x884863D2 );
+	printf( "\t=> %X", value );
+	value = ~ compute_crc32( ~ 0, "1234", 8 * 4 );
+	TEST( "1234", value, 0x9BE3E0A3 );
+	printf( "\t=> %X", value );
+	value = ~ compute_crc32( ~ 0, "12345678", 8 * 8 );
+	TEST( "12345678", value, 0x9AE0DAAF );
+	printf( "\t=> %X", value );
+	value = ~ compute_crc32( ~ 0, "ahoj pane", 8 * 9 );
+	TEST( "ahoj pane", value, 0x5FC3D706 );
+	printf( "\t=> %X", value );
+
+	if( error ) return EINVAL;
+
+#endif
+
+#if NET_SELF_TEST_DYNAMIC_FIFO
+	dyn_fifo_t	fifo;
+
+	printf( "\nDynamic fifo test" );
+	TEST( "add 1 einval", dyn_fifo_push( & fifo, 1, 0 ), EINVAL );
+	TEST( "initialize", dyn_fifo_initialize( & fifo, 1 ), EOK );
+	TEST( "add 1 eok", dyn_fifo_push( & fifo, 1, 0 ), EOK );
+	TEST( "pop 1", dyn_fifo_pop( & fifo ), 1 );
+	TEST( "pop enoent", dyn_fifo_pop( & fifo ), ENOENT );
+	TEST( "add 2 eok", dyn_fifo_push( & fifo, 2, 1 ), EOK );
+	TEST( "add 3 enomem", dyn_fifo_push( & fifo, 3, 1 ), ENOMEM );
+	TEST( "add 3 eok", dyn_fifo_push( & fifo, 3, 0 ), EOK );
+	TEST( "pop 2", dyn_fifo_pop( & fifo ), 2 );
+	TEST( "pop 3", dyn_fifo_pop( & fifo ), 3 );
+	TEST( "add 4 eok", dyn_fifo_push( & fifo, 4, 2 ), EOK );
+	TEST( "add 5 eok", dyn_fifo_push( & fifo, 5, 2 ), EOK );
+	TEST( "add 6 enomem", dyn_fifo_push( & fifo, 6, 2 ), ENOMEM );
+	TEST( "add 6 eok", dyn_fifo_push( & fifo, 6, 5 ), EOK );
+	TEST( "add 7 eok", dyn_fifo_push( & fifo, 7, 5 ), EOK );
+	TEST( "pop 4", dyn_fifo_pop( & fifo ), 4 );
+	TEST( "pop 5", dyn_fifo_pop( & fifo ), 5 );
+	TEST( "add 8 eok", dyn_fifo_push( & fifo, 8, 5 ), EOK );
+	TEST( "add 9 eok", dyn_fifo_push( & fifo, 9, 5 ), EOK );
+	TEST( "add 10 eok", dyn_fifo_push( & fifo, 10, 6 ), EOK );
+	TEST( "add 11 eok", dyn_fifo_push( & fifo, 11, 6 ), EOK );
+	TEST( "pop 6", dyn_fifo_pop( & fifo ), 6 );
+	TEST( "pop 7", dyn_fifo_pop( & fifo ), 7 );
+	TEST( "add 12 eok", dyn_fifo_push( & fifo, 12, 6 ), EOK );
+	TEST( "add 13 eok", dyn_fifo_push( & fifo, 13, 6 ), EOK );
+	TEST( "add 14 enomem", dyn_fifo_push( & fifo, 14, 6 ), ENOMEM );
+	TEST( "add 14 eok", dyn_fifo_push( & fifo, 14, 8 ), EOK );
+	TEST( "pop 8", dyn_fifo_pop( & fifo ), 8 );
+	TEST( "pop 9", dyn_fifo_pop( & fifo ), 9 );
+	TEST( "pop 10", dyn_fifo_pop( & fifo ), 10 );
+	TEST( "pop 11", dyn_fifo_pop( & fifo ), 11 );
+	TEST( "pop 12", dyn_fifo_pop( & fifo ), 12 );
+	TEST( "pop 13", dyn_fifo_pop( & fifo ), 13 );
+	TEST( "pop 14", dyn_fifo_pop( & fifo ), 14 );
+	TEST( "destroy", dyn_fifo_destroy( & fifo ), EOK );
+	TEST( "add 15 einval", dyn_fifo_push( & fifo, 1, 0 ), EINVAL );
+	if( error ) return EINVAL;
+
+#endif
+
+	return EOK;
+}
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/self_test.h
===================================================================
--- uspace/srv/net/self_test.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/self_test.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup net
+ *  @{
+ */
+
+/** @file
+ *  Self tests.
+ *  @see configuration.h
+ */
+
+#ifndef __SELF_TEST_H__
+#define __SELF_TEST_H__
+
+#include "configuration.h"
+
+/** Self test start function.
+ *  Runs all the configured self tests.
+ *  @see configuration.h
+ *  @returns EOK on success.
+ *  @returns The first error occurred.
+ */
+#if NET_SELF_TEST
+
+int	self_test( void );
+
+#else
+
+#include <errno.h>
+
+#define self_test()	EOK
+
+#endif
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/socket/Makefile
===================================================================
--- uspace/srv/net/socket/Makefile	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/socket/Makefile	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,44 @@
+#
+# 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.
+#
+
+NAME = socket
+
+NET_BASE = ../
+STRUCTURES = $(NET_BASE)structures/
+
+## Sources
+#
+
+LIB = lib$(NAME).a
+SOURCES = \
+	$(NAME)_client.c \
+	$(NET_BASE)inet.c \
+	$(NET_BASE)modules.c \
+	$(STRUCTURES)dynamic_fifo.c
+
+include $(NET_BASE)Makefile.module
Index: uspace/srv/net/socket/socket_client.c
===================================================================
--- uspace/srv/net/socket/socket_client.c	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/socket/socket_client.c	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,843 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup socket
+ *  @{
+ */
+
+/** @file
+ *  Socket application program interface (API) implementation.
+ *  @see socket.h for more information.
+ *  This is a part of the network application library.
+ */
+
+#include <assert.h>
+#include <async.h>
+#include <fibril_synch.h>
+#include <limits.h>
+#include <stdlib.h>
+
+#include <ipc/services.h>
+
+#include "../err.h"
+#include "../modules.h"
+
+#include "../include/in.h"
+#include "../include/socket.h"
+#include "../include/socket_errno.h"
+
+#include "../structures/dynamic_fifo.h"
+#include "../structures/int_map.h"
+
+#include "socket_messages.h"
+
+/** Initial received packet queue size.
+ */
+#define SOCKET_INITIAL_RECEIVED_SIZE	4
+
+/** Maximum received packet queue size.
+ */
+#define SOCKET_MAX_RECEIVED_SIZE		0
+
+/** Initial waiting sockets queue size.
+ */
+#define SOCKET_INITIAL_ACCEPTED_SIZE	1
+
+/** Maximum waiting sockets queue size.
+ */
+#define SOCKET_MAX_ACCEPTED_SIZE		0
+
+/** Default timeout for connections in microseconds.
+ */
+#define SOCKET_CONNECT_TIMEOUT	( 1 * 1000 * 1000 )
+
+/** Maximum number of random attempts to find a new socket identifier before switching to the sequence.
+ */
+#define SOCKET_ID_TRIES					100
+
+/** Type definition of the socket specific data.
+ *  @see socket
+ */
+typedef struct socket	socket_t;
+
+/** Type definition of the socket specific data pointer.
+ *  @see socket
+ */
+typedef socket_t *	socket_ref;
+
+/** Socket specific data.
+ *  Each socket lock locks only its structure part and any number of them may be locked simultaneously.
+ */
+struct socket{
+	/** Socket identifier.
+	 */
+	int					socket_id;
+	/** Parent module phone.
+	 */
+	int					phone;
+	/** Parent module service.
+	 */
+	services_t			service;
+	/** Underlying protocol header size.
+	 *  Sending and receiving optimalization.
+	 */
+	size_t				header_size;
+	/** Packet data fragment size.
+	 *  Sending optimalization.
+	 */
+	size_t				data_fragment_size;
+	/** Sending safety lock.
+	 *  Locks the header_size and data_fragment_size attributes.
+	 */
+	fibril_rwlock_t		sending_lock;
+	/** Received packets queue.
+	 */
+	dyn_fifo_t			received;
+	/** Received packets safety lock.
+	 *  Used for receiving and receive notifications.
+	 *  Locks the received attribute.
+	 */
+	fibril_mutex_t		receive_lock;
+	/** Received packets signaling.
+	 *  Signaled upon receive notification.
+	 */
+	fibril_condvar_t	receive_signal;
+	/** Waiting sockets queue.
+	 */
+	dyn_fifo_t			accepted;
+	/** Waiting sockets safety lock.
+	 *  Used for accepting and accept notifications.
+	 *  Locks the accepted attribute.
+	 */
+	fibril_mutex_t		accept_lock;
+	/** Waiting sockets signaling.
+	 *  Signaled upon accept notification.
+	 */
+	fibril_condvar_t	accept_signal;
+	/** The number of blocked functions called.
+	 *  Used while waiting for the received packets or accepted sockets.
+	 */
+	int					blocked;
+};
+
+/** Sockets map.
+ *  Maps socket identifiers to the socket specific data.
+ *  @see int_map.h
+ */
+INT_MAP_DECLARE( sockets, socket_t );
+
+/** Socket client library global data.
+ */
+static struct socket_client_globals {
+	/** TCP module phone.
+	 */
+	int	tcp_phone;
+	/** UDP module phone.
+	 */
+	int	udp_phone;
+//	/** The last socket identifier.
+//	 */
+//	int last_id;
+	/** Active sockets.
+	 */
+	sockets_ref	sockets;
+	/** Safety lock.
+	 *  Write lock is used only for adding or removing sockets.
+	 *  When locked for writing, no other socket locks need to be locked.
+	 *  When locked for reading, any other socket locks may be locked.
+	 *  No socket lock may be locked if this lock is unlocked.
+	 */
+	fibril_rwlock_t	lock;
+} socket_globals = {
+	.tcp_phone = -1,
+	.udp_phone = -1,
+//	.last_id = 0,
+	.sockets = NULL,
+	.lock = {
+		.readers = 0,
+		.writers = 0,
+		.waiters = {
+			.prev = & socket_globals.lock.waiters,
+			.next = & socket_globals.lock.waiters
+		}
+	}
+};
+
+INT_MAP_IMPLEMENT( sockets, socket_t );
+
+/** Returns the TCP module phone.
+ *  Connects to the TCP module if necessary.
+ *  @returns The TCP module phone.
+ *  @returns Other error codes as defined for the bind_service_timeout() function.
+ */
+static int	socket_get_tcp_phone( void );
+
+/** Returns the UDP module phone.
+ *  Connects to the UDP module if necessary.
+ *  @returns The UDP module phone.
+ *  @returns Other error codes as defined for the bind_service_timeout() function.
+ */
+static int	socket_get_udp_phone( void );
+
+/** Returns the active sockets.
+ *  @returns The active sockets.
+ */
+static sockets_ref	socket_get_sockets( void );
+
+/** Tries to find a new free socket identifier.
+ *	@returns The new socket identifier.
+ *  @returns ELIMIT if there is no socket identifier available.
+ */
+static int	socket_generate_new_id( void );
+
+/** Default thread for new connections.
+ *  @param[in] iid The initial message identifier.
+ *  @param[in] icall The initial message call structure.
+ */
+void	socket_connection( ipc_callid_t iid, ipc_call_t * icall );
+
+/** Sends message to the socket parent module with specified data.
+ *  @param[in] socket_id Socket identifier.
+ *  @param[in] message The action message.
+ *  @param[in] arg2 The second message parameter.
+ *  @param[in] data The data to be sent.
+ *  @param[in] datalength The data length.
+ *  @returns EOK on success.
+ *  @returns ENOTSOCK if the socket is not found.
+ *  @returns EBADMEM if the data parameter is NULL.
+ *  @returns NO_DATA if the datalength parameter is zero (0).
+ *  @returns Other error codes as defined for the spcific message.
+ */
+int	socket_send_data( int socket_id, ipcarg_t message, ipcarg_t arg2, const void * data, size_t datalength );
+
+/** Initializes a new socket specific data.
+ *  @param[in,out] socket The socket to be initialized.
+ *  @param[in] socket_id The new socket identifier.
+ *  @param[in] phone The parent module phone.
+ *  @param[in] service The parent module service.
+ */
+void	socket_initialize( socket_ref socket, int socket_id, int phone, services_t service );
+
+/** Clears and destroys the socket.
+ *  @param[in] socket The socket to be destroyed.
+ */
+void	socket_destroy( socket_ref socket );
+
+/** Receives data via the socket.
+ *  @param[in] message The action message.
+ *  @param[in] socket_id Socket identifier.
+ *  @param[out] data The data buffer to be filled.
+ *  @param[in] datalength The data length.
+ *  @param[in] flags Various receive flags.
+ *  @param[out] fromaddr The source address. May be NULL for connected sockets.
+ *  @param[in,out] addrlen The address length. The maximum address length is read. The actual address length is set. Used only if fromaddr is not NULL.
+ *  @returns EOK on success.
+ *  @returns ENOTSOCK if the socket is not found.
+ *  @returns EBADMEM if the data parameter is NULL.
+ *  @returns NO_DATA if the datalength or addrlen parameter is zero (0).
+ *  @returns Other error codes as defined for the spcific message.
+ */
+int	recvfrom_core( ipcarg_t message, int socket_id, void * data, size_t datalength, int flags, struct sockaddr * fromaddr, socklen_t * addrlen );
+
+/** Sends data via the socket to the remote address.
+ *  Binds the socket to a free port if not already connected/bound.
+ *  @param[in] message The action message.
+ *  @param[in] socket_id Socket identifier.
+ *  @param[in] data The data to be sent.
+ *  @param[in] datalength The data length.
+ *  @param[in] flags Various send flags.
+ *  @param[in] toaddr The destination address. May be NULL for connected sockets.
+ *  @param[in] addrlen The address length. Used only if toaddr is not NULL.
+ *  @returns EOK on success.
+ *  @returns ENOTSOCK if the socket is not found.
+ *  @returns EBADMEM if the data or toaddr parameter is NULL.
+ *  @returns NO_DATA if the datalength or the addrlen parameter is zero (0).
+ *  @returns Other error codes as defined for the NET_SOCKET_SENDTO message.
+ */
+int	sendto_core( ipcarg_t message, int socket_id, const void * data, size_t datalength, int flags, const struct sockaddr * toaddr, socklen_t addrlen );
+
+static int socket_get_tcp_phone( void ){
+	if( socket_globals.tcp_phone < 0 ){
+		socket_globals.tcp_phone = bind_service_timeout( SERVICE_TCP, 0, 0, SERVICE_TCP, socket_connection, SOCKET_CONNECT_TIMEOUT );
+	}
+	return socket_globals.tcp_phone;
+}
+
+static int socket_get_udp_phone( void ){
+	if( socket_globals.udp_phone < 0 ){
+		socket_globals.udp_phone = bind_service_timeout( SERVICE_UDP, 0, 0, SERVICE_UDP, socket_connection, SOCKET_CONNECT_TIMEOUT );
+	}
+	return socket_globals.udp_phone;
+}
+
+static sockets_ref socket_get_sockets( void ){
+	if( ! socket_globals.sockets ){
+		socket_globals.sockets = ( sockets_ref ) malloc( sizeof( sockets_t ));
+		if( ! socket_globals.sockets ) return NULL;
+		if( sockets_initialize( socket_globals.sockets ) != EOK ){
+			free( socket_globals.sockets );
+			socket_globals.sockets = NULL;
+		}
+		srand( task_get_id());
+	}
+	return socket_globals.sockets;
+}
+
+static int socket_generate_new_id( void ){
+	sockets_ref	sockets;
+	int			socket_id;
+	int			count;
+
+	sockets = socket_get_sockets();
+	count = 0;
+//	socket_id = socket_globals.last_id;
+	do{
+		if( count < SOCKET_ID_TRIES ){
+			socket_id = rand() % INT_MAX;
+			++ count;
+		}else if( count == SOCKET_ID_TRIES ){
+			socket_id = 1;
+			++ count;
+		// only this branch for last_id
+		}else{
+			if( socket_id < INT_MAX ){
+				++ socket_id;
+/*			}else if( socket_globals.last_id ){
+*				socket_globals.last_id = 0;
+*				socket_id = 1;
+*/			}else{
+				return ELIMIT;
+			}
+		}
+	}while( sockets_find( sockets, socket_id ));
+//	last_id = socket_id
+	return socket_id;
+}
+
+void socket_initialize( socket_ref socket, int socket_id, int phone, services_t service ){
+	socket->socket_id = socket_id;
+	socket->phone = phone;
+	socket->service = service;
+	dyn_fifo_initialize( & socket->received, SOCKET_INITIAL_RECEIVED_SIZE );
+	dyn_fifo_initialize( & socket->accepted, SOCKET_INITIAL_ACCEPTED_SIZE );
+	fibril_mutex_initialize( & socket->receive_lock );
+	fibril_condvar_initialize( & socket->receive_signal );
+	fibril_mutex_initialize( & socket->accept_lock );
+	fibril_condvar_initialize( & socket->accept_signal );
+	fibril_rwlock_initialize( & socket->sending_lock );
+}
+
+void socket_connection( ipc_callid_t iid, ipc_call_t * icall ){
+	ERROR_DECLARE;
+
+	ipc_callid_t	callid;
+	ipc_call_t		call;
+	socket_ref		socket;
+
+	while( true ){
+
+		callid = async_get_call( & call );
+		switch( IPC_GET_METHOD( call )){
+			case NET_SOCKET_RECEIVED:
+			case NET_SOCKET_ACCEPTED:
+			case NET_SOCKET_DATA_FRAGMENT_SIZE:
+				fibril_rwlock_read_lock( & socket_globals.lock );
+				// find the socket
+				socket = sockets_find( socket_get_sockets(), SOCKET_GET_SOCKET_ID( call ));
+				if( ! socket ){
+					ERROR_CODE = ENOTSOCK;
+				}else{
+					switch( IPC_GET_METHOD( call )){
+						case NET_SOCKET_RECEIVED:
+							fibril_mutex_lock( & socket->receive_lock );
+							// push the number of received packet fragments
+							if( ! ERROR_OCCURRED( dyn_fifo_push( & socket->received, SOCKET_GET_DATA_FRAGMENTS( call ), SOCKET_MAX_RECEIVED_SIZE ))){
+								// signal the received packet
+								fibril_condvar_signal( & socket->receive_signal );
+							}
+							fibril_mutex_unlock( & socket->receive_lock );
+							break;
+						case NET_SOCKET_ACCEPTED:
+							// push the new socket identifier
+							fibril_mutex_lock( & socket->accept_lock );
+							if( ! ERROR_OCCURRED( dyn_fifo_push( & socket->accepted, 1, SOCKET_MAX_ACCEPTED_SIZE ))){
+								// signal the accepted socket
+								fibril_condvar_signal( & socket->accept_signal );
+							}
+							fibril_mutex_unlock( & socket->accept_lock );
+							break;
+						default:
+							ERROR_CODE = ENOTSUP;
+					}
+					if(( SOCKET_GET_DATA_FRAGMENT_SIZE( call ) > 0 )
+					&& ( SOCKET_GET_DATA_FRAGMENT_SIZE( call ) != socket->data_fragment_size )){
+						fibril_rwlock_write_lock( & socket->sending_lock );
+						// set the data fragment size
+						socket->data_fragment_size = SOCKET_GET_DATA_FRAGMENT_SIZE( call );
+						fibril_rwlock_write_unlock( & socket->sending_lock );
+					}
+				}
+				fibril_rwlock_read_unlock( & socket_globals.lock );
+				break;
+			default:
+				ERROR_CODE = ENOTSUP;
+		}
+		ipc_answer_0( callid, ( ipcarg_t ) ERROR_CODE );
+	}
+}
+
+int socket( int domain, int type, int protocol ){
+	ERROR_DECLARE;
+
+	socket_ref	socket;
+	int			phone;
+	int			socket_id;
+	services_t	service;
+
+	// find the appropriate service
+	switch( domain ){
+		case PF_INET:
+			switch( type ){
+				case SOCK_STREAM:
+					if( ! protocol ) protocol = IPPROTO_TCP;
+					switch( protocol ){
+						case IPPROTO_TCP:
+							phone = socket_get_tcp_phone();
+							service = SERVICE_TCP;
+							break;
+						default:
+							return EPROTONOSUPPORT;
+					}
+					break;
+				case SOCK_DGRAM:
+					if( ! protocol ) protocol = IPPROTO_UDP;
+					switch( protocol ){
+						case IPPROTO_UDP:
+							phone = socket_get_udp_phone();
+							service = SERVICE_UDP;
+							break;
+						default:
+							return EPROTONOSUPPORT;
+					}
+					break;
+				case SOCK_RAW:
+				default:
+					return ESOCKTNOSUPPORT;
+			}
+			break;
+		// TODO IPv6
+		default:
+			return EPFNOSUPPORT;
+	}
+	if( phone < 0 ) return phone;
+	// create a new socket structure
+	socket = ( socket_ref ) malloc( sizeof( socket_t ));
+	if( ! socket ) return ENOMEM;
+	bzero( socket, sizeof( * socket ));
+	fibril_rwlock_write_lock( & socket_globals.lock );
+	// request a new socket
+	socket_id = socket_generate_new_id();
+	if( socket_id <= 0 ){
+		fibril_rwlock_write_unlock( & socket_globals.lock );
+		free( socket );
+		return socket_id;
+	}
+	if( ERROR_OCCURRED(( int ) async_req_3_3( phone, NET_SOCKET, socket_id, 0, service, NULL, ( ipcarg_t * ) & socket->data_fragment_size, ( ipcarg_t * ) & socket->header_size ))){
+		fibril_rwlock_write_unlock( & socket_globals.lock );
+		free( socket );
+		return ERROR_CODE;
+	}
+	// finish the new socket initialization
+	socket_initialize( socket, socket_id, phone, service );
+	// store the new socket
+	ERROR_CODE = sockets_add( socket_get_sockets(), socket_id, socket );
+	fibril_rwlock_write_unlock( & socket_globals.lock );
+	if( ERROR_CODE < 0 ){
+		dyn_fifo_destroy( & socket->received );
+		dyn_fifo_destroy( & socket->accepted );
+		free( socket );
+		async_msg_3( phone, NET_SOCKET_CLOSE, ( ipcarg_t ) socket_id, 0, service );
+		return ERROR_CODE;
+	}
+
+	return socket_id;
+}
+
+int socket_send_data( int socket_id, ipcarg_t message, ipcarg_t arg2, const void * data, size_t datalength ){
+	socket_ref		socket;
+	aid_t			message_id;
+	ipcarg_t		result;
+
+	if( ! data ) return EBADMEM;
+	if( ! datalength ) return NO_DATA;
+
+	fibril_rwlock_read_lock( & socket_globals.lock );
+	// find the socket
+	socket = sockets_find( socket_get_sockets(), socket_id );
+	if( ! socket ){
+		fibril_rwlock_read_unlock( & socket_globals.lock );
+		return ENOTSOCK;
+	}
+	// request the message
+	message_id = async_send_3( socket->phone, message, ( ipcarg_t ) socket->socket_id, arg2, socket->service, NULL );
+	// send the address
+	async_data_write_start( socket->phone, data, datalength );
+	fibril_rwlock_read_unlock( & socket_globals.lock );
+	async_wait_for( message_id, & result );
+	return ( int ) result;
+}
+
+int bind( int socket_id, const struct sockaddr * my_addr, socklen_t addrlen ){
+	if( addrlen <= 0 ) return EINVAL;
+	// send the address
+	return socket_send_data( socket_id, NET_SOCKET_BIND, 0, my_addr, ( size_t ) addrlen );
+}
+
+int listen( int socket_id, int backlog ){
+	socket_ref	socket;
+	int			result;
+
+	if( backlog <= 0 ) return EINVAL;
+	fibril_rwlock_read_lock( & socket_globals.lock );
+	// find the socket
+	socket = sockets_find( socket_get_sockets(), socket_id );
+	if( ! socket ){
+		fibril_rwlock_read_unlock( & socket_globals.lock );
+		return ENOTSOCK;
+	}
+	// request listen backlog change
+	result = ( int ) async_req_3_0( socket->phone, NET_SOCKET_LISTEN, ( ipcarg_t ) socket->socket_id, ( ipcarg_t ) backlog, socket->service );
+	fibril_rwlock_read_unlock( & socket_globals.lock );
+	return result;
+}
+
+int accept( int socket_id, struct sockaddr * cliaddr, socklen_t * addrlen ){
+	socket_ref		socket;
+	socket_ref		new_socket;
+	aid_t			message_id;
+	int				result;
+	ipc_call_t		answer;
+
+	if(( ! cliaddr ) || ( ! addrlen )) return EBADMEM;
+
+	fibril_rwlock_write_lock( & socket_globals.lock );
+	// find the socket
+	socket = sockets_find( socket_get_sockets(), socket_id );
+	if( ! socket ){
+		fibril_rwlock_write_unlock( & socket_globals.lock );
+		return ENOTSOCK;
+	}
+	fibril_mutex_lock( & socket->accept_lock );
+	// wait for an accepted socket
+	++ socket->blocked;
+	while( dyn_fifo_value( & socket->accepted ) <= 0 ){
+		fibril_rwlock_write_unlock( & socket_globals.lock );
+		fibril_condvar_wait( & socket->accept_signal, & socket->accept_lock );
+		fibril_rwlock_write_lock( & socket_globals.lock );
+	}
+	-- socket->blocked;
+
+	// create a new scoket
+	new_socket = ( socket_ref ) malloc( sizeof( socket_t ));
+	if( ! new_socket ){
+		fibril_mutex_unlock( & socket->accept_lock );
+		fibril_rwlock_write_unlock( & socket_globals.lock );
+		return ENOMEM;
+	}
+	bzero( new_socket, sizeof( * new_socket ));
+	socket_id = socket_generate_new_id();
+	if( socket_id <= 0 ){
+		fibril_mutex_unlock( & socket->accept_lock );
+		fibril_rwlock_write_unlock( & socket_globals.lock );
+		free( new_socket );
+		return socket_id;
+	}
+	socket_initialize( new_socket, socket_id, socket->phone, socket->service );
+	result = sockets_add( socket_get_sockets(), new_socket->socket_id, new_socket );
+	if( result < 0 ){
+		fibril_mutex_unlock( & socket->accept_lock );
+		fibril_rwlock_write_unlock( & socket_globals.lock );
+		free( new_socket );
+		return result;
+	}
+
+	// request accept
+	message_id = async_send_5( socket->phone, NET_SOCKET_ACCEPT, ( ipcarg_t ) socket->socket_id, 0, socket->service, 0, new_socket->socket_id, & answer );
+	// read address
+	ipc_data_read_start( socket->phone, cliaddr, * addrlen );
+	fibril_rwlock_write_unlock( & socket_globals.lock );
+	async_wait_for( message_id, ( ipcarg_t * ) & result );
+	if( result > 0 ){
+		if( result != socket_id ){
+			result = EINVAL;
+		}
+		// dequeue the accepted socket if successful
+		dyn_fifo_pop( & socket->accepted );
+		// set address length
+		* addrlen = SOCKET_GET_ADDRESS_LENGTH( answer );
+		new_socket->data_fragment_size = SOCKET_GET_DATA_FRAGMENT_SIZE( answer );
+	}else if( result == ENOTSOCK ){
+		// empty the queue if no accepted sockets
+		while( dyn_fifo_pop( & socket->accepted ) > 0 );
+	}
+	fibril_mutex_unlock( & socket->accept_lock );
+	return result;
+}
+
+int connect( int socket_id, const struct sockaddr * serv_addr, socklen_t addrlen ){
+	if( ! serv_addr ) return EDESTADDRREQ;
+	if( ! addrlen ) return EDESTADDRREQ;
+	// send the address
+	return socket_send_data( socket_id, NET_SOCKET_CONNECT, 0, serv_addr, addrlen );
+}
+
+int closesocket( int socket_id ){
+	ERROR_DECLARE;
+
+	socket_ref		socket;
+
+	fibril_rwlock_write_lock( & socket_globals.lock );
+	socket = sockets_find( socket_get_sockets(), socket_id );
+	if( ! socket ){
+		fibril_rwlock_write_unlock( & socket_globals.lock );
+		return ENOTSOCK;
+	}
+	if( socket->blocked ){
+		fibril_rwlock_write_unlock( & socket_globals.lock );
+		return EINPROGRESS;
+	}
+	// request close
+	ERROR_PROPAGATE(( int ) async_req_3_0( socket->phone, NET_SOCKET_CLOSE, ( ipcarg_t ) socket->socket_id, 0, socket->service ));
+	// free the socket structure
+	socket_destroy( socket );
+	fibril_rwlock_write_unlock( & socket_globals.lock );
+	return EOK;
+}
+
+void socket_destroy( socket_ref socket ){
+	int	accepted_id;
+
+	// destroy all accepted sockets
+	while(( accepted_id = dyn_fifo_pop( & socket->accepted )) >= 0 ){
+		socket_destroy( sockets_find( socket_get_sockets(), accepted_id ));
+	}
+	dyn_fifo_destroy( & socket->received );
+	dyn_fifo_destroy( & socket->accepted );
+	sockets_exclude( socket_get_sockets(), socket->socket_id );
+}
+
+int send( int socket_id, void * data, size_t datalength, int flags ){
+	// without the address
+	return sendto_core( NET_SOCKET_SEND, socket_id, data, datalength, flags, NULL, 0 );
+}
+
+int sendto( int socket_id, const void * data, size_t datalength, int flags, const struct sockaddr * toaddr, socklen_t addrlen ){
+	if( ! toaddr ) return EDESTADDRREQ;
+	if( ! addrlen ) return EDESTADDRREQ;
+	// with the address
+	return sendto_core( NET_SOCKET_SENDTO, socket_id, data, datalength, flags, toaddr, addrlen );
+}
+
+int sendto_core( ipcarg_t message, int socket_id, const void * data, size_t datalength, int flags, const struct sockaddr * toaddr, socklen_t addrlen ){
+	socket_ref		socket;
+	aid_t			message_id;
+	ipcarg_t		result;
+	size_t			fragments;
+	ipc_call_t		answer;
+
+	if( ! data ) return EBADMEM;
+	if( ! datalength ) return NO_DATA;
+	fibril_rwlock_read_lock( & socket_globals.lock );
+	// find socket
+	socket = sockets_find( socket_get_sockets(), socket_id );
+	if( ! socket ){
+		fibril_rwlock_read_unlock( & socket_globals.lock );
+		return ENOTSOCK;
+	}
+	fibril_rwlock_read_lock( & socket->sending_lock );
+	// compute data fragment count
+	if( socket->data_fragment_size > 0 ){
+		fragments = ( datalength + socket->header_size ) / socket->data_fragment_size;
+		if(( datalength + socket->header_size ) % socket->data_fragment_size ) ++ fragments;
+	}else{
+		fragments = 1;
+	}
+	// request send
+	message_id = async_send_5( socket->phone, message, ( ipcarg_t ) socket->socket_id, ( fragments == 1 ? datalength : socket->data_fragment_size ), socket->service, ( ipcarg_t ) flags, fragments, & answer );
+	// send the address if given
+	if(( ! toaddr ) || ( async_data_write_start( socket->phone, toaddr, addrlen ) == EOK )){
+		if( fragments == 1 ){
+			// send all if only one fragment
+			async_data_write_start( socket->phone, data, datalength );
+		}else{
+			// send the first fragment
+			async_data_write_start( socket->phone, data, socket->data_fragment_size - socket->header_size );
+			data = (( const uint8_t * ) data ) + socket->data_fragment_size - socket->header_size;
+			// send the middle fragments
+			while(( -- fragments ) > 1 ){
+				async_data_write_start( socket->phone, data, socket->data_fragment_size );
+				data = (( const uint8_t * ) data ) + socket->data_fragment_size;
+			}
+			// send the last fragment
+			async_data_write_start( socket->phone, data, ( datalength + socket->header_size ) % socket->data_fragment_size );
+		}
+	}
+	async_wait_for( message_id, & result );
+	if(( SOCKET_GET_DATA_FRAGMENT_SIZE( answer ) > 0 )
+	&& ( SOCKET_GET_DATA_FRAGMENT_SIZE( answer ) != socket->data_fragment_size )){
+		// set the data fragment size
+		socket->data_fragment_size = SOCKET_GET_DATA_FRAGMENT_SIZE( answer );
+	}
+	fibril_rwlock_read_unlock( & socket->sending_lock );
+	fibril_rwlock_read_unlock( & socket_globals.lock );
+	return ( int ) result;
+}
+
+int recv( int socket_id, void * data, size_t datalength, int flags ){
+	// without the address
+	return recvfrom_core( NET_SOCKET_RECV, socket_id, data, datalength, flags, NULL, NULL );
+}
+
+int recvfrom( int socket_id, void * data, size_t datalength, int flags, struct sockaddr * fromaddr, socklen_t * addrlen ){
+	if( ! fromaddr ) return EBADMEM;
+	if( ! addrlen ) return NO_DATA;
+	// with the address
+	return recvfrom_core( NET_SOCKET_RECVFROM, socket_id, data, datalength, flags, fromaddr, addrlen );
+}
+
+int recvfrom_core( ipcarg_t message, int socket_id, void * data, size_t datalength, int flags, struct sockaddr * fromaddr, socklen_t * addrlen ){
+	socket_ref		socket;
+	aid_t			message_id;
+	int				result;
+	size_t			fragments;
+	size_t *		lengths;
+	size_t			index;
+	ipc_call_t		answer;
+
+	if( ! data ) return EBADMEM;
+	if( ! datalength ) return NO_DATA;
+	if( fromaddr && ( ! addrlen )) return EINVAL;
+	fibril_rwlock_read_lock( & socket_globals.lock );
+	// find the socket
+	socket = sockets_find( socket_get_sockets(), socket_id );
+	if( ! socket ){
+		fibril_rwlock_read_unlock( & socket_globals.lock );
+		return ENOTSOCK;
+	}
+	fibril_mutex_lock( & socket->receive_lock );
+	// wait for a received packet
+	++ socket->blocked;
+	while(( result = dyn_fifo_value( & socket->received )) <= 0 ){
+		fibril_rwlock_read_unlock( & socket_globals.lock );
+		fibril_condvar_wait( & socket->receive_signal, & socket->receive_lock );
+		fibril_rwlock_read_lock( & socket_globals.lock );
+	}
+	-- socket->blocked;
+	fragments = ( size_t ) result;
+	// prepare lengths if more fragments
+	if( fragments > 1 ){
+		lengths = ( size_t * ) malloc( sizeof( size_t ) * fragments + sizeof( size_t ));
+		if( ! lengths ){
+			fibril_mutex_unlock( & socket->receive_lock );
+			fibril_rwlock_read_unlock( & socket_globals.lock );
+			return ENOMEM;
+		}
+		// request packet data
+		message_id = async_send_4( socket->phone, message, ( ipcarg_t ) socket->socket_id, 0, socket->service, ( ipcarg_t ) flags, & answer );
+		// read the address if desired
+		if(( ! fromaddr ) || ( async_data_read_start( socket->phone, fromaddr, * addrlen ) == EOK )){
+		// read the fragment lengths
+			if( async_data_read_start( socket->phone, lengths, sizeof( int ) * ( fragments + 1 )) == EOK ){
+				if( lengths[ fragments ] <= datalength ){
+					// read all fragments if long enough
+					for( index = 0; index < fragments; ++ index ){
+						async_data_read_start( socket->phone, data, lengths[ index ] );
+						data = (( uint8_t * ) data ) + lengths[ index ];
+					}
+				}
+			}
+		}
+		free( lengths );
+	}else{
+		// request packet data
+		message_id = async_send_4( socket->phone, message, ( ipcarg_t ) socket->socket_id, 0, socket->service, ( ipcarg_t ) flags, & answer );
+		// read the address if desired
+		if(( ! fromaddr ) || ( async_data_read_start( socket->phone, fromaddr, * addrlen ) == EOK )){
+			// read all if only one fragment
+			async_data_read_start( socket->phone, data, datalength );
+		}
+	}
+	async_wait_for( message_id, ( ipcarg_t * ) & result );
+	// if successful
+	if( result == EOK ){
+		// dequeue the received packet
+		dyn_fifo_pop( & socket->received );
+		// return read data length
+		result = SOCKET_GET_READ_DATA_LENGTH( answer );
+		// set address length
+		if( fromaddr && addrlen ) * addrlen = SOCKET_GET_ADDRESS_LENGTH( answer );
+	}
+	fibril_mutex_unlock( & socket->receive_lock );
+	fibril_rwlock_read_unlock( & socket_globals.lock );
+	return result;
+}
+
+int getsockopt( int socket_id, int level, int optname, void * value, size_t * optlen ){
+	socket_ref		socket;
+	aid_t			message_id;
+	ipcarg_t		result;
+
+	if( !( value && optlen )) return EBADMEM;
+	if( !( * optlen )) return NO_DATA;
+	fibril_rwlock_read_lock( & socket_globals.lock );
+	// find the socket
+	socket = sockets_find( socket_get_sockets(), socket_id );
+	if( ! socket ){
+		fibril_rwlock_read_unlock( & socket_globals.lock );
+		return ENOTSOCK;
+	}
+	// request option value
+	message_id = async_send_3( socket->phone, NET_SOCKET_GETSOCKOPT, ( ipcarg_t ) socket->socket_id, ( ipcarg_t ) optname, socket->service, NULL );
+	// read the length
+	if( async_data_read_start( socket->phone, optlen, sizeof( * optlen )) == EOK ){
+		// read the value
+		async_data_read_start( socket->phone, value, * optlen );
+	}
+	fibril_rwlock_read_unlock( & socket_globals.lock );
+	async_wait_for( message_id, & result );
+	return ( int ) result;
+}
+
+int setsockopt( int socket_id, int level, int optname, const void * value, size_t optlen ){
+	// send the value
+	return socket_send_data( socket_id, NET_SOCKET_SETSOCKOPT, ( ipcarg_t ) optname, value, optlen );
+
+}
+
+/** @}
+ */
Index: uspace/srv/net/socket/socket_core.c
===================================================================
--- uspace/srv/net/socket/socket_core.c	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/socket/socket_core.c	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,468 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup socket
+ *  @{
+ */
+
+/** @file
+ *  Socket common core implementation.
+ */
+
+#include <limits.h>
+#include <stdlib.h>
+
+#include "../err.h"
+
+#include "../include/in.h"
+#include "../include/inet.h"
+
+#include "../include/socket_codes.h"
+#include "../include/socket_errno.h"
+
+#include "../structures/dynamic_fifo.h"
+#include "../structures/int_map.h"
+#include "../structures/packet/packet.h"
+#include "../structures/packet/packet_client.h"
+
+#include "../modules.h"
+
+#include "socket_core.h"
+
+/** Maximum number of random attempts to find a new socket identifier before switching to the sequence.
+ */
+#define SOCKET_ID_TRIES					100
+
+/** Bound port sockets.
+ */
+struct socket_port{
+	/** The bound sockets map.
+	 */
+	socket_port_map_t	map;
+	/** The bound sockets count.
+	 */
+	int					count;
+};
+
+/** Binds the socket to the port.
+ *  The SOCKET_MAP_KEY_LISTENING key identifier is used.
+ *  @param[in] global_sockets The global sockets to be updated.
+ *  @param[in] socket The socket to be added.
+ *  @param[in] port The port number to be bound to.
+ *  @returns EOK on success.
+ *  @returns ENOMEM if there is not enough memory left.
+ *  @returns Other error codes as defined for the socket_ports_add() function.
+ */
+int	socket_bind_insert( socket_ports_ref global_sockets, socket_core_ref socket, int port );
+
+/** Destroys the socket.
+ *  If the socket is bound, the port is released.
+ *  Releases all buffered packets, calls the release function and removes the socket from the local sockets.
+ *  @param[in] packet_phone The packet server phone to release buffered packets.
+ *  @param[in] socket The socket to be destroyed.
+ *  @param[in,out] local_sockets The local sockets to be updated.
+ *  @param[in,out] global_sockets The global sockets to be updated.
+ *  @param[in] socket_release The client release callback function.
+ */
+void	socket_destroy_core( int packet_phone, socket_core_ref socket, socket_cores_ref local_sockets, socket_ports_ref global_sockets, void ( * socket_release )( socket_core_ref socket ));
+
+/** Adds the socket to a socket port.
+ *  @param[in,out] socket_port The socket port structure.
+ *  @param[in] socket The socket to be added.
+ *  @param[in] key The socket key identifier.
+ *  @param[in] key_length The socket key length.
+ *  @returns EOK on success.
+ *  @returns ENOMEM if there is not enough memory left.
+ */
+int	socket_port_add_core( socket_port_ref socket_port, socket_core_ref socket, const char * key, size_t key_length );
+
+/** Tries to find a new free socket identifier.
+ *  @param[in] local_sockets The local sockets to be searched.
+ *  @param[in] positive A value indicating whether a positive identifier is requested. A negative identifier is requested if set to false.
+ *	@returns The new socket identifier.
+ *  @returns ELIMIT if there is no socket identifier available.
+ */
+static int	socket_generate_new_id( socket_cores_ref local_sockets, int positive );
+
+INT_MAP_IMPLEMENT( socket_cores, socket_core_t );
+
+GENERIC_CHAR_MAP_IMPLEMENT( socket_port_map, socket_core_ref );
+
+INT_MAP_IMPLEMENT( socket_ports, socket_port_t );
+
+void socket_cores_release( int packet_phone, socket_cores_ref local_sockets, socket_ports_ref global_sockets, void ( * socket_release )( socket_core_ref socket )){
+	if( socket_cores_is_valid( local_sockets )){
+		int	index;
+
+		local_sockets->magic = 0;
+		for( index = 0; index < local_sockets->next; ++ index ){
+			if( socket_cores_item_is_valid( &( local_sockets->items[ index ] ))){
+				local_sockets->items[ index ].magic = 0;
+				if( local_sockets->items[ index ].value ){
+					socket_destroy_core( packet_phone, local_sockets->items[ index ].value, local_sockets, global_sockets, socket_release );
+					free( local_sockets->items[ index ].value );
+					local_sockets->items[ index ].value = NULL;
+				}
+			}
+		}
+		free( local_sockets->items );
+	}
+}
+
+void socket_destroy_core( int packet_phone, socket_core_ref socket, socket_cores_ref local_sockets, socket_ports_ref global_sockets, void ( * socket_release )( socket_core_ref socket )){
+	int	packet_id;
+
+	// if bound
+	if( socket->port ){
+		// release the port
+		socket_port_release( global_sockets, socket );
+	}
+	// release all received packets
+	while(( packet_id = dyn_fifo_pop( & socket->received )) >= 0 ){
+		pq_release( packet_phone, packet_id );
+	}
+	dyn_fifo_destroy( & socket->received );
+	dyn_fifo_destroy( & socket->accepted );
+	if( socket_release ){
+		socket_release( socket );
+	}
+	socket_cores_exclude( local_sockets, socket->socket_id );
+}
+
+int socket_bind( socket_cores_ref local_sockets, socket_ports_ref global_sockets, int socket_id, void * addr, size_t addrlen, int free_ports_start, int free_ports_end, int last_used_port ){
+	socket_core_ref			socket;
+	socket_port_ref			socket_port;
+	struct sockaddr *		address;
+	struct sockaddr_in *	address_in;
+
+	if( addrlen < sizeof( struct sockaddr )) return EINVAL;
+	address = ( struct sockaddr * ) addr;
+	switch( address->sa_family ){
+		case AF_INET:
+			if( addrlen != sizeof( struct sockaddr_in )) return EINVAL;
+			address_in = ( struct sockaddr_in * ) addr;
+			// find the socket
+			socket = socket_cores_find( local_sockets, socket_id );
+			if( ! socket ) return ENOTSOCK;
+			// bind a free port?
+			if( address_in->sin_port <= 0 ){
+				return socket_bind_free_port( global_sockets, socket, free_ports_start, free_ports_end, last_used_port );
+			}
+			// try to find the port
+			socket_port = socket_ports_find( global_sockets, ntohs( address_in->sin_port ));
+			if( socket_port ){
+				// already used
+				return EADDRINUSE;
+			}
+			// if bound
+			if( socket->port ){
+				// release the port
+				socket_port_release( global_sockets, socket );
+			}
+			socket->port = -1;
+			return socket_bind_insert( global_sockets, socket, ntohs( address_in->sin_port ));
+			break;
+		// TODO IPv6
+	}
+	return EAFNOSUPPORT;
+}
+
+int socket_bind_free_port( socket_ports_ref global_sockets, socket_core_ref socket, int free_ports_start, int free_ports_end, int last_used_port ){
+	int	index;
+
+	// from the last used one
+	index = last_used_port;
+	do{
+		++ index;
+		// til the range end
+		if( index >= free_ports_end ){
+			// start from the range beginning
+			index = free_ports_start - 1;
+			do{
+				++ index;
+				// til the last used one
+				if( index >= last_used_port ){
+					// none found
+					return ENOTCONN;
+				}
+			}while( socket_ports_find( global_sockets, index ) != NULL );
+			// found, break immediately
+			break;
+		}
+	}while( socket_ports_find( global_sockets, index ) != NULL );
+	return socket_bind_insert( global_sockets, socket, index );
+}
+
+int socket_bind_insert( socket_ports_ref global_sockets, socket_core_ref socket, int port ){
+	ERROR_DECLARE;
+
+	socket_port_ref	socket_port;
+
+	// create a wrapper
+	socket_port = malloc( sizeof( * socket_port ));
+	if( ! socket_port ) return ENOMEM;
+	socket_port->count = 0;
+	if( ERROR_OCCURRED( socket_port_map_initialize( & socket_port->map ))
+	|| ERROR_OCCURRED( socket_port_add_core( socket_port, socket, SOCKET_MAP_KEY_LISTENING, 0 ))){
+		socket_port_map_destroy( & socket_port->map );
+		free( socket_port );
+		return ERROR_CODE;
+	}
+	// register the incomming port
+	ERROR_CODE = socket_ports_add( global_sockets, port, socket_port );
+	if( ERROR_CODE < 0 ){
+		socket_port_map_destroy( & socket_port->map );
+		free( socket_port );
+		return ERROR_CODE;
+	}
+	socket->port = port;
+	return EOK;
+}
+
+
+static int socket_generate_new_id( socket_cores_ref local_sockets, int positive ){
+	int			socket_id;
+	int			count;
+
+	count = 0;
+//	socket_id = socket_globals.last_id;
+	do{
+		if( count < SOCKET_ID_TRIES ){
+			socket_id = rand() % INT_MAX;
+			++ count;
+		}else if( count == SOCKET_ID_TRIES ){
+			socket_id = 1;
+			++ count;
+		// only this branch for last_id
+		}else{
+			if( socket_id < INT_MAX ){
+				++ socket_id;
+/*			}else if( socket_globals.last_id ){
+*				socket_globals.last_id = 0;
+*				socket_id = 1;
+*/			}else{
+				return ELIMIT;
+			}
+		}
+	}while( socket_cores_find( local_sockets, (( positive ? 1 : -1 ) * socket_id )));
+//	last_id = socket_id
+	return socket_id;
+}
+
+int socket_create( socket_cores_ref local_sockets, int app_phone, void * specific_data, int * socket_id ){
+	ERROR_DECLARE;
+
+	socket_core_ref	socket;
+	int				res;
+	int				positive;
+
+	if( ! socket_id ) return EINVAL;
+	// store the socket
+	if( * socket_id <= 0 ){
+		positive = ( * socket_id == 0 );
+		* socket_id = socket_generate_new_id( local_sockets, positive );
+		if( * socket_id <= 0 ){
+			return * socket_id;
+		}
+		if( ! positive ){
+			* socket_id *= -1;
+		}
+	}else if( socket_cores_find( local_sockets, * socket_id )){
+		return EEXIST;
+	}
+	socket = ( socket_core_ref ) malloc( sizeof( * socket ));
+	if( ! socket ) return ENOMEM;
+	// initialize
+	socket->phone = app_phone;
+	socket->port = -1;
+	socket->key = NULL;
+	socket->key_length = 0;
+	socket->specific_data = specific_data;
+	if( ERROR_OCCURRED( dyn_fifo_initialize( & socket->received, SOCKET_INITIAL_RECEIVED_SIZE ))){
+		free( socket );
+		return ERROR_CODE;
+	}
+	if( ERROR_OCCURRED( dyn_fifo_initialize( & socket->accepted, SOCKET_INITIAL_ACCEPTED_SIZE ))){
+		dyn_fifo_destroy( & socket->received );
+		free( socket );
+		return ERROR_CODE;
+	}
+	socket->socket_id = * socket_id;
+	res = socket_cores_add( local_sockets, socket->socket_id, socket );
+	if( res < 0 ){
+		dyn_fifo_destroy( & socket->received );
+		dyn_fifo_destroy( & socket->accepted );
+		free( socket );
+		return res;
+	}
+	return EOK;
+}
+
+int socket_destroy( int packet_phone, int socket_id, socket_cores_ref local_sockets, socket_ports_ref global_sockets, void ( * socket_release )( socket_core_ref socket )){
+	socket_core_ref	socket;
+	int				accepted_id;
+
+	// find the socket
+	socket = socket_cores_find( local_sockets, socket_id );
+	if( ! socket ) return ENOTSOCK;
+	// destroy all accepted sockets
+	while(( accepted_id = dyn_fifo_pop( & socket->accepted )) >= 0 ){
+		socket_destroy( packet_phone, accepted_id, local_sockets, global_sockets, socket_release );
+	}
+	socket_destroy_core( packet_phone, socket, local_sockets, global_sockets, socket_release );
+	return EOK;
+}
+
+int socket_reply_packets( packet_t packet, size_t * length ){
+	ERROR_DECLARE;
+
+	packet_t		next_packet;
+	size_t			fragments;
+	size_t *		lengths;
+	size_t			index;
+
+	if( ! length ) return EBADMEM;
+	next_packet = pq_next( packet );
+	if( ! next_packet ){
+		// write all if only one fragment
+		ERROR_PROPAGATE( data_reply( packet_get_data( packet ), packet_get_data_length( packet )));
+		// 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 );
+		}while( next_packet );
+		// write the fragment lengths
+		ERROR_PROPAGATE( data_reply( lengths, sizeof( int ) * ( fragments + 1 )));
+		next_packet = packet;
+		// write the fragments
+		for( index = 0; index < fragments; ++ index ){
+			ERROR_PROPAGATE( data_reply( packet_get_data( next_packet ), lengths[ index ] ));
+			next_packet = pq_next( next_packet );
+		}while( next_packet );
+		// store the total length
+		* length = lengths[ fragments ];
+		free( lengths );
+	}
+	return EOK;
+}
+
+socket_core_ref socket_port_find( socket_ports_ref global_sockets, int port, const char * key, size_t key_length ){
+	socket_port_ref		socket_port;
+	socket_core_ref *	socket_ref;
+
+	socket_port = socket_ports_find( global_sockets, port );
+	if( socket_port && ( socket_port->count > 0 )){
+		socket_ref = socket_port_map_find( & socket_port->map, key, key_length );
+		if( socket_ref ){
+			return * socket_ref;
+		}
+	}
+	return NULL;
+}
+
+void socket_port_release( socket_ports_ref global_sockets, socket_core_ref socket ){
+	socket_port_ref	socket_port;
+	socket_core_ref *	socket_ref;
+
+	if( socket->port ){
+		// find ports
+		socket_port = socket_ports_find( global_sockets, socket->port );
+		if( socket_port ){
+			// find the socket
+			socket_ref = socket_port_map_find( & socket_port->map, socket->key, socket->key_length );
+			if( socket_ref ){
+				-- socket_port->count;
+				// release if empty
+				if( socket_port->count <= 0 ){
+					// destroy the map
+					socket_port_map_destroy( & socket_port->map );
+					// release the port
+					socket_ports_exclude( global_sockets, socket->port );
+				}else{
+					// remove
+					socket_port_map_exclude( & socket_port->map, socket->key, socket->key_length );
+				}
+			}
+		}
+		socket->port = 0;
+		socket->key = NULL;
+		socket->key_length = 0;
+	}
+}
+
+int socket_port_add( socket_ports_ref global_sockets, int port, socket_core_ref socket, const char * key, size_t key_length ){
+	ERROR_DECLARE;
+
+	socket_port_ref		socket_port;
+
+	// find ports
+	socket_port = socket_ports_find( global_sockets, port );
+	if( ! socket_port ) return ENOENT;
+	// add the socket
+	ERROR_PROPAGATE( socket_port_add_core( socket_port, socket, key, key_length ));
+	socket->port = port;
+	return EOK;
+}
+
+int socket_port_add_core( socket_port_ref socket_port, socket_core_ref socket, const char * key, size_t key_length ){
+	ERROR_DECLARE;
+
+	socket_core_ref *	socket_ref;
+
+	// create a wrapper
+	socket_ref = malloc( sizeof( * socket_ref ));
+	if( ! socket_ref ) return ENOMEM;
+	* socket_ref = socket;
+	// add the wrapper
+	if( ERROR_OCCURRED( socket_port_map_add( & socket_port->map, key, key_length, socket_ref ))){
+		free( socket_ref );
+		return ERROR_CODE;
+	}
+	++ socket_port->count;
+	socket->key = key;
+	socket->key_length = key_length;
+	return EOK;
+}
+
+/** @}
+ */
Index: uspace/srv/net/socket/socket_core.h
===================================================================
--- uspace/srv/net/socket/socket_core.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/socket/socket_core.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,243 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup socket
+ *  @{
+ */
+
+/** @file
+ *  Socket common core.
+ */
+
+#ifndef __NET_SOCKET_CORE_H__
+#define __NET_SOCKET_CORE_H__
+
+#include <sys/types.h>
+
+#include "../include/in.h"
+#include "../include/device.h"
+
+#include "../structures/generic_char_map.h"
+#include "../structures/dynamic_fifo.h"
+#include "../structures/int_map.h"
+#include "../structures/packet/packet.h"
+
+/** Initial size of the received packet queue.
+ */
+#define SOCKET_INITIAL_RECEIVED_SIZE	4
+
+/** Maximum size of the received packet queue.
+ */
+#define SOCKET_MAX_RECEIVED_SIZE		0
+
+/** Initial size of the sockets for acceptance queue.
+ */
+#define SOCKET_INITIAL_ACCEPTED_SIZE	1
+
+/** Maximum size of the sockets for acceptance queue.
+ */
+#define SOCKET_MAX_ACCEPTEDED_SIZE		0
+
+/** Listening sockets' port map key.
+ */
+#define SOCKET_MAP_KEY_LISTENING	"L"
+
+/** Type definition of the socket core.
+ *  @see socket_core
+ */
+typedef struct socket_core	socket_core_t;
+
+/** Type definition of the socket core pointer.
+ *  @see socket_core
+ */
+typedef socket_core_t *	socket_core_ref;
+
+/** Type definition of the socket port.
+ *  @see socket_port
+ */
+typedef struct socket_port	socket_port_t;
+
+/** Type definition of the socket port pointer.
+ *  @see socket_port
+ */
+typedef socket_port_t *	socket_port_ref;
+
+/** Socket core.
+ */
+struct socket_core{
+	/** Socket identifier.
+	 */
+	int				socket_id;
+	/** Client application phone.
+	 */
+	int				phone;
+	/** Bound port.
+	 */
+	int				port;
+	/** Received packets queue.
+	 */
+	dyn_fifo_t		received;
+	/** Sockets for acceptance queue.
+	 */
+	dyn_fifo_t		accepted;
+	/** Protocol specific data.
+	 */
+	void *			specific_data;
+	/** Socket ports map key.
+	 */
+	const char *	key;
+	/** Length of the Socket ports map key.
+	 */
+	size_t			key_length;
+};
+
+/** Sockets map.
+ *  The key is the socket identifier.
+ */
+INT_MAP_DECLARE( socket_cores, socket_core_t );
+
+/** Bount port sockets map.
+ *  The listening socket has the SOCKET_MAP_KEY_LISTENING key identifier whereas the other use the remote addresses.
+ */
+GENERIC_CHAR_MAP_DECLARE( socket_port_map, socket_core_ref );
+
+/** Ports map.
+ *  The key is the port number.
+ */
+INT_MAP_DECLARE( socket_ports, socket_port_t );
+
+/** Destroys local sockets.
+ *  Releases all buffered packets and calls the release function for each of the sockets.
+ *  @param[in] packet_phone The packet server phone to release buffered packets.
+ *  @param[in] local_sockets The local sockets to be destroyed.
+ *  @param[in,out] global_sockets The global sockets to be updated.
+ *  @param[in] socket_release The client release callback function.
+ */
+void	socket_cores_release( int packet_phone, socket_cores_ref local_sockets, socket_ports_ref global_sockets, void ( * socket_release )( socket_core_ref socket ));
+
+/** Binds the socket to the port.
+ *  The address port is used if set, a free port is used if not.
+ *  @param[in] local_sockets The local sockets to be searched.
+ *  @param[in,out] global_sockets The global sockets to be updated.
+ *  @param[in] socket_id The new socket identifier.
+ *  @param[in] addr The address to be bound to.
+ *  @param[in] addrlen The address length.
+ *  @param[in] free_ports_start The minimum free port.
+ *  @param[in] free_ports_end The maximum free port.
+ *  @param[in] last_used_port The last used free port.
+ *  @returns EOK on success.
+ *  @returns ENOTSOCK if the socket was not found.
+ *  @returns EAFNOSUPPORT if the address family is not supported.
+ *  @returns EADDRINUSE if the port is already in use.
+ *  @returns Other error codes as defined for the socket_bind_free_port() function.
+ *  @returns Other error codes as defined for the socket_bind_insert() function.
+ */
+int socket_bind( socket_cores_ref local_sockets, socket_ports_ref global_sockets, int socket_id, void * addr, size_t addrlen, int free_ports_start, int free_ports_end, int last_used_port );
+
+/** Binds the socket to a free port.
+ *  The first free port is used.
+ *  @param[in,out] global_sockets The global sockets to be updated.
+ *  @param[in,out] socket The socket to be bound.
+ *  @param[in] free_ports_start The minimum free port.
+ *  @param[in] free_ports_end The maximum free port.
+ *  @param[in] last_used_port The last used free port.
+ *  @returns EOK on success.
+ *  @returns ENOTCONN if no free port was found.
+ *  @returns Other error codes as defined for the socket_bind_insert() function.
+ */
+int	socket_bind_free_port( socket_ports_ref global_sockets, socket_core_ref socket, int free_ports_start, int free_ports_end, int last_used_port );
+
+/** Creates a new socket.
+ *  @param[in,out] local_sockets The local sockets to be updated.
+ *  @param[in] app_phone The application phone.
+ *  @param[in] specific_data The socket specific data.
+ *  @param[in,out] socket_id The new socket identifier. A new identifier is chosen if set to zero (0) or negative. A negative identifier is chosen if set to negative.
+ *  @returns EOK on success.
+ *  @returns EINVAL if the socket_id parameter is NULL.
+ *  @returns ENOMEM if there is not enough memory left.
+ */
+int socket_create( socket_cores_ref local_sockets, int app_phone, void * specific_data, int * socket_id );
+
+/** Destroys the socket.
+ *  If the socket is bound, the port is released.
+ *  Releases all buffered packets, calls the release function and removes the socket from the local sockets.
+ *  @param[in] packet_phone The packet server phone to release buffered packets.
+ *  @param[in] socket_id The socket identifier.
+ *  @param[in,out] local_sockets The local sockets to be updated.
+ *  @param[in,out] global_sockets The global sockets to be updated.
+ *  @param[in] socket_release The client release callback function.
+ *  @returns EOK on success.
+ *  @returns ENOTSOCK if the socket is not found.
+ */
+int socket_destroy( int packet_phone, int socket_id, socket_cores_ref local_sockets, socket_ports_ref global_sockets, void ( * socket_release )( socket_core_ref socket ));
+
+/** 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.
+ *  @returns EOK on success.
+ *  @returns EBADMEM if the length parameter is NULL.
+ *  @returns ENOMEM if there is not enough memory left.
+ *  @returns Other error codes as defined for the data_reply() function.
+ */
+int	socket_reply_packets( packet_t packet, size_t * length );
+
+/** Finds the bound port socket.
+ *  @param[in] global_sockets The global sockets to be searched.
+ *  @param[in] port The port number.
+ *  @param[in] key The socket key identifier.
+ *  @param[in] key_length The socket key length.
+ *  @returns The found socket.
+ *  @returns NULL if no socket was found.
+ */
+socket_core_ref	socket_port_find( socket_ports_ref global_sockets, int port, const char * key, size_t key_length );
+
+/** Releases the socket port.
+ *  If the socket is bound the port entry is released.
+ *  If there are no more port entries the port is release.
+ *  @param[in] global_sockets The global sockets to be updated.
+ *  @param[in] socket The socket to be unbound.
+ */
+void	socket_port_release( socket_ports_ref global_sockets, socket_core_ref socket );
+
+/** Adds the socket to an already bound port.
+ *  @param[in] global_sockets The global sockets to be updated.
+ *  @param[in] port The port number to be bound to.
+ *  @param[in] socket The socket to be added.
+ *  @param[in] key The socket key identifier.
+ *  @param[in] key_length The socket key length.
+ *  @returns EOK on success.
+ *  @returns ENOENT if the port is not already used.
+ *  @returns Other error codes as defined for the socket_port_add_core() function.
+ */
+int	socket_port_add( socket_ports_ref global_sockets, int port, socket_core_ref socket, const char * key, size_t key_length );
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/socket/socket_messages.h
===================================================================
--- uspace/srv/net/socket/socket_messages.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/socket/socket_messages.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup socket
+ *  @{
+ */
+
+/** @file
+ *  Socket messages.
+ *  @see socket.h
+ */
+
+
+#ifndef __NET_SOCKET_MESSAGES_H__
+#define __NET_SOCKET_MESSAGES_H__
+
+#include <ipc/ipc.h>
+
+#include "../messages.h"
+
+#include "../include/socket_codes.h"
+
+/** Socket client messages.
+ */
+typedef enum{
+	/** Creates a new socket.
+	 *  @see socket()
+	 */
+	NET_SOCKET = NET_SOCKET_FIRST,
+	/** Binds the socket.
+	 *  @see bind()
+	 */
+	NET_SOCKET_BIND,
+	/** Creates a new socket.
+	 *  @see socket()
+	 */
+	NET_SOCKET_LISTEN,
+	/** Accepts an incomming connection.
+	 *  @see accept()
+	 */
+	NET_SOCKET_ACCEPT,
+	/** Connects the socket.
+	 *  @see connect()
+	 */
+	NET_SOCKET_CONNECT,
+	/** Closes the socket.
+	 *  @see closesocket()
+	 */
+	NET_SOCKET_CLOSE,
+	/** Sends data via the stream socket.
+	 *  @see send()
+	 */
+	NET_SOCKET_SEND,
+	/** Sends data via the datagram socket.
+	 *  @see sendto()
+	 */
+	NET_SOCKET_SENDTO,
+	/** Receives data from the stream socket.
+	 *  @see socket()
+	 */
+	NET_SOCKET_RECV,
+	/** Receives data from the datagram socket.
+	 *  @see socket()
+	 */
+	NET_SOCKET_RECVFROM,
+	/** Gets the socket option.
+	 *  @see getsockopt()
+	 */
+	NET_SOCKET_GETSOCKOPT,
+	/** Sets the socket option.
+	 *  @see setsockopt()
+	 */
+	NET_SOCKET_SETSOCKOPT,
+	/** New socket for acceptence notification message.
+	 */
+	NET_SOCKET_ACCEPTED,
+	/** New data received notification message.
+	 */
+	NET_SOCKET_RECEIVED,
+	/** New socket data fragment size notification message.
+	 */
+	NET_SOCKET_DATA_FRAGMENT_SIZE
+} socket_messages;
+
+/** @name Socket specific message parameters definitions
+ */
+/*@{*/
+
+/** Sets the socket identifier in the message answer.
+ *  @param[out] answer The message answer structure.
+ */
+#define SOCKET_SET_SOCKET_ID( answer )			( int * ) & IPC_GET_ARG1( answer )
+
+/** Returns the socket identifier message parameter.
+ *  @param[in] call The message call structure.
+ */
+#define SOCKET_GET_SOCKET_ID( call )			( int ) IPC_GET_ARG1( call )
+
+/** Sets the read data length in the message answer.
+ *  @param[out] answer The message answer structure.
+ */
+#define SOCKET_SET_READ_DATA_LENGTH( answer )	( int * ) & IPC_GET_ARG1( answer )
+
+/** Returns the read data length message parameter.
+ *  @param[in] call The message call structure.
+ */
+#define SOCKET_GET_READ_DATA_LENGTH( call )		( int ) IPC_GET_ARG1( call )
+
+/** Returns the backlog message parameter.
+ *  @param[in] call The message call structure.
+ */
+#define SOCKET_GET_BACKLOG( call )				( int ) IPC_GET_ARG2( call )
+
+/** Returns the option level message parameter.
+ *  @param[in] call The message call structure.
+ */
+#define SOCKET_GET_OPT_LEVEL( call )			( int ) IPC_GET_ARG2( call )
+
+/** Returns the data fragment size message parameter.
+ *  @param[in] call The message call structure.
+ */
+#define SOCKET_GET_DATA_FRAGMENT_SIZE( call )	( size_t ) IPC_GET_ARG2( call )
+
+/** Sets the data fragment size in the message answer.
+ *  @param[out] answer The message answer structure.
+ */
+#define SOCKET_SET_DATA_FRAGMENT_SIZE( answer )	( size_t * ) & IPC_GET_ARG2( answer )
+
+/** Sets the address length in the message answer.
+ *  @param[out] answer The message answer structure.
+ */
+#define SOCKET_SET_ADDRESS_LENGTH( answer )		( socklen_t * ) & IPC_GET_ARG3( answer )
+
+/** Returns the address length message parameter.
+ *  @param[in] call The message call structure.
+ */
+#define SOCKET_GET_ADDRESS_LENGTH( call )		( socklen_t ) IPC_GET_ARG3( call )
+
+/** Sets the header size in the message answer.
+ *  @param[out] answer The message answer structure.
+ */
+#define SOCKET_SET_HEADER_SIZE( answer )		( int * ) & IPC_GET_ARG3( answer )
+
+/** Returns the header size message parameter.
+ *  @param[in] call The message call structure.
+ */
+#define SOCKET_GET_HEADER_SIZE( call )			( int ) IPC_GET_ARG3( call )
+
+/** Returns the flags message parameter.
+ *  @param[in] call The message call structure.
+ */
+#define SOCKET_GET_FLAGS( call )				( int ) IPC_GET_ARG4( call )
+
+/** Returns the option name message parameter.
+ *  @param[in] call The message call structure.
+ */
+#define SOCKET_GET_OPT_NAME( call )				( int ) IPC_GET_ARG4( call )
+
+/** Returns the data fragments message parameter.
+ *  @param[in] call The message call structure.
+ */
+#define SOCKET_GET_DATA_FRAGMENTS( call )		( int ) IPC_GET_ARG5( call )
+
+/** Returns the new socket identifier message parameter.
+ *  @param[in] call The message call structure.
+ */
+#define SOCKET_GET_NEW_SOCKET_ID( call )		( int ) IPC_GET_ARG5( call )
+
+/*@}*/
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/structures/char_map.c
===================================================================
--- uspace/srv/net/structures/char_map.c	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/structures/char_map.c	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,222 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup net
+ *  @{
+ */
+
+/** @file
+ *  Character string to integer map implementation.
+ *  @see char_map.h
+ */
+
+#include <errno.h>
+#include <malloc.h>
+#include <mem.h>
+#include <unistd.h>
+
+#include "char_map.h"
+
+/** Internal magic value for a&nbsp;consistency check.
+ */
+#define CHAR_MAP_MAGIC_VALUE	0x12345611
+
+/** Adds the value with the key to the map.
+ *  Creates new nodes to map the key.
+ *  @param[in,out] map The character string to integer map.
+ *  @param[in] identifier The key zero ('\\0') terminated character string. The key character string is processed until the first terminating zero ('\\0') character after the given length is found.
+ *  @param[in] length The key character string length. The parameter may be zero (0) which means that the string is processed until the terminating zero ('\\0') character is found.
+ *  @param[in] value The integral value to be stored for the key character string.
+ *  @returns EOK on success.
+ *  @returns ENOMEM if there is not enough memory left.
+ *  @returns EEXIST if the key character string is already used.
+ */
+int	char_map_add_item( char_map_ref map, const char * identifier, size_t length, const int value );
+
+/** Returns the node assigned to the key from the map.
+ *  @param[in] map The character string to integer map.
+ *  @param[in] identifier The key zero ('\\0') terminated character string. The key character string is processed until the first terminating zero ('\\0') character after the given length is found.
+ *  @param[in] length The key character string length. The parameter may be zero (0) which means that the string is processed until the terminating zero ('\\0') character is found.
+ *  @returns The node holding the integral value assigned to the key character string.
+ *  @returns NULL if the key is not assigned a&nbsp;node.
+ */
+char_map_ref	char_map_find_node( const char_map_ref map, const char * identifier, const size_t length );
+
+/** Returns the value assigned to the map.
+ *  @param[in] map The character string to integer map.
+ *  @returns The integral value assigned to the map.
+ *  @returns CHAR_MAP_NULL if the map is not assigned a&nbsp;value.
+ */
+int	char_map_get_value( const char_map_ref map );
+
+/** Checks if the map is valid.
+ *  @param[in] map The character string to integer map.
+ *  @returns TRUE if the map is valid.
+ *  @returns FALSE otherwise.
+ */
+int	char_map_is_valid( const char_map_ref map );
+
+int char_map_add( char_map_ref map, const char * identifier, size_t length, const int value ){
+	if( char_map_is_valid( map ) && ( identifier ) && (( length ) || ( * identifier ))){
+		int	index;
+
+		for( index = 0; index < map->next; ++ index ){
+			if( map->items[ index ]->c == * identifier ){
+				++ identifier;
+				if(( length > 1 ) || (( length == 0 ) && ( * identifier ))){
+					return char_map_add( map->items[ index ], identifier, length ? length - 1 : 0, value );
+				}else{
+					if( map->items[ index ]->value != CHAR_MAP_NULL ) return EEXISTS;
+					map->items[ index ]->value = value;
+					return EOK;
+				}
+			}
+		}
+		return char_map_add_item( map, identifier, length, value );
+	}
+	return EINVAL;
+}
+
+int char_map_add_item( char_map_ref map, const char * identifier, size_t length, const int value ){
+	if( map->next == ( map->size - 1 )){
+		char_map_ref	* tmp;
+
+		tmp = ( char_map_ref * ) realloc( map->items, sizeof( char_map_ref ) * 2 * map->size );
+		if( ! tmp ) return ENOMEM;
+		map->size *= 2;
+		map->items = tmp;
+	}
+	map->items[ map->next ] = ( char_map_ref ) malloc( sizeof( char_map_t ));
+	if( ! map->items[ map->next ] ) return ENOMEM;
+	if( char_map_initialize( map->items[ map->next ] ) != EOK ){
+		free( map->items[ map->next ] );
+		map->items[ map->next ] = NULL;
+		return ENOMEM;
+	}
+	map->items[ map->next ]->c = * identifier;
+	++ identifier;
+	++ map->next;
+	if(( length > 1 ) || (( length == 0 ) && ( * identifier ))){
+		map->items[ map->next - 1 ]->value = CHAR_MAP_NULL;
+		return char_map_add_item( map->items[ map->next - 1 ], identifier, length ? length - 1 : 0, value );
+	}else{
+		map->items[ map->next - 1 ]->value = value;
+	}
+	return EOK;
+}
+
+void char_map_destroy( char_map_ref map ){
+	if( char_map_is_valid( map )){
+		int	index;
+
+		map->magic = 0;
+		for( index = 0; index < map->next; ++ index ){
+			char_map_destroy( map->items[ index ] );
+		}
+		free( map->items );
+		map->items = NULL;
+	}
+}
+
+int char_map_exclude( char_map_ref map, const char * identifier, size_t length ){
+	char_map_ref	node;
+
+	node = char_map_find_node( map, identifier, length );
+	if( node ){
+		int	value;
+
+		value = node->value;
+		node->value = CHAR_MAP_NULL;
+		return value;
+	}
+	return CHAR_MAP_NULL;
+}
+
+int char_map_find( const char_map_ref map, const char * identifier, size_t length ){
+	char_map_ref	node;
+
+	node = char_map_find_node( map, identifier, length );
+	return node ? node->value : CHAR_MAP_NULL;
+}
+
+char_map_ref char_map_find_node( const char_map_ref map, const char * identifier, size_t length ){
+	if( ! char_map_is_valid( map )) return NULL;
+	if( length || ( * identifier )){
+		int	index;
+
+		for( index = 0; index < map->next; ++ index ){
+			if( map->items[ index ]->c == * identifier ){
+				++ identifier;
+				if( length == 1 ) return map->items[ index ];
+				return char_map_find_node( map->items[ index ], identifier, length ? length - 1 : 0 );
+			}
+		}
+		return NULL;
+	}
+	return map;
+}
+
+int char_map_get_value( const char_map_ref map ){
+	return char_map_is_valid( map ) ? map->value : CHAR_MAP_NULL;
+}
+
+int char_map_initialize( char_map_ref map ){
+	if( ! map ) return EINVAL;
+	map->c = '\0';
+	map->value = CHAR_MAP_NULL;
+	map->size = 2;
+	map->next = 0;
+	map->items = malloc( sizeof( char_map_ref ) * map->size );
+	if( ! map->items ){
+		map->magic = 0;
+		return ENOMEM;
+	}
+	map->items[ map->next ] = NULL;
+	map->magic = CHAR_MAP_MAGIC_VALUE;
+	return EOK;
+}
+
+int char_map_is_valid( const char_map_ref map ){
+	return map && ( map->magic == CHAR_MAP_MAGIC_VALUE );
+}
+
+int char_map_update( char_map_ref map, const char * identifier, const size_t length, const int value ){
+	char_map_ref	node;
+
+//	if( ! char_map_is_valid( map )) return EINVAL;
+	node = char_map_find_node( map, identifier, length );
+	if( node ){
+		node->value = value;
+		return EOK;
+	}else{
+		return char_map_add( map, identifier, length, value );
+	}
+}
+
+/** @}
+ */
Index: uspace/srv/net/structures/char_map.h
===================================================================
--- uspace/srv/net/structures/char_map.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/structures/char_map.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup net
+ *  @{
+ */
+
+/** @file
+ *  Character string to integer map.
+ */
+
+#ifndef __CHAR_MAP_H__
+#define __CHAR_MAP_H__
+
+/** Invalid assigned value used also if an&nbsp;entry does not exist.
+ */
+#define CHAR_MAP_NULL	( -1 )
+
+/** Type definition of the character string to integer map.
+ *  @see char_map
+ */
+typedef struct char_map	char_map_t;
+
+/** Type definition of the character string to integer map pointer.
+ *  @see char_map
+ */
+typedef char_map_t *	char_map_ref;
+
+/** Character string to integer map item.
+ *  This structure recursivelly contains itself as a&nbsp;character by character tree.
+ *  The actually mapped character string consists o fall the parent characters and the actual one.
+ */
+struct	char_map{
+	/** Actually mapped character.
+	 */
+	char			c;
+	/** Stored integral value.
+	 */
+	int				value;
+	/** Next character array size.
+	 */
+	int				size;
+	/** First free position in the next character array.
+	 */
+	int				next;
+	/** Next character array.
+	 */
+	char_map_ref *	items;
+	/** Consistency check magic value.
+	 */
+	int				magic;
+};
+
+/** Adds the value with the key to the map.
+ *  @param[in,out] map The character string to integer map.
+ *  @param[in] identifier The key zero ('\\0') terminated character string. The key character string is processed until the first terminating zero ('\\0') character after the given length is found.
+ *  @param[in] length The key character string length. The parameter may be zero (0) which means that the string is processed until the terminating zero ('\\0') character is found.
+ *  @param[in] value The integral value to be stored for the key character string.
+ *  @returns EOK on success.
+ *  @returns EINVAL if the map is not valid.
+ *  @returns EINVAL if the identifier parameter is NULL.
+ *  @returns EINVAL if the length parameter zero (0) and the identifier parameter is an empty character string (the first character is the terminating zero ('\\0') character.
+ *  @returns EEXIST if the key character string is already used.
+ *  @returns Other error codes as defined for the char_map_add_item() function.
+ */
+int	char_map_add( char_map_ref map, const char * identifier, size_t length, const int value );
+
+/** Clears and destroys the map.
+ *  @param[in,out] map The character string to integer map.
+ */
+void	char_map_destroy( char_map_ref map );
+
+/** Excludes the value assigned to the key from the map.
+ *  The entry is cleared from the map.
+ *  @param[in,out] map The character string to integer map.
+ *  @param[in] identifier The key zero ('\\0') terminated character string. The key character string is processed until the first terminating zero ('\\0') character after the given length is found.
+ *  @param[in] length The key character string length. The parameter may be zero (0) which means that the string is processed until the terminating zero ('\\0') character is found.
+ *  @returns The integral value assigned to the key character string.
+ *  @returns CHAR_MAP_NULL if the key is not assigned a&nbsp;value.
+ */
+int	char_map_exclude( char_map_ref map, const char * identifier, size_t length );
+
+/** Returns the value assigned to the key from the map.
+ *  @param[in] map The character string to integer map.
+ *  @param[in] identifier The key zero ('\\0') terminated character string. The key character string is processed until the first terminating zero ('\\0') character after the given length is found.
+ *  @param[in] length The key character string length. The parameter may be zero (0) which means that the string is processed until the terminating zero ('\\0') character is found.
+ *  @returns The integral value assigned to the key character string.
+ *  @returns CHAR_MAP_NULL if the key is not assigned a&nbsp;value.
+ */
+int	char_map_find( const char_map_ref map, const char * identifier, size_t length );
+
+/** Initializes the map.
+ *  @param[in,out] map The character string to integer map.
+ *  @returns EOK on success.
+ *  @returns EINVAL if the map parameter is NULL.
+ *  @returns ENOMEM if there is not enough memory left.
+ */
+int	char_map_initialize( char_map_ref map );
+
+/** Adds or updates the value with the key to the map.
+ *  @param[in,out] map The character string to integer map.
+ *  @param[in] identifier The key zero ('\\0') terminated character string. The key character string is processed until the first terminating zero ('\\0') character after the given length is found.
+ *  @param[in] length The key character string length. The parameter may be zero (0) which means that the string is processed until the terminating zero ('\\0') character is found.
+ *  @param[in] value The integral value to be stored for the key character string.
+ *  @returns EOK on success.
+ *  @returns EINVAL if the map is not valid.
+ *  @returns EINVAL if the identifier parameter is NULL.
+ *  @returns EINVAL if the length parameter zero (0) and the identifier parameter is an empty character string (the first character is the terminating zero ('\\0) character.
+ *  @returns EEXIST if the key character string is already used.
+ *  @returns Other error codes as defined for the char_map_add_item() function.
+ */
+int	char_map_update( char_map_ref map, const char * identifier, size_t length, const int value );
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/structures/dynamic_fifo.c
===================================================================
--- uspace/srv/net/structures/dynamic_fifo.c	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/structures/dynamic_fifo.c	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup net
+ *  @{
+ */
+
+/** @file
+ *  Dynamic first in first out positive integer queue implementation.
+ */
+
+#include <errno.h>
+#include <malloc.h>
+#include <mem.h>
+
+#include "dynamic_fifo.h"
+
+/** Internal magic value for a&nbsp;consistency check.
+ */
+#define DYN_FIFO_MAGIC_VALUE	0x58627659
+
+/** Returns the next queue index.
+ *  The queue field is circular.
+ *  @param[in] fifo The dynamic queue.
+ *  @param[in] index The actual index to be shifted.
+ */
+#define NEXT_INDEX( fifo, index )	((( index ) + 1 ) % (( fifo )->size + 1 ))
+
+/** Checks if the queue is valid.
+ *  @param[in] fifo The dynamic queue.
+ *  @returns TRUE if the queue is valid.
+ *  @returns FALSE otherwise.
+ */
+int	dyn_fifo_is_valid( dyn_fifo_ref fifo );
+
+int dyn_fifo_is_valid( dyn_fifo_ref fifo ){
+	return fifo && ( fifo->magic_value == DYN_FIFO_MAGIC_VALUE );
+}
+
+int dyn_fifo_initialize( dyn_fifo_ref fifo, int size ){
+	if( ! fifo ) return EBADMEM;
+	if( size <= 0 ) return EINVAL;
+	fifo->items = ( int * ) malloc( sizeof( int ) * size + 1 );
+	if( ! fifo->items ) return ENOMEM;
+	fifo->size = size;
+	fifo->head = 0;
+	fifo->tail = 0;
+	fifo->magic_value = DYN_FIFO_MAGIC_VALUE;
+	return EOK;
+}
+
+int	dyn_fifo_push( dyn_fifo_ref fifo, int value, int max_size ){
+	int *	new_items;
+
+	if( ! dyn_fifo_is_valid( fifo )) return EINVAL;
+	if( NEXT_INDEX( fifo, fifo->tail ) == fifo->head ){
+		if(( max_size > 0 ) && (( fifo->size * 2 ) > max_size )){
+			if( fifo->size >= max_size ) return ENOMEM;
+		}else{
+			max_size = fifo->size * 2;
+		}
+		new_items = realloc( fifo->items, sizeof( int ) * max_size + 1 );
+		if( ! new_items ) return ENOMEM;
+		fifo->items = new_items;
+		if( fifo->tail < fifo->head ){
+			if( fifo->tail < max_size - fifo->size ){
+				memcpy( fifo->items + fifo->size + 1, fifo->items, fifo->tail * sizeof( int ));
+				fifo->tail += fifo->size + 1;
+			}else{
+				memcpy( fifo->items + fifo->size + 1, fifo->items, ( max_size - fifo->size ) * sizeof( int ));
+				memcpy( fifo->items, fifo->items + max_size - fifo->size, fifo->tail - max_size + fifo->size );
+				fifo->tail -= max_size - fifo->size;
+			}
+		}
+		fifo->size = max_size;
+	}
+	fifo->items[ fifo->tail ] = value;
+	fifo->tail = NEXT_INDEX( fifo, fifo->tail );
+	return EOK;
+}
+
+int dyn_fifo_pop( dyn_fifo_ref fifo ){
+	int	value;
+
+	if( ! dyn_fifo_is_valid( fifo )) return EINVAL;
+	if( fifo->head == fifo->tail ) return ENOENT;
+	value = fifo->items[ fifo->head ];
+	fifo->head = NEXT_INDEX( fifo, fifo->head );
+	return value;
+}
+
+int dyn_fifo_value( dyn_fifo_ref fifo ){
+	if( ! dyn_fifo_is_valid( fifo )) return EINVAL;
+	if( fifo->head == fifo->tail ) return ENOENT;
+	return fifo->items[ fifo->head ];
+}
+
+int dyn_fifo_destroy( dyn_fifo_ref fifo ){
+	if( ! dyn_fifo_is_valid( fifo )) return EINVAL;
+	free( fifo->items );
+	fifo->magic_value = 0;
+	return EOK;
+}
+
+/** @}
+ */
Index: uspace/srv/net/structures/dynamic_fifo.h
===================================================================
--- uspace/srv/net/structures/dynamic_fifo.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/structures/dynamic_fifo.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup net
+ *  @{
+ */
+
+/** @file
+ *  Dynamic first in first out positive integer queue.
+ *  Possitive integer values only.
+ */
+
+#ifndef __NET_DYNAMIC_FIFO_H__
+#define __NET_DYNAMIC_FIFO_H__
+
+/** Type definition of the dynamic fifo queue.
+ *  @see dyn_fifo
+ */
+typedef struct dyn_fifo	dyn_fifo_t;
+
+/** Type definition of the dynamic fifo queue pointer.
+ *  @see dyn_fifo
+ */
+typedef dyn_fifo_t *	dyn_fifo_ref;
+
+/** Dynamic first in first out positive integer queue.
+ *  Possitive integer values only.
+ *  The queue automatically resizes if needed.
+ */
+struct dyn_fifo{
+	/** Stored item field.
+	 */
+	int	*	items;
+	/** Actual field size.
+	 */
+	int		size;
+	/** First item in the queue index.
+	 */
+	int		head;
+	/** Last item in the queue index.
+	 */
+	int		tail;
+	/** Consistency check magic value.
+	 */
+	int		magic_value;
+};
+
+/** Initializes the dynamic queue.
+ *  @param[in,out] fifo The dynamic queue.
+ *  @param[in] size The initial queue size.
+ *  @returns EOK on success.
+ *  @returns EINVAL if the queue is not valid.
+ *  @returns EBADMEM if the fifo parameter is NULL.
+ *  @returns ENOMEM if there is not enough memory left.
+ */
+int	dyn_fifo_initialize( dyn_fifo_ref fifo, int size );
+
+/** Appends a new item to the queue end.
+ *  @param[in,out] fifo The dynamic queue.
+ *  @param[in] value The new item value. Should be positive.
+ *  @param[in] max_size The maximum queue size. The queue is not resized beyound this limit. May be zero or negative (<=0) to indicate no limit.
+ *  @returns EOK on success.
+ *  @returns EINVAL if the queue is not valid.
+ *  @returns ENOMEM if there is not enough memory left.
+ */
+int	dyn_fifo_push( dyn_fifo_ref fifo, int value, int max_size );
+
+/** Returns and excludes the first item in the queue.
+ *  @param[in,out] fifo The dynamic queue.
+ *  @returns Value of the first item in the queue.
+ *  @returns EINVAL if the queue is not valid.
+ *  @returns ENOENT if the queue is empty.
+ */
+int	dyn_fifo_pop( dyn_fifo_ref fifo );
+
+/** Returns and keeps the first item in the queue.
+ *  @param[in,out] fifo The dynamic queue.
+ *  @returns Value of the first item in the queue.
+ *  @returns EINVAL if the queue is not valid.
+ *  @returns ENOENT if the queue is empty.
+ */
+int	dyn_fifo_value( dyn_fifo_ref fifo );
+
+/** Clears and destroys the queue.
+ *  @param[in,out] fifo The dynamic queue.
+ *  @returns EOK on success.
+ *  @returns EINVAL if the queue is not valid.
+ */
+int dyn_fifo_destroy( dyn_fifo_ref fifo );
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/structures/generic_char_map.h
===================================================================
--- uspace/srv/net/structures/generic_char_map.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/structures/generic_char_map.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,155 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup net
+ *  @{
+ */
+
+/** @file
+ *  Character string to generic type map.
+ */
+
+#ifndef __GENERIC_CHAR_MAP_H__
+#define __GENERIC_CHAR_MAP_H__
+
+#include <errno.h>
+#include <unistd.h>
+
+#include "../err.h"
+
+#include "char_map.h"
+#include "generic_field.h"
+
+/** Internal magic value for a&nbsp;map consistency check.
+ */
+#define GENERIC_CHAR_MAP_MAGIC_VALUE	0x12345622
+
+/** Character string to generic type map declaration.
+ *  @param[in] name Name of the map.
+ *  @param[in] type Inner object type.
+ */
+#define GENERIC_CHAR_MAP_DECLARE( name, type )									\
+																				\
+GENERIC_FIELD_DECLARE( name##_items, type )										\
+																				\
+typedef	struct name		name##_t;												\
+typedef	name##_t *		name##_ref;												\
+																				\
+struct	name{																	\
+	char_map_t		names;														\
+	name##_items_t	values;														\
+	int				magic;														\
+};																				\
+																				\
+int	name##_add( name##_ref map, const char * name, const size_t length, type * value );	\
+int	name##_count( name##_ref map );												\
+void	name##_destroy( name##_ref map );										\
+void	name##_exclude( name##_ref map, const char * name, const size_t length );	\
+type *	name##_find( name##_ref map, const char * name, const size_t length );	\
+int	name##_initialize( name##_ref map );										\
+int	name##_is_valid( name##_ref map );
+
+/** Character string to generic type map implementation.
+ *  Should follow declaration with the same parameters.
+ *  @param[in] name Name of the map.
+ *  @param[in] type Inner object type.
+ */
+#define GENERIC_CHAR_MAP_IMPLEMENT( name, type )								\
+																				\
+GENERIC_FIELD_IMPLEMENT( name##_items, type )									\
+																				\
+int name##_add( name##_ref map, const char * name, const size_t length, type * value ){	\
+	ERROR_DECLARE;																\
+																				\
+	int	index;																	\
+																				\
+	if( ! name##_is_valid( map )) return EINVAL;								\
+	index = name##_items_add( & map->values, value );							\
+	if( index < 0 ) return index;												\
+	if( ERROR_OCCURRED( char_map_add( & map->names, name, length, index ))){		\
+		name##_items_exclude_index( & map->values, index );						\
+		return ERROR_CODE;														\
+	}																			\
+	return EOK;																	\
+}																				\
+																				\
+int name##_count( name##_ref map ){												\
+	return name##_is_valid( map ) ? name##_items_count( & map->values ) : -1;	\
+}																				\
+																				\
+void name##_destroy( name##_ref map ){											\
+	if( name##_is_valid( map )){												\
+		char_map_destroy( & map->names );										\
+		name##_items_destroy( & map->values );									\
+	}																			\
+}																				\
+																				\
+void name##_exclude( name##_ref map, const char * name, const size_t length ){	\
+	if( name##_is_valid( map )){												\
+		int	index;																\
+																				\
+		index = char_map_exclude( & map->names, name, length );					\
+		if( index != CHAR_MAP_NULL ){											\
+			name##_items_exclude_index( & map->values, index );					\
+		}																		\
+	}																			\
+}																				\
+																				\
+type * name##_find( name##_ref map, const char * name, const size_t length ){	\
+	if( name##_is_valid( map )){												\
+		int	index;																\
+																				\
+		index = char_map_find( & map->names, name, length );					\
+		if( index != CHAR_MAP_NULL ){											\
+			return name##_items_get_index( & map->values, index );				\
+		}																		\
+	}																			\
+	return NULL;																\
+}																				\
+																				\
+int name##_initialize( name##_ref map ){										\
+	ERROR_DECLARE;																\
+																				\
+	if( ! map ) return EINVAL;													\
+	ERROR_PROPAGATE( char_map_initialize( & map->names ));						\
+	if( ERROR_OCCURRED( name##_items_initialize( & map->values ))){				\
+		char_map_destroy( & map->names );										\
+		return ERROR_CODE;														\
+	}																			\
+	map->magic = GENERIC_CHAR_MAP_MAGIC_VALUE;									\
+	return EOK;																	\
+}																				\
+																				\
+int name##_is_valid( name##_ref map ){											\
+	return map && ( map->magic == GENERIC_CHAR_MAP_MAGIC_VALUE );				\
+}
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/structures/generic_field.h
===================================================================
--- uspace/srv/net/structures/generic_field.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/structures/generic_field.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup net
+ *  @{
+ */
+
+/** @file
+ *  Generic type field.
+ */
+
+#ifndef __GENERIC_FIELD_H__
+#define __GENERIC_FIELD_H__
+
+#include <errno.h>
+#include <malloc.h>
+#include <mem.h>
+#include <unistd.h>
+
+/** Internal magic value for a&nbsp;field consistency check.
+ */
+#define GENERIC_FIELD_MAGIC_VALUE		0x55667788
+
+/** Generic type field declaration.
+ *  @param[in] name Name of the field.
+ *  @param[in] type Inner object type.
+ */
+#define GENERIC_FIELD_DECLARE( name, type )					\
+										\
+typedef	struct name		name##_t;					\
+typedef	name##_t *		name##_ref;					\
+										\
+struct	name{									\
+	int	size;								\
+	int	next;								\
+	type **	items;								\
+	int	magic;								\
+};										\
+										\
+int	name##_add( name##_ref field, type * value );				\
+int	name##_count( name##_ref field );					\
+void	name##_destroy( name##_ref field );					\
+void	name##_exclude_index( name##_ref field, int index );			\
+type **	name##_get_field( name##_ref field );					\
+type *	name##_get_index( name##_ref field, int index );			\
+int	name##_initialize( name##_ref field );					\
+int	name##_is_valid( name##_ref field );
+
+/** Generic type field implementation.
+ *  Should follow declaration with the same parameters.
+ *  @param[in] name Name of the field.
+ *  @param[in] type Inner object type.
+ */
+#define GENERIC_FIELD_IMPLEMENT( name, type )					\
+										\
+int name##_add( name##_ref field, type * value ){				\
+	if( name##_is_valid( field )){						\
+		if( field->next == ( field->size - 1 )){			\
+			type **	tmp;					\
+										\
+			tmp = ( type ** ) realloc( field->items, sizeof( type * ) * 2 * field->size );	\
+			if( ! tmp ) return ENOMEM;				\
+			field->size *= 2;					\
+			field->items = tmp;					\
+		}								\
+		field->items[ field->next ] = value;				\
+		++ field->next;							\
+		field->items[ field->next ] = NULL;				\
+		return field->next - 1;						\
+	}									\
+	return EINVAL;								\
+}										\
+										\
+int name##_count( name##_ref field ){						\
+	return name##_is_valid( field ) ? field->next : -1;			\
+}										\
+										\
+void name##_destroy( name##_ref field ){					\
+	if( name##_is_valid( field )){						\
+		int	index;							\
+										\
+		field->magic = 0;						\
+		for( index = 0; index < field->next; ++ index ){		\
+			if( field->items[ index ] ) free( field->items[ index ] );				\
+		}								\
+		free( field->items );						\
+	}									\
+}										\
+										\
+void name##_exclude_index( name##_ref field, int index ){			\
+	if( name##_is_valid( field ) && ( index >= 0 ) && ( index < field->next ) && ( field->items[ index ] )){	\
+		free( field->items[ index ] );					\
+		field->items[ index ] = NULL;					\
+	}									\
+}										\
+										\
+type * name##_get_index( name##_ref field, int index ){				\
+	if( name##_is_valid( field ) && ( index >= 0 ) && ( index < field->next ) && ( field->items[ index ] )){	\
+		return field->items[ index ];					\
+	}									\
+	return NULL;								\
+}										\
+										\
+type ** name##_get_field( name##_ref field ){					\
+	return name##_is_valid( field ) ? field->items : NULL;			\
+}										\
+										\
+int name##_initialize( name##_ref field ){					\
+	if( ! field ) return EINVAL;						\
+	field->size = 2;							\
+	field->next = 0;							\
+	field->items = ( type ** ) malloc( sizeof( type * ) * field->size );	\
+	if( ! field->items ) return ENOMEM;					\
+	field->items[ field->next ] = NULL;					\
+	field->magic = GENERIC_FIELD_MAGIC_VALUE;					\
+	return EOK;								\
+}										\
+										\
+int name##_is_valid( name##_ref field ){					\
+	return field && ( field->magic == GENERIC_FIELD_MAGIC_VALUE );		\
+}
+
+#endif
+
+/** @}
+ */
+
Index: uspace/srv/net/structures/int_map.h
===================================================================
--- uspace/srv/net/structures/int_map.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/structures/int_map.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,241 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup net
+ *  @{
+ */
+
+/** @file
+ *  Integer to generic type map.
+ */
+
+#ifndef __NET_INT_MAP_H__
+#define __NET_INT_MAP_H__
+
+#include <errno.h>
+#include <malloc.h>
+#include <mem.h>
+#include <unistd.h>
+
+/** Internal magic value for a&nbsp;map consistency check.
+ */
+#define INT_MAP_MAGIC_VALUE			0x11223344
+
+/** Internal magic value for an item consistency check.
+ */
+#define INT_MAP_ITEM_MAGIC_VALUE	0x55667788
+
+/** Integer to generic type map declaration.
+ *  @param[in] name Name of the map.
+ *  @param[in] type Inner object type.
+ */
+#define INT_MAP_DECLARE( name, type )											\
+																				\
+typedef	struct name			name##_t;											\
+typedef	name##_t *			name##_ref;											\
+typedef	struct name##_item	name##_item_t;										\
+typedef	name##_item_t *		name##_item_ref;									\
+																				\
+struct	name##_item{															\
+	int		key;																\
+	type *	value;																\
+	int		magic;																\
+};																				\
+																				\
+struct	name{																	\
+	int				size;														\
+	int				next;														\
+	name##_item_ref	items;														\
+	int				magic;														\
+};																				\
+																				\
+int		name##_add( name##_ref map, int key, type * value );					\
+void	name##_clear( name##_ref map );											\
+int		name##_count( name##_ref map );											\
+void	name##_destroy( name##_ref map );										\
+void	name##_exclude( name##_ref map, int key );								\
+void	name##_exclude_index( name##_ref map, int index );						\
+type *	name##_find( name##_ref map, int key );									\
+int		name##_update( name##_ref map, int key, int new_key );					\
+type *	name##_get_index( name##_ref map, int index );							\
+int		name##_initialize( name##_ref map );									\
+int		name##_is_valid( name##_ref map );										\
+void	name##_item_destroy( name##_item_ref item );							\
+int		name##_item_is_valid( name##_item_ref item );
+
+/** Integer to generic type map implementation.
+ *  Should follow declaration with the same parameters.
+ *  @param[in] name Name of the map.
+ *  @param[in] type Inner object type.
+ */
+#define INT_MAP_IMPLEMENT( name, type )											\
+																				\
+int name##_add( name##_ref map, int key, type * value ){						\
+	if( name##_is_valid( map )){												\
+		if( map->next == ( map->size - 1 )){									\
+			name##_item_ref	tmp;												\
+																				\
+			tmp = ( name##_item_ref ) realloc( map->items, sizeof( name##_item_t ) * 2 * map->size );	\
+			if( ! tmp ) return ENOMEM;											\
+			map->size *= 2;														\
+			map->items = tmp;													\
+		}																		\
+		map->items[ map->next ].key = key;										\
+		map->items[ map->next ].value = value;									\
+		map->items[ map->next ].magic = INT_MAP_ITEM_MAGIC_VALUE;				\
+		++ map->next;															\
+		map->items[ map->next ].magic = 0;										\
+		return map->next - 1;													\
+	}																			\
+	return EINVAL;																\
+}																				\
+																				\
+void name##_clear( name##_ref map ){											\
+	if( name##_is_valid( map )){												\
+		int	index;																\
+																				\
+/*		map->magic = 0;*/														\
+		for( index = 0; index < map->next; ++ index ){							\
+			if( name##_item_is_valid( &( map->items[ index ] ))){				\
+				name##_item_destroy( &( map->items[ index ] ));					\
+			}																	\
+		}																		\
+		map->next = 0;															\
+		map->items[ map->next ].magic = 0;										\
+/*		map->magic = INT_MAP_MAGIC_VALUE;*/										\
+	}																			\
+}																				\
+																				\
+int name##_count( name##_ref map ){												\
+	return name##_is_valid( map ) ? map->next : -1;								\
+}																				\
+																				\
+void name##_destroy( name##_ref map ){											\
+	if( name##_is_valid( map )){												\
+		int	index;																\
+																				\
+		map->magic = 0;															\
+		for( index = 0; index < map->next; ++ index ){							\
+			if( name##_item_is_valid( &( map->items[ index ] ))){				\
+				name##_item_destroy( &( map->items[ index ] ));					\
+			}																	\
+		}																		\
+		free( map->items );														\
+	}																			\
+}																				\
+																				\
+void name##_exclude( name##_ref map, int key ){									\
+	if( name##_is_valid( map )){												\
+		int	index;																\
+																				\
+		for( index = 0; index < map->next; ++ index ){							\
+			if( name##_item_is_valid( &( map->items[ index ] )) && ( map->items[ index ].key == key )){	\
+				name##_item_destroy( &( map->items[ index ] ));					\
+			}																	\
+		}																		\
+	}																			\
+}																				\
+																				\
+void name##_exclude_index( name##_ref map, int index ){							\
+	if( name##_is_valid( map ) && ( index >= 0 ) && ( index < map->next ) && name##_item_is_valid( &( map->items[ index ] ))){	\
+		name##_item_destroy( &( map->items[ index ] ));							\
+	}																			\
+}																				\
+																				\
+type * name##_find( name##_ref map, int key ){									\
+	if( name##_is_valid( map )){												\
+		int	index;																\
+																				\
+		for( index = 0; index < map->next; ++ index ){							\
+			if( name##_item_is_valid( &( map->items[ index ] )) && ( map->items[ index ].key == key )){	\
+				return map->items[ index ].value;								\
+			}																	\
+		}																		\
+	}																			\
+	return NULL;																\
+}																				\
+																				\
+int name##_update( name##_ref map, int key, int new_key ){						\
+	if( name##_is_valid( map )){												\
+		int	index;																\
+																				\
+		for( index = 0; index < map->next; ++ index ){							\
+			if( name##_item_is_valid( &( map->items[ index ] ))){				\
+				if( map->items[ index ].key == new_key ){						\
+					return EEXIST;												\
+				}else if( map->items[ index ].key == key ){						\
+					map->items[ index ].key = new_key;							\
+					return EOK;													\
+				}																\
+			}																	\
+		}																		\
+	}																			\
+	return ENOENT;																\
+}																				\
+																				\
+type * name##_get_index( name##_ref map, int index ){							\
+	if( name##_is_valid( map ) && ( index >= 0 ) && ( index < map->next ) && name##_item_is_valid( &( map->items[ index ] ))){	\
+		return map->items[ index ].value;										\
+	}																			\
+	return NULL;																\
+}																				\
+																				\
+int name##_initialize( name##_ref map ){										\
+	if( ! map ) return EINVAL;													\
+	map->size = 2;																\
+	map->next = 0;																\
+	map->items = ( name##_item_ref ) malloc( sizeof( name##_item_t ) * map->size );	\
+	if( ! map->items ) return ENOMEM;											\
+	map->items[ map->next ].magic = 0;											\
+	map->magic = INT_MAP_MAGIC_VALUE;											\
+	return EOK;																	\
+}																				\
+																				\
+int name##_is_valid( name##_ref map ){											\
+	return map && ( map->magic == INT_MAP_MAGIC_VALUE );						\
+}																				\
+																				\
+void name##_item_destroy( name##_item_ref item ){								\
+	if( name##_item_is_valid( item )){											\
+		item->magic = 0;														\
+		if( item->value ){														\
+			free( item->value );												\
+			item->value = NULL;													\
+		}																		\
+	}																			\
+}																				\
+																				\
+int name##_item_is_valid( name##_item_ref item ){								\
+	return item && ( item->magic == INT_MAP_ITEM_MAGIC_VALUE );					\
+}
+
+#endif
+
+/** @}
+ */
+
Index: uspace/srv/net/structures/measured_strings.c
===================================================================
--- uspace/srv/net/structures/measured_strings.c	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/structures/measured_strings.c	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,267 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup net
+ *  @{
+ */
+
+/** @file
+ *  Character string with measured length implementation.
+ *  @see measured_strings.h
+ */
+
+#include <errno.h>
+#include <malloc.h>
+#include <mem.h>
+#include <unistd.h>
+
+#include <ipc/ipc.h>
+
+#include "../err.h"
+#include "../modules.h"
+
+#include "measured_strings.h"
+
+/** 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.
+ *  @returns The computed sizes array.
+ *  @returns NULL if there is not enough memory left.
+ */
+size_t *	prepare_lengths( const measured_string_ref strings, size_t count );
+
+measured_string_ref measured_string_create_bulk( const char * string, size_t length ){
+	measured_string_ref	new;
+
+	if( length == 0 ){
+		while( string[ length ] ) ++ length;
+	}
+	new = ( measured_string_ref ) malloc( sizeof( measured_string_t ) + ( sizeof( char ) * ( length + 1 )));
+	if( ! new ) return NULL;
+	new->length = length;
+	new->value = (( char * ) 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;
+}
+
+measured_string_ref measured_string_copy( measured_string_ref source ){
+	measured_string_ref	new;
+
+	if( ! source ) return NULL;
+	new = ( measured_string_ref ) malloc( sizeof( measured_string_t ));
+	if( new ){
+		new->value = ( char * ) 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;
+		}else{
+			free( new );
+		}
+	}
+	return NULL;
+}
+
+int measured_strings_receive( measured_string_ref * strings, char ** data, size_t count ){
+	ERROR_DECLARE;
+
+	size_t *		lengths;
+	size_t			index;
+	size_t			length;
+	char *			next;
+	ipc_callid_t	callid;
+
+	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;
+	}
+	if( ERROR_OCCURRED( async_data_write_finalize( callid, lengths, sizeof( size_t ) * ( count + 1 )))){
+		free( lengths );
+		return ERROR_CODE;
+	}
+	* data = malloc( lengths[ count ] );
+	if( !( * data )) return ENOMEM;
+	( * data )[ lengths[ count ] - 1 ] = '\0';
+	* strings = ( measured_string_ref ) 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;
+			}
+			ERROR_PROPAGATE( async_data_write_finalize( callid, next, lengths[ index ] ));
+			( * strings)[ index ].value = next;
+			next += lengths[ index ];
+			* next = '\0';
+			++ next;
+		}else{
+			( * strings )[ index ].value = NULL;
+		}
+	}
+	free( lengths );
+	return EOK;
+}
+
+int measured_strings_reply( const measured_string_ref strings, size_t count ){
+	ERROR_DECLARE;
+
+	size_t *		lengths;
+	size_t			index;
+	size_t			length;
+	ipc_callid_t	callid;
+
+	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;
+	}
+	if( ERROR_OCCURRED( async_data_read_finalize( callid, lengths, sizeof( size_t ) * ( count + 1 )))){
+		free( lengths );
+		return ERROR_CODE;
+	}
+	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;
+			}
+			ERROR_PROPAGATE( async_data_read_finalize( callid, strings[ index ].value, strings[ index ].length ));
+		}
+	}
+	return EOK;
+}
+
+int measured_strings_return( int phone, measured_string_ref * strings, char ** data, size_t count ){
+	ERROR_DECLARE;
+
+	size_t *	lengths;
+	size_t		index;
+	char *		next;
+
+	if(( phone <= 0 ) || ( ! strings ) || ( ! data ) || ( count <= 0 )){
+		return EINVAL;
+	}
+	lengths = ( size_t * ) malloc( sizeof( size_t ) * ( count + 1 ));
+	if( ! lengths ) return ENOMEM;
+	if( ERROR_OCCURRED( async_data_read_start( phone, lengths, sizeof( size_t ) * ( count + 1 )))){
+		free( lengths );
+		return ERROR_CODE;
+	}
+	* data = malloc( lengths[ count ] );
+	if( !( * data )) return ENOMEM;
+	* strings = ( measured_string_ref ) 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 ){
+			ERROR_PROPAGATE( async_data_read_start( phone, next, lengths[ index ] ));
+			( * strings )[ index ].value = next;
+			next += lengths[ index ];
+			* next = '\0';
+			++ next;
+		}else{
+			( * strings )[ index ].value = NULL;
+		}
+	}
+	free( lengths );
+	return EOK;
+}
+
+int measured_strings_send( int phone, const measured_string_ref strings, size_t count ){
+	ERROR_DECLARE;
+
+	size_t *	lengths;
+	size_t		index;
+
+	if(( phone <= 0 ) || ( ! strings ) || ( count <= 0 )){
+		return EINVAL;
+	}
+	lengths = prepare_lengths( strings, count );
+	if( ! lengths ) return ENOMEM;
+	if( ERROR_OCCURRED( async_data_write_start( phone, lengths, sizeof( size_t ) * ( count + 1 )))){
+		free( lengths );
+		return ERROR_CODE;
+	}
+	free( lengths );
+	for( index = 0; index < count; ++ index ){
+		if( strings[ index ].length > 0 ){
+			ERROR_PROPAGATE( async_data_write_start( phone, strings[ index ].value, strings[ index ].length ));
+		}
+	}
+	return EOK;
+}
+
+size_t * prepare_lengths( const measured_string_ref 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;
+}
+
+/** @}
+ */
+
Index: uspace/srv/net/structures/measured_strings.h
===================================================================
--- uspace/srv/net/structures/measured_strings.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/structures/measured_strings.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup net
+ *  @{
+ */
+
+/** @file
+ *  Character string with measured length.
+ *  The structure has been designed for serialization of character strings between modules.
+ */
+
+#ifndef __MEASURED_STRINGS_H__
+#define __MEASURED_STRINGS_H__
+
+#include <sys/types.h>
+
+/** Type definition of the character string with measured length.
+ *  @see measured_string
+ */
+typedef struct measured_string	measured_string_t;
+
+/** Type definition of the character string with measured length pointer.
+ *  @see measured_string
+ */
+typedef measured_string_t *		measured_string_ref;
+
+/** Character string with measured length.
+ *  This structure has been designed for serialization of character strings between modules.
+ */
+struct	measured_string{
+	/** Character string data.
+	 */
+	char *	value;
+	/** Character string length.
+	 */
+	size_t	length;
+};
+
+/** Creates a&nbsp;new measured string bundled with a&nbsp;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&nbsp;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 (0), the actual length is computed. The given length is used and appended with the terminating zero ('\\0') character otherwise.
+ *  @returns The new bundled character string with measured length.
+ *  @returns NULL if there is not enough memory left.
+ */
+measured_string_ref	measured_string_create_bulk( const char * string, size_t length );
+
+/** Copies the given measured string with separated header and data parts.
+ *  @param[in] source The source measured string to be copied.
+ *  @returns The copy of the given measured string.
+ *  @returns NULL if the source parameter is NULL.
+ *  @returns NULL if there is not enough memory left.
+ */
+measured_string_ref	measured_string_copy( measured_string_ref source );
+
+/** Receives a&nbsp;measured strings array from a&nbsp;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.
+ *  @returns EOK on success.
+ *  @returns EINVAL if the strings or data parameter is NULL.
+ *  @returns EINVAL if the count parameter is zero (0).
+ *  @returns EINVAL if the sent array differs in size.
+ *  @returns EINVAL if there is inconsistency in sent measured strings' lengths (should not occur).
+ *  @returns ENOMEM if there is not enough memory left.
+ *  @returns Other error codes as defined for the async_data_write_finalize() function.
+ */
+int	measured_strings_receive( measured_string_ref * strings, char ** data, size_t count );
+
+/** Replies the given measured strings array to a&nbsp;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.
+ *  @returns EOK on success.
+ *  @returns EINVAL if the strings parameter is NULL.
+ *  @returns EINVAL if the count parameter is zero (0).
+ *  @returns EINVAL if the calling module does not accept the given array size.
+ *  @returns EINVAL if there is inconsistency in sent measured strings' lengths (should not occur).
+ *  @returns Other error codes as defined for the async_data_read_finalize() function.
+ */
+int	measured_strings_reply( const measured_string_ref strings, size_t count );
+
+/** Receives a&nbsp;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] phone The other module phone.
+ *  @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.
+ *  @returns EOK on success.
+ *  @returns EINVAL if the strings or data parameter is NULL.
+ *  @returns EINVAL if the phone or count parameter is not positive (<=0).
+ *  @returns EINVAL if the sent array differs in size.
+ *  @returns ENOMEM if there is not enough memory left.
+ *  @returns Other error codes as defined for the async_data_read_start() function.
+ */
+int	measured_strings_return( int phone, measured_string_ref * strings, char ** data, size_t count );
+
+/** 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] phone The other module phone.
+ *  @param[in] strings The measured strings array to be transferred.
+ *  @param[in] count The measured strings array size.
+ *  @returns EOK on success.
+ *  @returns EINVAL if the strings parameter is NULL.
+ *  @returns EINVAL if the phone or count parameter is not positive (<=0).
+ *  @returns Other error codes as defined for the async_data_write_start() function.
+ */
+int	measured_strings_send( int phone, const measured_string_ref strings, size_t count );
+
+#endif
+
+/** @}
+ */
+
Index: uspace/srv/net/structures/module_map.c
===================================================================
--- uspace/srv/net/structures/module_map.c	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/structures/module_map.c	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup net
+ *  @{
+ */
+
+/** @file
+ *  Character string to module map implementation.
+ */
+
+#include <malloc.h>
+#include <task.h>
+#include <unistd.h>
+
+#include <ipc/services.h>
+
+#include "../err.h"
+#include "../modules.h"
+
+#include "generic_char_map.h"
+#include "module_map.h"
+
+GENERIC_CHAR_MAP_IMPLEMENT( modules, module_t )
+
+int add_module( module_ref * module, modules_ref modules, char * name, char * filename, services_t service, task_id_t task_id, connect_module_t connect_module ){
+	ERROR_DECLARE;
+
+	module_ref	tmp_module;
+
+	tmp_module = ( module_ref ) malloc( sizeof( module_t ));
+	if( ! tmp_module ) return ENOMEM;
+	tmp_module->task_id = task_id;
+	tmp_module->phone = 0;
+	tmp_module->usage = 0;
+	tmp_module->name = name;
+	tmp_module->filename = filename;
+	tmp_module->service = service;
+	tmp_module->connect_module = connect_module;
+	if( ERROR_OCCURRED( modules_add( modules, tmp_module->name, 0, tmp_module ))){
+		free( tmp_module );
+		return ERROR_CODE;
+	}
+	if( module ) * module = tmp_module;
+	return EOK;
+}
+
+module_ref get_running_module( modules_ref modules, char * name ){
+	module_ref	module;
+
+	module = modules_find( modules, name, 0 );
+	if( ! module ) return NULL;
+	if( ! module->task_id ){
+		module->task_id = spawn( module->filename );
+		if( ! module->task_id ) return NULL;
+	}
+	if( ! module->phone ){
+		module->phone = module->connect_module( module->service );
+	}
+	return module;
+}
+
+task_id_t spawn( char * fname ){
+	char * argv[ 2 ];
+//	char * argv[ 4 ];
+	task_id_t	res;
+
+//	printf( "Spawning %s\n", fname );
+	argv[ 0 ] = fname;
+	argv[ 1 ] = NULL;
+	res = task_spawn( fname, argv );
+/*	argv[ 0 ] = "/app/trace";
+	argv[ 1 ] = "+ti";
+	argv[ 2 ] = fname;
+	argv[ 3 ] = NULL;
+	res = task_spawn( "/app/trace", argv );
+*/
+	if( res != 0 ){
+		/* Success */
+		usleep( 10000 );
+	}
+	return res;
+}
+
+/** @}
+ */
Index: uspace/srv/net/structures/module_map.h
===================================================================
--- uspace/srv/net/structures/module_map.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/structures/module_map.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup net
+ *  @{
+ */
+
+/** @file
+ *  Character string to module map.
+ */
+
+#ifndef __NET_MODULES_MAP_H__
+#define __NET_MODULES_MAP_H__
+
+#include <task.h>
+
+#include <ipc/services.h>
+
+#include "../modules.h"
+
+#include "generic_char_map.h"
+
+/** Type definition of the module structure.
+ *  @see module_struct
+ */
+typedef struct module_struct	module_t;
+
+/** Type definition of the module structure pointer.
+ *  @see module_struct
+ */
+typedef module_t *				module_ref;
+
+/** 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 phone if running and connected.
+	 */
+	int			phone;
+	/** Usage counter.
+	 */
+	int			usage;
+	/** Module name.
+	 */
+	char *		name;
+	/** Module full path filename.
+	 */
+	char *		filename;
+	/** Connecting function.
+	 */
+	connect_module_t *	connect_module;
+};
+
+/** Adds module to the module map.
+ *  @param[out] module The module structure added.
+ *  @param[in] modules The module map.
+ *  @param[in] name The module name.
+ *  @param[in] filename The full path filename.
+ *  @param[in] service The module service.
+ *  @param[in] task_id The module current task identifier. Zero (0) means not running.
+ *  @param[in] connect_module The module connecting function.
+ *  @returns EOK on success.
+ *  @returns ENOMEM if there is not enough memory left.
+ */
+int	add_module( module_ref * module, modules_ref modules, char * name, char * filename, services_t service, task_id_t task_id, connect_module_t * connect_module );
+
+/** Searches and returns 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 The module map.
+ *  @param[in] name The module name.
+ *  @returns The running module found. It does not have to be connected.
+ *  @returns NULL if there is no such module.
+ */
+module_ref	get_running_module( modules_ref modules, char * name );
+
+/** Starts the given module.
+ *  @param[in] fname The module full or relative path filename.
+ *  @returns The new module task identifier on success.
+ *  @returns 0 if there is no such module.
+ */
+task_id_t	spawn( char * fname );
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/structures/packet/packet.c
===================================================================
--- uspace/srv/net/structures/packet/packet.c	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/structures/packet/packet.c	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,299 @@
+/*
+ * 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 packet
+ *  @{
+ */
+
+/** @file
+ *  Packet map and queue implementation.
+ *  This file has to be compiled with both the packet server and the client.
+ */
+
+#include <errno.h>
+#include <malloc.h>
+#include <mem.h>
+#include <fibril_synch.h>
+//#include <stdio.h>
+#include <unistd.h>
+
+#include <sys/mman.h>
+
+#include "../../err.h"
+
+#include "../generic_field.h"
+
+#include "packet.h"
+#include "packet_header.h"
+
+/** Packet map page size.
+ */
+#define PACKET_MAP_SIZE	100
+
+/** Returns the packet map page index.
+ *  @param[in] packet_id The packet identifier.
+ */
+#define PACKET_MAP_PAGE( packet_id )	((( packet_id ) - 1 ) / PACKET_MAP_SIZE )
+
+/** Returns the packet index in the corresponding packet map page.
+ *  @param[in] packet_id The packet identifier.
+ */
+#define PACKET_MAP_INDEX( packet_id )	((( packet_id ) - 1 ) % PACKET_MAP_SIZE )
+
+/** Type definition of the packet map page.
+ */
+typedef packet_t packet_map_t[ PACKET_MAP_SIZE ];
+/** Type definition of the packet map page pointer.
+ */
+typedef packet_map_t * packet_map_ref;
+
+/** Packet map.
+ *  Maps packet identifiers to the packet references.
+ *  @see generic_field.h
+ */
+GENERIC_FIELD_DECLARE( gpm, packet_map_t );
+
+/** Releases the packet.
+ *  @param[in] packet The packet to be released.
+ *  @returns EOK on success.
+ *  @returns EINVAL if the packet is not valid.
+ */
+int packet_destroy( packet_t packet );
+
+/** Packet map global data.
+ */
+static struct{
+	/** Safety lock.
+	 */
+	fibril_rwlock_t	lock;
+	/** Packet map.
+	 */
+	gpm_t	packet_map;
+} pm_globals;
+
+GENERIC_FIELD_IMPLEMENT( gpm, packet_map_t );
+
+int packet_destroy( packet_t packet ){
+	if( ! packet_is_valid( packet )) return EINVAL;
+	return munmap( packet, packet->length );
+}
+
+int pm_init( void ){
+	ERROR_DECLARE;
+
+	fibril_rwlock_initialize( & pm_globals.lock );
+	fibril_rwlock_write_lock( & pm_globals.lock );
+	ERROR_PROPAGATE( gpm_initialize( & pm_globals.packet_map ));
+	fibril_rwlock_write_unlock( & pm_globals.lock );
+	return EOK;
+}
+
+packet_t pm_find( packet_id_t packet_id ){
+	packet_map_ref map;
+	packet_t packet;
+
+	if( ! packet_id ) return NULL;
+	fibril_rwlock_read_lock( & pm_globals.lock );
+	if( packet_id > PACKET_MAP_SIZE * gpm_count( & pm_globals.packet_map )){
+		fibril_rwlock_read_unlock( & pm_globals.lock );
+		return NULL;
+	}
+	map = gpm_get_index( & pm_globals.packet_map, PACKET_MAP_PAGE( packet_id ));
+	if( ! map ){
+		fibril_rwlock_read_unlock( & pm_globals.lock );
+		return NULL;
+	}
+	packet = ( * map )[ PACKET_MAP_INDEX( packet_id ) ];
+	fibril_rwlock_read_unlock( & pm_globals.lock );
+	return packet;
+}
+
+int pm_add( packet_t packet ){
+	ERROR_DECLARE;
+
+	packet_map_ref map;
+
+	if( ! packet_is_valid( packet )) return EINVAL;
+	fibril_rwlock_write_lock( & pm_globals.lock );
+	if( PACKET_MAP_PAGE( packet->packet_id ) < gpm_count( & pm_globals.packet_map )){
+		map = gpm_get_index( & pm_globals.packet_map, PACKET_MAP_PAGE( packet->packet_id ));
+	}else{
+		do{
+			map = ( packet_map_ref ) malloc( sizeof( packet_map_t ));
+			if( ! map ){
+				fibril_rwlock_write_unlock( & pm_globals.lock );
+				return ENOMEM;
+			}
+			bzero( map, sizeof( packet_map_t ));
+			if(( ERROR_CODE = gpm_add( & pm_globals.packet_map, map )) < 0 ){
+				fibril_rwlock_write_unlock( & pm_globals.lock );
+				free( map );
+				return ERROR_CODE;
+			}
+		}while( PACKET_MAP_PAGE( packet->packet_id ) >= gpm_count( & pm_globals.packet_map ));
+	}
+	( * map )[ PACKET_MAP_INDEX( packet->packet_id ) ] = packet;
+	fibril_rwlock_write_unlock( & pm_globals.lock );
+	return EOK;
+}
+
+void pm_destroy( void ){
+	int count;
+	int index;
+	packet_map_ref map;
+	packet_t packet;
+
+	fibril_rwlock_write_lock( & pm_globals.lock );
+	count = gpm_count( & pm_globals.packet_map );
+	while( count > 0 ){
+		map = gpm_get_index( & pm_globals.packet_map, count - 1 );
+		for( index = PACKET_MAP_SIZE - 1; index >= 0; -- index ){
+			packet = ( * map )[ index ];
+			if( packet_is_valid( packet )){
+				munmap( packet, packet->length );
+			}
+		}
+	}
+	gpm_destroy( & pm_globals.packet_map );
+	// leave locked
+}
+
+packet_t pq_add( packet_t first, packet_t packet, size_t order, size_t metric ){
+	packet_t	item;
+
+	if( ! packet_is_valid( packet )) return NULL;
+	pq_set_order( packet, order, metric );
+	if( packet_is_valid( first )){
+		item = first;
+		do{
+			if( item->order < order ){
+				if( item->next ){
+					item = pm_find( item->next );
+				}else{
+					item->next = packet->packet_id;
+					packet->previous = item->packet_id;
+					return first;
+				}
+			}else{
+				packet->previous = item->previous;
+				packet->next = item->packet_id;
+				item->previous = packet->packet_id;
+				item = pm_find( packet->previous );
+				if( item ) item->next = packet->packet_id;
+				return item ? first : packet;
+			}
+		}while( packet_is_valid( item ));
+	}
+	return packet;
+}
+
+packet_t pq_find( packet_t packet, size_t order ){
+	packet_t	item;
+
+	if( ! packet_is_valid( packet )) return NULL;
+	if( packet->order == order ) return packet;
+	item = pm_find( packet->next );
+	while( item && ( item != packet )){
+		item = pm_find( item->next );
+		if( item->order == order ){
+			return item;
+		}
+	}
+	return NULL;
+}
+
+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;
+}
+
+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( next->previous );
+		if( previous ){
+			previous->next = next->packet_id;
+		}
+	}
+	packet->previous = 0;
+	packet->next = 0;
+	return next;
+}
+
+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;
+}
+
+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;
+}
+
+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;
+	}
+}
+
+packet_t pq_next( packet_t packet ){
+	if( ! packet_is_valid( packet )) return NULL;
+	return pm_find( packet->next );
+}
+
+packet_t pq_previous( packet_t packet ){
+	if( ! packet_is_valid( packet )) return NULL;
+	return pm_find( packet->previous );
+}
+
+/** @}
+ */
Index: uspace/srv/net/structures/packet/packet.h
===================================================================
--- uspace/srv/net/structures/packet/packet.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/structures/packet/packet.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,168 @@
+/*
+ * 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 packet
+ *  @{
+ */
+
+/** @file
+ *  Packet map and queue.
+ */
+
+#ifndef __NET_PACKET_H__
+#define __NET_PACKET_H__
+
+/** Packet identifier type.
+ *  Value zero (0) is used as an invalid identifier.
+ */
+typedef int	packet_id_t;
+
+/** Type definition of the packet.
+ *  @see packet
+ */
+typedef struct packet *	packet_t;
+
+/** Type definition of the packet pointer.
+ *  @see packet
+ */
+typedef packet_t *		packet_ref;
+
+/** @name Packet management system interface
+ */
+/*@{*/
+
+/** Finds the packet mapping.
+ *  @param[in] packet_id The packet identifier to be found.
+ *  @returns The found packet reference.
+ *  @returns NULL if the mapping does not exist.
+ */
+packet_t	pm_find( packet_id_t packet_id );
+
+/** Adds the packet mapping.
+ *  @param[in] packet The packet to be remembered.
+ *  @returns EOK on success.
+ *  @returns EINVAL if the packet is not valid.
+ *  @returns EINVAL if the packet map is not initialized.
+ *  @returns ENOMEM if there is not enough memory left.
+ */
+int	pm_add( packet_t packet );
+
+/** Initializes the packet map.
+ *  @returns EOK on success.
+ *  @returns ENOMEM if there is not enough memory left.
+ */
+int	pm_init( void );
+
+/** Releases the packet map.
+ */
+void	pm_destroy( void );
+
+/** 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] first The first packet of the queue. May be NULL.
+ *  @param[in] packet The packet to be added.
+ *  @param[in] order The packet order value.
+ *  @param[in] metric The metric value of the packet.
+ *  @returns The first packet of the queue. The original first packet may be shifted by the new packet.
+ *  @returns NULL if the packet is not valid.
+ */
+packet_t	pq_add( packet_t first, packet_t packet, size_t order, size_t metric );
+
+/** Finds the packet with the given order.
+ *  @param[in] first The first packet of the queue.
+ *  @param[in] order The packet order value.
+ *  @returns The packet with the given order.
+ *  @returns NULL if the first packet is not valid.
+ *  @returns NULL if the packet is not found.
+ */
+packet_t	pq_find( packet_t first, size_t order );
+
+/** Inserts packet after the given one.
+ *  @param[in] packet The packet in the queue.
+ *  @param[in] new_packet The new packet to be inserted.
+ *  @returns EOK on success.
+ *  @returns EINVAL if etiher of the packets is invalid.
+ */
+int	pq_insert_after( packet_t packet, packet_t new_packet );
+
+/** Detach the packet from the queue.
+ *  @param[in] packet The packet to be detached.
+ *  @returns The next packet in the queue. If the packet is the first one of the queue, this becomes the new first one.
+ *  @returns NULL if there is no packet left.
+ *  @returns NULL if the packet is not valid.
+ */
+packet_t	pq_detach( packet_t packet );
+
+/** Sets the packet order and metric attributes.
+ *  @param[in] packet The packet to be set.
+ *  @param[in] order The packet order value.
+ *  @param[in] metric The metric value of the packet.
+ *  @returns EOK on success.
+ *  @returns EINVAL if the packet is invalid..
+ */
+int	pq_set_order( packet_t packet, size_t order, size_t metric );
+
+/** 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.
+ *  @returns EOK on success.
+ *  @returns EINVAL if the packet is invalid..
+ */
+int	pq_get_order( packet_t packet, size_t * order, size_t * metric );
+
+/** 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 ));
+
+/** Returns the next packet in the queue.
+ *  @param[in] packet The packet queue member.
+ *  @returns The next packet in the queue.
+ *  @returns NULL if there is no next packet.
+ *  @returns NULL if the packet is not valid.
+ */
+packet_t	pq_next( packet_t packet );
+
+/** Returns the previous packet in the queue.
+ *  @param[in] packet The packet queue member.
+ *  @returns The previous packet in the queue.
+ *  @returns NULL if there is no previous packet.
+ *  @returns NULL if the packet is not valid.
+ */
+packet_t	pq_previous( packet_t packet );
+
+/*@}*/
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/structures/packet/packet_client.c
===================================================================
--- uspace/srv/net/structures/packet/packet_client.c	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/structures/packet/packet_client.c	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,152 @@
+/*
+ * 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 packet
+ *  @{
+ */
+
+/** @file
+ *  Packet client implementation.
+ */
+
+#include <errno.h>
+#include <mem.h>
+#include <unistd.h>
+//#include <stdio.h>
+
+#include <sys/mman.h>
+
+#include "../../messages.h"
+
+#include "packet.h"
+#include "packet_header.h"
+#include "packet_client.h"
+
+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;
+}
+
+void * packet_prefix( packet_t packet, size_t length ){
+	if(( ! packet_is_valid( packet )) || ( packet->data_start - sizeof( struct packet ) - 2 * ( packet->dest_addr - packet->src_addr ) < length )) return NULL;
+	packet->data_start -= length;
+	return ( void * ) packet + packet->data_start;
+}
+
+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;
+}
+
+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;
+}
+
+packet_id_t packet_get_id( const packet_t packet ){
+	return packet_is_valid( packet ) ? packet->packet_id : 0;
+}
+
+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;
+}
+
+size_t packet_get_data_length( const packet_t packet ){
+	if( ! packet_is_valid( packet )) return 0;
+	return PACKET_DATA_LENGTH( packet );
+}
+
+void * packet_get_data( const packet_t packet ){
+	if( ! packet_is_valid( packet )) return NULL;
+	return ( void * ) packet + packet->data_start;
+}
+
+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;
+}
+
+packet_t packet_get_copy( int phone, packet_t packet ){
+	packet_t	copy;
+	uint8_t *	src;
+	uint8_t *	dest;
+	size_t		addrlen;
+
+	if( ! packet_is_valid( packet )) return NULL;
+	// get a new packet
+	copy = packet_get_4( phone, PACKET_DATA_LENGTH( packet ), PACKET_MAX_ADDRESS_LENGTH( packet ), packet->max_prefix, PACKET_MIN_SUFFIX( packet ));
+	if( ! copy ) return NULL;
+	// get addresses
+	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( phone, copy->packet_id );
+		return NULL;
+	}
+}
+
+/** @}
+ */
Index: uspace/srv/net/structures/packet/packet_client.h
===================================================================
--- uspace/srv/net/structures/packet/packet_client.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/structures/packet/packet_client.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,221 @@
+/*
+ * 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 packet
+ *  @{
+ */
+
+/** @file
+ *  Packet client.
+ *  The hosting module has to be compiled with both the packet.c and the packet_client.c source files.
+ *  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 -&nbsp;by passing the packets to the next module and stopping using the passed ones.
+ *  @see packet.h
+ */
+
+#ifndef __NET_PACKET_CLIENT_H__
+#define __NET_PACKET_CLIENT_H__
+
+#include "packet.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.
+ *  @returns The typed pointer to the allocated memory.
+ *  @returns NULL if the packet is not valid.
+ *  @returns 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.
+ *  @returns The typed pointer to the allocated memory.
+ *  @returns NULL if the packet is not valid.
+ *  @returns 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.
+ *  @returns EOK on success.
+ *  @returns EINVAL if the packet is not valid.
+ *  @returns ENOMEM if there is not enough memory left.
+ */
+#define PACKET_TRIM( packet, prefix, suffix )	packet_trim(( packet ), sizeof( prefix ), sizeof( suffix ))
+
+/** 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.
+ *  @returns The pointer to the allocated memory.
+ *  @returns NULL if there is not enough memory left.
+ */
+void *	packet_prefix( packet_t packet, size_t length );
+
+/** 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.
+ *  @returns The pointer to the allocated memory.
+ *  @returns NULL if there is not enough memory left.
+ */
+void *	packet_suffix( packet_t packet, size_t 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.
+ *  @returns EOK on success.
+ *  @returns EINVAL if the packet is not valid.
+ *  @returns ENOMEM if there is not enough memory left.
+ */
+int	packet_trim( packet_t packet, size_t prefix, size_t suffix );
+
+/** 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.
+ *  @returns EOK on success.
+ *  @returns EINVAL if the packet is not valid.
+ *  @returns ENOMEM if there is not enough memory left.
+ */
+int	packet_copy_data( packet_t packet, const void * data, size_t length );
+
+/** Returns the packet identifier.
+ *  @param[in] packet The packet.
+ *  @returns The packet identifier.
+ *  @returns Zero (0) if the packet is not valid.
+ */
+packet_id_t packet_get_id( const packet_t packet );
+
+/** Returns the packet content length.
+ *  @param[in] packet The packet.
+ *  @returns The packet content length in bytes.
+ *  @returns Zero (0) if the packet is not valid.
+ */
+size_t	packet_get_data_length( const packet_t packet );
+
+/** Returns the pointer to the beginning of the packet content.
+ *  @param[in] packet The packet.
+ *  @returns The pointer to the beginning of the packet content.
+ *  @returns NULL if the packet is not valid.
+ */
+void *	packet_get_data( const packet_t packet );
+
+/** 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.
+ *  @returns The stored addresses length.
+ *  @returns Zero (0) if the addresses are not present.
+ *  @returns EINVAL if the packet is not valid.
+ */
+int	packet_get_addr( const packet_t packet, uint8_t ** src, uint8_t ** dest );
+
+/** 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.
+ *  @returns EOK on success.
+ *  @returns EINVAL if the packet is not valid.
+ *  @returns 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 );
+
+/** Translates the packet identifier to the packet reference.
+ *  Tries to find mapping first.
+ *  Contacts the packet server to share the packet if the mapping is not present.
+ *  @param[in] phone The packet server module phone.
+ *  @param[out] packet The packet reference.
+ *  @param[in] packet_id The packet identifier.
+ *  @returns EOK on success.
+ *  @returns EINVAL if the packet parameter is NULL.
+ *  @returns Other error codes as defined for the NET_PACKET_GET_SIZE message.
+ *  @returns Other error codes as defined for the packet_return() function.
+ */
+int packet_translate( int phone, packet_ref packet, packet_id_t packet_id );
+
+/** Obtains the packet of the given dimensions.
+ *  Contacts the packet server to return the appropriate packet.
+ *  @param[in] phone The packet server module phone.
+ *  @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.
+ *  @returns The packet reference.
+ *  @returns NULL on error.
+ */
+packet_t packet_get_4( int phone, size_t max_content, size_t addr_len, size_t max_prefix, size_t max_suffix );
+
+/** Obtains the packet of the given content size.
+ *  Contacts the packet server to return the appropriate packet.
+ *  @param[in] phone The packet server module phone.
+ *  @param[in] content The maximal content length in bytes.
+ *  @returns The packet reference.
+ *  @returns NULL on error.
+ */
+packet_t packet_get_1( int phone, size_t content );
+
+/** Releases 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] phone The packet server module phone.
+ *  @param[in] packet_id The packet identifier.
+ */
+void pq_release( int phone, packet_id_t packet_id );
+
+/** Returns the packet copy.
+ *  Copies the addresses, data, order and metric values.
+ *  Does not copy the queue placement.
+ *  @param[in] phone The packet server module phone.
+ *  @param[in] packet The original packet.
+ *  @returns The packet copy.
+ *  @returns NULL on error.
+ */
+packet_t	packet_get_copy( int phone, packet_t packet );
+
+/*@}*/
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/structures/packet/packet_header.h
===================================================================
--- uspace/srv/net/structures/packet/packet_header.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/structures/packet/packet_header.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,123 @@
+/*
+ * 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 packet
+ *  @{
+ */
+
+/** @file
+ *  Packet header.
+ */
+
+#ifndef __NET_PACKET_HEADER_H__
+#define __NET_PACKET_HEADER_H__
+
+#include "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
+
+/** 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;
+	/** 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.
+ *  @returns true if the packet is not NULL and the magic value is correct.
+ *  @returns false otherwise.
+ */
+static inline int	packet_is_valid( const packet_t packet ){
+	return packet && ( packet->magic_value == PACKET_MAGIC_VALUE );
+}
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/structures/packet/packet_messages.h
===================================================================
--- uspace/srv/net/structures/packet/packet_messages.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/structures/packet/packet_messages.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,96 @@
+/*
+ * 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 packet
+ *  @{
+ */
+
+/** @file
+ *  Packet server module messages.
+ */
+
+#ifndef __NET_PACKET_MESSAGES__
+#define __NET_PACKET_MESSAGES__
+
+#include <ipc/ipc.h>
+
+#include "../../messages.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;
+
+/** Returns the protocol service message parameter.
+ */
+#define ARP_GET_PROTO( call )		( services_t ) IPC_GET_ARG2( * call )
+
+/** Returns the packet identifier message parameter.
+ */
+#define IPC_GET_ID( call )			( packet_id_t ) IPC_GET_ARG1( * call )
+
+/** Returns the maximal content length message parameter.
+ */
+#define IPC_GET_CONTENT( call )		( size_t ) IPC_GET_ARG1( * call )
+
+/** Returns the maximal address length message parameter.
+ */
+#define IPC_GET_ADDR_LEN( call )	( size_t ) IPC_GET_ARG2( * call )
+
+/** Returns the maximal prefix length message parameter.
+ */
+#define IPC_GET_PREFIX( call )		( size_t ) IPC_GET_ARG3( * call )
+
+/** Returns the maximal suffix length message parameter.
+ */
+#define IPC_GET_SUFFIX( call )		( size_t ) IPC_GET_ARG4( * call )
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/structures/packet/packet_remote.c
===================================================================
--- uspace/srv/net/structures/packet/packet_remote.c	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/structures/packet/packet_remote.c	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,143 @@
+/*
+ * 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 packet
+ *  @{
+ */
+
+/** @file
+ *  Packet client interface implementation for standalone remote modules.
+ *  @see packet_client.h
+ */
+
+#include <async.h>
+#include <errno.h>
+
+#include <ipc/ipc.h>
+#include <sys/mman.h>
+
+#include "../../err.h"
+#include "../../messages.h"
+
+#include "packet.h"
+#include "packet_client.h"
+#include "packet_header.h"
+#include "packet_messages.h"
+
+/** Obtains the packet from the packet server as the shared memory block.
+ *  Creates the local packet mapping as well.
+ *  @param[in] phone The packet server module phone.
+ *  @param[out] packet The packet reference pointer to store the received packet reference.
+ *  @param[in] packet_id The packet identifier.
+ *  @param[in] size The packet total size in bytes.
+ *  @returns EOK on success.
+ *  @returns Other error codes as defined for the pm_add() function.
+ *  @returns Other error codes as defined for the async_share_in_start() function.
+ */
+int packet_return( int phone, packet_ref packet, packet_id_t packet_id, size_t size );
+
+int packet_translate( int phone, packet_ref packet, packet_id_t packet_id ){
+	ERROR_DECLARE;
+
+	unsigned int		size;
+	packet_t			next;
+
+	if( ! packet ) return EINVAL;
+	* packet = pm_find( packet_id );
+	if( !( * packet )){
+		ERROR_PROPAGATE( async_req_1_1( phone, NET_PACKET_GET_SIZE, packet_id, & size ));
+		ERROR_PROPAGATE( packet_return( phone, packet, packet_id, size ));
+	}
+	if(( ** packet ).next ){
+		return packet_translate( phone, & next, ( ** packet ).next );
+	}else return EOK;
+}
+
+int packet_return( int phone, packet_ref packet, packet_id_t packet_id, size_t size ){
+	ERROR_DECLARE;
+
+	aid_t		message;
+	ipc_call_t	answer;
+	ipcarg_t	result;
+
+	message = async_send_1( phone, NET_PACKET_GET, packet_id, & answer );
+	* packet = ( packet_t ) as_get_mappable_page( size );
+	if( ERROR_OCCURRED( async_share_in_start_0_0( phone, * packet, size ))
+	|| ERROR_OCCURRED( pm_add( * packet ))){
+		munmap( * packet, size );
+		async_wait_for( message, NULL );
+		return ERROR_CODE;
+	}
+	async_wait_for( message, & result );
+	return result;
+}
+
+packet_t packet_get_4( int phone, size_t max_content, size_t addr_len, size_t max_prefix, size_t max_suffix ){
+	ERROR_DECLARE;
+
+	packet_id_t	packet_id;
+	unsigned int size;
+	packet_t packet;
+
+	if( ERROR_OCCURRED( async_req_4_2( phone, NET_PACKET_CREATE_4, max_content, addr_len, max_prefix, max_suffix, ( ipcarg_t * ) & packet_id, & size ))){
+		return NULL;
+	}
+	packet = pm_find( packet_id );
+	if( ! packet ){
+		if( ERROR_OCCURRED( packet_return( phone, & packet, packet_id, size ))){
+			return NULL;
+		}
+	}
+	return packet;
+}
+
+packet_t packet_get_1( int phone, size_t content ){
+	ERROR_DECLARE;
+
+	packet_id_t	packet_id;
+	unsigned int	size;
+	packet_t	packet;
+
+	if( ERROR_OCCURRED( async_req_1_2( phone, NET_PACKET_CREATE_1, content, ( ipcarg_t * ) & packet_id, & size ))){
+		return NULL;
+	}
+	packet = pm_find( packet_id );
+	if( ! packet ){
+		if( ERROR_OCCURRED( packet_return( phone, & packet, packet_id, size ))){
+			return NULL;
+		}
+	}
+	return packet;
+}
+
+void pq_release( int phone, packet_id_t packet_id ){
+	async_msg_1( phone, NET_PACKET_RELEASE, packet_id );
+}
+
+/** @}
+ */
Index: uspace/srv/net/structures/packet/packet_server.c
===================================================================
--- uspace/srv/net/structures/packet/packet_server.c	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/structures/packet/packet_server.c	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,321 @@
+/*
+ * 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 packet
+ *  @{
+ */
+
+/** @file
+ *  Packet server implementation.
+ */
+
+#include <align.h>
+#include <assert.h>
+#include <async.h>
+#include <errno.h>
+#include <fibril_synch.h>
+#include <unistd.h>
+
+#include <ipc/ipc.h>
+#include <sys/mman.h>
+
+#include "../../err.h"
+#include "../../messages.h"
+
+#include "packet.h"
+#include "packet_client.h"
+#include "packet_header.h"
+#include "packet_messages.h"
+#include "packet_server.h"
+
+#define FREE_QUEUES_COUNT	7
+
+/** 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
+
+/** Packet server global data.
+ */
+static struct{
+	/** Safety lock.
+	 */
+	fibril_mutex_t lock;
+	/** Free packet queues.
+	 */
+	packet_t free[ FREE_QUEUES_COUNT ];
+	/** Packet length upper bounds of the free packet queues.
+	 *  The maximal lengths of packets in each queue in the ascending order.
+	 *  The last queue is not limited.
+	 */
+	size_t sizes[ FREE_QUEUES_COUNT ];
+	/** Total packets allocated.
+	 */
+	unsigned int count;
+} ps_globals = {
+	.lock = {
+		.counter = 1,
+		.waiters = {
+			.prev = & ps_globals.lock.waiters,
+			.next = & ps_globals.lock.waiters,
+		}
+	},
+	.free = { NULL, NULL, NULL, NULL, NULL, NULL, NULL },
+	.sizes = { PAGE_SIZE, PAGE_SIZE * 2, PAGE_SIZE * 4, PAGE_SIZE * 8, PAGE_SIZE * 16, PAGE_SIZE * 32, PAGE_SIZE * 64 },
+	.count = 0
+};
+
+/** @name Packet server support functions
+ */
+/*@{*/
+
+/** Returns the packet of dimensions at least as given.
+ *  Tries to reuse free packets first.
+ *  Creates a&nbsp;new packet aligned to the memory page size if none available.
+ *  Locks 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.
+ *  @returns The packet of dimensions at least as given.
+ *  @returns NULL if there is not enough memory left.
+ */
+packet_t	packet_get( size_t addr_len, size_t max_prefix, size_t max_content, size_t max_suffix );
+
+/** Releases the packet queue.
+ *  @param[in] packet_id The first packet identifier.
+ *  @returns EOK on success.
+ *  @returns ENOENT if there is no such packet.
+ */
+int	packet_release_wrapper( packet_id_t packet_id );
+
+/** Releases the packet and returns it to the appropriate free packet queue.
+ *  Should be used only when the global data are locked.
+ *  @param[in] packet The packet to be released.
+ */
+void packet_release( packet_t packet );
+
+/** Creates a&nbsp;new packet of dimensions at least as given.
+ *  Should be used only when the global data are locked.
+ *  @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.
+ *  @returns The packet of dimensions at least as given.
+ *  @returns NULL if there is not enough memory left.
+ */
+packet_t	packet_create( size_t length, size_t addr_len, size_t max_prefix, size_t max_content, size_t max_suffix );
+
+/** 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.
+ */
+void	packet_init( packet_t packet, size_t addr_len, size_t max_prefix, size_t max_content, size_t max_suffix );
+
+/** Shares the packet memory block.
+ *  @param[in] packet The packet to be shared.
+ *  @returns EOK on success.
+ *  @returns EINVAL if the packet is not valid.
+ *  @returns EINVAL if the calling module does not accept the memory.
+ *  @returns ENOMEM if the desired and actual sizes differ.
+ *  @returns Other error codes as defined for the async_share_in_finalize() function.
+ */
+int packet_reply( const packet_t packet );
+
+/*@}*/
+
+int packet_translate( int phone, packet_ref packet, packet_id_t packet_id ){
+	if( ! packet ) return EINVAL;
+	* packet = pm_find( packet_id );
+	return ( * packet ) ? EOK : ENOENT;
+}
+
+packet_t packet_get_4( int phone, size_t max_content, size_t addr_len, size_t max_prefix, size_t max_suffix ){
+	return packet_get( addr_len, max_prefix, max_content, max_suffix );
+}
+
+packet_t packet_get_1( int phone, size_t content ){
+	return packet_get( DEFAULT_ADDR_LEN, DEFAULT_PREFIX, content, DEFAULT_SUFFIX );
+}
+
+void pq_release( int phone, packet_id_t packet_id ){
+	( void ) packet_release_wrapper( packet_id );
+}
+
+int	packet_server_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){
+	packet_t packet;
+
+	* answer_count = 0;
+	switch( IPC_GET_METHOD( * call )){
+		case IPC_M_PHONE_HUNGUP:
+			return EOK;
+		case NET_PACKET_CREATE_1:
+			packet = packet_get( DEFAULT_ADDR_LEN, DEFAULT_PREFIX, IPC_GET_CONTENT( call ), DEFAULT_SUFFIX );
+			if( ! packet ) return ENOMEM;
+			* answer_count = 2;
+			IPC_SET_ARG1( * answer, packet->packet_id );
+			IPC_SET_ARG2( * answer, packet->length );
+			return EOK;
+		case NET_PACKET_CREATE_4:
+			packet = packet_get((( 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, packet->packet_id );
+			IPC_SET_ARG2( * answer, 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, packet->length );
+			* answer_count = 1;
+			return EOK;
+		case NET_PACKET_RELEASE:
+			return packet_release_wrapper( IPC_GET_ID( call ));
+	}
+	return ENOTSUP;
+}
+
+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;
+}
+
+void packet_release( packet_t packet ){
+	int index;
+
+	// remove debug dump
+//	printf( "packet %d released\n", packet->packet_id );
+	for( index = 0; ( index < FREE_QUEUES_COUNT - 1 ) && ( packet->length > ps_globals.sizes[ index ] ); ++ index );
+	ps_globals.free[ index ] = pq_add( ps_globals.free[ index ], packet, packet->length, packet->length );
+	assert( ps_globals.free[ index ] );
+}
+
+packet_t packet_get( size_t addr_len, size_t max_prefix, size_t max_content, size_t max_suffix ){
+	int index;
+	packet_t packet;
+	size_t length;
+
+	length = ALIGN_UP( sizeof( struct packet ) + 2 * addr_len + max_prefix + max_content + max_suffix, PAGE_SIZE );
+	fibril_mutex_lock( & ps_globals.lock );
+	for( index = 0; index < FREE_QUEUES_COUNT - 1; ++ index ){
+		if( length <= ps_globals.sizes[ index ] ){
+			packet = ps_globals.free[ index ];
+			while( packet_is_valid( packet ) && ( packet->length < length )){
+				packet = pm_find( packet->next );
+			}
+			if( packet_is_valid( packet )){
+				if( packet == ps_globals.free[ index ] ){
+					ps_globals.free[ index ] = pq_detach( packet );
+				}else{
+					pq_detach( packet );
+				}
+				packet_init( packet, addr_len, max_prefix, max_content, max_suffix );
+				fibril_mutex_unlock( & ps_globals.lock );
+				// remove debug dump
+//				printf( "packet %d got\n", packet->packet_id );
+				return packet;
+			}
+		}
+	}
+	packet = packet_create( length, addr_len, max_prefix, max_content, max_suffix );
+	fibril_mutex_unlock( & ps_globals.lock );
+	// remove debug dump
+//	printf( "packet %d created\n", packet->packet_id );
+	return packet;
+}
+
+packet_t packet_create( size_t length, size_t addr_len, size_t max_prefix, size_t max_content, size_t max_suffix ){
+	ERROR_DECLARE;
+
+	packet_t	packet;
+
+	// already locked
+	packet = ( packet_t ) mmap( NULL, length, PROTO_READ | PROTO_WRITE, MAP_SHARED | MAP_ANONYMOUS, 0, 0 );
+	if( packet == MAP_FAILED ) return NULL;
+	++ ps_globals.count;
+	packet->packet_id = ps_globals.count;
+	packet->length = length;
+	packet_init( packet, addr_len, max_prefix, max_content, max_suffix );
+	packet->magic_value = PACKET_MAGIC_VALUE;
+	if( ERROR_OCCURRED( pm_add( packet ))){
+		munmap( packet, packet->length );
+		return NULL;
+	}
+	return packet;
+}
+
+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( struct packet ), packet->length - sizeof( struct packet ));
+	// clear the packet header
+	packet->order = 0;
+	packet->metric = 0;
+	packet->previous = 0;
+	packet->next = 0;
+	packet->addr_len = 0;
+	packet->src_addr = sizeof( struct packet );
+	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;
+}
+
+int packet_reply( const packet_t packet ){
+	ipc_callid_t	callid;
+	size_t			size;
+
+	if( ! packet_is_valid( packet )) return EINVAL;
+	if( async_share_in_receive( & callid, & size ) <= 0 ) return EINVAL;
+	if( size != packet->length ) return ENOMEM;
+	return async_share_in_finalize( callid, packet, PROTO_READ | PROTO_WRITE );
+}
+
+/** @}
+ */
Index: uspace/srv/net/structures/packet/packet_server.h
===================================================================
--- uspace/srv/net/structures/packet/packet_server.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/structures/packet/packet_server.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,63 @@
+/*
+ * 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 packet
+ *  @{
+ */
+
+/** @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/ipc.h>
+
+/** 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.
+ *  @returns EOK on success.
+ *  @returns ENOMEM if there is not enough memory left.
+ *  @returns ENOENT if there is no such packet as in the packet message parameter..
+ *  @returns ENOTSUP if the message is not known.
+ *  @returns 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, int * answer_count );
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/tl/icmp/Makefile
===================================================================
--- uspace/srv/net/tl/icmp/Makefile	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/tl/icmp/Makefile	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,53 @@
+#
+# 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.
+#
+
+NAME = icmp
+
+NET_BASE = ../../
+STRUCTURES = $(NET_BASE)structures/
+
+## Sources
+#
+
+OUTPUT = $(NAME)
+SOURCES = \
+	$(NAME).c \
+	$(NAME)_module.c \
+	$(NAME)_client.c \
+	$(NET_BASE)checksum.c \
+	$(NET_BASE)module.c \
+	$(NET_BASE)modules.c \
+	$(NET_BASE)il/ip/ip_client.c \
+	$(NET_BASE)il/ip/ip_remote.c \
+	$(NET_BASE)net/net_remote.c \
+	$(STRUCTURES)measured_strings.c \
+	$(STRUCTURES)packet/packet.c \
+	$(STRUCTURES)packet/packet_client.c \
+	$(STRUCTURES)packet/packet_remote.c
+
+include $(NET_BASE)Makefile.module
Index: uspace/srv/net/tl/icmp/icmp.c
===================================================================
--- uspace/srv/net/tl/icmp/icmp.c	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/tl/icmp/icmp.c	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,864 @@
+/*
+ * 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.
+ *  @see icmp.h
+ */
+
+#include <async.h>
+#include <atomic.h>
+#include <fibril.h>
+#include <fibril_synch.h>
+#include <stdint.h>
+
+#include <ipc/ipc.h>
+#include <ipc/services.h>
+
+#include <sys/time.h>
+#include <sys/types.h>
+
+#include "../../err.h"
+#include "../../messages.h"
+#include "../../modules.h"
+
+#include "../../structures/packet/packet_client.h"
+
+#include "../../include/byteorder.h"
+#include "../../include/checksum.h"
+#include "../../include/icmp_api.h"
+#include "../../include/icmp_client.h"
+#include "../../include/icmp_codes.h"
+#include "../../include/icmp_common.h"
+#include "../../include/icmp_interface.h"
+#include "../../include/il_interface.h"
+#include "../../include/inet.h"
+#include "../../include/ip_client.h"
+#include "../../include/ip_interface.h"
+#include "../../include/ip_protocols.h"
+#include "../../include/net_interface.h"
+#include "../../include/socket_codes.h"
+#include "../../include/socket_errno.h"
+
+#include "../../tl/tl_messages.h"
+
+#include "icmp.h"
+#include "icmp_header.h"
+#include "icmp_messages.h"
+#include "icmp_module.h"
+
+/** Default ICMP error reporting.
+ */
+#define NET_DEFAULT_ICMP_ERROR_REPORTING	true
+
+/** Default ICMP echo replying.
+ */
+#define NET_DEFAULT_ICMP_ECHO_REPLYING		true
+
+/** Original datagram length in bytes transfered to the error notification message.
+ */
+#define ICMP_KEEP_LENGTH	8
+
+/** Free identifier numbers pool start.
+ */
+#define ICMP_FREE_IDS_START	1
+
+/** Free identifier numbers pool end.
+ */
+#define ICMP_FREE_IDS_END	MAX_UINT16
+
+/** Computes the ICMP datagram checksum.
+ *  @param[in,out] header The ICMP datagram header.
+ *  @param[in] length The total datagram length.
+ *  @returns The computed checksum.
+ */
+#define ICMP_CHECKSUM( header, length )		htons( ip_checksum(( uint8_t * ) ( header ), ( length )))
+
+/** An echo request datagrams pattern.
+ */
+#define ICMP_ECHO_TEXT					"Hello from HelenOS."
+
+/** Computes an ICMP reply data key.
+ *  @param[in] id The message identifier.
+ *  @param[in] sequence The message sequence number.
+ *  @returns The computed ICMP reply data key.
+ */
+#define ICMP_GET_REPLY_KEY( id, sequence )	((( id ) << 16 ) | ( sequence & 0xFFFF ))
+
+/** Type definition of the ICMP reply timeout.
+ *  @see icmp_reply_timeout
+ */
+typedef struct icmp_reply_timeout	icmp_reply_timeout_t;
+
+/** Type definition of the ICMP reply timeout pointer.
+ *  @see icmp_reply_timeout
+ */
+typedef icmp_reply_timeout_t *	icmp_reply_timeout_ref;
+
+/** ICMP reply timeout data.
+ *  Used as a timeouting fibril argument.
+ *  @see icmp_timeout_for_reply()
+ */
+struct icmp_reply_timeout{
+	/** Reply data key.
+	 */
+	int			reply_key;
+	/** Timeout in microseconds.
+	 */
+	suseconds_t	timeout;
+};
+
+/** Processes the received ICMP packet.
+ *  Is used as an entry point from the underlying IP module.
+ *  Releases the packet on error.
+ *  @param device_id The device identifier. Ignored parameter.
+ *  @param[in,out] packet The received packet.
+ *  @param receiver The target service. Ignored parameter.
+ *  @param[in] error The packet error reporting service. Prefixes the received packet.
+ *  @returns EOK on success.
+ *  @returns Other error codes as defined for the icmp_process_packet() function.
+ */
+int	icmp_received_msg( device_id_t device_id, packet_t packet, services_t receiver, services_t error );
+
+/** Processes the received ICMP packet.
+ *  Notifies the destination socket application.
+ *  @param[in,out] packet The received packet.
+ *  @param[in] error The packet error reporting service. Prefixes the received packet.
+ *  @returns EOK on success.
+ *  @returns EINVAL if the packet is not valid.
+ *  @returns EINVAL if the stored packet address is not the an_addr_t.
+ *  @returns EINVAL if the packet does not contain any data.
+ *  @returns NO_DATA if the packet content is shorter than the user datagram header.
+ *  @returns ENOMEM if there is not enough memory left.
+ *  @returns EADDRNOTAVAIL if the destination socket does not exist.
+ *  @returns Other error codes as defined for the ip_client_process_packet() function.
+ */
+int	icmp_process_packet( packet_t packet, services_t error );
+
+/** Processes the client messages.
+ *  Remembers the assigned identifier and sequence numbers.
+ *  Runs until the client module disconnects.
+ *  @param[in] callid The message identifier.
+ *  @param[in] call The message parameters.
+ *  @returns EOK.
+ *  @see icmp_interface.h
+ *  @see icmp_api.h
+ */
+int icmp_process_client_messages( ipc_callid_t callid, ipc_call_t call );
+
+/** Processes the generic client messages.
+ *  @param[in] call The message parameters.
+ *  @returns EOK on success.
+ *  @returns ENOTSUP if the message is not known.
+ *  @returns Other error codes as defined for the packet_translate() function.
+ *  @returns Other error codes as defined for the icmp_destination_unreachable_msg() function.
+ *  @returns Other error codes as defined for the icmp_source_quench_msg() function.
+ *  @returns Other error codes as defined for the icmp_time_exceeded_msg() function.
+ *  @returns Other error codes as defined for the icmp_parameter_problem_msg() function.
+ *  @see icmp_interface.h
+ */
+int	icmp_process_message( ipc_call_t * call );
+
+/** Releases the packet and returns the result.
+ *  @param[in] packet The packet queue to be released.
+ *  @param[in] result The result to be returned.
+ *  @returns The result parameter.
+ */
+int	icmp_release_and_return( packet_t packet, int result );
+
+/** 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 occurres.
+ *  @param[in] id The message identifier.
+ *  @param[in] sequence The message sequence parameter.
+ *  @param[in] size The message data length in bytes.
+ *  @param[in] timeout The timeout in miliseconds.
+ *  @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.
+ *  @returns ICMP_ECHO on success.
+ *  @returns ETIMEOUT if the reply has not arrived before the timeout.
+ *  @returns ICMP type of the received error notification. 
+ *  @returns EINVAL if the addrlen parameter is less or equal to zero (<=0).
+ *  @returns ENOMEM if there is not enough memory left.
+ *  @returns EPARTY if there was an internal error.
+ */
+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, int dont_fragment, const struct sockaddr * addr, socklen_t addrlen );
+
+/** Prepares the ICMP error packet.
+ *  Truncates the original packet if longer than ICMP_KEEP_LENGTH bytes.
+ *  Prefixes and returns the ICMP header.
+ *  @param[in,out] packet The original packet.
+ *  @returns The prefixed ICMP header.
+ *  @returns NULL on errors.
+ */
+icmp_header_ref	icmp_prepare_packet( packet_t packet );
+
+/** Sends the ICMP message.
+ *  Sets the message type and code and computes the checksum.
+ *  Error messages are sent only if allowed in the configuration.
+ *  Releases the packet on errors.
+ *  @param[in] type The message type.
+ *  @param[in] code The message code.
+ *  @param[in] packet The message packet to be sent.
+ *  @param[in] header The ICMP header.
+ *  @param[in] error The error service to be announced. Should be SERVICE_ICMP or zero (0).
+ *  @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.
+ *  @returns EOK on success.
+ *  @returns EPERM if the error message is not allowed.
+ */
+int	icmp_send_packet( icmp_type_t type, icmp_code_t code, packet_t packet, icmp_header_ref header, services_t error, ip_ttl_t ttl, ip_tos_t tos, int dont_fragment );
+
+/** Tries to set the pending reply result as the received message type.
+ *  If the reply data are still present, the reply timeouted and the parent fibril is awaken.
+ *  The global lock is not released in this case to be reused by the parent fibril.
+ *  Releases the packet.
+ *  @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.
+ *  @returns EOK.
+ */
+int	icmp_process_echo_reply( packet_t packet, icmp_header_ref header, icmp_type_t type, icmp_code_t code );
+
+/** Tries to set the pending reply result as timeouted.
+ *  Sleeps the timeout period of time and then tries to obtain and set the pending reply result as timeouted and signals the reply result.
+ *  If the reply data are still present, the reply timeouted and the parent fibril is awaken.
+ *  The global lock is not released in this case to be reused by the parent fibril.
+ *  Should run in a searate fibril.
+ *  @param[in] data The icmp_reply_timeout structure.
+ *  @returns EOK on success.
+ *  @returns EINVAL if the data parameter is NULL.
+ */
+int	icmp_timeout_for_reply( void * data );
+
+/** Assigns a new identifier for the connection.
+ *  Fills the echo data parameter with the assigned values.
+ *  @param[in,out] echo_data The echo data to be bound.
+ *  @returns Index of the inserted echo data.
+ *  @returns EBADMEM if the echo_data parameter is NULL.
+ *  @returns ENOTCONN if no free identifier have been found.
+ */
+int	icmp_bind_free_id( icmp_echo_ref echo_data );
+
+/** ICMP global data.
+ */
+icmp_globals_t	icmp_globals;
+
+INT_MAP_IMPLEMENT( icmp_replies, icmp_reply_t );
+
+INT_MAP_IMPLEMENT( icmp_echo_data, icmp_echo_t );
+
+int icmp_echo_msg( int icmp_phone, size_t size, mseconds_t timeout, ip_ttl_t ttl, ip_tos_t tos, int dont_fragment, const struct sockaddr * addr, socklen_t addrlen ){
+	icmp_echo_ref	echo_data;
+	int				res;
+
+	fibril_rwlock_write_lock( & icmp_globals.lock );
+	// use the phone as the echo data index
+	echo_data = icmp_echo_data_find( & icmp_globals.echo_data, icmp_phone );
+	if( ! echo_data ){
+		res = ENOENT;
+	}else{
+		res = icmp_echo( echo_data->identifier, echo_data->sequence_number, size, timeout, ttl, tos, dont_fragment, addr, addrlen );
+		if( echo_data->sequence_number < MAX_UINT16 ){
+			++ echo_data->sequence_number;
+		}else{
+			echo_data->sequence_number = 0;
+		}
+	}
+	fibril_rwlock_write_unlock( & icmp_globals.lock );
+	return res;
+}
+
+int icmp_timeout_for_reply( void * data ){
+	icmp_reply_ref			reply;
+	icmp_reply_timeout_ref	timeout = data;
+
+	if( ! timeout ){
+		return EINVAL;
+	}
+	// sleep the given timeout
+	async_usleep( timeout->timeout );
+	// lock the globals
+	fibril_rwlock_write_lock( & icmp_globals.lock );
+	// find the pending reply
+	reply = icmp_replies_find( & icmp_globals.replies, timeout->reply_key );
+	if( reply ){
+		// set the timeout result
+		reply->result = ETIMEOUT;
+		// notify the main fibril
+		fibril_condvar_signal( & reply->condvar );
+	}else{
+		// unlock only if no reply
+		fibril_rwlock_write_unlock( & icmp_globals.lock );
+	}
+	// release the timeout structure
+	free( timeout );
+	return EOK;
+}
+
+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, int dont_fragment, const struct sockaddr * addr, socklen_t addrlen ){
+	ERROR_DECLARE;
+
+	icmp_header_ref	header;
+	packet_t		packet;
+	size_t			length;
+	uint8_t *		data;
+	icmp_reply_ref			reply;
+	icmp_reply_timeout_ref	reply_timeout;
+	int				result;
+	int				index;
+	fid_t			fibril;
+
+	if( addrlen <= 0 ){
+		return EINVAL;
+	}
+	length = ( size_t ) addrlen;
+	// TODO do not ask all the time
+	ERROR_PROPAGATE( ip_packet_size_req( icmp_globals.ip_phone, -1, & icmp_globals.addr_len, & icmp_globals.prefix, & icmp_globals.content, & icmp_globals.suffix ));
+	packet = packet_get_4( icmp_globals.net_phone, size, icmp_globals.addr_len, ICMP_HEADER_SIZE + icmp_globals.prefix, icmp_globals.suffix );
+	if( ! packet ) return ENOMEM;
+
+	// prepare the requesting packet
+	// set the destination address
+	if( ERROR_OCCURRED( packet_set_addr( packet, NULL, ( const uint8_t * ) addr, length ))){
+		return icmp_release_and_return( packet, ERROR_CODE );
+	}
+	// allocate space in the packet
+	data = ( uint8_t * ) packet_suffix( packet, size );
+	if( ! data ){
+		return icmp_release_and_return( packet, 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
+	header = PACKET_PREFIX( packet, icmp_header_t );
+	if( ! header ){
+		return icmp_release_and_return( packet, ENOMEM );
+	}
+	bzero( header, sizeof( * header ));
+	header->un.echo.identifier = id;
+	header->un.echo.sequence_number = sequence;
+
+	// prepare the reply and the reply timeout structures
+	reply_timeout = malloc( sizeof( * reply_timeout ));
+	if( ! reply_timeout ){
+		return icmp_release_and_return( packet, ENOMEM );
+	}
+	reply = malloc( sizeof( * reply ));
+	if( ! reply ){
+		free( reply_timeout );
+		return icmp_release_and_return( packet, ENOMEM );
+	}
+	// prepare the timeouting thread
+	fibril = fibril_create( icmp_timeout_for_reply, reply_timeout );
+	if( ! fibril ){
+		free( reply );
+		free( reply_timeout );
+		return icmp_release_and_return( packet, EPARTY );
+	}
+	reply_timeout->reply_key = ICMP_GET_REPLY_KEY( header->un.echo.identifier, header->un.echo.sequence_number );
+	// timeout in microseconds
+	reply_timeout->timeout = timeout * 1000;
+	fibril_mutex_initialize( & reply->mutex );
+	fibril_mutex_lock( & reply->mutex );
+	fibril_condvar_initialize( & reply->condvar );
+	// start the timeouting fibril
+	fibril_add_ready( fibril );
+	index = icmp_replies_add( & icmp_globals.replies, reply_timeout->reply_key, reply );
+	if( index < 0 ){
+		free( reply );
+		return icmp_release_and_return( packet, index );
+	}
+
+	// unlock the globals and wait for a reply
+	fibril_rwlock_write_unlock( & icmp_globals.lock );
+
+	// send the request
+	icmp_send_packet( ICMP_ECHO, 0, packet, header, 0, ttl, tos, dont_fragment );
+
+	// wait for a reply
+	fibril_condvar_wait( & reply->condvar, & reply->mutex );
+
+	// read the result
+	result = reply->result;
+
+	// destroy the reply structure
+	fibril_mutex_unlock( & reply->mutex );
+	icmp_replies_exclude_index( & icmp_globals.replies, index );
+	return result;
+}
+
+int icmp_destination_unreachable_msg( int icmp_phone, icmp_code_t code, icmp_param_t mtu, packet_t packet ){
+	icmp_header_ref	header;
+
+	header = icmp_prepare_packet( packet );
+	if( ! header ){
+		return icmp_release_and_return( packet, ENOMEM );
+	}
+	if( mtu ){
+		header->un.frag.mtu = mtu;
+	}
+	return icmp_send_packet( ICMP_DEST_UNREACH, code, packet, header, SERVICE_ICMP, 0, 0, 0 );
+}
+
+int icmp_source_quench_msg( int icmp_phone, packet_t packet ){
+	icmp_header_ref	header;
+
+	header = icmp_prepare_packet( packet );
+	if( ! header ){
+		return icmp_release_and_return( packet, ENOMEM );
+	}
+	return icmp_send_packet( ICMP_SOURCE_QUENCH, 0, packet, header, SERVICE_ICMP, 0, 0, 0 );
+}
+
+int icmp_time_exceeded_msg( int icmp_phone, icmp_code_t code, packet_t packet ){
+	icmp_header_ref	header;
+
+	header = icmp_prepare_packet( packet );
+	if( ! header ){
+		return icmp_release_and_return( packet, ENOMEM );
+	}
+	return icmp_send_packet( ICMP_TIME_EXCEEDED, code, packet, header, SERVICE_ICMP, 0, 0, 0 );
+}
+
+int icmp_parameter_problem_msg( int icmp_phone, icmp_code_t code, icmp_param_t pointer, packet_t packet ){
+	icmp_header_ref	header;
+
+	header = icmp_prepare_packet( packet );
+	if( ! header ){
+		return icmp_release_and_return( packet, ENOMEM );
+	}
+	header->un.param.pointer = pointer;
+	return icmp_send_packet( ICMP_PARAMETERPROB, code, packet, header, SERVICE_ICMP, 0, 0, 0 );
+}
+
+icmp_header_ref icmp_prepare_packet( packet_t packet ){
+	icmp_header_ref	header;
+	size_t			header_length;
+	size_t			total_length;
+
+	total_length = packet_get_data_length( packet );
+	if( total_length <= 0 ) return NULL;
+	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;
+	}
+	header = PACKET_PREFIX( packet, icmp_header_t );
+	if( ! header ) return NULL;
+	bzero( header, sizeof( * header ));
+	return header;
+}
+
+int icmp_send_packet( icmp_type_t type, icmp_code_t code, packet_t packet, icmp_header_ref header, services_t error, ip_ttl_t ttl, ip_tos_t tos, int dont_fragment ){
+	ERROR_DECLARE;
+
+	// do not send an error if disabled
+	if( error && ( ! icmp_globals.error_reporting )){
+		return icmp_release_and_return( packet, EPERM );
+	}
+	header->type = type;
+	header->code = code;
+	header->checksum = 0;
+	header->checksum = ICMP_CHECKSUM( header, packet_get_data_length( packet ));
+	if( ERROR_OCCURRED( ip_client_prepare_packet( packet, IPPROTO_ICMP, ttl, tos, dont_fragment, 0 ))){
+		return icmp_release_and_return( packet, ERROR_CODE );
+	}
+	return ip_send_msg( icmp_globals.ip_phone, -1, packet, SERVICE_ICMP, error );
+}
+
+int icmp_connect_module( services_t service, suseconds_t timeout ){
+	icmp_echo_ref	echo_data;
+	icmp_param_t	id;
+	int				index;
+
+	echo_data = ( icmp_echo_ref ) malloc( sizeof( * echo_data ));
+	if( ! echo_data ) return ENOMEM;
+	// assign a new identifier
+	fibril_rwlock_write_lock( & icmp_globals.lock );
+	index = icmp_bind_free_id( echo_data );
+	if( index < 0 ){
+		free( echo_data );
+		fibril_rwlock_write_unlock( & icmp_globals.lock );
+		return index;
+	}else{
+		id = echo_data->identifier;
+		fibril_rwlock_write_unlock( & icmp_globals.lock );
+		// return the echo data identifier as the ICMP phone
+		return id;
+	}
+}
+
+int icmp_initialize( async_client_conn_t client_connection ){
+	ERROR_DECLARE;
+
+	measured_string_t	names[] = {{ "ICMP_ERROR_REPORTING", 20 }, { "ICMP_ECHO_REPLYING", 18 }};
+	measured_string_ref	configuration;
+	size_t				count = sizeof( names ) / sizeof( measured_string_t );
+	char *				data;
+
+	fibril_rwlock_initialize( & icmp_globals.lock );
+	fibril_rwlock_write_lock( & icmp_globals.lock );
+	icmp_replies_initialize( & icmp_globals.replies );
+	icmp_echo_data_initialize( & icmp_globals.echo_data );
+	icmp_globals.ip_phone = ip_bind_service( SERVICE_IP, IPPROTO_ICMP, SERVICE_ICMP, client_connection, icmp_received_msg );
+	if( icmp_globals.ip_phone < 0 ){
+		return icmp_globals.ip_phone;
+	}
+	ERROR_PROPAGATE( ip_packet_size_req( icmp_globals.ip_phone, -1, & icmp_globals.addr_len, & icmp_globals.prefix, & icmp_globals.content, & icmp_globals.suffix ));
+	icmp_globals.prefix += ICMP_HEADER_SIZE;
+	icmp_globals.content -= ICMP_HEADER_SIZE;
+	// get configuration
+	icmp_globals.error_reporting = NET_DEFAULT_ICMP_ERROR_REPORTING;
+	icmp_globals.echo_replying = NET_DEFAULT_ICMP_ECHO_REPLYING;
+	configuration = & names[ 0 ];
+	ERROR_PROPAGATE( net_get_conf_req( icmp_globals.net_phone, & configuration, count, & data ));
+	if( configuration ){
+		if( configuration[ 0 ].value ){
+			icmp_globals.error_reporting = ( configuration[ 0 ].value[ 0 ] == 'y' );
+		}
+		if( configuration[ 1 ].value ){
+			icmp_globals.echo_replying = ( configuration[ 1 ].value[ 0 ] == 'y' );
+		}
+		net_free_settings( configuration, data );
+	}
+	fibril_rwlock_write_unlock( & icmp_globals.lock );
+	return EOK;
+}
+
+int	icmp_received_msg( device_id_t device_id, packet_t packet, services_t receiver, services_t error ){
+	ERROR_DECLARE;
+
+	if( ERROR_OCCURRED( icmp_process_packet( packet, error ))){
+		return icmp_release_and_return( packet, ERROR_CODE );
+	}
+
+	return EOK;
+}
+
+int icmp_process_packet( packet_t packet, services_t error ){
+	ERROR_DECLARE;
+
+	size_t			length;
+	uint8_t *		src;
+	int				addrlen;
+	int				result;
+	void *			data;
+	icmp_header_ref	header;
+	icmp_type_t		type;
+	icmp_code_t		code;
+
+	if( error ){
+		switch( error ){
+			case SERVICE_ICMP:
+				// process error
+				result = icmp_client_process_packet( packet, & type, & code, NULL, NULL );
+				if( result < 0 ) return result;
+				length = ( size_t ) result;
+				// remove the error header
+				ERROR_PROPAGATE( packet_trim( packet, length, 0 ));
+				break;
+			default:
+				return ENOTSUP;
+		}
+	}
+	// get rid of the ip header
+	length = ip_client_header_length( packet );
+	ERROR_PROPAGATE( packet_trim( packet, length, 0 ));
+
+	length = packet_get_data_length( packet );
+	if( length <= 0 ) return EINVAL;
+	if( length < ICMP_HEADER_SIZE) return EINVAL;
+	data = packet_get_data( packet );
+	if( ! data ) return EINVAL;
+	// get icmp header
+	header = ( icmp_header_ref ) data;
+	// checksum
+	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 ){
+				return icmp_process_echo_reply( packet, header, type, code );
+			}else{
+				return icmp_process_echo_reply( packet, header, ICMP_ECHO, 0 );
+			}
+		case ICMP_ECHO:
+			if( error ){
+				return icmp_process_echo_reply( packet, header, type, code );
+			// do not send a reply if disabled
+			}else if( icmp_globals.echo_replying ){
+				addrlen = packet_get_addr( packet, & src, NULL );
+				if(( addrlen > 0 )
+				// 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 ) addrlen ) == EOK )){
+					// send the reply
+					icmp_send_packet( ICMP_ECHOREPLY, 0, packet, header, 0, 0, 0, 0 );
+					return EOK;
+				}else{
+					return EINVAL;
+				}
+			}else{
+				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( icmp_globals.ip_phone, -1, packet, SERVICE_IP, SERVICE_ICMP );
+			return EOK;
+		default:
+			return ENOTSUP;
+	}
+}
+
+int icmp_process_echo_reply( packet_t packet, icmp_header_ref header, icmp_type_t type, icmp_code_t code ){
+	int				reply_key;
+	icmp_reply_ref	reply;
+
+	// compute the reply key
+	reply_key = ICMP_GET_REPLY_KEY( header->un.echo.identifier, header->un.echo.sequence_number );
+	pq_release( icmp_globals.net_phone, packet_get_id( packet ));
+	// lock the globals
+	fibril_rwlock_write_lock( & icmp_globals.lock );
+	// find the pending reply
+	reply = icmp_replies_find( & icmp_globals.replies, reply_key );
+	if( reply ){
+		// set the result
+		reply->result = type;
+		// notify the main fibril
+		fibril_condvar_signal( & reply->condvar );
+	}else{
+		// unlock only if no reply
+		fibril_rwlock_write_unlock( & icmp_globals.lock );
+	}
+	return EOK;
+}
+
+int icmp_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){
+	ERROR_DECLARE;
+
+	packet_t			packet;
+
+	* answer_count = 0;
+	switch( IPC_GET_METHOD( * call )){
+		case NET_TL_RECEIVED:
+			if( ! ERROR_OCCURRED( packet_translate( icmp_globals.net_phone, & packet, IPC_GET_PACKET( call )))){
+				ERROR_CODE = icmp_received_msg( IPC_GET_DEVICE( call ), packet, SERVICE_ICMP, IPC_GET_ERROR( call ));
+			}
+			return ERROR_CODE;
+		case NET_ICMP_INIT:
+			return icmp_process_client_messages( callid, * call );
+		default:
+			return icmp_process_message( call );
+	}
+	return ENOTSUP;
+}
+
+int icmp_process_client_messages( ipc_callid_t callid, ipc_call_t call ){
+	ERROR_DECLARE;
+
+	bool					keep_on_going = true;
+//	fibril_rwlock_t			lock;
+	ipc_call_t				answer;
+	int						answer_count;
+	size_t					length;
+	struct sockaddr *		addr;
+	ipc_callid_t			data_callid;
+	icmp_echo_ref			echo_data;
+
+	/*
+	 * Accept the connection
+	 *  - Answer the first NET_ICMP_INIT call.
+	 */
+	ipc_answer_0( callid, EOK );
+
+//	fibril_rwlock_initialize( & lock );
+
+	echo_data = ( icmp_echo_ref ) malloc( sizeof( * echo_data ));
+	if( ! echo_data ) return ENOMEM;
+	// assign a new identifier
+	fibril_rwlock_write_lock( & icmp_globals.lock );
+	ERROR_CODE = icmp_bind_free_id( echo_data );
+	fibril_rwlock_write_unlock( & icmp_globals.lock );
+	if( ERROR_CODE < 0 ){
+		free( echo_data );
+		return ERROR_CODE;
+	}
+
+	while( keep_on_going ){
+		refresh_answer( & answer, & answer_count );
+
+		callid = async_get_call( & call );
+
+		switch( IPC_GET_METHOD( call )){
+			case IPC_M_PHONE_HUNGUP:
+				keep_on_going = false;
+				ERROR_CODE = EOK;
+				break;
+			case NET_ICMP_ECHO:
+//				fibril_rwlock_write_lock( & lock );
+				if( ! async_data_write_receive( & data_callid, & length )){
+					ERROR_CODE = EINVAL;
+				}else{
+					addr = malloc( length );
+					if( ! addr ){
+						ERROR_CODE = ENOMEM;
+					}else{
+						if( ! ERROR_OCCURRED( async_data_write_finalize( data_callid, addr, length ))){
+							fibril_rwlock_write_lock( & icmp_globals.lock );
+							ERROR_CODE = icmp_echo( echo_data->identifier, echo_data->sequence_number, ICMP_GET_SIZE( call ), ICMP_GET_TIMEOUT( call ), ICMP_GET_TTL( call ), ICMP_GET_TOS( call ), ICMP_GET_DONT_FRAGMENT( call ), addr, ( socklen_t ) length );
+							fibril_rwlock_write_unlock( & icmp_globals.lock );
+							free( addr );
+							if( echo_data->sequence_number < MAX_UINT16 ){
+								++ echo_data->sequence_number;
+							}else{
+								echo_data->sequence_number = 0;
+							}
+						}
+					}
+				}
+//				fibril_rwlock_write_unlock( & lock );
+				break;
+			default:
+				ERROR_CODE = icmp_process_message( & call );
+		}
+
+		answer_call( callid, ERROR_CODE, & answer, answer_count );
+	}
+
+	// release the identifier
+	fibril_rwlock_write_lock( & icmp_globals.lock );
+	icmp_echo_data_exclude( & icmp_globals.echo_data, echo_data->identifier );
+	fibril_rwlock_write_unlock( & icmp_globals.lock );
+	return EOK;
+}
+
+int icmp_process_message( ipc_call_t * call ){
+	ERROR_DECLARE;
+
+	packet_t	packet;
+
+	switch( IPC_GET_METHOD( * call )){
+		case NET_ICMP_DEST_UNREACH:
+			if( ! ERROR_OCCURRED( packet_translate( icmp_globals.net_phone, & packet, IPC_GET_PACKET( call )))){
+				ERROR_CODE = icmp_destination_unreachable_msg( 0, ICMP_GET_CODE( call ), ICMP_GET_MTU( call ), packet );
+			}
+			return ERROR_CODE;
+		case NET_ICMP_SOURCE_QUENCH:
+			if( ! ERROR_OCCURRED( packet_translate( icmp_globals.net_phone, & packet, IPC_GET_PACKET( call )))){
+				ERROR_CODE = icmp_source_quench_msg( 0, packet );
+			}
+			return ERROR_CODE;
+		case NET_ICMP_TIME_EXCEEDED:
+			if( ! ERROR_OCCURRED( packet_translate( icmp_globals.net_phone, & packet, IPC_GET_PACKET( call )))){
+				ERROR_CODE = icmp_time_exceeded_msg( 0, ICMP_GET_CODE( call ), packet );
+			}
+			return ERROR_CODE;
+		case NET_ICMP_PARAMETERPROB:
+			if( ! ERROR_OCCURRED( packet_translate( icmp_globals.net_phone, & packet, IPC_GET_PACKET( call )))){
+				ERROR_CODE = icmp_parameter_problem_msg( 0, ICMP_GET_CODE( call ), ICMP_GET_POINTER( call ), packet );
+			}
+			return ERROR_CODE;
+		default:
+			return ENOTSUP;
+	}
+}
+
+int	icmp_release_and_return( packet_t packet, int result ){
+	pq_release( icmp_globals.net_phone, packet_get_id( packet ));
+	return result;
+}
+
+int icmp_bind_free_id( icmp_echo_ref echo_data ){
+	icmp_param_t	index;
+
+	if( ! echo_data ) return EBADMEM;
+	// from the last used one
+	index = icmp_globals.last_used_id;
+	do{
+		++ index;
+		// til the range end
+		if( index >= ICMP_FREE_IDS_END ){
+			// start from the range beginning
+			index = ICMP_FREE_IDS_START - 1;
+			do{
+				++ index;
+				// til the last used one
+				if( index >= icmp_globals.last_used_id ){
+					// none found
+					return ENOTCONN;
+				}
+			}while( icmp_echo_data_find( & icmp_globals.echo_data, index ) != NULL );
+			// found, break immediately
+			break;
+		}
+	}while( icmp_echo_data_find( & icmp_globals.echo_data, index ) != NULL );
+	echo_data->identifier = index;
+	echo_data->sequence_number = 0;
+	return icmp_echo_data_add( & icmp_globals.echo_data, index, echo_data );
+}
+
+/** @}
+ */
Index: uspace/srv/net/tl/icmp/icmp.h
===================================================================
--- uspace/srv/net/tl/icmp/icmp.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/tl/icmp/icmp.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,135 @@
+/*
+ * 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.
+ */
+
+#ifndef __NET_ICMP_H__
+#define __NET_ICMP_H__
+
+#include <fibril_synch.h>
+
+#include "../../include/icmp_codes.h"
+
+#include "../../structures/int_map.h"
+
+#include "icmp_header.h"
+
+/** Type definition of the ICMP reply data.
+ *  @see icmp_reply
+ */
+typedef struct icmp_reply	icmp_reply_t;
+
+/** Type definition of the ICMP reply data pointer.
+ *  @see icmp_reply
+ */
+typedef icmp_reply_t *	icmp_reply_ref;
+
+/** Type definition of the ICMP global data.
+ *  @see icmp_globals
+ */
+typedef struct icmp_globals	icmp_globals_t;
+
+/** Pending replies map.
+ *  Maps message identifiers to the pending replies.
+ *  Sending fibril waits for its associated reply event.
+ *  Receiving fibril sets the associated reply with the return value and signals the event.
+ */
+INT_MAP_DECLARE( icmp_replies, icmp_reply_t );
+
+/** Echo specific data map.
+ *  The bundle module gets an identifier of the assigned echo specific data while connecting.
+ *  The identifier is used in the future semi-remote calls instead of the ICMP phone.
+ */
+INT_MAP_DECLARE( icmp_echo_data, icmp_echo_t );
+
+/** ICMP reply data.
+ */
+struct icmp_reply{
+	/** Reply result.
+	 */
+	int					result;
+	/** Safety lock.
+	 */
+	fibril_mutex_t		mutex;
+	/** Received or timeouted reply signaling.
+	 */
+	fibril_condvar_t	condvar;
+};
+
+/** ICMP global data.
+ */
+struct	icmp_globals{
+	/** IP module phone.
+	 */
+	int				ip_phone;
+	/** Reserved packet prefix length.
+	 */
+	size_t			prefix;
+	/** Maximal packet content length.
+	 */
+	size_t			content;
+	/** Reserved packet suffix length.
+	 */
+	size_t			suffix;
+	/** Packet address length.
+	 */
+	size_t			addr_len;
+	/** Networking module phone.
+	 */
+	int				net_phone;
+	/** Indicates whether ICMP error reporting is enabled.
+	 */
+	int				error_reporting;
+	/** Indicates whether ICMP echo replying (ping) is enabled.
+	 */
+	int				echo_replying;
+	/** The last used identifier number.
+	 */
+	icmp_param_t	last_used_id;
+	/** The budled modules assigned echo specific data.
+	 */
+	icmp_echo_data_t	echo_data;
+	/** Echo timeout locks.
+	 */
+	icmp_replies_t	replies;
+	/** Safety lock.
+	 */
+	fibril_rwlock_t	lock;
+};
+
+#endif
+
+/** @}
+ */
+
Index: uspace/srv/net/tl/icmp/icmp_api.c
===================================================================
--- uspace/srv/net/tl/icmp/icmp_api.c	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/tl/icmp/icmp_api.c	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,71 @@
+/*
+ * 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 icmp
+ *  @{
+ */
+
+/** @file
+ *  ICMP application interface implementation.
+ *  @see icmp_api.h
+ */
+
+#include <async.h>
+
+#include <ipc/ipc.h>
+#include <ipc/services.h>
+
+#include <sys/types.h>
+
+#include "../../modules.h"
+
+#include "../../include/icmp_api.h"
+#include "../../include/inet.h"
+#include "../../include/ip_codes.h"
+#include "../../include/socket_codes.h"
+
+#include "icmp_messages.h"
+
+int icmp_echo_msg( int icmp_phone, 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;
+	ipcarg_t		result;
+
+	if( addrlen <= 0 ){
+		return EINVAL;
+	}
+	message_id = async_send_5( icmp_phone, NET_ICMP_ECHO, size, timeout, ttl, tos, ( ipcarg_t ) dont_fragment, NULL );
+	// send the address
+	async_data_write_start( icmp_phone, addr, ( size_t ) addrlen );
+	// timeout version may cause inconsistency - there is also an inner timer
+	// return async_wait_timeout( message_id, & result, timeout );
+	async_wait_for( message_id, & result );
+	return ( int ) result;
+}
+
+/** @}
+ */
Index: uspace/srv/net/tl/icmp/icmp_client.c
===================================================================
--- uspace/srv/net/tl/icmp/icmp_client.c	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/tl/icmp/icmp_client.c	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,76 @@
+/*
+ * 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 icmp
+ *  @{
+ */
+
+/** @file
+ *  ICMP client interface implementation.
+ *  @see icmp_client.h
+ */
+
+#include <errno.h>
+//#include <stdio.h>
+
+#include <sys/types.h>
+
+#include "../../include/icmp_codes.h"
+#include "../../include/icmp_client.h"
+
+#include "../../structures/packet/packet.h"
+#include "../../structures/packet/packet_client.h"
+
+#include "icmp_header.h"
+
+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_ref	header;
+
+	header = ( icmp_header_ref ) 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;
+	// remove debug dump
+//	printf( "ICMP error %d (%d) in packet %d\n", header->type, header->code, packet_get_id( packet ));
+	return sizeof( icmp_header_t );
+}
+
+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: uspace/srv/net/tl/icmp/icmp_common.c
===================================================================
--- uspace/srv/net/tl/icmp/icmp_common.c	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/tl/icmp/icmp_common.c	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,58 @@
+/*
+ * 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 icmp
+ *  @{
+ */
+
+/** @file
+ *  ICMP common interface implementation.
+ *  @see icmp_common.h
+ */
+
+#include <async.h>
+#include <ipc/services.h>
+
+#include "../../modules.h"
+
+#include "../../include/icmp_common.h"
+
+#include "icmp_messages.h"
+
+int icmp_connect_module( services_t service, suseconds_t timeout ){
+	int	phone;
+
+	phone = connect_to_service_timeout( SERVICE_ICMP, timeout );
+	if( phone >= 0 ){
+		async_req_0_0( phone, NET_ICMP_INIT );
+	}
+	return phone;
+}
+
+/** @}
+ */
Index: uspace/srv/net/tl/icmp/icmp_header.h
===================================================================
--- uspace/srv/net/tl/icmp/icmp_header.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/tl/icmp/icmp_header.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,133 @@
+/*
+ * 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 icmp
+ *  @{
+ */
+
+/** @file
+ *  ICMP header definition.
+ *  Based on the RFC~792.
+ */
+
+#ifndef __NET_ICMP_HEADER_H__
+#define __NET_ICMP_HEADER_H__
+
+#include <sys/types.h>
+
+#include "../../include/in.h"
+#include "../../include/icmp_codes.h"
+
+/** ICMP header size in bytes.
+ */
+#define ICMP_HEADER_SIZE			sizeof( icmp_header_t )
+
+/** Type definition of the echo specific data.
+ *  @see icmp_echo
+ */
+typedef struct icmp_echo	icmp_echo_t;
+
+/** Type definition of the echo specific data pointer.
+ *  @see icmp_echo
+ */
+typedef icmp_echo_t *		icmp_echo_ref;
+
+/** Echo specific data.
+ */
+struct icmp_echo{
+	/** Message idintifier.
+	 */
+	icmp_param_t	identifier;
+	/** Message sequence number.
+	 */
+	icmp_param_t	sequence_number;
+} __attribute__ ((packed));
+
+/** Type definition of the internet control message header.
+ *  @see icmp_header
+ */
+typedef struct icmp_header	icmp_header_t;
+
+/** Type definition of the internet control message header pointer.
+ *  @see icmp_header
+ */
+typedef icmp_header_t *		icmp_header_ref;
+
+/** Internet control message header.
+ */
+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));
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/tl/icmp/icmp_messages.h
===================================================================
--- uspace/srv/net/tl/icmp/icmp_messages.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/tl/icmp/icmp_messages.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,126 @@
+/*
+ * 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 icmp
+ *  @{
+ */
+
+/** @file
+ *  ICMP module messages.
+ *  @see icmp_interface.h
+ */
+
+#ifndef __NET_ICMP_MESSAGES__
+#define __NET_ICMP_MESSAGES__
+
+#include <ipc/ipc.h>
+
+#include <sys/types.h>
+
+#include "../../include/icmp_codes.h"
+
+#include "../../messages.h"
+
+/** ICMP module messages.
+ */
+typedef enum{
+	/** Sends echo request.
+	 *  @see icmp_echo()
+	 */
+	NET_ICMP_ECHO = NET_ICMP_FIRST,
+	/** Sends destination unreachable error message.
+	 *  @see icmp_destination_unreachable_msg()
+	 */
+	NET_ICMP_DEST_UNREACH,
+	/** Sends source quench error message.
+	 *  @see icmp_source_quench_msg()
+	 */
+	NET_ICMP_SOURCE_QUENCH,
+	/** Sends time exceeded error message.
+	 *  @see icmp_time_exceeded_msg()
+	 */
+	NET_ICMP_TIME_EXCEEDED,
+	/** Sends parameter problem error message.
+	 *  @see icmp_parameter_problem_msg()
+	 */
+	NET_ICMP_PARAMETERPROB,
+	/** Initializes new connection.
+	 */
+	NET_ICMP_INIT
+} icmp_messages;
+
+/** @name ICMP specific message parameters definitions
+ */
+/*@{*/
+
+/** Returns the ICMP code message parameter.
+ *  @param[in] call The message call structure.
+ */
+#define ICMP_GET_CODE( call )		( icmp_code_t ) IPC_GET_ARG1( * call )
+
+/** Returns the ICMP link MTU message parameter.
+ *  @param[in] call The message call structure.
+ */
+#define ICMP_GET_MTU( call )		( icmp_param_t ) IPC_GET_ARG3( * call )
+
+/** Returns the pointer message parameter.
+ *  @param[in] call The message call structure.
+ */
+#define ICMP_GET_POINTER( call )		( icmp_param_t ) IPC_GET_ARG3( * call )
+
+/** Returns the size message parameter.
+ *  @param[in] call The message call structure.
+ */
+#define ICMP_GET_SIZE( call )	( size_t ) IPC_GET_ARG1( call )
+
+/** Returns the timeout message parameter.
+ *  @param[in] call The message call structure.
+ */
+#define ICMP_GET_TIMEOUT( call )	(( suseconds_t ) IPC_GET_ARG2( call ))
+
+/** Returns the time to live message parameter.
+ *  @param[in] call The message call structure.
+ */
+#define ICMP_GET_TTL( call )	( ip_ttl_t ) IPC_GET_ARG3( call )
+
+/** Returns the type of service message parameter.
+ *  @param[in] call The message call structure.
+ */
+#define ICMP_GET_TOS( call )	( ip_tos_t ) IPC_GET_ARG4( call )
+
+/** Returns the dont fragment message parameter.
+ *  @param[in] call The message call structure.
+ */
+#define ICMP_GET_DONT_FRAGMENT( call )		( int ) IPC_GET_ARG5( call )
+
+/*@}*/
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/tl/icmp/icmp_module.c
===================================================================
--- uspace/srv/net/tl/icmp/icmp_module.c	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/tl/icmp/icmp_module.c	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,120 @@
+/*
+ * 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 standalone module implementation.
+ *  Contains skeleton module functions mapping.
+ *  The functions are used by the module skeleton as module specific entry points.
+ *  @see module.c
+ */
+
+#include <async.h>
+#include <stdio.h>
+
+#include <ipc/ipc.h>
+#include <ipc/services.h>
+
+#include "../../err.h"
+#include "../../modules.h"
+
+#include "../../structures/packet/packet.h"
+
+#include "../../include/net_interface.h"
+
+#include "icmp.h"
+#include "icmp_module.h"
+
+/** ICMP module name.
+ */
+#define NAME	"ICMP protocol"
+
+/** Prints the module name.
+ *  @see NAME
+ */
+void	module_print_name( void );
+
+/** Starts the ICMP module.
+ *  Initializes the client connection serving function, initializes the module, registers the module service and starts the async manager, processing IPC messages in an infinite loop.
+ *  @param[in] client_connection The client connection processing function. The module skeleton propagates its own one.
+ *  @returns EOK on successful module termination.
+ *  @returns Other error codes as defined for the arp_initialize() function.
+ *  @returns Other error codes as defined for the REGISTER_ME() macro function.
+ */
+int	module_start( async_client_conn_t client_connection );
+
+/** Processes the ICMP 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.
+ *  @returns EOK on success.
+ *  @returns Other error codes as defined for the icmp_message() function.
+ */
+int	module_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count );
+
+/** ICMP module global data.
+ */
+extern icmp_globals_t	icmp_globals;
+
+void module_print_name( void ){
+	printf( "%s", NAME );
+}
+
+int module_start( async_client_conn_t client_connection ){
+	ERROR_DECLARE;
+
+	ipcarg_t	phonehash;
+
+	async_set_client_connection( client_connection );
+	icmp_globals.net_phone = net_connect_module( SERVICE_NETWORKING );
+	if( icmp_globals.net_phone < 0 ){
+		return icmp_globals.net_phone;
+	}
+	ERROR_PROPAGATE( pm_init());
+	if( ERROR_OCCURRED( icmp_initialize( client_connection ))
+	|| ERROR_OCCURRED( REGISTER_ME( SERVICE_ICMP, & phonehash ))){
+		pm_destroy();
+		return ERROR_CODE;
+	}
+
+	async_manager();
+
+	pm_destroy();
+	return EOK;
+}
+
+int	module_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){
+	return icmp_message( callid, call, answer, answer_count );
+}
+
+/** @}
+ */
Index: uspace/srv/net/tl/icmp/icmp_module.h
===================================================================
--- uspace/srv/net/tl/icmp/icmp_module.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/tl/icmp/icmp_module.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,66 @@
+/*
+ * 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 functions.
+ *  The functions are used as ICMP module entry points.
+ */
+
+#ifndef __NET_ICMP_MODULE_H__
+#define __NET_ICMP_MODULE_H__
+
+#include <async.h>
+#include <ipc/ipc.h>
+
+/** Initializes the ICMP module.
+ *  @param[in] client_connection The client connection processing function. The module skeleton propagates its own one.
+ *  @returns EOK on success.
+ *  @returns ENOMEM if there is not enough memory left.
+ */
+int	icmp_initialize( async_client_conn_t client_connection );
+
+/** Processes the ICMP 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.
+ *  @returns EOK on success.
+ *  @returns ENOTSUP if the message is not known.
+ *  @see icmp_interface.h
+ *  @see IS_NET_ICMP_MESSAGE()
+ */
+int	icmp_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count );
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/tl/icmp/icmp_remote.c
===================================================================
--- uspace/srv/net/tl/icmp/icmp_remote.c	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/tl/icmp/icmp_remote.c	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,76 @@
+/*
+ * 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 icmp
+ *  @{
+ */
+
+/** @file
+ *  ICMP interface implementation for standalone remote modules.
+ *  @see icmp_interface.h
+ */
+
+#include <async.h>
+#include <errno.h>
+
+#include <ipc/ipc.h>
+#include <ipc/services.h>
+
+#include <sys/types.h>
+
+#include "../../messages.h"
+#include "../../modules.h"
+
+#include "../../include/icmp_interface.h"
+
+#include "../../structures/packet/packet_client.h"
+
+#include "icmp_messages.h"
+
+int icmp_destination_unreachable_msg( int icmp_phone, icmp_code_t code, icmp_param_t mtu, packet_t packet ){
+	async_msg_3( icmp_phone, NET_ICMP_DEST_UNREACH, ( ipcarg_t ) code, ( ipcarg_t ) packet_get_id( packet ), ( ipcarg_t ) mtu );
+	return EOK;
+}
+
+int icmp_source_quench_msg( int icmp_phone, packet_t packet ){
+	async_msg_2( icmp_phone, NET_ICMP_SOURCE_QUENCH, 0, ( ipcarg_t ) packet_get_id( packet ));
+	return EOK;
+}
+
+int icmp_time_exceeded_msg( int icmp_phone, icmp_code_t code, packet_t packet ){
+	async_msg_2( icmp_phone, NET_ICMP_TIME_EXCEEDED, ( ipcarg_t ) code, ( ipcarg_t ) packet_get_id( packet ));
+	return EOK;
+}
+
+int icmp_parameter_problem_msg( int icmp_phone, icmp_code_t code, icmp_param_t pointer, packet_t packet ){
+	async_msg_3( icmp_phone, NET_ICMP_PARAMETERPROB, ( ipcarg_t ) code, ( ipcarg_t ) packet_get_id( packet ), ( ipcarg_t ) pointer );
+	return EOK;
+}
+
+/** @}
+ */
Index: uspace/srv/net/tl/tcp/Makefile
===================================================================
--- uspace/srv/net/tl/tcp/Makefile	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/tl/tcp/Makefile	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,59 @@
+#
+# 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.
+#
+
+NAME = tcp
+
+NET_BASE = ../../
+STRUCTURES = $(NET_BASE)structures/
+
+## Sources
+#
+
+OUTPUT = $(NAME)
+SOURCES = \
+	$(NAME).c \
+	$(NAME)_module.c \
+	$(NET_BASE)checksum.c \
+	$(NET_BASE)module.c \
+	$(NET_BASE)modules.c \
+	$(NET_BASE)il/ip/ip_client.c \
+	$(NET_BASE)il/ip/ip_remote.c \
+	$(NET_BASE)net/net_remote.c \
+	$(NET_BASE)socket/socket_core.c \
+	$(NET_BASE)tl/icmp/icmp_client.c \
+	$(NET_BASE)tl/icmp/icmp_common.c \
+	$(NET_BASE)tl/icmp/icmp_remote.c \
+	$(NET_BASE)tl/tl_common.c \
+	$(STRUCTURES)char_map.c \
+	$(STRUCTURES)dynamic_fifo.c \
+	$(STRUCTURES)measured_strings.c \
+	$(STRUCTURES)packet/packet.c \
+	$(STRUCTURES)packet/packet_client.c \
+	$(STRUCTURES)packet/packet_remote.c
+
+include $(NET_BASE)Makefile.module
Index: uspace/srv/net/tl/tcp/tcp.c
===================================================================
--- uspace/srv/net/tl/tcp/tcp.c	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/tl/tcp/tcp.c	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,1961 @@
+/*
+ * 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 tcp
+ *  @{
+ */
+
+/** @file
+ *  TCP module implementation.
+ *  @see tcp.h
+ */
+
+#include <assert.h>
+#include <async.h>
+#include <fibril_synch.h>
+#include <malloc.h>
+//TODO remove stdio
+#include <stdio.h>
+
+#include <ipc/ipc.h>
+#include <ipc/services.h>
+
+#include "../../err.h"
+#include "../../messages.h"
+#include "../../modules.h"
+
+#include "../../structures/dynamic_fifo.h"
+#include "../../structures/packet/packet_client.h"
+
+#include "../../include/checksum.h"
+#include "../../include/in.h"
+#include "../../include/in6.h"
+#include "../../include/inet.h"
+#include "../../include/ip_client.h"
+#include "../../include/ip_interface.h"
+#include "../../include/ip_protocols.h"
+#include "../../include/icmp_client.h"
+#include "../../include/icmp_interface.h"
+#include "../../include/net_interface.h"
+#include "../../include/socket_codes.h"
+#include "../../include/socket_errno.h"
+#include "../../include/tcp_codes.h"
+
+#include "../../socket/socket_core.h"
+#include "../../socket/socket_messages.h"
+
+#include "../tl_common.h"
+#include "../tl_messages.h"
+
+#include "tcp.h"
+#include "tcp_header.h"
+#include "tcp_module.h"
+
+/** The TCP window default value.
+ */
+#define NET_DEFAULT_TCP_WINDOW	10240
+
+/** Initial timeout for new connections.
+ */
+#define NET_DEFAULT_TCP_INITIAL_TIMEOUT	3000000L
+
+/** Default timeout for closing.
+ */
+#define NET_DEFAULT_TCP_TIME_WAIT_TIMEOUT	2000L
+
+/** The initial outgoing sequence number.
+ */
+#define TCP_INITIAL_SEQUENCE_NUMBER		2999
+
+/** Maximum TCP fragment size.
+ */
+#define MAX_TCP_FRAGMENT_SIZE	65535
+
+/** Free ports pool start.
+ */
+#define TCP_FREE_PORTS_START	1025
+
+/** Free ports pool end.
+ */
+#define TCP_FREE_PORTS_END		65535
+
+/** Timeout for connection initialization, SYN sent.
+ */
+#define TCP_SYN_SENT_TIMEOUT	1000000L
+
+/** The maximum number of timeouts in a row before singaling connection lost.
+ */
+#define TCP_MAX_TIMEOUTS		8
+
+/** The number of acknowledgements before retransmit.
+ */
+#define TCP_FAST_RETRANSMIT_COUNT	3
+
+/** Returns a value indicating whether the value is in the interval respecting the possible overflow.
+ *  The high end and/or the value may overflow, be lower than the low value.
+ *  @param[in] lower The last value before the interval.
+ *  @param[in] value The value to be checked.
+ *  @param[in] higher_equal The last value in the interval.
+ */
+#define IS_IN_INTERVAL_OVERFLOW( lower, value, higher_equal )	(((( lower ) < ( value )) && ((( value ) <= ( higher_equal )) || (( higher_equal ) < ( lower )))) || ((( value ) <= ( higher_equal )) && (( higher_equal ) < ( lower ))))
+
+/** Type definition of the TCP timeout.
+ *  @see tcp_timeout
+ */
+typedef struct tcp_timeout	tcp_timeout_t;
+
+/** Type definition of the TCP timeout pointer.
+ *  @see tcp_timeout
+ */
+typedef tcp_timeout_t *	tcp_timeout_ref;
+
+/** TCP reply timeout data.
+ *  Used as a timeouting fibril argument.
+ *  @see tcp_timeout()
+ */
+struct tcp_timeout{
+	/** TCP global data are going to be read only.
+	 */
+	int					globals_read_only;
+	/** Socket port.
+	 */
+	int					port;
+	/** Local sockets.
+	 */
+	socket_cores_ref	local_sockets;
+	/** Socket identifier.
+	 */
+	int					socket_id;
+	/** Socket state.
+	 */
+	tcp_socket_state_t	state;
+	/** Sent packet sequence number.
+	 */
+	int					sequence_number;
+	/** Timeout in microseconds.
+	 */
+	suseconds_t			timeout;
+	/** Port map key.
+	 */
+	char *				key;
+	/** Port map key length.
+	 */
+	size_t				key_length;
+};
+
+/** 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.
+ */
+int	tcp_release_and_return( packet_t packet, int result );
+
+void	tcp_prepare_operation_header( socket_core_ref socket, tcp_socket_data_ref socket_data, tcp_header_ref header, int synchronize, int finalize );
+int	tcp_prepare_timeout( int ( * timeout_function )( void * tcp_timeout_t ), socket_core_ref socket, tcp_socket_data_ref socket_data, size_t sequence_number, tcp_socket_state_t state, suseconds_t timeout, int globals_read_only );
+void	tcp_free_socket_data( socket_core_ref socket );
+int	tcp_timeout( void * data );
+int	tcp_release_after_timeout( void * data );
+int	tcp_process_packet( device_id_t device_id, packet_t packet, services_t error );
+int	tcp_connect_core( socket_core_ref socket, socket_cores_ref local_sockets, struct sockaddr * addr, socklen_t addrlen );
+int	tcp_queue_prepare_packet( socket_core_ref socket, tcp_socket_data_ref socket_data, packet_t packet, size_t data_length );
+int	tcp_queue_packet( socket_core_ref socket, tcp_socket_data_ref socket_data, packet_t packet, size_t data_length );
+packet_t	tcp_get_packets_to_send( socket_core_ref socket, tcp_socket_data_ref socket_data );
+void	tcp_send_packets( device_id_t device_id, packet_t packet );
+void	tcp_process_acknowledgement( socket_core_ref socket, tcp_socket_data_ref socket_data, tcp_header_ref header );
+packet_t	tcp_send_prepare_packet( socket_core_ref socket, tcp_socket_data_ref socket_data, packet_t packet, size_t data_length, size_t sequence_number );
+packet_t	tcp_prepare_copy( socket_core_ref socket, tcp_socket_data_ref socket_data, packet_t packet, size_t data_length, size_t sequence_number );
+void	tcp_retransmit_packet( socket_core_ref socket, tcp_socket_data_ref socket_data, size_t sequence_number );
+int	tcp_create_notification_packet( packet_t * packet, socket_core_ref socket, tcp_socket_data_ref socket_data, int synchronize, int finalize );
+void	tcp_refresh_socket_data( tcp_socket_data_ref socket_data );
+void	tcp_initialize_socket_data( tcp_socket_data_ref socket_data );
+int	tcp_process_listen( socket_core_ref listening_socket, tcp_socket_data_ref listening_socket_data, tcp_header_ref header, packet_t packet, struct sockaddr * src, struct sockaddr * dest, size_t addrlen );
+int	tcp_process_syn_sent( socket_core_ref socket, tcp_socket_data_ref socket_data, tcp_header_ref header, packet_t packet );
+int	tcp_process_syn_received( socket_core_ref socket, tcp_socket_data_ref socket_data, tcp_header_ref header, packet_t packet );
+int	tcp_process_established( socket_core_ref socket, tcp_socket_data_ref socket_data, tcp_header_ref header, packet_t packet, int fragments, size_t total_length );
+int	tcp_queue_received_packet( socket_core_ref socket, tcp_socket_data_ref socket_data, packet_t packet, int fragments, size_t total_length );
+
+int	tcp_received_msg( device_id_t device_id, packet_t packet, services_t receiver, services_t error );
+int	tcp_process_client_messages( ipc_callid_t callid, ipc_call_t call );
+int	tcp_listen_message( socket_cores_ref local_sockets, int socket_id, int backlog );
+int	tcp_connect_message( socket_cores_ref local_sockets, int socket_id, struct sockaddr * addr, socklen_t addrlen );
+int	tcp_recvfrom_message( socket_cores_ref local_sockets, int socket_id, int flags, size_t * addrlen );
+int	tcp_send_message( socket_cores_ref local_sockets, int socket_id, int fragments, size_t * data_fragment_size, int flags );
+int	tcp_accept_message( socket_cores_ref local_sockets, int socket_id, int new_socket_id, size_t * data_fragment_size, size_t * addrlen );
+int tcp_close_message( socket_cores_ref local_sockets, int socket_id );
+
+/** TCP global data.
+ */
+tcp_globals_t	tcp_globals;
+
+int tcp_initialize( async_client_conn_t client_connection ){
+	ERROR_DECLARE;
+
+	assert( client_connection );
+	fibril_rwlock_initialize( & tcp_globals.lock );
+	fibril_rwlock_write_lock( & tcp_globals.lock );
+	tcp_globals.icmp_phone = icmp_connect_module( SERVICE_ICMP, ICMP_CONNECT_TIMEOUT );
+	tcp_globals.ip_phone = ip_bind_service( SERVICE_IP, IPPROTO_TCP, SERVICE_TCP, client_connection, tcp_received_msg );
+	if( tcp_globals.ip_phone < 0 ){
+		return tcp_globals.ip_phone;
+	}
+	ERROR_PROPAGATE( socket_ports_initialize( & tcp_globals.sockets ));
+	if( ERROR_OCCURRED( packet_dimensions_initialize( & tcp_globals.dimensions ))){
+		socket_ports_destroy( & tcp_globals.sockets );
+		return ERROR_CODE;
+	}
+	tcp_globals.last_used_port = TCP_FREE_PORTS_START - 1;
+	fibril_rwlock_write_unlock( & tcp_globals.lock );
+	return EOK;
+}
+
+int	tcp_received_msg( device_id_t device_id, packet_t packet, services_t receiver, services_t error ){
+	ERROR_DECLARE;
+
+	if( receiver != SERVICE_TCP ) return EREFUSED;
+	fibril_rwlock_write_lock( & tcp_globals.lock );
+	if( ERROR_OCCURRED( tcp_process_packet( device_id, packet, error ))){
+		fibril_rwlock_write_unlock( & tcp_globals.lock );
+	}
+	printf( "receive %d \n", ERROR_CODE );
+
+	return ERROR_CODE;
+}
+
+int tcp_process_packet( device_id_t device_id, packet_t packet, services_t error ){
+	ERROR_DECLARE;
+
+	size_t				length;
+	size_t				offset;
+	int					result;
+	tcp_header_ref		header;
+	socket_core_ref 	socket;
+	tcp_socket_data_ref	socket_data;
+	packet_t			next_packet;
+	size_t				total_length;
+	uint32_t			checksum;
+	int					fragments;
+	icmp_type_t			type;
+	icmp_code_t			code;
+	struct sockaddr *	src;
+	struct sockaddr *	dest;
+	size_t				addrlen;
+
+	printf( "p1 \n" );
+	if( error ){
+		switch( error ){
+			case SERVICE_ICMP:
+				// process error
+				result = icmp_client_process_packet( packet, & type, & code, NULL, NULL );
+				if( result < 0 ){
+					return tcp_release_and_return( packet, result );
+				}
+				length = ( size_t ) result;
+				if( ERROR_OCCURRED( packet_trim( packet, length, 0 ))){
+					return tcp_release_and_return( packet, ERROR_CODE );
+				}
+				break;
+			default:
+				return tcp_release_and_return( packet, ENOTSUP );
+		}
+	}
+
+	// TODO process received ipopts?
+	result = ip_client_process_packet( packet, NULL, NULL, NULL, NULL, NULL );
+//	printf("ip len %d\n", result );
+	if( result < 0 ){
+		return tcp_release_and_return( packet, result );
+	}
+	offset = ( size_t ) result;
+
+	length = packet_get_data_length( packet );
+//	printf("packet len %d\n", length );
+	if( length <= 0 ){
+		return tcp_release_and_return( packet, EINVAL );
+	}
+	if( length < TCP_HEADER_SIZE + offset ){
+		return tcp_release_and_return( packet, NO_DATA );
+	}
+
+	// trim all but TCP header
+	if( ERROR_OCCURRED( packet_trim( packet, offset, 0 ))){
+		return tcp_release_and_return( packet, ERROR_CODE );
+	}
+
+	// get tcp header
+	header = ( tcp_header_ref ) packet_get_data( packet );
+	if( ! header ){
+		return tcp_release_and_return( packet, NO_DATA );
+	}
+//	printf( "header len %d, port %d \n", TCP_HEADER_LENGTH( header ), ntohs( header->destination_port ));
+
+	result = packet_get_addr( packet, ( uint8_t ** ) & src, ( uint8_t ** ) & dest );
+	if( result <= 0 ){
+		return tcp_release_and_return( packet, result );
+	}
+	addrlen = ( size_t ) result;
+
+	if( ERROR_OCCURRED( tl_set_address_port( src, addrlen, ntohs( header->source_port )))){
+		return tcp_release_and_return( packet, ERROR_CODE );
+	}
+
+	// find the destination socket
+	socket = socket_port_find( & tcp_globals.sockets, ntohs( header->destination_port ), ( const char * ) src, addrlen );
+	if( ! socket ){
+//		printf("listening?\n");
+		// find the listening destination socket
+		socket = socket_port_find( & tcp_globals.sockets, ntohs( header->destination_port ), SOCKET_MAP_KEY_LISTENING, 0 );
+		if( ! socket ){
+			if( tl_prepare_icmp_packet( tcp_globals.net_phone, tcp_globals.icmp_phone, packet, error ) == EOK ){
+				icmp_destination_unreachable_msg( tcp_globals.icmp_phone, ICMP_PORT_UNREACH, 0, packet );
+			}
+			return EADDRNOTAVAIL;
+		}
+	}
+	printf("socket id %d\n", socket->socket_id );
+	socket_data = ( tcp_socket_data_ref ) socket->specific_data;
+	assert( socket_data );
+
+	// some data received, clear the timeout counter
+	socket_data->timeout_count = 0;
+
+	// count the received packet fragments
+	next_packet = packet;
+	fragments = 0;
+	checksum = 0;
+	total_length = 0;
+	do{
+		++ fragments;
+		length = packet_get_data_length( next_packet );
+		if( length <= 0 ){
+			return tcp_release_and_return( packet, NO_DATA );
+		}
+		total_length += length;
+		// add partial checksum if set
+		if( ! error ){
+			checksum = compute_checksum( checksum, packet_get_data( packet ), packet_get_data_length( packet ));
+		}
+	}while(( next_packet = pq_next( next_packet )));
+//	printf( "fragments %d of %d bytes\n", fragments, total_length );
+
+//	printf("lock?\n");
+	fibril_rwlock_write_lock( socket_data->local_lock );
+//	printf("locked\n");
+	if( ! error ){
+		if( socket_data->state == TCP_SOCKET_LISTEN ){
+			if( socket_data->pseudo_header ){
+				free( socket_data->pseudo_header );
+				socket_data->pseudo_header = NULL;
+				socket_data->headerlen = 0;
+			}
+			if( ERROR_OCCURRED( ip_client_get_pseudo_header( IPPROTO_TCP, src, addrlen, dest, addrlen, total_length, & socket_data->pseudo_header, & socket_data->headerlen ))){
+				fibril_rwlock_write_unlock( socket_data->local_lock );
+				return tcp_release_and_return( packet, ERROR_CODE );
+			}
+		}else if( ERROR_OCCURRED( ip_client_set_pseudo_header_data_length( socket_data->pseudo_header, socket_data->headerlen, total_length ))){
+			fibril_rwlock_write_unlock( socket_data->local_lock );
+			return tcp_release_and_return( packet, ERROR_CODE );
+		}
+		checksum = compute_checksum( checksum, socket_data->pseudo_header, socket_data->headerlen );
+		if( flip_checksum( compact_checksum( checksum )) != IP_CHECKSUM_ZERO ){
+			printf( "checksum err %x -> %x\n", header->checksum, flip_checksum( compact_checksum( checksum )));
+			fibril_rwlock_write_unlock( socket_data->local_lock );
+			if( ! ERROR_OCCURRED( tl_prepare_icmp_packet( tcp_globals.net_phone, tcp_globals.icmp_phone, packet, error ))){
+				// checksum error ICMP
+				icmp_parameter_problem_msg( tcp_globals.icmp_phone, ICMP_PARAM_POINTER, (( size_t ) (( void * ) & header->checksum )) - (( size_t ) (( void * ) header )), packet );
+			}
+			return EINVAL;
+		}
+	}
+
+	fibril_rwlock_read_unlock( & tcp_globals.lock );
+
+	// TODO error reporting/handling
+//	printf( "st %d\n", socket_data->state );
+	switch( socket_data->state ){
+		case TCP_SOCKET_LISTEN:
+			ERROR_CODE = tcp_process_listen( socket, socket_data, header, packet, src, dest, addrlen );
+			break;
+		case TCP_SOCKET_SYN_RECEIVED:
+			ERROR_CODE = tcp_process_syn_received( socket, socket_data, header, packet );
+			break;
+		case TCP_SOCKET_SYN_SENT:
+			ERROR_CODE = tcp_process_syn_sent( socket, socket_data, header, packet );
+			break;
+		case TCP_SOCKET_FIN_WAIT_1:
+			// ack changing the state to FIN_WAIT_2 gets processed later
+		case TCP_SOCKET_FIN_WAIT_2:
+			// fin changing state to LAST_ACK gets processed later
+		case TCP_SOCKET_LAST_ACK:
+			// ack releasing the socket get processed later
+		case TCP_SOCKET_CLOSING:
+			// ack releasing the socket gets processed later
+		case TCP_SOCKET_ESTABLISHED:
+			ERROR_CODE = tcp_process_established( socket, socket_data, header, packet, fragments, total_length );
+			break;
+		default:
+			pq_release( tcp_globals.net_phone, packet_get_id( packet ));
+	}
+
+	if( ERROR_CODE != EOK ){
+		printf( "process %d\n", ERROR_CODE );
+		fibril_rwlock_write_unlock( socket_data->local_lock );
+	}
+	return EOK;
+}
+
+int tcp_process_established( socket_core_ref socket, tcp_socket_data_ref socket_data, tcp_header_ref header, packet_t packet, int fragments, size_t total_length ){
+	ERROR_DECLARE;
+
+	packet_t	next_packet;
+	packet_t	tmp_packet;
+	uint32_t	old_incoming;
+	size_t		order;
+	uint32_t	sequence_number;
+	size_t		length;
+	size_t		offset;
+	uint32_t	new_sequence_number;
+
+	assert( socket );
+	assert( socket_data );
+	assert( socket->specific_data == socket_data );
+	assert( header );
+	assert( packet );
+
+	new_sequence_number = ntohl( header->sequence_number );
+	old_incoming = socket_data->next_incoming;
+
+	if( header->finalize ){
+		socket_data->fin_incoming = new_sequence_number;
+	}
+
+//	printf( "pe %d < %d <= %d\n", new_sequence_number, socket_data->next_incoming, new_sequence_number + total_length );
+	// trim begining if containing expected data
+	if( IS_IN_INTERVAL_OVERFLOW( new_sequence_number, socket_data->next_incoming, new_sequence_number + total_length )){
+		// get the acknowledged offset
+		if( socket_data->next_incoming < new_sequence_number ){
+			offset = new_sequence_number - socket_data->next_incoming;
+		}else{
+			offset = socket_data->next_incoming - new_sequence_number;
+		}
+//		printf( "offset %d\n", offset );
+		new_sequence_number += offset;
+		total_length -= offset;
+		length = packet_get_data_length( packet );
+		// trim the acknowledged data
+		while( length <= offset ){
+			// release the acknowledged packets
+			next_packet = pq_next( packet );
+			pq_release( tcp_globals.net_phone, packet_get_id( packet ));
+			packet = next_packet;
+			offset -= length;
+			length = packet_get_data_length( packet );
+		}
+		if(( offset > 0 )
+		&& ( ERROR_OCCURRED( packet_trim( packet, offset, 0 )))){
+			return tcp_release_and_return( packet, ERROR_CODE );
+		}
+		assert( new_sequence_number == socket_data->next_incoming );
+	}
+
+	// release if overflowing the window
+//	if( IS_IN_INTERVAL_OVERFLOW( socket_data->next_incoming + socket_data->window, new_sequence_number, new_sequence_number + total_length )){
+//		return tcp_release_and_return( packet, EOVERFLOW );
+//	}
+
+/*
+	// trim end if overflowing the window
+	if( IS_IN_INTERVAL_OVERFLOW( new_sequence_number, socket_data->next_incoming + socket_data->window, new_sequence_number + total_length )){
+		// get the allowed data length
+		if( socket_data->next_incoming + socket_data->window < new_sequence_number ){
+			offset = new_sequence_number - socket_data->next_incoming + socket_data->window;
+		}else{
+			offset = socket_data->next_incoming + socket_data->window - new_sequence_number;
+		}
+		next_packet = packet;
+		// trim the overflowing data
+		while( next_packet && ( offset > 0 )){
+			length = packet_get_data_length( packet );
+			if( length <= offset ){
+				next_packet = pq_next( next_packet );
+			}else if( ERROR_OCCURRED( packet_trim( next_packet, 0, length - offset ))){
+				return tcp_release_and_return( packet, ERROR_CODE );
+			}
+			offset -= length;
+			total_length -= length - offset;
+		}
+		// release the overflowing packets
+		next_packet = pq_next( next_packet );
+		if( next_packet ){
+			tmp_packet = next_packet;
+			next_packet = pq_next( next_packet );
+			pq_insert_after( tmp_packet, next_packet );
+			pq_release( tcp_globals.net_phone, packet_get_id( tmp_packet ));
+		}
+		assert( new_sequence_number + total_length == socket_data->next_incoming + socket_data->window );
+	}
+*/
+	// the expected one arrived?
+	if( new_sequence_number == socket_data->next_incoming ){
+		printf("expected\n");
+		// process acknowledgement
+		tcp_process_acknowledgement( socket, socket_data, header );
+
+		// remove the header
+		total_length -= TCP_HEADER_LENGTH( header );
+		if( ERROR_OCCURRED( packet_trim( packet, TCP_HEADER_LENGTH( header ), 0 ))){
+			return tcp_release_and_return( packet, ERROR_CODE );
+		}
+
+		if( total_length ){
+			ERROR_PROPAGATE( tcp_queue_received_packet( socket, socket_data, packet, fragments, total_length ));
+		}else{
+			total_length = 1;
+		}
+		socket_data->next_incoming = old_incoming + total_length;
+		packet = socket_data->incoming;
+		while( packet ){
+			if( ERROR_OCCURRED( pq_get_order( socket_data->incoming, & order, NULL ))){
+				// remove the corrupted packet
+				next_packet = pq_detach( packet );
+				if( packet == socket_data->incoming ){
+					socket_data->incoming = next_packet;
+				}
+				pq_release( tcp_globals.net_phone, packet_get_id( packet ));
+				packet = next_packet;
+				continue;
+			}
+			sequence_number = ( uint32_t ) order;
+			if( IS_IN_INTERVAL_OVERFLOW( sequence_number, old_incoming, socket_data->next_incoming )){
+				// move to the next
+				packet = pq_next( packet );
+			// coninual data?
+			}else if( IS_IN_INTERVAL_OVERFLOW( old_incoming, sequence_number, socket_data->next_incoming )){
+				// detach the packet
+				next_packet = pq_detach( packet );
+				if( packet == socket_data->incoming ){
+					socket_data->incoming = next_packet;
+				}
+				// get data length
+				length = packet_get_data_length( packet );
+				new_sequence_number = sequence_number + length;
+				if( length <= 0 ){
+					// remove the empty packet
+					pq_release( tcp_globals.net_phone, packet_get_id( packet ));
+					packet = next_packet;
+					continue;
+				}
+				// exactly following
+				if( sequence_number == socket_data->next_incoming ){
+					// queue received data
+					ERROR_PROPAGATE( tcp_queue_received_packet( socket, socket_data, packet, 1, packet_get_data_length( packet )));
+					socket_data->next_incoming = new_sequence_number;
+					packet = next_packet;
+					continue;
+				// at least partly following data?
+				}else if( IS_IN_INTERVAL_OVERFLOW( sequence_number, socket_data->next_incoming, new_sequence_number )){
+					if( socket_data->next_incoming < new_sequence_number ){
+						length = new_sequence_number - socket_data->next_incoming;
+					}else{
+						length = socket_data->next_incoming - new_sequence_number;
+					}
+					if( ! ERROR_OCCURRED( packet_trim( packet, length, 0 ))){
+						// queue received data
+						ERROR_PROPAGATE( tcp_queue_received_packet( socket, socket_data, packet, 1, packet_get_data_length( packet )));
+						socket_data->next_incoming = new_sequence_number;
+						packet = next_packet;
+						continue;
+					}
+				}
+				// remove the duplicit or corrupted packet
+				pq_release( tcp_globals.net_phone, packet_get_id( packet ));
+				packet = next_packet;
+				continue;
+			}else{
+				break;
+			}
+		}
+	}else if( IS_IN_INTERVAL( socket_data->next_incoming, new_sequence_number, socket_data->next_incoming + socket_data->window )){
+		printf("in window\n");
+		// process acknowledgement
+		tcp_process_acknowledgement( socket, socket_data, header );
+
+		// remove the header
+		total_length -= TCP_HEADER_LENGTH( header );
+		if( ERROR_OCCURRED( packet_trim( packet, TCP_HEADER_LENGTH( header ), 0 ))){
+			return tcp_release_and_return( packet, ERROR_CODE );
+		}
+
+		next_packet = pq_detach( packet );
+		length = packet_get_data_length( packet );
+		tmp_packet = pq_add( socket_data->incoming, packet, new_sequence_number, length );
+		if( ! tmp_packet ){
+			// remove the corrupted packets
+			pq_release( tcp_globals.net_phone, packet_get_id( packet ));
+			pq_release( tcp_globals.net_phone, packet_get_id( next_packet ));
+		}else{
+			socket_data->incoming = tmp_packet;
+			while( next_packet ){
+				new_sequence_number += length;
+				tmp_packet = pq_detach( next_packet );
+				length = packet_get_data_length( next_packet );
+				if( ERROR_OCCURRED( pq_set_order( next_packet, new_sequence_number, length ))
+				|| ERROR_OCCURRED( pq_insert_after( packet, next_packet ))){
+					pq_release( tcp_globals.net_phone, packet_get_id( next_packet ));
+				}
+				next_packet = tmp_packet;
+			}
+		}
+	}else{
+		printf("unexpected\n");
+		// release duplicite or restricted
+		pq_release( tcp_globals.net_phone, packet_get_id( packet ));
+	}
+
+	// change state according to the acknowledging incoming fin
+	if( IS_IN_INTERVAL_OVERFLOW( old_incoming, socket_data->fin_incoming, socket_data->next_incoming )){
+		switch( socket_data->state ){
+			case TCP_SOCKET_FIN_WAIT_1:
+			case TCP_SOCKET_FIN_WAIT_2:
+			case TCP_SOCKET_CLOSING:
+				socket_data->state = TCP_SOCKET_CLOSING;
+				break;
+			//case TCP_ESTABLISHED:
+			default:
+				socket_data->state = TCP_SOCKET_CLOSE_WAIT;
+				break;
+		}
+	}
+
+	packet = tcp_get_packets_to_send( socket, socket_data );
+	if( ! packet ){
+		// create the notification packet
+		ERROR_PROPAGATE( tcp_create_notification_packet( & packet, socket, socket_data, 0, 0 ));
+		ERROR_PROPAGATE( tcp_queue_prepare_packet( socket, socket_data, packet, 1 ));
+		packet = tcp_send_prepare_packet( socket, socket_data, packet, 1, socket_data->last_outgoing + 1 );
+	}
+	fibril_rwlock_write_unlock( socket_data->local_lock );
+	// send the packet
+	tcp_send_packets( socket_data->device_id, packet );
+	return EOK;
+}
+
+int tcp_queue_received_packet( socket_core_ref socket, tcp_socket_data_ref socket_data, packet_t packet, int fragments, size_t total_length ){
+	ERROR_DECLARE;
+
+	packet_dimension_ref	packet_dimension;
+
+	assert( socket );
+	assert( socket_data );
+	assert( socket->specific_data == socket_data );
+	assert( packet );
+	assert( fragments >= 1 );
+	assert( socket_data->window > total_length );
+
+	// queue the received packet
+	if( ERROR_OCCURRED( dyn_fifo_push( & socket->received, packet_get_id( packet ), SOCKET_MAX_RECEIVED_SIZE ))
+	|| ERROR_OCCURRED( tl_get_ip_packet_dimension( tcp_globals.ip_phone, & tcp_globals.dimensions, socket_data->device_id, & packet_dimension ))){
+		return tcp_release_and_return( packet, ERROR_CODE );
+	}
+
+	// decrease the window size
+	socket_data->window -= total_length;
+
+	// notify the destination socket
+	async_msg_5( socket->phone, NET_SOCKET_RECEIVED, ( ipcarg_t ) socket->socket_id, (( packet_dimension->content < socket_data->data_fragment_size ) ? packet_dimension->content : socket_data->data_fragment_size ), 0, 0, ( ipcarg_t ) fragments );
+	return EOK;
+}
+
+int tcp_process_syn_sent( socket_core_ref socket, tcp_socket_data_ref socket_data, tcp_header_ref header, packet_t packet ){
+	ERROR_DECLARE;
+
+	packet_t	next_packet;
+
+	assert( socket );
+	assert( socket_data );
+	assert( socket->specific_data == socket_data );
+	assert( header );
+	assert( packet );
+
+	if( header->synchronize ){
+		// process acknowledgement
+		tcp_process_acknowledgement( socket, socket_data, header );
+
+		socket_data->next_incoming = ntohl( header->sequence_number ) + 1;
+		// release additional packets
+		next_packet = pq_detach( packet );
+		if( next_packet ){
+			pq_release( tcp_globals.net_phone, packet_get_id( next_packet ));
+		}
+		// trim if longer than the header
+		if(( packet_get_data_length( packet ) > sizeof( * header ))
+		&& ERROR_OCCURRED( packet_trim( packet, 0, packet_get_data_length( packet ) - sizeof( * header )))){
+			return tcp_release_and_return( packet, ERROR_CODE );
+		}
+		tcp_prepare_operation_header( socket, socket_data, header, 0, 0 );
+		fibril_mutex_lock( & socket_data->operation.mutex );
+		socket_data->operation.result = tcp_queue_packet( socket, socket_data, packet, 1 );
+		if( socket_data->operation.result == EOK ){
+			socket_data->state = TCP_SOCKET_ESTABLISHED;
+			packet = tcp_get_packets_to_send( socket, socket_data );
+			if( packet ){
+				fibril_rwlock_write_unlock( socket_data->local_lock );
+				// send the packet
+				tcp_send_packets( socket_data->device_id, packet );
+				// signal the result
+				fibril_condvar_signal( & socket_data->operation.condvar );
+				fibril_mutex_unlock( & socket_data->operation.mutex );
+				return EOK;
+			}
+		}
+		fibril_mutex_unlock( & socket_data->operation.mutex );
+	}
+	return tcp_release_and_return( packet, EINVAL );
+}
+
+int tcp_process_listen( socket_core_ref listening_socket, tcp_socket_data_ref listening_socket_data, tcp_header_ref header, packet_t packet, struct sockaddr * src, struct sockaddr * dest, size_t addrlen ){
+	ERROR_DECLARE;
+
+	packet_t			next_packet;
+	socket_core_ref		socket;
+	tcp_socket_data_ref	socket_data;
+	int					socket_id;
+	int					listening_socket_id = listening_socket->socket_id;
+	int					listening_port = listening_socket->port;
+
+	assert( listening_socket );
+	assert( listening_socket_data );
+	assert( listening_socket->specific_data == listening_socket_data );
+	assert( header );
+	assert( packet );
+
+//	printf( "syn %d\n", header->synchronize );
+	if( header->synchronize ){
+		socket_data = ( tcp_socket_data_ref ) malloc( sizeof( * socket_data ));
+		if( ! socket_data ){
+			return tcp_release_and_return( packet, ENOMEM );
+		}else{
+			tcp_initialize_socket_data( socket_data );
+			socket_data->local_lock = listening_socket_data->local_lock;
+			socket_data->local_sockets = listening_socket_data->local_sockets;
+			socket_data->listening_socket_id = listening_socket->socket_id;
+
+			socket_data->next_incoming = ntohl( header->sequence_number );
+			socket_data->treshold = socket_data->next_incoming + ntohs( header->window );
+
+			socket_data->addrlen = addrlen;
+			socket_data->addr = malloc( socket_data->addrlen );
+			if( ! socket_data->addr ){
+				free( socket_data );
+				return tcp_release_and_return( packet, ENOMEM );
+			}
+			memcpy( socket_data->addr, src, socket_data->addrlen );
+
+			socket_data->dest_port = ntohs( header->source_port );
+			if( ERROR_OCCURRED( tl_set_address_port( socket_data->addr, socket_data->addrlen, socket_data->dest_port ))){
+				free( socket_data->addr );
+				free( socket_data );
+				pq_release( tcp_globals.net_phone, packet_get_id( packet ));
+				return ERROR_CODE;
+			}
+
+//			printf( "addr %p\n", socket_data->addr, socket_data->addrlen );
+			// create a socket
+			socket_id = -1;
+			if( ERROR_OCCURRED( socket_create( socket_data->local_sockets, listening_socket->phone, socket_data, & socket_id ))){
+				free( socket_data->addr );
+				free( socket_data );
+				return tcp_release_and_return( packet, ERROR_CODE );
+			}
+
+			printf("new_sock %d\n", socket_id);
+			socket_data->pseudo_header = listening_socket_data->pseudo_header;
+			socket_data->headerlen = listening_socket_data->headerlen;
+			listening_socket_data->pseudo_header = NULL;
+			listening_socket_data->headerlen = 0;
+
+			fibril_rwlock_write_unlock( socket_data->local_lock );
+//			printf("list lg\n");
+			fibril_rwlock_write_lock( & tcp_globals.lock );
+//			printf("list locked\n");
+			// find the destination socket
+			listening_socket = socket_port_find( & tcp_globals.sockets, listening_port, SOCKET_MAP_KEY_LISTENING, 0 );
+			if(( ! listening_socket ) || ( listening_socket->socket_id != listening_socket_id )){
+				fibril_rwlock_write_unlock( & tcp_globals.lock );
+				// a shadow may remain until app hangs up
+				return tcp_release_and_return( packet, EOK/*ENOTSOCK*/ );
+			}
+//			printf("port %d\n", listening_socket->port );
+			listening_socket_data = ( tcp_socket_data_ref ) listening_socket->specific_data;
+			assert( listening_socket_data );
+
+//			printf("list ll\n");
+			fibril_rwlock_write_lock( listening_socket_data->local_lock );
+//			printf("list locked\n");
+
+			socket = socket_cores_find( listening_socket_data->local_sockets, socket_id );
+			if( ! socket ){
+				// where is the socket?!?
+				fibril_rwlock_write_unlock( & tcp_globals.lock );
+				return ENOTSOCK;
+			}
+			socket_data = ( tcp_socket_data_ref ) socket->specific_data;
+			assert( socket_data );
+
+//			uint8_t * data = socket_data->addr;
+//			printf( "addr %d of %x %x %x %x-%x %x %x %x-%x %x %x %x-%x %x %x %x\n", socket_data->addrlen, data[ 0 ], data[ 1 ], data[ 2 ], data[ 3 ], data[ 4 ], data[ 5 ], data[ 6 ], data[ 7 ], data[ 8 ], data[ 9 ], data[ 10 ], data[ 11 ], data[ 12 ], data[ 13 ], data[ 14 ], data[ 15 ] );
+
+			ERROR_CODE = socket_port_add( & tcp_globals.sockets, listening_port, socket, ( const char * ) socket_data->addr, socket_data->addrlen );
+			assert( socket == socket_port_find( & tcp_globals.sockets, listening_port, ( const char * ) socket_data->addr, socket_data->addrlen ));
+			//ERROR_CODE = socket_bind_free_port( & tcp_globals.sockets, socket, TCP_FREE_PORTS_START, TCP_FREE_PORTS_END, tcp_globals.last_used_port );
+			//tcp_globals.last_used_port = socket->port;
+//			printf("bound %d\n", socket->port );
+			fibril_rwlock_write_unlock( & tcp_globals.lock );
+			if( ERROR_CODE != EOK ){
+				socket_destroy( tcp_globals.net_phone, socket->socket_id, socket_data->local_sockets, & tcp_globals.sockets, tcp_free_socket_data );
+				return tcp_release_and_return( packet, ERROR_CODE );
+			}
+
+			socket_data->state = TCP_SOCKET_LISTEN;
+			socket_data->next_incoming = ntohl( header->sequence_number ) + 1;
+			// release additional packets
+			next_packet = pq_detach( packet );
+			if( next_packet ){
+				pq_release( tcp_globals.net_phone, packet_get_id( next_packet ));
+			}
+			// trim if longer than the header
+			if(( packet_get_data_length( packet ) > sizeof( * header ))
+			&& ERROR_OCCURRED( packet_trim( packet, 0, packet_get_data_length( packet ) - sizeof( * header )))){
+				socket_destroy( tcp_globals.net_phone, socket->socket_id, socket_data->local_sockets, & tcp_globals.sockets, tcp_free_socket_data );
+				return tcp_release_and_return( packet, ERROR_CODE );
+			}
+			tcp_prepare_operation_header( socket, socket_data, header, 1, 0 );
+			if( ERROR_OCCURRED( tcp_queue_packet( socket, socket_data, packet, 1 ))){
+				socket_destroy( tcp_globals.net_phone, socket->socket_id, socket_data->local_sockets, & tcp_globals.sockets, tcp_free_socket_data );
+				return ERROR_CODE;
+			}
+			packet = tcp_get_packets_to_send( socket, socket_data );
+//			printf("send %d\n", packet_get_id( packet ));
+			if( ! packet ){
+				socket_destroy( tcp_globals.net_phone, socket->socket_id, socket_data->local_sockets, & tcp_globals.sockets, tcp_free_socket_data );
+				return EINVAL;
+			}else{
+				socket_data->state = TCP_SOCKET_SYN_RECEIVED;
+//				printf("unlock\n");
+				fibril_rwlock_write_unlock( socket_data->local_lock );
+				// send the packet
+				tcp_send_packets( socket_data->device_id, packet );
+				return EOK;
+			}
+		}
+	}
+	return tcp_release_and_return( packet, EINVAL );
+}
+
+int	tcp_process_syn_received( socket_core_ref socket, tcp_socket_data_ref socket_data, tcp_header_ref header, packet_t packet ){
+	ERROR_DECLARE;
+
+	socket_core_ref		listening_socket;
+	tcp_socket_data_ref	listening_socket_data;
+
+	assert( socket );
+	assert( socket_data );
+	assert( socket->specific_data == socket_data );
+	assert( header );
+	assert( packet );
+
+	printf("syn_rec\n");
+	if( header->acknowledge ){
+		// process acknowledgement
+		tcp_process_acknowledgement( socket, socket_data, header );
+
+		socket_data->next_incoming = ntohl( header->sequence_number );// + 1;
+		pq_release( tcp_globals.net_phone, packet_get_id( packet ));
+		socket_data->state = TCP_SOCKET_ESTABLISHED;
+		listening_socket = socket_cores_find( socket_data->local_sockets, socket_data->listening_socket_id );
+		if( listening_socket ){
+			listening_socket_data = ( tcp_socket_data_ref ) listening_socket->specific_data;
+			assert( listening_socket_data );
+
+			// queue the received packet
+			if( ! ERROR_OCCURRED( dyn_fifo_push( & listening_socket->accepted, ( -1 * socket->socket_id ), listening_socket_data->backlog ))){
+				// notify the destination socket
+				async_msg_5( socket->phone, NET_SOCKET_ACCEPTED, ( ipcarg_t ) listening_socket->socket_id, socket_data->data_fragment_size, TCP_HEADER_SIZE, 0, ( ipcarg_t ) socket->socket_id );
+				fibril_rwlock_write_unlock( socket_data->local_lock );
+				return EOK;
+			}
+		}
+		// send FIN
+		socket_data->state = TCP_SOCKET_FIN_WAIT_1;
+
+		// create the notification packet
+		ERROR_PROPAGATE( tcp_create_notification_packet( & packet, socket, socket_data, 0, 1 ));
+
+		// send the packet
+		ERROR_PROPAGATE( tcp_queue_packet( socket, socket_data, packet, 1 ));
+
+		// flush packets
+		packet = tcp_get_packets_to_send( socket, socket_data );
+		fibril_rwlock_write_unlock( socket_data->local_lock );
+		if( packet ){
+			// send the packet
+			tcp_send_packets( socket_data->device_id, packet );
+		}
+		return EOK;
+	}else{
+		return tcp_release_and_return( packet, EINVAL );
+	}
+	return EINVAL;
+}
+
+void tcp_process_acknowledgement( socket_core_ref socket, tcp_socket_data_ref socket_data, tcp_header_ref header ){
+	size_t		number;
+	size_t		length;
+	packet_t	packet;
+	packet_t	next;
+	packet_t	acknowledged = NULL;
+	packet_t	first;
+	uint32_t	old;
+
+	assert( socket );
+	assert( socket_data );
+	assert( socket->specific_data == socket_data );
+	assert( header );
+
+	if( header->acknowledge ){
+		number = ntohl( header->acknowledgement_number );
+		// if more data acknowledged
+		if( number != socket_data->expected ){
+			old = socket_data->expected;
+			if( IS_IN_INTERVAL_OVERFLOW( old, socket_data->fin_outgoing, number )){
+				switch( socket_data->state ){
+					case TCP_SOCKET_FIN_WAIT_1:
+						socket_data->state = TCP_SOCKET_FIN_WAIT_2;
+						break;
+					case TCP_SOCKET_LAST_ACK:
+					case TCP_SOCKET_CLOSING:
+						// fin acknowledged - release the socket in another fibril
+						tcp_prepare_timeout( tcp_release_after_timeout, socket, socket_data, 0, TCP_SOCKET_TIME_WAIT, NET_DEFAULT_TCP_TIME_WAIT_TIMEOUT, true );
+						break;
+					default:
+						break;
+				}
+			}
+			// update the treshold if higher than set
+			if( number + ntohs( header->window ) > socket_data->expected + socket_data->treshold ){
+				socket_data->treshold = number + ntohs( header->window ) - socket_data->expected;
+			}
+			// set new expected sequence number
+			socket_data->expected = number;
+			socket_data->expected_count = 1;
+			packet = socket_data->outgoing;
+			while( pq_get_order( packet, & number, & length ) == EOK ){
+				if( IS_IN_INTERVAL_OVERFLOW(( uint32_t ) old, ( uint32_t )( number + length ), ( uint32_t ) socket_data->expected )){
+					next = pq_detach( packet );
+					if( packet == socket_data->outgoing ){
+						socket_data->outgoing = next;
+					}
+					// add to acknowledged or release
+					first = pq_add( acknowledged, packet, 0, 0 );
+					if( first ){
+						acknowledged = first;
+					}else{
+						pq_release( tcp_globals.net_phone, packet_get_id( packet ));
+					}
+					packet = next;
+				}else if( old < socket_data->expected ){
+					break;
+				}
+			}
+			// release acknowledged
+			if( acknowledged ){
+				pq_release( tcp_globals.net_phone, packet_get_id( acknowledged ));
+			}
+			return;
+		// if the same as the previous time
+		}else if( number == socket_data->expected ){
+			// increase the counter
+			++ socket_data->expected_count;
+			if( socket_data->expected_count == TCP_FAST_RETRANSMIT_COUNT ){
+				socket_data->expected_count = 1;
+				// TODO retransmit lock
+				//tcp_retransmit_packet( socket, socket_data, number );
+			}
+		}
+	}
+}
+
+int tcp_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){
+	ERROR_DECLARE;
+
+	packet_t	packet;
+
+	assert( call );
+	assert( answer );
+	assert( answer_count );
+
+	* answer_count = 0;
+	switch( IPC_GET_METHOD( * call )){
+		case NET_TL_RECEIVED:
+			//fibril_rwlock_read_lock( & tcp_globals.lock );
+			if( ! ERROR_OCCURRED( packet_translate( tcp_globals.net_phone, & packet, IPC_GET_PACKET( call )))){
+				ERROR_CODE = tcp_received_msg( IPC_GET_DEVICE( call ), packet, SERVICE_TCP, IPC_GET_ERROR( call ));
+			}
+			//fibril_rwlock_read_unlock( & tcp_globals.lock );
+			return ERROR_CODE;
+		case IPC_M_CONNECT_TO_ME:
+			return tcp_process_client_messages( callid, * call );
+	}
+	return ENOTSUP;
+}
+
+void tcp_refresh_socket_data( tcp_socket_data_ref socket_data ){
+	assert( socket_data );
+
+	bzero( socket_data, sizeof( * socket_data ));
+	socket_data->state = TCP_SOCKET_INITIAL;
+	socket_data->device_id = DEVICE_INVALID_ID;
+	socket_data->window = NET_DEFAULT_TCP_WINDOW;
+	socket_data->treshold = socket_data->window;
+	socket_data->last_outgoing = TCP_INITIAL_SEQUENCE_NUMBER;
+	socket_data->timeout = NET_DEFAULT_TCP_INITIAL_TIMEOUT;
+	socket_data->acknowledged = socket_data->last_outgoing;
+	socket_data->next_outgoing = socket_data->last_outgoing + 1;
+	socket_data->expected = socket_data->next_outgoing;
+}
+
+void tcp_initialize_socket_data( tcp_socket_data_ref socket_data ){
+	assert( socket_data );
+
+	tcp_refresh_socket_data( socket_data );
+	fibril_mutex_initialize( & socket_data->operation.mutex );
+	fibril_condvar_initialize( & socket_data->operation.condvar );
+	socket_data->data_fragment_size = MAX_TCP_FRAGMENT_SIZE;
+}
+
+int tcp_process_client_messages( ipc_callid_t callid, ipc_call_t call ){
+	int						res;
+	bool					keep_on_going = true;
+	socket_cores_t			local_sockets;
+	int						app_phone = IPC_GET_PHONE( & call );
+	struct sockaddr *		addr;
+	size_t					addrlen;
+	fibril_rwlock_t			lock;
+	ipc_call_t				answer;
+	int						answer_count;
+	tcp_socket_data_ref		socket_data;
+	socket_core_ref			socket;
+	packet_dimension_ref	packet_dimension;
+
+	/*
+	 * Accept the connection
+	 *  - Answer the first IPC_M_CONNECT_ME_TO call.
+	 */
+	ipc_answer_0( callid, EOK );
+
+	socket_cores_initialize( & local_sockets );
+	fibril_rwlock_initialize( & lock );
+
+	while( keep_on_going ){
+		// refresh data
+		refresh_answer( & answer, & answer_count );
+
+		callid = async_get_call( & call );
+//		printf( "message %d\n", IPC_GET_METHOD( * call ));
+
+		switch( IPC_GET_METHOD( call )){
+			case IPC_M_PHONE_HUNGUP:
+				keep_on_going = false;
+				res = EOK;
+				break;
+			case NET_SOCKET:
+				socket_data = ( tcp_socket_data_ref ) malloc( sizeof( * socket_data ));
+				if( ! socket_data ){
+					res = ENOMEM;
+				}else{
+					tcp_initialize_socket_data( socket_data );
+					socket_data->local_lock = & lock;
+					socket_data->local_sockets = & local_sockets;
+					fibril_rwlock_write_lock( & lock );
+					* SOCKET_SET_SOCKET_ID( answer ) = SOCKET_GET_SOCKET_ID( call );
+					res = socket_create( & local_sockets, app_phone, socket_data, SOCKET_SET_SOCKET_ID( answer ));
+					fibril_rwlock_write_unlock( & lock );
+					if( res == EOK ){
+						if( tl_get_ip_packet_dimension( tcp_globals.ip_phone, & tcp_globals.dimensions, DEVICE_INVALID_ID, & packet_dimension ) == EOK ){
+							* SOCKET_SET_DATA_FRAGMENT_SIZE( answer ) = (( packet_dimension->content < socket_data->data_fragment_size ) ? packet_dimension->content : socket_data->data_fragment_size );
+						}
+//						* SOCKET_SET_DATA_FRAGMENT_SIZE( answer ) = MAX_TCP_FRAGMENT_SIZE;
+						* SOCKET_SET_HEADER_SIZE( answer ) = TCP_HEADER_SIZE;
+						answer_count = 3;
+					}else{
+						free( socket_data );
+					}
+				}
+				break;
+			case NET_SOCKET_BIND:
+				res = data_receive(( void ** ) & addr, & addrlen );
+				if( res == EOK ){
+					fibril_rwlock_write_lock( & tcp_globals.lock );
+					fibril_rwlock_write_lock( & lock );
+					res = socket_bind( & local_sockets, & tcp_globals.sockets, SOCKET_GET_SOCKET_ID( call ), addr, addrlen, TCP_FREE_PORTS_START, TCP_FREE_PORTS_END, tcp_globals.last_used_port );
+					if( res == EOK ){
+						socket = socket_cores_find( & local_sockets, SOCKET_GET_SOCKET_ID( call ));
+						if( socket ){
+							socket_data = ( tcp_socket_data_ref ) socket->specific_data;
+							assert( socket_data );
+							socket_data->state = TCP_SOCKET_LISTEN;
+						}
+					}
+					fibril_rwlock_write_unlock( & lock );
+					fibril_rwlock_write_unlock( & tcp_globals.lock );
+					free( addr );
+				}
+				break;
+			case NET_SOCKET_LISTEN:
+				fibril_rwlock_read_lock( & tcp_globals.lock );
+//				fibril_rwlock_write_lock( & tcp_globals.lock );
+				fibril_rwlock_write_lock( & lock );
+				res = tcp_listen_message( & local_sockets, SOCKET_GET_SOCKET_ID( call ), SOCKET_GET_BACKLOG( call ));
+				fibril_rwlock_write_unlock( & lock );
+//				fibril_rwlock_write_unlock( & tcp_globals.lock );
+				fibril_rwlock_read_unlock( & tcp_globals.lock );
+				break;
+			case NET_SOCKET_CONNECT:
+				res = data_receive(( void ** ) & addr, & addrlen );
+				if( res == EOK ){
+					// the global lock may be released in the tcp_connect_message() function
+					fibril_rwlock_write_lock( & tcp_globals.lock );
+					fibril_rwlock_write_lock( & lock );
+					res = tcp_connect_message( & local_sockets, SOCKET_GET_SOCKET_ID( call ), addr, addrlen );
+					if( res != EOK ){
+						fibril_rwlock_write_unlock( & lock );
+						fibril_rwlock_write_unlock( & tcp_globals.lock );
+						free( addr );
+					}
+				}
+				break;
+			case NET_SOCKET_ACCEPT:
+				fibril_rwlock_read_lock( & tcp_globals.lock );
+				fibril_rwlock_write_lock( & lock );
+				res = tcp_accept_message( & local_sockets, SOCKET_GET_SOCKET_ID( call ), SOCKET_GET_NEW_SOCKET_ID( call ), SOCKET_SET_DATA_FRAGMENT_SIZE( answer ), & addrlen );
+				fibril_rwlock_write_unlock( & lock );
+				fibril_rwlock_read_unlock( & tcp_globals.lock );
+				if( res > 0 ){
+					* SOCKET_SET_SOCKET_ID( answer ) = res;
+					* SOCKET_SET_ADDRESS_LENGTH( answer ) = addrlen;
+					answer_count = 3;
+				}
+				break;
+			case NET_SOCKET_SEND:
+				fibril_rwlock_read_lock( & tcp_globals.lock );
+				fibril_rwlock_write_lock( & lock );
+				res = tcp_send_message( & local_sockets, SOCKET_GET_SOCKET_ID( call ), SOCKET_GET_DATA_FRAGMENTS( call ), SOCKET_SET_DATA_FRAGMENT_SIZE( answer ), SOCKET_GET_FLAGS( call ));
+				if( res != EOK ){
+					fibril_rwlock_write_unlock( & lock );
+					fibril_rwlock_read_unlock( & tcp_globals.lock );
+				}else{
+					answer_count = 2;
+				}
+				break;
+			case NET_SOCKET_SENDTO:
+				res = data_receive(( void ** ) & addr, & addrlen );
+				if( res == EOK ){
+					fibril_rwlock_read_lock( & tcp_globals.lock );
+					fibril_rwlock_write_lock( & lock );
+					res = tcp_send_message( & local_sockets, SOCKET_GET_SOCKET_ID( call ), SOCKET_GET_DATA_FRAGMENTS( call ), SOCKET_SET_DATA_FRAGMENT_SIZE( answer ), SOCKET_GET_FLAGS( call ));
+					if( res != EOK ){
+						fibril_rwlock_write_unlock( & lock );
+						fibril_rwlock_read_unlock( & tcp_globals.lock );
+					}else{
+						answer_count = 2;
+					}
+					free( addr );
+				}
+				break;
+			case NET_SOCKET_RECV:
+				fibril_rwlock_read_lock( & tcp_globals.lock );
+				fibril_rwlock_write_lock( & lock );
+				res = tcp_recvfrom_message( & local_sockets, SOCKET_GET_SOCKET_ID( call ), SOCKET_GET_FLAGS( call ), NULL );
+				fibril_rwlock_write_unlock( & lock );
+				fibril_rwlock_read_unlock( & tcp_globals.lock );
+				if( res > 0 ){
+					* SOCKET_SET_READ_DATA_LENGTH( answer ) = res;
+					answer_count = 1;
+					res = EOK;
+				}
+				break;
+			case NET_SOCKET_RECVFROM:
+				fibril_rwlock_read_lock( & tcp_globals.lock );
+				fibril_rwlock_write_lock( & lock );
+				res = tcp_recvfrom_message( & local_sockets, SOCKET_GET_SOCKET_ID( call ), SOCKET_GET_FLAGS( call ), & addrlen );
+				fibril_rwlock_write_unlock( & lock );
+				fibril_rwlock_read_unlock( & tcp_globals.lock );
+				if( res > 0 ){
+					* 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( & tcp_globals.lock );
+				fibril_rwlock_write_lock( & lock );
+				res = tcp_close_message( & local_sockets, SOCKET_GET_SOCKET_ID( call ));
+				if( res != EOK ){
+					fibril_rwlock_write_unlock( & lock );
+					fibril_rwlock_write_unlock( & tcp_globals.lock );
+				}
+				break;
+			case NET_SOCKET_GETSOCKOPT:
+			case NET_SOCKET_SETSOCKOPT:
+			default:
+				res = ENOTSUP;
+				break;
+		}
+
+//		printf( "res = %d\n", res );
+
+		answer_call( callid, res, & answer, answer_count );
+	}
+
+	printf("release\n");
+	// release all local sockets
+	socket_cores_release( tcp_globals.net_phone, & local_sockets, & tcp_globals.sockets, tcp_free_socket_data );
+
+	return EOK;
+}
+
+int tcp_timeout( void * data ){
+	tcp_timeout_ref		timeout = data;
+	int					keep_write_lock = false;
+	socket_core_ref		socket;
+	tcp_socket_data_ref	socket_data;
+
+	assert( timeout );
+
+	// sleep the given timeout
+	async_usleep( timeout->timeout );
+	// lock the globals
+	if( timeout->globals_read_only ){
+		fibril_rwlock_read_lock( & tcp_globals.lock );
+	}else{
+		fibril_rwlock_write_lock( & tcp_globals.lock );
+	}
+	// find the pending operation socket
+	socket = socket_port_find( & tcp_globals.sockets, timeout->port, timeout->key, timeout->key_length );
+	if( socket && ( socket->socket_id == timeout->socket_id )){
+		socket_data = ( tcp_socket_data_ref ) socket->specific_data;
+		assert( socket_data );
+		if( socket_data->local_sockets == timeout->local_sockets ){
+			fibril_rwlock_write_lock( socket_data->local_lock );
+			if( timeout->sequence_number ){
+				// increase the timeout counter;
+				++ socket_data->timeout_count;
+				if( socket_data->timeout_count == TCP_MAX_TIMEOUTS ){
+					// TODO release as connection lost
+					//tcp_refresh_socket_data( socket_data );
+				}
+				// retransmit
+				// TODO enable retransmit
+				//tcp_retransmit_packet( socket, socket_data, timeout->sequence_number );
+				fibril_rwlock_write_unlock( socket_data->local_lock );
+			}else{
+				fibril_mutex_lock( & socket_data->operation.mutex );
+				// set the timeout operation result if state not changed
+				if( socket_data->state == timeout->state ){
+					socket_data->operation.result = ETIMEOUT;
+					// notify the main fibril
+					fibril_condvar_signal( & socket_data->operation.condvar );
+					// keep the global write lock
+					keep_write_lock = true;
+				}else{
+					// operation is ok, do nothing
+					// unlocking from now on, so the unlock order does not matter...
+					fibril_rwlock_write_unlock( socket_data->local_lock );
+				}
+				fibril_mutex_unlock( & socket_data->operation.mutex );
+			}
+		}
+	}
+	// unlock only if no socket
+	if( timeout->globals_read_only ){
+		fibril_rwlock_read_unlock( & tcp_globals.lock );
+	}else if( ! keep_write_lock ){
+		// release if not desired
+		fibril_rwlock_write_unlock( & tcp_globals.lock );
+	}
+	// release the timeout structure
+	free( timeout );
+	return EOK;
+}
+
+int tcp_release_after_timeout( void * data ){
+	tcp_timeout_ref		timeout = data;
+	socket_core_ref		socket;
+	tcp_socket_data_ref	socket_data;
+	fibril_rwlock_t *	local_lock;
+
+	assert( timeout );
+
+	// sleep the given timeout
+	async_usleep( timeout->timeout );
+	// lock the globals
+	fibril_rwlock_write_lock( & tcp_globals.lock );
+	// find the pending operation socket
+	socket = socket_port_find( & tcp_globals.sockets, timeout->port, timeout->key, timeout->key_length );
+	if( socket && ( socket->socket_id == timeout->socket_id )){
+		socket_data = ( tcp_socket_data_ref ) socket->specific_data;
+		assert( socket_data );
+		if( socket_data->local_sockets == timeout->local_sockets ){
+			local_lock = socket_data->local_lock;
+			fibril_rwlock_write_lock( local_lock );
+			socket_destroy( tcp_globals.net_phone, timeout->socket_id, timeout->local_sockets, & tcp_globals.sockets, tcp_free_socket_data );
+			fibril_rwlock_write_unlock( local_lock );
+		}
+	}
+	// unlock the globals
+	fibril_rwlock_write_unlock( & tcp_globals.lock );
+	// release the timeout structure
+	free( timeout );
+	return EOK;
+}
+
+void tcp_retransmit_packet( socket_core_ref socket, tcp_socket_data_ref socket_data, size_t sequence_number ){
+	packet_t	packet;
+	packet_t	copy;
+	size_t		data_length;
+
+	assert( socket );
+	assert( socket_data );
+	assert( socket->specific_data == socket_data );
+
+	// sent packet?
+	packet = pq_find( socket_data->outgoing, sequence_number );
+	printf("retransmit %d\n", packet_get_id( packet ));
+	if( packet ){
+		pq_get_order( packet, NULL, & data_length );
+		copy = tcp_prepare_copy( socket, socket_data, packet, data_length, sequence_number );
+		fibril_rwlock_write_unlock( socket_data->local_lock );
+//		printf( "r send %d\n", packet_get_id( packet ));
+		if( copy ){
+			tcp_send_packets( socket_data->device_id, copy );
+		}
+	}else{
+		fibril_rwlock_write_unlock( socket_data->local_lock );
+	}
+}
+
+int tcp_listen_message( socket_cores_ref local_sockets, int socket_id, int backlog ){
+	socket_core_ref		socket;
+	tcp_socket_data_ref	socket_data;
+
+	assert( local_sockets );
+
+	if( backlog < 0 ) return EINVAL;
+	// find the socket
+	socket = socket_cores_find( local_sockets, socket_id );
+	if( ! socket ) return ENOTSOCK;
+	// get the socket specific data
+	socket_data = ( tcp_socket_data_ref ) socket->specific_data;
+	assert( socket_data );
+	// set the backlog
+	socket_data->backlog = backlog;
+	return EOK;
+}
+
+int tcp_connect_message( socket_cores_ref local_sockets, int socket_id, struct sockaddr * addr, socklen_t addrlen ){
+	ERROR_DECLARE;
+
+	socket_core_ref			socket;
+
+	assert( local_sockets );
+	assert( addr );
+	assert( addrlen > 0 );
+
+	// find the socket
+	socket = socket_cores_find( local_sockets, socket_id );
+	if( ! socket ) return ENOTSOCK;
+	if( ERROR_OCCURRED( tcp_connect_core( socket, local_sockets, addr, addrlen ))){
+		tcp_free_socket_data( socket );
+		// unbind if bound
+		if( socket->port > 0 ){
+			socket_ports_exclude( & tcp_globals.sockets, socket->port );
+			socket->port = 0;
+		}
+	}
+	return ERROR_CODE;
+}
+
+int tcp_connect_core( socket_core_ref socket, socket_cores_ref local_sockets, struct sockaddr * addr, socklen_t addrlen ){
+	ERROR_DECLARE;
+
+	tcp_socket_data_ref		socket_data;
+	packet_t				packet;
+
+	assert( socket );
+	assert( addr );
+	assert( addrlen > 0 );
+
+	// get the socket specific data
+	socket_data = ( tcp_socket_data_ref ) socket->specific_data;
+	assert( socket_data );
+	assert( socket->specific_data == socket_data );
+	if(( socket_data->state != TCP_SOCKET_INITIAL )
+	&& (( socket_data->state != TCP_SOCKET_LISTEN ) || ( socket->port <= 0 ))){
+		return EINVAL;
+	}
+	// get the destination port
+	ERROR_PROPAGATE( tl_get_address_port( addr, addrlen, & socket_data->dest_port ));
+	if( socket->port <= 0 ){
+		// try to find a free port
+		ERROR_PROPAGATE( socket_bind_free_port( & tcp_globals.sockets, socket, TCP_FREE_PORTS_START, TCP_FREE_PORTS_END, tcp_globals.last_used_port ));
+		// set the next port as the search starting port number
+		tcp_globals.last_used_port = socket->port;
+	}
+	ERROR_PROPAGATE( ip_get_route_req( tcp_globals.ip_phone, IPPROTO_TCP, addr, addrlen, & socket_data->device_id, & socket_data->pseudo_header, & socket_data->headerlen ));
+
+	// create the notification packet
+	ERROR_PROPAGATE( tcp_create_notification_packet( & packet, socket, socket_data, 1, 0 ));
+
+	// unlock the globals and wait for an operation
+	fibril_rwlock_write_unlock( & tcp_globals.lock );
+
+	socket_data->addr = addr;
+	socket_data->addrlen = addrlen;
+	// send the packet
+	if( ERROR_OCCURRED( tcp_queue_packet( socket, socket_data, packet, 1 ))
+	|| ERROR_OCCURRED( tcp_prepare_timeout( tcp_timeout, socket, socket_data, 0, TCP_SOCKET_INITIAL, NET_DEFAULT_TCP_INITIAL_TIMEOUT, false ))){
+		socket_data->addr = NULL;
+		socket_data->addrlen = 0;
+		fibril_rwlock_write_lock( & tcp_globals.lock );
+	}else{
+		packet = tcp_get_packets_to_send( socket, socket_data );
+		if( packet ){
+			fibril_mutex_lock( & socket_data->operation.mutex );
+			fibril_rwlock_write_unlock( socket_data->local_lock );
+			// send the packet
+			printf( "connecting %d\n", packet_get_id( packet ));
+			tcp_send_packets( socket_data->device_id, packet );
+			// wait for a reply
+			fibril_condvar_wait( & socket_data->operation.condvar, & socket_data->operation.mutex );
+			ERROR_CODE = socket_data->operation.result;
+			if( ERROR_CODE != EOK ){
+				socket_data->addr = NULL;
+				socket_data->addrlen = 0;
+			}
+		}else{
+			socket_data->addr = NULL;
+			socket_data->addrlen = 0;
+			ERROR_CODE = EINTR;
+		}
+	}
+
+	fibril_mutex_unlock( & socket_data->operation.mutex );
+
+	// return the result
+	return ERROR_CODE;
+}
+
+int tcp_queue_prepare_packet( socket_core_ref socket, tcp_socket_data_ref socket_data, packet_t packet, size_t data_length ){
+	ERROR_DECLARE;
+
+	tcp_header_ref	header;
+
+	assert( socket );
+	assert( socket_data );
+	assert( socket->specific_data == socket_data );
+
+	// get tcp header
+	header = ( tcp_header_ref ) packet_get_data( packet );
+	if( ! header ) return NO_DATA;
+	header->destination_port = htons( socket_data->dest_port );
+	header->source_port = htons( socket->port );
+	header->sequence_number = htonl( socket_data->next_outgoing );
+	if( ERROR_OCCURRED( packet_set_addr( packet, NULL, ( uint8_t * ) socket_data->addr, socket_data->addrlen ))){
+		return tcp_release_and_return( packet, EINVAL );
+	}
+	// remember the outgoing FIN
+	if( header->finalize ){
+		socket_data->fin_outgoing = socket_data->next_outgoing;
+	}
+	return EOK;
+}
+
+int	tcp_queue_packet( socket_core_ref socket, tcp_socket_data_ref socket_data, packet_t packet, size_t data_length ){
+	ERROR_DECLARE;
+	packet_t		first;
+
+	assert( socket );
+	assert( socket_data );
+	assert( socket->specific_data == socket_data );
+
+	ERROR_PROPAGATE( tcp_queue_prepare_packet( socket, socket_data, packet, data_length ));
+
+	first = pq_add( socket_data->outgoing, packet, socket_data->next_outgoing, data_length );
+	if( ! first ){
+		return tcp_release_and_return( packet, EINVAL );
+	}
+	socket_data->outgoing = first;
+	socket_data->next_outgoing += data_length;
+	return EOK;
+}
+
+packet_t tcp_get_packets_to_send( socket_core_ref socket, tcp_socket_data_ref socket_data ){
+	ERROR_DECLARE;
+
+	packet_t		packet;
+	packet_t		copy;
+	packet_t		sending = NULL;
+	packet_t		previous = NULL;
+	size_t			data_length;
+
+	assert( socket );
+	assert( socket_data );
+	assert( socket->specific_data == socket_data );
+
+	packet = pq_find( socket_data->outgoing, socket_data->last_outgoing + 1 );
+	while( packet ){
+		pq_get_order( packet, NULL, & data_length );
+		// send only if fits into the window
+		// respecting the possible overflow
+		if( IS_IN_INTERVAL_OVERFLOW(( uint32_t ) socket_data->last_outgoing, ( uint32_t )( socket_data->last_outgoing + data_length ), ( uint32_t )( socket_data->expected + socket_data->treshold ))){
+			copy = tcp_prepare_copy( socket, socket_data, packet, data_length, socket_data->last_outgoing + 1 );
+			if( ! copy ){
+				return sending;
+			}
+			if( ! sending ){
+				sending = copy;
+			}else{
+				if( ERROR_OCCURRED( pq_insert_after( previous, copy ))){
+					pq_release( tcp_globals.net_phone, packet_get_id( copy ));
+					return sending;
+				}
+			}
+			previous = copy;
+			packet = pq_next( packet );
+			// overflow occurred ?
+			if(( ! packet ) && ( socket_data->last_outgoing > socket_data->next_outgoing )){
+				printf("gpts overflow\n");
+				// continue from the beginning
+				packet = socket_data->outgoing;
+			}
+			socket_data->last_outgoing += data_length;
+		}else{
+			break;
+		}
+	}
+	return sending;
+}
+
+packet_t tcp_send_prepare_packet( socket_core_ref socket, tcp_socket_data_ref socket_data, packet_t packet, size_t data_length, size_t sequence_number ){
+	ERROR_DECLARE;
+
+	tcp_header_ref	header;
+	uint32_t		checksum;
+
+	assert( socket );
+	assert( socket_data );
+	assert( socket->specific_data == socket_data );
+
+	// adjust the pseudo header
+	if( ERROR_OCCURRED( ip_client_set_pseudo_header_data_length( socket_data->pseudo_header, socket_data->headerlen, packet_get_data_length( packet )))){
+		pq_release( tcp_globals.net_phone, packet_get_id( packet ));
+		return NULL;
+	}
+
+	// get the header
+	header = ( tcp_header_ref ) packet_get_data( packet );
+	if( ! header ){
+		pq_release( tcp_globals.net_phone, packet_get_id( packet ));
+		return NULL;
+	}
+	assert( ntohl( header->sequence_number ) == sequence_number );
+
+	// adjust the header
+	if( socket_data->next_incoming ){
+		header->acknowledgement_number = htonl( socket_data->next_incoming );
+		header->acknowledge = 1;
+	}
+	header->window = htons( socket_data->window );
+
+	// checksum
+	header->checksum = 0;
+	checksum = compute_checksum( 0, socket_data->pseudo_header, socket_data->headerlen );
+	checksum = compute_checksum( checksum, ( uint8_t * ) packet_get_data( packet ), packet_get_data_length( packet ));
+	header->checksum = htons( flip_checksum( compact_checksum( checksum )));
+	// prepare the packet
+	if( ERROR_OCCURRED( ip_client_prepare_packet( packet, IPPROTO_TCP, 0, 0, 0, 0 ))
+	// prepare the timeout
+	|| ERROR_OCCURRED( tcp_prepare_timeout( tcp_timeout, socket, socket_data, sequence_number, socket_data->state, socket_data->timeout, true ))){
+		pq_release( tcp_globals.net_phone, packet_get_id( packet ));
+		return NULL;
+	}
+	return packet;
+}
+
+packet_t tcp_prepare_copy( socket_core_ref socket, tcp_socket_data_ref socket_data, packet_t packet, size_t data_length, size_t sequence_number ){
+	packet_t		copy;
+
+	assert( socket );
+	assert( socket_data );
+	assert( socket->specific_data == socket_data );
+
+	// make a copy of the packet
+	copy = packet_get_copy( tcp_globals.net_phone, packet );
+	if( ! copy ) return NULL;
+
+	return tcp_send_prepare_packet( socket, socket_data, copy, data_length, sequence_number );
+}
+
+void tcp_send_packets( device_id_t device_id, packet_t packet ){
+	packet_t	next;
+
+	while( packet ){
+		next = pq_detach( packet );
+		ip_send_msg( tcp_globals.ip_phone, device_id, packet, SERVICE_TCP, 0 );
+		packet = next;
+	}
+}
+
+void tcp_prepare_operation_header( socket_core_ref socket, tcp_socket_data_ref socket_data, tcp_header_ref header, int synchronize, int finalize ){
+	assert( socket );
+	assert( socket_data );
+	assert( socket->specific_data == socket_data );
+	assert( header );
+
+	bzero( header, sizeof( * header ));
+	header->source_port = htons( socket->port );
+	header->source_port = htons( socket_data->dest_port );
+	header->header_length = TCP_COMPUTE_HEADER_LENGTH( sizeof( * header ));
+	header->synchronize = synchronize;
+	header->finalize = finalize;
+}
+
+int tcp_prepare_timeout( int ( * timeout_function )( void * tcp_timeout_t ), socket_core_ref socket, tcp_socket_data_ref socket_data, size_t sequence_number, tcp_socket_state_t state, suseconds_t timeout, int globals_read_only ){
+	tcp_timeout_ref	operation_timeout;
+	fid_t			fibril;
+
+	assert( socket );
+	assert( socket_data );
+	assert( socket->specific_data == socket_data );
+
+	// prepare the timeout with key bundle structure
+	operation_timeout = malloc( sizeof( * operation_timeout ) + socket->key_length + 1 );
+	if( ! operation_timeout ) return ENOMEM;
+	bzero( operation_timeout, sizeof( * operation_timeout ));
+	operation_timeout->globals_read_only = globals_read_only;
+	operation_timeout->port = socket->port;
+	operation_timeout->local_sockets = socket_data->local_sockets;
+	operation_timeout->socket_id = socket->socket_id;
+	operation_timeout->timeout = timeout;
+	operation_timeout->sequence_number = sequence_number;
+	operation_timeout->state = state;
+
+	// copy the key
+	operation_timeout->key = (( char * ) operation_timeout ) + sizeof( * operation_timeout );
+	operation_timeout->key_length = socket->key_length;
+	memcpy( operation_timeout->key, socket->key, socket->key_length );
+	operation_timeout->key[ operation_timeout->key_length ] = '\0';
+
+	// prepare the timeouting thread
+	fibril = fibril_create( timeout_function, operation_timeout );
+	if( ! fibril ){
+		free( operation_timeout );
+		return EPARTY;
+	}
+//	fibril_mutex_lock( & socket_data->operation.mutex );
+	// start the timeouting fibril
+	fibril_add_ready( fibril );
+	//socket_data->state = state;
+	return EOK;
+}
+
+int tcp_recvfrom_message( socket_cores_ref local_sockets, int socket_id, int flags, size_t * addrlen ){
+	ERROR_DECLARE;
+
+	socket_core_ref		socket;
+	tcp_socket_data_ref	socket_data;
+	int					packet_id;
+	packet_t			packet;
+	size_t				length;
+
+	assert( local_sockets );
+
+	// find the socket
+	socket = socket_cores_find( local_sockets, socket_id );
+	if( ! socket ) return ENOTSOCK;
+	// get the socket specific data
+	if( ! socket->specific_data ) return NO_DATA;
+	socket_data = ( tcp_socket_data_ref ) socket->specific_data;
+
+	// check state
+	if(( socket_data->state != TCP_SOCKET_ESTABLISHED ) && ( socket_data->state != TCP_SOCKET_CLOSE_WAIT )){
+		return ENOTCONN;
+	}
+
+	// send the source address if desired
+	if( addrlen ){
+		ERROR_PROPAGATE( data_reply( socket_data->addr, socket_data->addrlen ));
+		* addrlen = socket_data->addrlen;
+	}
+
+	// get the next received packet
+	packet_id = dyn_fifo_value( & socket->received );
+	if( packet_id < 0 ) return NO_DATA;
+	ERROR_PROPAGATE( packet_translate( tcp_globals.net_phone, & packet, packet_id ));
+
+	// reply the packets
+	ERROR_PROPAGATE( socket_reply_packets( packet, & length ));
+
+	// release the packet
+	dyn_fifo_pop( & socket->received );
+	pq_release( tcp_globals.net_phone, packet_get_id( packet ));
+	// return the total length
+	return ( int ) length;
+}
+
+int tcp_send_message( socket_cores_ref local_sockets, int socket_id, int fragments, size_t * data_fragment_size, int flags ){
+	ERROR_DECLARE;
+
+	socket_core_ref			socket;
+	tcp_socket_data_ref		socket_data;
+	packet_dimension_ref	packet_dimension;
+	packet_t				packet;
+	size_t					total_length;
+	tcp_header_ref			header;
+	int						index;
+	int						result;
+
+	assert( local_sockets );
+	assert( data_fragment_size );
+
+	// find the socket
+	socket = socket_cores_find( local_sockets, socket_id );
+	if( ! socket ) return ENOTSOCK;
+	// get the socket specific data
+	if( ! socket->specific_data ) return NO_DATA;
+	socket_data = ( tcp_socket_data_ref ) socket->specific_data;
+
+	// check state
+	if(( socket_data->state != TCP_SOCKET_ESTABLISHED ) && ( socket_data->state != TCP_SOCKET_CLOSE_WAIT )){
+		return ENOTCONN;
+	}
+
+	ERROR_PROPAGATE( tl_get_ip_packet_dimension( tcp_globals.ip_phone, & tcp_globals.dimensions, socket_data->device_id, & packet_dimension ));
+
+	* data_fragment_size = (( packet_dimension->content < socket_data->data_fragment_size ) ? packet_dimension->content : socket_data->data_fragment_size );
+
+	for( index = 0; index < fragments; ++ index ){
+		// read the data fragment
+		result = tl_socket_read_packet_data( tcp_globals.net_phone, & packet, TCP_HEADER_SIZE, packet_dimension, socket_data->addr, socket_data->addrlen );
+		if( result < 0 ) return result;
+		total_length = ( size_t ) result;
+		// prefix the tcp header
+		header = PACKET_PREFIX( packet, tcp_header_t );
+		if( ! header ){
+			return tcp_release_and_return( packet, ENOMEM );
+		}
+		tcp_prepare_operation_header( socket, socket_data, header, 0, 0 );
+		ERROR_PROPAGATE( tcp_queue_packet( socket, socket_data, packet, 0 ));
+	}
+
+	// flush packets
+	packet = tcp_get_packets_to_send( socket, socket_data );
+	fibril_rwlock_write_unlock( socket_data->local_lock );
+	fibril_rwlock_read_unlock( & tcp_globals.lock );
+	if( packet ){
+		// send the packet
+		tcp_send_packets( socket_data->device_id, packet );
+	}
+
+	return EOK;
+}
+
+int tcp_close_message( socket_cores_ref local_sockets, int socket_id ){
+	ERROR_DECLARE;
+
+	socket_core_ref			socket;
+	tcp_socket_data_ref		socket_data;
+	packet_t				packet;
+
+	// find the socket
+	socket = socket_cores_find( local_sockets, socket_id );
+	if( ! socket ) return ENOTSOCK;
+	// get the socket specific data
+	socket_data = ( tcp_socket_data_ref ) socket->specific_data;
+	assert( socket_data );
+
+	// check state
+	switch( socket_data->state ){
+		case TCP_SOCKET_ESTABLISHED:
+			socket_data->state = TCP_SOCKET_FIN_WAIT_1;
+			break;
+		case TCP_SOCKET_CLOSE_WAIT:
+			socket_data->state = TCP_SOCKET_LAST_ACK;
+			break;
+//		case TCP_SOCKET_LISTEN:
+		default:
+			// just destroy
+			if( ! ERROR_OCCURRED( socket_destroy( tcp_globals.net_phone, socket_id, local_sockets, & tcp_globals.sockets, tcp_free_socket_data ))){
+				fibril_rwlock_write_unlock( socket_data->local_lock );
+				fibril_rwlock_write_unlock( & tcp_globals.lock );
+			}
+			return ERROR_CODE;
+	}
+	// send FIN
+	// TODO should I wait to complete?
+
+	// create the notification packet
+	ERROR_PROPAGATE( tcp_create_notification_packet( & packet, socket, socket_data, 0, 1 ));
+
+	// send the packet
+	ERROR_PROPAGATE( tcp_queue_packet( socket, socket_data, packet, 1 ));
+
+	// flush packets
+	packet = tcp_get_packets_to_send( socket, socket_data );
+	fibril_rwlock_write_unlock( socket_data->local_lock );
+	fibril_rwlock_write_unlock( & tcp_globals.lock );
+	if( packet ){
+		// send the packet
+		tcp_send_packets( socket_data->device_id, packet );
+	}
+	return EOK;
+}
+
+int tcp_create_notification_packet( packet_t * packet, socket_core_ref socket, tcp_socket_data_ref socket_data, int synchronize, int finalize ){
+	ERROR_DECLARE;
+
+	packet_dimension_ref	packet_dimension;
+	tcp_header_ref			header;
+
+	assert( packet );
+
+	// get the device packet dimension
+	ERROR_PROPAGATE( tl_get_ip_packet_dimension( tcp_globals.ip_phone, & tcp_globals.dimensions, socket_data->device_id, & packet_dimension ));
+	// get a new packet
+	* packet = packet_get_4( tcp_globals.net_phone, TCP_HEADER_SIZE, packet_dimension->addr_len, packet_dimension->prefix, packet_dimension->suffix );
+	if( ! * packet ) return ENOMEM;
+	// allocate space in the packet
+	header = PACKET_SUFFIX( * packet, tcp_header_t );
+	if( ! header ){
+		tcp_release_and_return( * packet, ENOMEM );
+	}
+
+	tcp_prepare_operation_header( socket, socket_data, header, synchronize, finalize );
+	return EOK;
+}
+
+int tcp_accept_message( socket_cores_ref local_sockets, int socket_id, int new_socket_id, size_t * data_fragment_size, size_t * addrlen ){
+	ERROR_DECLARE;
+
+	socket_core_ref		accepted;
+	socket_core_ref		socket;
+	tcp_socket_data_ref	socket_data;
+	packet_dimension_ref	packet_dimension;
+
+	assert( local_sockets );
+	assert( data_fragment_size );
+	assert( addrlen );
+
+	// find the socket
+	socket = socket_cores_find( local_sockets, socket_id );
+	if( ! socket ) return ENOTSOCK;
+	// get the socket specific data
+	socket_data = ( tcp_socket_data_ref ) socket->specific_data;
+	assert( socket_data );
+
+	// check state
+	if( socket_data->state != TCP_SOCKET_LISTEN ){
+		return EINVAL;
+	}
+
+	do{
+		socket_id = dyn_fifo_value( & socket->accepted );
+		if( socket_id < 0 ) return ENOTSOCK;
+		socket_id *= -1;
+
+		accepted = socket_cores_find( local_sockets, socket_id );
+		if( ! accepted ) return ENOTSOCK;
+		// get the socket specific data
+		socket_data = ( tcp_socket_data_ref ) accepted->specific_data;
+		assert( socket_data );
+		// TODO can it be in another state?
+		if( socket_data->state == TCP_SOCKET_ESTABLISHED ){
+			ERROR_PROPAGATE( data_reply( socket_data->addr, socket_data->addrlen ));
+			ERROR_PROPAGATE( tl_get_ip_packet_dimension( tcp_globals.ip_phone, & tcp_globals.dimensions, socket_data->device_id, & packet_dimension ));
+			* addrlen = socket_data->addrlen;
+			* data_fragment_size = (( packet_dimension->content < socket_data->data_fragment_size ) ? packet_dimension->content : socket_data->data_fragment_size );
+			if( new_socket_id > 0 ){
+				ERROR_PROPAGATE( socket_cores_update( local_sockets, accepted->socket_id, new_socket_id ));
+				accepted->socket_id = new_socket_id;
+			}
+		}
+		dyn_fifo_pop( & socket->accepted );
+	}while( socket_data->state != TCP_SOCKET_ESTABLISHED );
+	printf("ret accept %d\n", accepted->socket_id );
+	return accepted->socket_id;
+}
+
+void tcp_free_socket_data( socket_core_ref socket ){
+	tcp_socket_data_ref		socket_data;
+
+	assert( socket );
+
+	printf( "destroy_socket %d\n", socket->socket_id );
+
+	// get the socket specific data
+	socket_data = ( tcp_socket_data_ref ) socket->specific_data;
+	assert( socket_data );
+	//free the pseudo header
+	if( socket_data->pseudo_header ){
+		if( socket_data->headerlen ){
+			printf("d pseudo\n");
+			free( socket_data->pseudo_header );
+			socket_data->headerlen = 0;
+		}
+		socket_data->pseudo_header = NULL;
+	}
+	socket_data->headerlen = 0;
+	// free the address
+	if( socket_data->addr ){
+		if( socket_data->addrlen ){
+			printf("d addr\n");
+			free( socket_data->addr );
+			socket_data->addrlen = 0;
+		}
+		socket_data->addr = NULL;
+	}
+	socket_data->addrlen = 0;
+}
+
+int	tcp_release_and_return( packet_t packet, int result ){
+	pq_release( tcp_globals.net_phone, packet_get_id( packet ));
+	return result;
+}
+
+/** @}
+ */
Index: uspace/srv/net/tl/tcp/tcp.h
===================================================================
--- uspace/srv/net/tl/tcp/tcp.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/tl/tcp/tcp.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,301 @@
+/*
+ * 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 tcp
+ *  @{
+ */
+
+/** @file
+ *  TCP module.
+ */
+
+#ifndef __NET_TCP_H__
+#define __NET_TCP_H__
+
+#include <fibril_synch.h>
+
+#include "../../structures/packet/packet.h"
+
+#include "../../include/device.h"
+
+#include "../../socket/socket_core.h"
+
+#include "../tl_common.h"
+
+/** Type definition of the TCP global data.
+ *  @see tcp_globals
+ */
+typedef struct tcp_globals	tcp_globals_t;
+
+/** Type definition of the TCP socket specific data.
+ *  @see tcp_socket_data
+ */
+typedef struct tcp_socket_data	tcp_socket_data_t;
+
+/** Type definition of the TCP socket specific data pointer.
+ *  @see tcp_socket_data
+ */
+typedef tcp_socket_data_t *	tcp_socket_data_ref;
+
+/** Type definition of the TCP operation data.
+ *  @see tcp_operation
+ */
+typedef struct tcp_operation	tcp_operation_t;
+
+/** Type definition of the TCP operation data pointer.
+ *  @see tcp_operation
+ */
+typedef tcp_operation_t *	tcp_operation_ref;
+
+/** TCP socket state type definition.
+ *  @see tcp_socket_state
+ */
+typedef enum tcp_socket_state	tcp_socket_state_t;
+
+/** TCP socket state.
+ */
+enum tcp_socket_state{
+	/** Initial.
+	 *  Not connected or bound.
+	 */
+	TCP_SOCKET_INITIAL,
+	/** Listening.
+	 *  Awaiting a connection request from another TCP layer.
+	 *  When SYN is received a new bound socket in the TCP_SOCKET_SYN_RECEIVED state should be created.
+	 */
+	TCP_SOCKET_LISTEN,
+	/** Connecting issued.
+	 *  A~SYN has been sent, and TCP is awaiting the response SYN.
+	 *  Should continue to the TCP_SOCKET_ESTABLISHED state.
+	 */
+	TCP_SOCKET_SYN_SENT,
+	/** Connecting received.
+	 *  A~SYN has been received, a~SYN has been sent, and TCP is awaiting an ACK.
+	 *  Should continue to the TCP_SOCKET_ESTABLISHED state.
+	 */
+	TCP_SOCKET_SYN_RECEIVED,
+	/** Connected.
+	 *  The three-way handshake has been completed.
+	 */
+	TCP_SOCKET_ESTABLISHED,
+	/** Closing started.
+	 *  The local application has issued a~CLOSE.
+	 *  TCP has sent a~FIN, and is awaiting an ACK or a~FIN.
+	 *  Should continue to the TCP_SOCKET_FIN_WAIT_2 state when an ACK is received.
+	 *  Should continue to the TCP_SOCKET_CLOSING state when a~FIN is received.
+	 */
+	TCP_SOCKET_FIN_WAIT_1,
+	/** Closing confirmed.
+	 *  A~FIN has been sent, and an ACK received.
+	 *  TCP is awaiting a~FIN from the remote TCP layer.
+	 *  Should continue to the TCP_SOCKET_CLOSING state.
+	 */
+	TCP_SOCKET_FIN_WAIT_2,
+	/** Closing.
+	 *  A FIN has been sent, a FIN has been received, and an ACK has been sent.
+	 *  TCP is awaiting an ACK for the FIN that was sent.
+	 *  Should continue to the TCP_SOCKET_TIME_WAIT state.
+	 */
+	TCP_SOCKET_CLOSING,
+	/** Closing received.
+	 *  TCP has received a~FIN, and has sent an ACK.
+	 *  It is awaiting a~close request from the local application before sending a~FIN.
+	 *  Should continue to the TCP_SOCKET_SOCKET_LAST_ACK state.
+	 */
+	TCP_SOCKET_CLOSE_WAIT,
+	/** 
+	 *  A~FIN has been received, and an ACK and a~FIN have been sent.
+	 *  TCP is awaiting an ACK.
+	 *  Should continue to the TCP_SOCKET_TIME_WAIT state.
+	 */
+	TCP_SOCKET_LAST_ACK,
+	/** Closing finished.
+	 *  FINs have been received and ACK’d, and TCP is waiting two MSLs to remove the connection from the table.
+	 */
+	TCP_SOCKET_TIME_WAIT,
+	/** Closed.
+	 *  Imaginary, this indicates that a~connection has been removed from the connection table.
+	 */
+	TCP_SOCKET_CLOSED
+};
+
+/** TCP operation data.
+ */
+struct tcp_operation{
+	/** Operation result.
+	 */
+	int					result;
+	/** Safety lock.
+	 */
+	fibril_mutex_t		mutex;
+	/** Operation result signaling.
+	 */
+	fibril_condvar_t	condvar;
+};
+
+/** TCP socket specific data.
+ */
+struct tcp_socket_data{
+	/** TCP socket state.
+	 */
+	tcp_socket_state_t	state;
+	/** Data fragment size.
+	 *  Sending optimalization.
+	 */
+	size_t			data_fragment_size;
+	/** Device identifier.
+	 */
+	device_id_t		device_id;
+	/** Listening backlog.
+	 *  The maximal number of connected but not yet accepted sockets.
+	 */
+	int				backlog;
+//	/** Segment size.
+//	 */
+//	size_t			segment_size;
+	/** Parent listening socket identifier.
+	 *  Set if this socket is an accepted one.
+	 */
+	int				listening_socket_id;
+	/** Treshold size in bytes.
+	 */
+	size_t			treshold;
+	/** Window size in bytes.
+	 */
+	size_t			window;
+	/** Acknowledgement timeout.
+	 */
+	suseconds_t		timeout;
+	/** Last acknowledged byte.
+	 */
+	uint32_t		acknowledged;
+	/** Next incoming sequence number.
+	 */
+	uint32_t		next_incoming;
+	/** Incoming FIN.
+	 */
+	uint32_t		fin_incoming;
+	/** Next outgoing sequence number.
+	 */
+	uint32_t		next_outgoing;
+	/** Last outgoing sequence number.
+	 */
+	uint32_t		last_outgoing;
+	/** Outgoing FIN.
+	 */
+	uint32_t		fin_outgoing;
+	/** Expected sequence number by the remote host.
+	 *  The sequence number the other host expects.
+	 *  The notification is sent only upon a packet reecival.
+	 */
+	uint32_t		expected;
+	/** Expected sequence number counter.
+	 *  Counts the number of received notifications for the same sequence number.
+	 */
+	int				expected_count;
+	/** Incoming packet queue.
+	 *  Packets are buffered until received in the right order.
+	 *  The packets are excluded after successfully read.
+	 *  Packets are sorted by their starting byte.
+	 *  Packets metric is set as their data length.
+	 */
+	packet_t		incoming;
+	/** Outgoing packet queue.
+	 *  Packets are buffered until acknowledged by the remote host in the right order.
+	 *  The packets are excluded after acknowledged.
+	 *  Packets are sorted by their starting byte.
+	 *  Packets metric is set as their data length.
+	 */
+	packet_t		outgoing;
+	/** IP pseudo header.
+	 */
+	ip_pseudo_header_ref	pseudo_header;
+	/** IP pseudo header length.
+	 */
+	size_t			headerlen;
+	/** Remote host address.
+	 */
+	struct sockaddr *	addr;
+	/** Remote host address length.
+	 */
+	socklen_t			addrlen;
+	/** Remote host port.
+	 */
+	uint16_t			dest_port;
+	/** Parent local sockets.
+	 */
+	socket_cores_ref	local_sockets;
+	/** Local sockets safety lock.
+	 *  May be locked for writing while holding the global lock for reading when changing the local sockets only.
+	 *  The global lock may to be locked only before locking the local lock.
+	 *  The global lock may be locked more weakly than the local lock.
+	 *  The global lock may be released before releasing the local lock.
+	 *  @see tcp_globals:lock
+	 */
+	fibril_rwlock_t *	local_lock;
+	/** Pending operation data.
+	 */
+	tcp_operation_t		operation;
+	/** Timeouts in a row counter.
+	 *  If TCP_MAX_TIMEOUTS is reached, the connection is lost.
+	 */
+	int					timeout_count;
+};
+
+/** TCP global data.
+ */
+struct	tcp_globals{
+	/** Networking module phone.
+	 */
+	int				net_phone;
+	/** IP module phone.
+	 */
+	int				ip_phone;
+	/** ICMP module phone.
+	 */
+	int				icmp_phone;
+	/** Last used free port.
+	 */
+	int				last_used_port;
+	/** Active sockets.
+	 */
+	socket_ports_t	sockets;
+	/** Device packet dimensions.
+	 */
+	packet_dimensions_t	dimensions;
+	/** Safety lock.
+	 *  Write lock is used only for adding or removing socket ports.
+	 */
+	fibril_rwlock_t	lock;
+};
+
+#endif
+
+/** @}
+ */
+
Index: uspace/srv/net/tl/tcp/tcp_header.h
===================================================================
--- uspace/srv/net/tl/tcp/tcp_header.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/tl/tcp/tcp_header.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,226 @@
+/*
+ * 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 tcp
+ *  @{
+ */
+
+/** @file
+ *  TCP header definition.
+ *  Based on the RFC~793.
+ */
+
+#ifndef __NET_TCP_HEADER_H__
+#define __NET_TCP_HEADER_H__
+
+#include <sys/types.h>
+
+/** TCP header size in bytes.
+ */
+#define TCP_HEADER_SIZE			sizeof( tcp_header_t )
+
+/** Returns the actual TCP header length in bytes.
+ *  @param[in] header The TCP packet header.
+ */
+#define TCP_HEADER_LENGTH( header )		(( header )->header_length * 4u )
+
+/** Returns the TCP header length.
+ *  @param[in] length The TCP header length in bytes.
+ */
+#define TCP_COMPUTE_HEADER_LENGTH( length )		(( uint8_t ) (( length ) / 4u ))
+
+/** Type definition of the transmission datagram header.
+ *  @see tcp_header
+ */
+typedef struct tcp_header	tcp_header_t;
+
+/** Type definition of the transmission datagram header pointer.
+ *  @see tcp_header
+ */
+typedef tcp_header_t *		tcp_header_ref;
+
+/** Type definition of the transmission datagram header option.
+ *  @see tcp_option
+ */
+typedef struct tcp_option	tcp_option_t;
+
+/** Type definition of the transmission datagram header option pointer.
+ *  @see tcp_option
+ */
+typedef tcp_option_t *		tcp_option_ref;
+
+/** Type definition of the Maximum segment size TCP option.
+ *  @see ...
+ */
+typedef struct tcp_max_segment_size_option	tcp_max_segment_size_option_t;
+
+/** Type definition of the Maximum segment size TCP option pointer.
+ *  @see tcp_max_segment_size_option
+ */
+typedef tcp_max_segment_size_option_t *		tcp_max_segment_size_option_ref;
+
+/** Transmission datagram header.
+ */
+struct tcp_header{
+	/** The source port number.
+	 */
+	uint16_t	source_port;
+	/** The destination port number.
+	 */
+	uint16_t	destination_port;
+	/** The sequence number of the first data octet in this segment (except when SYN is present).
+	 *  If SYN is present the sequence number is the initial sequence number (ISN) and the first data octet is ISN+1.
+	 */
+	uint32_t	sequence_number;
+	/** If the ACK control bit is set this field contains the value of the next sequence number the sender of the segment is expecting to receive.
+	 *  Once a~connection is established this is always sent.
+	 *  @see acknowledge
+	 */
+	uint32_t	acknowledgement_number;
+#ifdef ARCH_IS_BIG_ENDIAN
+	/** The number of 32~bit words in the TCP Header.
+	 *  This indicates where the data begins.
+	 *  The TCP header (even one including options) is an integral number of 32~bits long.
+	 */
+	uint8_t	header_length:4;
+	/** Four bits reserved for future use.
+	 *  Must be zero.
+	 */
+	uint8_t	reserved1:4;
+#else
+	/** Four bits reserved for future use.
+	 *  Must be zero.
+	 */
+	uint8_t	reserved1:4;
+	/** The number of 32~bit words in the TCP Header.
+	 *  This indicates where the data begins.
+	 *  The TCP header (even one including options) is an integral number of 32~bits long.
+	 */
+	uint8_t	header_length:4;
+#endif
+#ifdef ARCH_IS_BIG_ENDIAN
+	/** Two bits reserved for future use.
+	 *  Must be zero.
+	 */
+	uint8_t	reserved2:2;
+	/** Urgent Pointer field significant.
+	 *  @see tcp_header:urgent_pointer
+	 */
+	uint8_t	urgent:1;
+	/** Acknowledgment field significant
+	 *  @see tcp_header:acknowledgement_number
+	 */
+	uint8_t	acknowledge:1;
+	/** Push function.
+	 */
+	uint8_t	push:1;
+	/** Reset the connection.
+	 */
+	uint8_t	reset:1;
+	/** Synchronize the sequence numbers.
+	 */
+	uint8_t	synchronize:1;
+	/** No more data from the sender.
+	 */
+	uint8_t	finalize:1;
+#else
+	/** No more data from the sender.
+	 */
+	uint8_t	finalize:1;
+	/** Synchronize the sequence numbers.
+	 */
+	uint8_t	synchronize:1;
+	/** Reset the connection.
+	 */
+	uint8_t	reset:1;
+	/** Push function.
+	 */
+	uint8_t	push:1;
+	/** Acknowledgment field significant.
+	 *  @see tcp_header:acknowledgement_number
+	 */
+	uint8_t	acknowledge:1;
+	/** Urgent Pointer field significant.
+	 *  @see tcp_header:urgent_pointer
+	 */
+	uint8_t	urgent:1;
+	/** Two bits reserved for future use.
+	 *  Must be zero.
+	 */
+	uint8_t	reserved2:2;
+#endif
+	/** The number of data octets beginning with the one indicated in the acknowledgment field which the sender of this segment is willing to accept.
+	 *  @see tcp_header:acknowledge
+	 */
+	uint16_t	window;
+	/** The checksum field is the 16~bit one's complement of the one's complement sum of all 16~bit words in the header and text.
+	 *  If a~segment contains an odd number of header and text octets to be checksummed, the last octet is padded on the right with zeros to form a~16~bit word for checksum purposes.
+	 *  The pad is not transmitted as part of the segment.
+	 *  While computing the checksum, the checksum field itself is replaced with zeros.
+	 *  The checksum also coves a~pseudo header conceptually.
+	 *  The pseudo header conceptually prefixed to the TCP header contains the source address, the destination address, the protocol, and the TCP length.
+	 *  This information gives protection against misrouted datagrams.
+	 *  If the computed checksum is zero, it is transmitted as all ones (the equivalent in one's complement arithmetic).
+	 */
+	uint16_t	checksum;
+	/** This field communicates the current value of the urgent pointer as a~positive offset from the sequence number in this segment.
+	 *  The urgent pointer points to the sequence number of the octet following the urgent data.
+	 *  This field is only be interpreted in segments with the URG control bit set.
+	 *  @see tcp_header:urgent
+	 */
+	uint16_t	urgent_pointer;
+} __attribute__ ((packed));
+
+/** Transmission datagram header option.
+ */
+struct tcp_option{
+	/** Option type.
+	 */
+	uint8_t		type;
+	/** Option length.
+	 */
+	uint8_t		length;
+};
+
+/** Maximum segment size TCP option.
+ */
+struct tcp_max_segment_size_option{
+	/** TCP option.
+	 *  @see TCPOPT_MAX_SEGMENT_SIZE
+	 *  @see TCPOPT_MAX_SEGMENT_SIZE_LENGTH
+	 */
+	tcp_option_t	option;
+	/** Maximum segment size in bytes.
+	 */
+	uint16_t		max_segment_size;
+} __attribute__ ((packed));
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/tl/tcp/tcp_module.c
===================================================================
--- uspace/srv/net/tl/tcp/tcp_module.c	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/tl/tcp/tcp_module.c	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,119 @@
+/*
+ * 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 tcp
+ *  @{
+ */
+
+/** @file
+ *  TCP standalone module implementation.
+ *  Contains skeleton module functions mapping.
+ *  The functions are used by the module skeleton as module specific entry points.
+ *  @see module.c
+ */
+
+#include <async.h>
+#include <stdio.h>
+
+#include <ipc/ipc.h>
+#include <ipc/services.h>
+
+#include "../../err.h"
+#include "../../modules.h"
+
+#include "../../structures/packet/packet.h"
+
+#include "../../include/net_interface.h"
+#include "../../include/ip_protocols.h"
+#include "../../include/ip_interface.h"
+
+#include "tcp.h"
+#include "tcp_module.h"
+
+/** TCP module name.
+ */
+#define NAME	"TCP protocol"
+
+/** Prints the module name.
+ *  @see NAME
+ */
+void	module_print_name( void );
+
+/** Starts the TCP module.
+ *  Initializes the client connection serving function, initializes the module, registers the module service and starts the async manager, processing IPC messages in an infinite loop.
+ *  @param[in] client_connection The client connection processing function. The module skeleton propagates its own one.
+ *  @returns EOK on successful module termination.
+ *  @returns Other error codes as defined for the tcp_initialize() function.
+ *  @returns Other error codes as defined for the REGISTER_ME() macro function.
+ */
+int	module_start( async_client_conn_t client_connection );
+
+/** Processes the TCP 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.
+ *  @returns EOK on success.
+ *  @returns Other error codes as defined for the tcp_message() function.
+ */
+int	module_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count );
+
+/** TCP module global data.
+ */
+extern tcp_globals_t	tcp_globals;
+
+void module_print_name( void ){
+	printf( "%s", NAME );
+}
+
+int module_start( async_client_conn_t client_connection ){
+	ERROR_DECLARE;
+
+	ipcarg_t	phonehash;
+
+	async_set_client_connection( client_connection );
+	tcp_globals.net_phone = net_connect_module( SERVICE_NETWORKING );
+	ERROR_PROPAGATE( pm_init());
+	if( ERROR_OCCURRED( tcp_initialize( client_connection ))
+	|| ERROR_OCCURRED( REGISTER_ME( SERVICE_TCP, & phonehash ))){
+		pm_destroy();
+		return ERROR_CODE;
+	}
+
+	async_manager();
+
+	pm_destroy();
+	return EOK;
+}
+
+int	module_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){
+	return tcp_message( callid, call, answer, answer_count );
+}
+
+/** @}
+ */
Index: uspace/srv/net/tl/tcp/tcp_module.h
===================================================================
--- uspace/srv/net/tl/tcp/tcp_module.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/tl/tcp/tcp_module.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,66 @@
+/*
+ * 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 tcp
+ *  @{
+ */
+
+/** @file
+ *  TCP module functions.
+ *  The functions are used as TCP module entry points.
+ */
+
+#ifndef __NET_TCP_MODULE_H__
+#define __NET_TCP_MODULE_H__
+
+#include <async.h>
+#include <ipc/ipc.h>
+
+/** Initializes the TCP module.
+ *  @param[in] client_connection The client connection processing function. The module skeleton propagates its own one.
+ *  @returns EOK on success.
+ *  @returns ENOMEM if there is not enough memory left.
+ */
+int	tcp_initialize( async_client_conn_t client_connection );
+
+/** Processes the TCP 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.
+ *  @returns EOK on success.
+ *  @returns ENOTSUP if the message is not known.
+ *  @see tcp_interface.h
+ *  @see IS_NET_TCP_MESSAGE()
+ */
+int	tcp_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count );
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/tl/tl_common.c
===================================================================
--- uspace/srv/net/tl/tl_common.c	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/tl/tl_common.c	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,200 @@
+/*
+ * 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 net_tl
+ *  @{
+ */
+
+/** @file
+ *  Transport layer common functions implementation.
+ *  @see tl_common.h
+ */
+
+#include <async.h>
+#include <ipc/services.h>
+
+#include "../err.h"
+
+#include "../structures/packet/packet.h"
+#include "../structures/packet/packet_client.h"
+
+#include "../include/device.h"
+#include "../include/icmp_interface.h"
+#include "../include/in.h"
+#include "../include/in6.h"
+#include "../include/inet.h"
+#include "../include/ip_interface.h"
+#include "../include/socket_codes.h"
+#include "../include/socket_errno.h"
+
+#include "tl_common.h"
+
+DEVICE_MAP_IMPLEMENT( packet_dimensions, packet_dimension_t );
+
+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;
+}
+
+int tl_get_ip_packet_dimension( int ip_phone, packet_dimensions_ref packet_dimensions, device_id_t device_id, packet_dimension_ref * packet_dimension ){
+	ERROR_DECLARE;
+
+	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;
+		if( ERROR_OCCURRED( ip_packet_size_req( ip_phone, device_id, & ( ** packet_dimension ).addr_len, & ( ** packet_dimension ).prefix, & ( ** packet_dimension ).content, & ( ** packet_dimension ).suffix ))){
+			free( * packet_dimension );
+			return ERROR_CODE;
+		}
+		ERROR_CODE = packet_dimensions_add( packet_dimensions, device_id, * packet_dimension );
+		if( ERROR_CODE < 0 ){
+			free( * packet_dimension );
+			return ERROR_CODE;
+		}
+	}
+	return EOK;
+}
+
+int tl_update_ip_packet_dimension( packet_dimensions_ref packet_dimensions, device_id_t device_id, size_t content ){
+	packet_dimension_ref	packet_dimension;
+
+	packet_dimension = packet_dimensions_find( packet_dimensions, device_id );
+	if( ! packet_dimension ) return ENOENT;
+	packet_dimension->content = content;
+	if( device_id != DEVICE_INVALID_ID ){
+		packet_dimension = packet_dimensions_find( packet_dimensions, DEVICE_INVALID_ID );
+		if( packet_dimension ){
+			if( packet_dimension->content >= content ){
+				packet_dimension->content = content;
+			}else{
+				packet_dimensions_exclude( packet_dimensions, DEVICE_INVALID_ID );
+			}
+		}
+	}
+	return EOK;
+}
+
+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;
+	}
+}
+
+int tl_prepare_icmp_packet( int packet_phone, int icmp_phone, packet_t packet, services_t error ){
+	packet_t	next;
+	uint8_t *	src;
+	int			length;
+
+	// detach the first packet and release the others
+	next = pq_detach( packet );
+	if( next ){
+		pq_release( packet_phone, packet_get_id( next ));
+	}
+	length = packet_get_addr( packet, & src, NULL );
+	if(( length > 0 )
+	&& ( ! error )
+	&& ( icmp_phone >= 0 )
+	// 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( packet_phone, packet_get_id( packet ));
+	}
+	return ENOENT;
+}
+
+int tl_socket_read_packet_data( int packet_phone, packet_ref packet, size_t prefix, const packet_dimension_ref dimension, const struct sockaddr * addr, socklen_t addrlen ){
+	ERROR_DECLARE;
+
+	ipc_callid_t	callid;
+	size_t			length;
+	void *			data;
+
+	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( packet_phone, 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( packet_phone, packet_get_id( * packet ));
+		return ENOMEM;
+	}
+	// read the data into the packet
+	if( ERROR_OCCURRED( async_data_write_finalize( callid, data, length ))
+	// set the packet destination address
+	|| ERROR_OCCURRED( packet_set_addr( * packet, NULL, ( uint8_t * ) addr, addrlen ))){
+		pq_release( packet_phone, packet_get_id( * packet ));
+		return ERROR_CODE;
+	}
+	return ( int ) length;
+}
+
+/** @}
+ */
Index: uspace/srv/net/tl/tl_common.h
===================================================================
--- uspace/srv/net/tl/tl_common.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/tl/tl_common.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,155 @@
+/*
+ * 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 net_tl
+ *  @{
+ */
+
+/** @file
+ *  Transport layer common functions.
+ */
+
+#ifndef __NET_TL_COMMON_H__
+#define __NET_TL_COMMON_H__
+
+#include "../structures/packet/packet.h"
+
+#include "../include/device.h"
+#include "../include/inet.h"
+#include "../include/socket_codes.h"
+
+/** Type definition of the packet dimension.
+ *  @see packet_dimension
+ */
+typedef struct packet_dimension	packet_dimension_t;
+
+/** Type definition of the packet dimension pointer.
+ *  @see packet_dimension
+ */
+typedef packet_dimension_t *	packet_dimension_ref;
+
+/** 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;
+};
+
+/** Device packet dimensions.
+ *  Maps devices to the packet dimensions.
+ *  @see device.h
+ */
+DEVICE_MAP_DECLARE( 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.
+ *  @returns EOK on success.
+ *  @returns EINVAL if the address length does not match the address family.
+ *  @returns EAFNOSUPPORT if the address family is not supported.
+ */
+int	tl_get_address_port( const struct sockaddr * addr, int addrlen, uint16_t * port );
+
+/** Gets IP packet dimensions.
+ *  Tries to search a cache and queries the IP module if not found.
+ *  The reply is cached then.
+ *  @param[in] ip_phone The IP moduel phone for (semi)remote calls.
+ *  @param[in] packet_dimensions The packet dimensions cache.
+ *  @param[in] device_id The device identifier.
+ *  @param[out] packet_dimension The IP packet dimensions.
+ *  @returns EOK on success.
+ *  @returns EBADMEM if the packet_dimension parameter is NULL.
+ *  @return ENOMEM if there is not enough memory left.
+ *  @returns EINVAL if the packet_dimensions cache is not valid.
+ *  @returns Other codes as defined for the ip_packet_size_req() function.
+ */
+int	tl_get_ip_packet_dimension( int ip_phone, packet_dimensions_ref packet_dimensions, device_id_t device_id, packet_dimension_ref * packet_dimension );
+
+/** 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.
+ *  @returns EOK on success.
+ *  @returns ENOENT if the packet dimension is not cached.
+ */
+int	tl_update_ip_packet_dimension( packet_dimensions_ref packet_dimensions, device_id_t device_id, size_t content );
+
+/** 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.
+ *  @returns EOK on success.
+ *  @returns EINVAL if the address length does not match the address family.
+ *  @returns EAFNOSUPPORT if the address family is not supported.
+ */
+int	tl_set_address_port( struct sockaddr * addr, int addrlen, uint16_t port );
+
+/** Prepares the packet for ICMP error notification.
+ *  Keeps the first packet and releases all the others.
+ *  Releases all the packets on error.
+ *  @param[in] packet_phone The packet server module phone.
+ *  @param[in] icmp_phone The ICMP module phone.
+ *  @param[in] packet The packet to be send.
+ *  @param[in] error The packet error reporting service. Prefixes the received packet.
+ *  @returns EOK on success.
+ *  @returns ENOENT if no packet may be sent.
+ */
+int	tl_prepare_icmp_packet( int packet_phone, int icmp_phone, packet_t packet, services_t error );
+
+/** Receives data from the socket into a packet.
+ *  @param[in] packet_phone The packet server module phone.
+ *  @param[out] packet The new created packet.
+ *  @param[in] prefix Reserved packet data prefix length.
+ *  @param[in] dimension The packet dimension.
+ *  @param[in] addr The destination address.
+ *  @param[in] addrlen The address length.
+ *  @returns Number of bytes received.
+ *  @returns EINVAL if the client does not send data.
+ *  @returns ENOMEM if there is not enough memory left.
+ *  @returns Other error codes as defined for the async_data_read_finalize() function.
+ */
+int	tl_socket_read_packet_data( int packet_phone, packet_ref packet, size_t prefix, const packet_dimension_ref dimension, const struct sockaddr * addr, socklen_t addrlen );
+
+#endif
+
+/** @}
+ */
+
Index: uspace/srv/net/tl/tl_messages.h
===================================================================
--- uspace/srv/net/tl/tl_messages.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/tl/tl_messages.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup net_tl
+ *  @{
+ */
+
+/** @file
+ *  Transport layer modules messages.
+ *  @see tl_interface.h
+ */
+
+#ifndef __NET_TL_MESSAGES_H__
+#define __NET_TL_MESSAGES_H__
+
+#include <ipc/ipc.h>
+
+#include "../messages.h"
+
+/** Transport layer modules messages.
+ */
+typedef enum{
+	/** Packet received message.
+	 *  @see tl_received_msg()
+	 */
+	NET_TL_RECEIVED = NET_TL_FIRST
+} tl_messages;
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/tl/udp/Makefile
===================================================================
--- uspace/srv/net/tl/udp/Makefile	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/tl/udp/Makefile	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,59 @@
+#
+# 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.
+#
+
+NAME = udp
+
+NET_BASE = ../../
+STRUCTURES = $(NET_BASE)structures/
+
+## Sources
+#
+
+OUTPUT = $(NAME)
+SOURCES = \
+	$(NAME).c \
+	$(NAME)_module.c \
+	$(NET_BASE)checksum.c \
+	$(NET_BASE)module.c \
+	$(NET_BASE)modules.c \
+	$(NET_BASE)il/ip/ip_client.c \
+	$(NET_BASE)il/ip/ip_remote.c \
+	$(NET_BASE)net/net_remote.c \
+	$(NET_BASE)socket/socket_core.c \
+	$(NET_BASE)tl/icmp/icmp_client.c \
+	$(NET_BASE)tl/icmp/icmp_common.c \
+	$(NET_BASE)tl/icmp/icmp_remote.c \
+	$(NET_BASE)tl/tl_common.c \
+	$(STRUCTURES)char_map.c \
+	$(STRUCTURES)dynamic_fifo.c \
+	$(STRUCTURES)measured_strings.c \
+	$(STRUCTURES)packet/packet.c \
+	$(STRUCTURES)packet/packet_client.c \
+	$(STRUCTURES)packet/packet_remote.c
+
+include $(NET_BASE)Makefile.module
Index: uspace/srv/net/tl/udp/udp.c
===================================================================
--- uspace/srv/net/tl/udp/udp.c	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/tl/udp/udp.c	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,698 @@
+/*
+ * 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/ipc.h>
+#include <ipc/services.h>
+
+#include "../../err.h"
+#include "../../messages.h"
+#include "../../modules.h"
+
+#include "../../structures/dynamic_fifo.h"
+#include "../../structures/packet/packet_client.h"
+
+#include "../../include/checksum.h"
+#include "../../include/in.h"
+#include "../../include/in6.h"
+#include "../../include/inet.h"
+#include "../../include/ip_client.h"
+#include "../../include/ip_interface.h"
+#include "../../include/ip_protocols.h"
+#include "../../include/icmp_client.h"
+#include "../../include/icmp_interface.h"
+#include "../../include/net_interface.h"
+#include "../../include/socket_codes.h"
+#include "../../include/socket_errno.h"
+
+#include "../../socket/socket_core.h"
+#include "../../socket/socket_messages.h"
+
+#include "../tl_common.h"
+#include "../tl_messages.h"
+
+#include "udp.h"
+#include "udp_header.h"
+#include "udp_module.h"
+
+/** 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
+
+/** 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.
+ *  @returns EOK on success.
+ *  @returns Other error codes as defined for the udp_process_packet() function.
+ */
+int	udp_received_msg( device_id_t device_id, packet_t packet, services_t receiver, services_t error );
+
+/** 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.
+ *  @returns EOK on success.
+ *  @returns EINVAL if the packet is not valid.
+ *  @returns EINVAL if the stored packet address is not the an_addr_t.
+ *  @returns EINVAL if the packet does not contain any data.
+ *  @returns NO_DATA if the packet content is shorter than the user datagram header.
+ *  @returns ENOMEM if there is not enough memory left.
+ *  @returns EADDRNOTAVAIL if the destination socket does not exist.
+ *  @returns Other error codes as defined for the ip_client_process_packet() function.
+ */
+int udp_process_packet( device_id_t device_id, packet_t packet, services_t error );
+
+/** 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.
+ */
+int	udp_release_and_return( packet_t packet, int result );
+
+/** @name Socket messages processing functions
+ */
+/*@{*/
+
+/** Processes the socket client messages.
+ *  Runs until the client module disconnects.
+ *  @param[in] callid The message identifier.
+ *  @param[in] call The message parameters.
+ *  @returns EOK on success.
+ *  @see socket.h
+ */
+int udp_process_client_messages( ipc_callid_t callid, ipc_call_t call );
+
+/** 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.
+ *  @returns EOK on success.
+ *  @returns EAFNOTSUPPORT if the address family is not supported.
+ *  @returns ENOTSOCK if the socket is not found.
+ *  @returns EINVAL if the address is invalid.
+ *  @returns ENOTCONN if the sending socket is not and cannot be bound.
+ *  @returns ENOMEM if there is not enough memory left.
+ *  @returns Other error codes as defined for the socket_read_packet_data() function.
+ *  @returns Other error codes as defined for the ip_client_prepare_packet() function.
+ *  @returns Other error codes as defined for the ip_send_msg() function.
+ */
+int udp_sendto_message( socket_cores_ref local_sockets, int socket_id, const struct sockaddr * addr, socklen_t addrlen, int fragments, size_t * data_fragment_size, int flags );
+
+/** 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.
+ *  @returns The number of bytes received.
+ *  @returns ENOTSOCK if the socket is not found.
+ *  @returns NO_DATA if there are no received packets or data.
+ *  @returns ENOMEM if there is not enough memory left.
+ *  @returns EINVAL if the received address is not an IP address.
+ *  @returns Other error codes as defined for the packet_translate() function.
+ *  @returns Other error codes as defined for the data_reply() function.
+ */
+int	udp_recvfrom_message( socket_cores_ref local_sockets, int socket_id, int flags, size_t * addrlen );
+
+/*@}*/
+
+/** UDP global data.
+ */
+udp_globals_t	udp_globals;
+
+int udp_initialize( async_client_conn_t client_connection ){
+	ERROR_DECLARE;
+
+	measured_string_t	names[] = {{ "UDP_CHECKSUM_COMPUTING", 22 }, { "UDP_AUTOBINDING", 15 }};
+	measured_string_ref	configuration;
+	size_t				count = sizeof( names ) / sizeof( measured_string_t );
+	char *				data;
+
+	fibril_rwlock_initialize( & udp_globals.lock );
+	fibril_rwlock_write_lock( & udp_globals.lock );
+	udp_globals.icmp_phone = icmp_connect_module( SERVICE_ICMP, ICMP_CONNECT_TIMEOUT );
+	udp_globals.ip_phone = ip_bind_service( SERVICE_IP, IPPROTO_UDP, SERVICE_UDP, client_connection, udp_received_msg );
+	if( udp_globals.ip_phone < 0 ){
+		return udp_globals.ip_phone;
+	}
+	// read default packet dimensions
+	ERROR_PROPAGATE( ip_packet_size_req( udp_globals.ip_phone, -1, & udp_globals.packet_dimension.addr_len, & udp_globals.packet_dimension.prefix, & udp_globals.packet_dimension.content, & udp_globals.packet_dimension.suffix ));
+	ERROR_PROPAGATE( socket_ports_initialize( & udp_globals.sockets ));
+	if( ERROR_OCCURRED( packet_dimensions_initialize( & udp_globals.dimensions ))){
+		socket_ports_destroy( & udp_globals.sockets );
+		return ERROR_CODE;
+	}
+	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;
+	// get configuration
+	udp_globals.checksum_computing = NET_DEFAULT_UDP_CHECKSUM_COMPUTING;
+	udp_globals.autobinding = NET_DEFAULT_UDP_AUTOBINDING;
+	configuration = & names[ 0 ];
+	ERROR_PROPAGATE( net_get_conf_req( udp_globals.net_phone, & configuration, count, & data ));
+	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;
+}
+
+int	udp_received_msg( 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;
+}
+
+int udp_process_packet( device_id_t device_id, packet_t packet, services_t error ){
+	ERROR_DECLARE;
+
+	size_t			length;
+	size_t			offset;
+	int				result;
+	udp_header_ref	header;
+	socket_core_ref	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;
+	ip_pseudo_header_ref	ip_header;
+	struct sockaddr *		src;
+	struct sockaddr *		dest;
+	packet_dimension_ref	packet_dimension;
+
+	if( error ){
+		switch( error ){
+			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;
+				if( ERROR_OCCURRED( packet_trim( packet, length, 0 ))){
+					return udp_release_and_return( packet, ERROR_CODE );
+				}
+				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
+	if( ERROR_OCCURRED( packet_trim( packet, offset, 0 ))){
+		return udp_release_and_return( packet, ERROR_CODE );
+	}
+
+	// get udp header
+	header = ( udp_header_ref ) 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 ), SOCKET_MAP_KEY_LISTENING, 0 );
+	if( ! socket ){
+		if( tl_prepare_icmp_packet( udp_globals.net_phone, udp_globals.icmp_phone, packet, error ) == EOK ){
+			icmp_destination_unreachable_msg( udp_globals.icmp_phone, 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 );
+		}
+		if( ERROR_OCCURRED( ip_client_get_pseudo_header( IPPROTO_UDP, src, result, dest, result, total_length, & ip_header, & length ))){
+			return udp_release_and_return( packet, ERROR_CODE );
+		}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 ){
+			if( ERROR_OCCURRED( packet_trim( next_packet, 0, length - total_length ))){
+				return udp_release_and_return( packet, ERROR_CODE );
+			}
+			// 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( udp_globals.net_phone, 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 ));
+
+	// check checksum
+	if( header->checksum ){
+		if( flip_checksum( compact_checksum( checksum )) != IP_CHECKSUM_ZERO ){
+			if( tl_prepare_icmp_packet( udp_globals.net_phone, udp_globals.icmp_phone, packet, error ) == EOK ){
+				// checksum error ICMP
+				icmp_parameter_problem_msg( udp_globals.icmp_phone, ICMP_PARAM_POINTER, (( size_t ) (( void * ) & header->checksum )) - (( size_t ) (( void * ) header )), packet );
+			}
+			return EINVAL;
+		}
+	}
+
+	// queue the received packet
+	if( ERROR_OCCURRED( dyn_fifo_push( & socket->received, packet_get_id( packet ), SOCKET_MAX_RECEIVED_SIZE ))
+	|| ERROR_OCCURRED( tl_get_ip_packet_dimension( udp_globals.ip_phone, & udp_globals.dimensions, device_id, & packet_dimension ))){
+		return udp_release_and_return( packet, ERROR_CODE );
+	}
+
+	// notify the destination socket
+	fibril_rwlock_write_unlock( & udp_globals.lock );
+	async_msg_5( socket->phone, NET_SOCKET_RECEIVED, ( ipcarg_t ) socket->socket_id, packet_dimension->content, 0, 0, ( ipcarg_t ) fragments );
+/*	fibril_rwlock_write_unlock( & udp_globals.lock );
+	async_msg_5( socket->phone, NET_SOCKET_RECEIVED, ( ipcarg_t ) socket->socket_id, 0, 0, 0, ( ipcarg_t ) fragments );
+*/	return EOK;
+}
+
+int udp_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){
+	ERROR_DECLARE;
+
+	packet_t	packet;
+
+	* answer_count = 0;
+	switch( IPC_GET_METHOD( * call )){
+		case NET_TL_RECEIVED:
+			if( ! ERROR_OCCURRED( packet_translate( udp_globals.net_phone, & packet, IPC_GET_PACKET( call )))){
+				ERROR_CODE = udp_received_msg( IPC_GET_DEVICE( call ), packet, SERVICE_UDP, IPC_GET_ERROR( call ));
+			}
+			return ERROR_CODE;
+		case IPC_M_CONNECT_TO_ME:
+			return udp_process_client_messages( callid, * call );
+	}
+	return ENOTSUP;
+}
+
+int udp_process_client_messages( ipc_callid_t callid, ipc_call_t call ){
+	int						res;
+	bool					keep_on_going = true;
+	socket_cores_t			local_sockets;
+	int						app_phone = IPC_GET_PHONE( & call );
+	struct sockaddr *		addr;
+	size_t					addrlen;
+	fibril_rwlock_t			lock;
+	ipc_call_t				answer;
+	int						answer_count;
+	packet_dimension_ref	packet_dimension;
+
+	/*
+	 * Accept the connection
+	 *  - Answer the first IPC_M_CONNECT_TO_ME call.
+	 */
+	ipc_answer_0( callid, EOK );
+
+	// The client connection is only in one fibril and therefore no additional locks are needed.
+
+	socket_cores_initialize( & local_sockets );
+	fibril_rwlock_initialize( & lock );
+
+	while( keep_on_going ){
+		// refresh data
+		refresh_answer( & answer, & answer_count );
+
+		callid = async_get_call( & call );
+//		printf( "message %d\n", IPC_GET_METHOD( * call ));
+
+		switch( IPC_GET_METHOD( call )){
+			case IPC_M_PHONE_HUNGUP:
+				keep_on_going = false;
+				res = EOK;
+				break;
+			case NET_SOCKET:
+				fibril_rwlock_write_lock( & lock );
+				* SOCKET_SET_SOCKET_ID( answer ) = SOCKET_GET_SOCKET_ID( call );
+				res = socket_create( & local_sockets, app_phone, NULL, SOCKET_SET_SOCKET_ID( answer ));
+				fibril_rwlock_write_unlock( & lock );
+				if( res == EOK ){
+					if( tl_get_ip_packet_dimension( udp_globals.ip_phone, & udp_globals.dimensions, DEVICE_INVALID_ID, & packet_dimension ) == EOK ){
+						* SOCKET_SET_DATA_FRAGMENT_SIZE( answer ) = packet_dimension->content;
+					}
+//					* SOCKET_SET_DATA_FRAGMENT_SIZE( answer ) = MAX_UDP_FRAGMENT_SIZE;
+					* SOCKET_SET_HEADER_SIZE( answer ) = UDP_HEADER_SIZE;
+					answer_count = 3;
+				}
+				break;
+			case NET_SOCKET_BIND:
+				res = data_receive(( void ** ) & addr, & addrlen );
+				if( res == EOK ){
+					fibril_rwlock_read_lock( & lock );
+					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 );
+					fibril_rwlock_read_unlock( & lock );
+					free( addr );
+				}
+				break;
+			case NET_SOCKET_SENDTO:
+				res = data_receive(( void ** ) & addr, & addrlen );
+				if( res == EOK ){
+					fibril_rwlock_read_lock( & lock );
+					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 ), SOCKET_SET_DATA_FRAGMENT_SIZE( answer ), SOCKET_GET_FLAGS( call ));
+					if( res != EOK ){
+						fibril_rwlock_write_unlock( & udp_globals.lock );
+					}else{
+						answer_count = 2;
+					}
+					fibril_rwlock_read_unlock( & lock );
+					free( addr );
+				}
+				break;
+			case NET_SOCKET_RECVFROM:
+				fibril_rwlock_read_lock( & lock );
+				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 );
+				fibril_rwlock_read_unlock( & lock );
+				if( res > 0 ){
+					* 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( & lock );
+				fibril_rwlock_write_lock( & udp_globals.lock );
+				res = socket_destroy( udp_globals.net_phone, SOCKET_GET_SOCKET_ID( call ), & local_sockets, & udp_globals.sockets, NULL );
+				fibril_rwlock_write_unlock( & udp_globals.lock );
+				fibril_rwlock_write_unlock( & lock );
+				break;
+			case NET_SOCKET_GETSOCKOPT:
+			case NET_SOCKET_SETSOCKOPT:
+			default:
+				res = ENOTSUP;
+				break;
+		}
+
+//		printf( "res = %d\n", res );
+
+		answer_call( callid, res, & answer, answer_count );
+	}
+
+	// release all local sockets
+	socket_cores_release( udp_globals.net_phone, & local_sockets, & udp_globals.sockets, NULL );
+
+	return EOK;
+}
+
+int udp_sendto_message( socket_cores_ref local_sockets, int socket_id, const struct sockaddr * addr, socklen_t addrlen, int fragments, size_t * data_fragment_size, int flags ){
+	ERROR_DECLARE;
+
+	socket_core_ref			socket;
+	packet_t				packet;
+	packet_t				next_packet;
+	udp_header_ref			header;
+	int						index;
+	size_t					total_length;
+	int						result;
+	uint16_t				dest_port;
+	uint32_t				checksum;
+	ip_pseudo_header_ref	ip_header;
+	size_t					headerlen;
+	device_id_t				device_id;
+	packet_dimension_ref	packet_dimension;
+
+	ERROR_PROPAGATE( tl_get_address_port( addr, addrlen, & dest_port ));
+
+	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
+//		do{
+			// try to find a free port
+//			fibril_rwlock_read_unlock( & udp_globals.lock );
+//			fibril_rwlock_write_lock( & udp_globals.lock );
+			// might be changed in the meantime
+//			if( socket->port <= 0 ){
+				if( ERROR_OCCURRED( socket_bind_free_port( & udp_globals.sockets, socket, UDP_FREE_PORTS_START, UDP_FREE_PORTS_END, udp_globals.last_used_port ))){
+//					fibril_rwlock_write_unlock( & udp_globals.lock );
+//					fibril_rwlock_read_lock( & udp_globals.lock );
+					return ERROR_CODE;
+				}
+				// set the next port as the search starting port number
+				udp_globals.last_used_port = socket->port;
+//			}
+//			fibril_rwlock_write_unlock( & udp_globals.lock );
+//			fibril_rwlock_read_lock( & udp_globals.lock );
+			// might be changed in the meantime
+//		}while( socket->port <= 0 );
+	}
+
+	if( udp_globals.checksum_computing ){
+		if( ERROR_OCCURRED( ip_get_route_req( udp_globals.ip_phone, IPPROTO_UDP, addr, addrlen, & device_id, & ip_header, & headerlen ))){
+			return udp_release_and_return( packet, ERROR_CODE );
+		}
+		// get the device packet dimension
+//		ERROR_PROPAGATE( tl_get_ip_packet_dimension( udp_globals.ip_phone, & udp_globals.dimensions, device_id, & packet_dimension ));
+	}
+//	}else{
+		// do not ask all the time
+		ERROR_PROPAGATE( ip_packet_size_req( udp_globals.ip_phone, -1, & udp_globals.packet_dimension.addr_len, & udp_globals.packet_dimension.prefix, & udp_globals.packet_dimension.content, & udp_globals.packet_dimension.suffix ));
+		packet_dimension = & udp_globals.packet_dimension;
+//	}
+
+	// read the first packet fragment
+	result = tl_socket_read_packet_data( udp_globals.net_phone, & 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_phone, & next_packet, 0, packet_dimension, addr, addrlen );
+		if( result < 0 ){
+			return udp_release_and_return( packet, result );
+		}
+		packet = pq_add( packet, next_packet, index, 0 );
+		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 ){
+//		if( ERROR_OCCURRED( ip_get_route_req( udp_globals.ip_phone, IPPROTO_UDP, addr, addrlen, & device_id, & ip_header, & headerlen ))){
+//			return udp_release_and_return( packet, ERROR_CODE );
+//		}
+		if( ERROR_OCCURRED( ip_client_set_pseudo_header_data_length( ip_header, headerlen, total_length + UDP_HEADER_SIZE))){
+			free( ip_header );
+			return udp_release_and_return( packet, ERROR_CODE );
+		}
+		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 = DEVICE_INVALID_ID;
+	}
+	// prepare the first packet fragment
+	if( ERROR_OCCURRED( ip_client_prepare_packet( packet, IPPROTO_UDP, 0, 0, 0, 0 ))){
+		return udp_release_and_return( packet, ERROR_CODE );
+	}
+	// send the packet
+	fibril_rwlock_write_unlock( & udp_globals.lock );
+	ip_send_msg( udp_globals.ip_phone, device_id, packet, SERVICE_UDP, 0 );
+	return EOK;
+}
+
+int udp_recvfrom_message( socket_cores_ref local_sockets, int socket_id, int flags, size_t * addrlen ){
+	ERROR_DECLARE;
+
+	socket_core_ref	socket;
+	int				packet_id;
+	packet_t		packet;
+	udp_header_ref	header;
+	struct sockaddr *	addr;
+	size_t			length;
+	uint8_t *		data;
+	int				result;
+
+	// 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;
+	ERROR_PROPAGATE( packet_translate( udp_globals.net_phone, & packet, packet_id ));
+	// get udp header
+	data = packet_get_data( packet );
+	if( ! data ){
+		pq_release( udp_globals.net_phone, packet_id );
+		return NO_DATA;
+	}
+	header = ( udp_header_ref ) data;
+
+	// set the source address port
+	result = packet_get_addr( packet, ( uint8_t ** ) & addr, NULL );
+	if( ERROR_OCCURRED( tl_set_address_port( addr, result, ntohs( header->source_port )))){
+		pq_release( udp_globals.net_phone, packet_id );
+		return ERROR_CODE;
+	}
+	* addrlen = ( size_t ) result;
+	// send the source address
+	ERROR_PROPAGATE( data_reply( addr, * addrlen ));
+
+	// trim the header
+	ERROR_PROPAGATE( packet_trim( packet, UDP_HEADER_SIZE, 0 ));
+
+	// reply the packets
+	ERROR_PROPAGATE( socket_reply_packets( packet, & length ));
+
+	// release the packet
+	dyn_fifo_pop( & socket->received );
+	pq_release( udp_globals.net_phone, packet_get_id( packet ));
+	// return the total length
+	return ( int ) length;
+}
+
+int	udp_release_and_return( packet_t packet, int result ){
+	pq_release( udp_globals.net_phone, packet_get_id( packet ));
+	return result;
+}
+
+/** @}
+ */
Index: uspace/srv/net/tl/udp/udp.h
===================================================================
--- uspace/srv/net/tl/udp/udp.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/tl/udp/udp.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,90 @@
+/*
+ * 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 <fibril_synch.h>
+
+#include "../../socket/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 phone.
+	 */
+	int				net_phone;
+	/** IP module phone.
+	 */
+	int				ip_phone;
+	/** ICMP module phone.
+	 */
+	int				icmp_phone;
+	/** 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: uspace/srv/net/tl/udp/udp_header.h
===================================================================
--- uspace/srv/net/tl/udp/udp_header.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/tl/udp/udp_header.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,83 @@
+/*
+ * 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;
+
+/** Type definition of the user datagram header pointer.
+ *  @see udp_header
+ */
+typedef udp_header_t *		udp_header_ref;
+
+/** User datagram header.
+ */
+struct udp_header{
+	/** Source Port is an optional field, when meaningful, it indicates the port of the sending process, and may be assumed to be the port to which a reply should be addressed in the absence of any other information.
+	 *  If not used, a value of zero is inserted.
+	 */
+	uint16_t	source_port;
+	/** Destination port has a meaning within the context of a particular internet destination address.
+	 */
+	uint16_t	destination_port;
+	/** Length is the length in octets of this user datagram including this header and the data.
+	 *  This means the minimum value of the length is eight.
+	 */
+	uint16_t	total_length;
+	/** Checksum is the 16-bit one's complement of the one's complement sum of a pseudo header of information from the IP header, the UDP header, and the data, padded with zero octets at the end (if necessary) to make a multiple of two octets.
+	 *  The pseudo header conceptually prefixed to the UDP header contains the source address, the destination address, the protocol, and the UDP length.
+	 *  This information gives protection against misrouted datagrams.
+	 *  If the computed checksum is zero, it is transmitted as all ones (the equivalent in one's complement arithmetic).
+	 *  An all zero transmitted checksum value means that the transmitter generated no checksum (for debugging or for higher level protocols that don't care).
+	 */
+	uint16_t	checksum;
+} __attribute__ ((packed));
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/tl/udp/udp_module.c
===================================================================
--- uspace/srv/net/tl/udp/udp_module.c	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/tl/udp/udp_module.c	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,120 @@
+/*
+ * 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 standalone module implementation.
+ *  Contains skeleton module functions mapping.
+ *  The functions are used by the module skeleton as module specific entry points.
+ *  @see module.c
+ */
+
+#include <async.h>
+#include <stdio.h>
+
+#include <ipc/ipc.h>
+#include <ipc/services.h>
+
+#include "../../err.h"
+#include "../../modules.h"
+
+#include "../../structures/packet/packet.h"
+
+#include "../../include/net_interface.h"
+
+#include "udp.h"
+#include "udp_module.h"
+
+/** UDP module name.
+ */
+#define NAME	"UDP protocol"
+
+/** Prints the module name.
+ *  @see NAME
+ */
+void	module_print_name( void );
+
+/** Starts the UDP module.
+ *  Initializes the client connection serving function, initializes the module, registers the module service and starts the async manager, processing IPC messages in an infinite loop.
+ *  @param[in] client_connection The client connection processing function. The module skeleton propagates its own one.
+ *  @returns EOK on successful module termination.
+ *  @returns Other error codes as defined for the udp_initialize() function.
+ *  @returns Other error codes as defined for the REGISTER_ME() macro function.
+ */
+int	module_start( async_client_conn_t client_connection );
+
+/** 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.
+ *  @returns EOK on success.
+ *  @returns Other error codes as defined for the udp_message() function.
+ */
+int	module_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count );
+
+/** UDP module global data.
+ */
+extern udp_globals_t	udp_globals;
+
+void module_print_name( void ){
+	printf( "%s", NAME );
+}
+
+int module_start( async_client_conn_t client_connection ){
+	ERROR_DECLARE;
+
+	ipcarg_t	phonehash;
+
+	async_set_client_connection( client_connection );
+	udp_globals.net_phone = net_connect_module( SERVICE_NETWORKING );
+	if( udp_globals.net_phone < 0 ){
+		return udp_globals.net_phone;
+	}
+	ERROR_PROPAGATE( pm_init());
+	if( ERROR_OCCURRED( udp_initialize( client_connection ))
+	|| ERROR_OCCURRED( REGISTER_ME( SERVICE_UDP, & phonehash ))){
+		pm_destroy();
+		return ERROR_CODE;
+	}
+
+	async_manager();
+
+	pm_destroy();
+	return EOK;
+}
+
+int	module_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){
+	return udp_message( callid, call, answer, answer_count );
+}
+
+/** @}
+ */
Index: uspace/srv/net/tl/udp/udp_module.h
===================================================================
--- uspace/srv/net/tl/udp/udp_module.h	(revision 209faf93503c78d1423ac244db45224381577454)
+++ uspace/srv/net/tl/udp/udp_module.h	(revision 209faf93503c78d1423ac244db45224381577454)
@@ -0,0 +1,66 @@
+/*
+ * 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 functions.
+ *  The functions are used as UDP module entry points.
+ */
+
+#ifndef __NET_UDP_MODULE_H__
+#define __NET_UDP_MODULE_H__
+
+#include <async.h>
+#include <ipc/ipc.h>
+
+/** Initializes the UDP module.
+ *  @param[in] client_connection The client connection processing function. The module skeleton propagates its own one.
+ *  @returns EOK on success.
+ *  @returns ENOMEM if there is not enough memory left.
+ */
+int	udp_initialize( async_client_conn_t client_connection );
+
+/** 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.
+ *  @returns EOK on success.
+ *  @returns ENOTSUP if the message is not known.
+ *  @see udp_interface.h
+ *  @see IS_NET_UDP_MESSAGE()
+ */
+int	udp_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count );
+
+#endif
+
+/** @}
+ */
