Index: boot/Makefile.common
===================================================================
--- boot/Makefile.common	(revision bf31e3f1ebd6e88e0c8425f109e42ccd92b6c9b3)
+++ boot/Makefile.common	(revision 4d9fe7b307128cbbbd04d982fef935c842053872)
@@ -107,12 +107,4 @@
 	$(USPACE_PATH)/srv/hid/remcons/remcons \
 	$(USPACE_PATH)/srv/taskmon/taskmon \
-	$(USPACE_PATH)/srv/net/nil/eth/eth \
-	$(USPACE_PATH)/srv/net/nil/nildummy/nildummy \
-	$(USPACE_PATH)/srv/net/il/arp/arp \
-	$(USPACE_PATH)/srv/net/il/ip/ip \
-	$(USPACE_PATH)/srv/net/tl/icmp/icmp \
-	$(USPACE_PATH)/srv/net/tl/udp/udp \
-	$(USPACE_PATH)/srv/net/tl/tcp/tcp \
-	$(USPACE_PATH)/srv/net/net/net \
 	$(USPACE_PATH)/srv/devman/devman
 
@@ -202,12 +194,4 @@
 endif
 
-ifneq ($(CONFIG_BAREBONE),y)
-NET_CFG = \
-	$(USPACE_PATH)/srv/net/cfg/general \
-	$(USPACE_PATH)/srv/net/cfg/lo.nic \
-	$(USPACE_PATH)/srv/net/cfg/ne2k.nic \
-	$(USPACE_PATH)/srv/net/cfg/e1k.nic
-endif
-
 COMPONENTS = \
 	$(KERNEL_PATH)/kernel.bin \
Index: uspace/Makefile
===================================================================
--- uspace/Makefile	(revision bf31e3f1ebd6e88e0c8425f109e42ccd92b6c9b3)
+++ uspace/Makefile	(revision 4d9fe7b307128cbbbd04d982fef935c842053872)
@@ -95,12 +95,4 @@
 	srv/hid/remcons \
 	srv/hw/char/s3c24xx_uart \
-	srv/net/il/arp \
-	srv/net/il/ip \
-	srv/net/tl/icmp \
-	srv/net/tl/udp \
-	srv/net/tl/tcp \
-	srv/net/nil/eth \
-	srv/net/nil/nildummy \
-	srv/net/net \
 	drv/infrastructure/root \
 	drv/infrastructure/rootvirt \
Index: pace/srv/net/cfg/e1k.nic
===================================================================
--- uspace/srv/net/cfg/e1k.nic	(revision bf31e3f1ebd6e88e0c8425f109e42ccd92b6c9b3)
+++ 	(revision )
@@ -1,21 +1,0 @@
-# E1000 configuration
-
-NAME=e1k
-
-HWPATH=devices/\hw\pci0\00:03.0\port0
-NIL=eth
-IL=ip
-
-# 8023_2_LSAP, 8023_2_SNAP
-ETH_MODE=DIX
-ETH_DUMMY=no
-
-IP_CONFIG=static
-IP_ADDR=10.0.2.15
-IP_ROUTING=yes
-IP_NETMASK=255.255.255.240
-IP_BROADCAST=10.0.2.255
-IP_GATEWAY=10.0.2.2
-ARP=arp
-
-MTU=1500
Index: pace/srv/net/cfg/general
===================================================================
--- uspace/srv/net/cfg/general	(revision bf31e3f1ebd6e88e0c8425f109e42ccd92b6c9b3)
+++ 	(revision )
@@ -1,12 +1,0 @@
-# general configuration
-
-IPV=4
-IP_ROUTING=no
-
-MTU=1500
-
-ICMP_ERROR_REPORTING=yes
-ICMP_ECHO_REPLYING=yes
-
-UDP_CHECKSUM_COMPUTING=yes
-UDP_AUTOBINDING=yes
Index: pace/srv/net/cfg/lo.nic
===================================================================
--- uspace/srv/net/cfg/lo.nic	(revision bf31e3f1ebd6e88e0c8425f109e42ccd92b6c9b3)
+++ 	(revision )
@@ -1,13 +1,0 @@
-# loopback configuration
-
-NAME=lo
-
-HWPATH=devices/\virt\lo\port0
-NIL=nildummy
-IL=ip
-
-IP_CONFIG=static
-IP_ADDR=127.0.0.1
-IP_NETMASK=255.0.0.0
-
-MTU=15535
Index: pace/srv/net/cfg/ne2k.nic
===================================================================
--- uspace/srv/net/cfg/ne2k.nic	(revision bf31e3f1ebd6e88e0c8425f109e42ccd92b6c9b3)
+++ 	(revision )
@@ -1,21 +1,0 @@
-# NE2000 configuration
-
-NAME=ne2k
-
-HWPATH=devices/\hw\pci0\00:01.0\ne2k\port0
-NIL=eth
-IL=ip
-
-# 8023_2_LSAP, 8023_2_SNAP
-ETH_MODE=DIX
-ETH_DUMMY=no
-
-IP_CONFIG=static
-IP_ADDR=10.0.2.15
-IP_ROUTING=yes
-IP_NETMASK=255.255.255.240
-IP_BROADCAST=10.0.2.255
-IP_GATEWAY=10.0.2.2
-ARP=arp
-
-MTU=1500
Index: pace/srv/net/il/arp/Makefile
===================================================================
--- uspace/srv/net/il/arp/Makefile	(revision bf31e3f1ebd6e88e0c8425f109e42ccd92b6c9b3)
+++ 	(revision )
@@ -1,38 +1,0 @@
-#
-# Copyright (c) 2005 Martin Decky
-# Copyright (c) 2007 Jakub Jermar
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# - Redistributions of source code must retain the above copyright
-#   notice, this list of conditions and the following disclaimer.
-# - Redistributions in binary form must reproduce the above copyright
-#   notice, this list of conditions and the following disclaimer in the
-#   documentation and/or other materials provided with the distribution.
-# - The name of the author may not be used to endorse or promote products
-#   derived from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-
-USPACE_PREFIX = ../../../..
-LIBS = $(LIBNET_PREFIX)/libnet.a
-EXTRA_CFLAGS = -I$(LIBNET_PREFIX)/include
-BINARY = arp
-
-SOURCES = \
-	arp.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/srv/net/il/arp/arp.c
===================================================================
--- uspace/srv/net/il/arp/arp.c	(revision bf31e3f1ebd6e88e0c8425f109e42ccd92b6c9b3)
+++ 	(revision )
@@ -1,946 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup arp
- * @{
- */
-
-/** @file
- * ARP module implementation.
- * @see arp.h
- */
-
-#include <async.h>
-#include <malloc.h>
-#include <mem.h>
-#include <fibril_synch.h>
-#include <assert.h>
-#include <stdio.h>
-#include <str.h>
-#include <task.h>
-#include <adt/measured_strings.h>
-#include <ipc/services.h>
-#include <ipc/net.h>
-#include <ipc/arp.h>
-#include <ipc/il.h>
-#include <ipc/nil.h>
-#include <byteorder.h>
-#include <errno.h>
-#include <net/modules.h>
-#include <net/device.h>
-#include <net/packet.h>
-#include <nil_remote.h>
-#include <protocol_map.h>
-#include <packet_client.h>
-#include <packet_remote.h>
-#include <il_remote.h>
-#include <il_skel.h>
-#include "arp.h"
-
-/** ARP module name. */
-#define NAME  "arp"
-
-/** Number of microseconds to wait for an ARP reply. */
-#define ARP_TRANS_WAIT  1000000
-
-/** @name ARP operation codes definitions */
-/*@{*/
-
-/** REQUEST operation code. */
-#define ARPOP_REQUEST  1
-
-/** REPLY operation code. */
-#define ARPOP_REPLY  2
-
-/*@}*/
-
-/** Type definition of an ARP protocol header.
- * @see arp_header
- */
-typedef struct arp_header arp_header_t;
-
-/** ARP protocol header. */
-struct arp_header {
-	/**
-	 * Hardware type identifier.
-	 * @see hardware.h
-	 */
-	uint16_t hardware;
-	
-	/** Protocol identifier. */
-	uint16_t protocol;
-	/** Hardware address length in bytes. */
-	uint8_t hardware_length;
-	/** Protocol address length in bytes. */
-	uint8_t protocol_length;
-	
-	/**
-	 * ARP packet type.
-	 * @see arp_oc.h
-	 */
-	uint16_t operation;
-} __attribute__ ((packed));
-
-/** ARP global data. */
-arp_globals_t arp_globals;
-
-DEVICE_MAP_IMPLEMENT(arp_cache, arp_device_t);
-INT_MAP_IMPLEMENT(arp_protos, arp_proto_t);
-GENERIC_CHAR_MAP_IMPLEMENT(arp_addr, arp_trans_t);
-
-static void arp_clear_trans(arp_trans_t *trans)
-{
-	if (trans->hw_addr) {
-		free(trans->hw_addr);
-		trans->hw_addr = NULL;
-	}
-	
-	fibril_condvar_broadcast(&trans->cv);
-}
-
-static void arp_clear_addr(arp_addr_t *addresses)
-{
-	int count;
-	
-	for (count = arp_addr_count(addresses) - 1; count >= 0; count--) {
-		arp_trans_t *trans = arp_addr_items_get_index(&addresses->values,
-		    count);
-		if (trans)
-			arp_clear_trans(trans);
-	}
-}
-
-/** Clear the device specific data.
- *
- * @param[in] device Device specific data.
- */
-static void arp_clear_device(arp_device_t *device)
-{
-	int count;
-	
-	for (count = arp_protos_count(&device->protos) - 1; count >= 0;
-	    count--) {
-		arp_proto_t *proto = arp_protos_get_index(&device->protos,
-		    count);
-		
-		if (proto) {
-			if (proto->addr)
-				free(proto->addr);
-			
-			if (proto->addr_data)
-				free(proto->addr_data);
-			
-			arp_clear_addr(&proto->addresses);
-			arp_addr_destroy(&proto->addresses, free);
-		}
-	}
-	
-	arp_protos_clear(&device->protos, free);
-}
-
-static int arp_clean_cache_req(void)
-{
-	int count;
-	
-	fibril_mutex_lock(&arp_globals.lock);
-	for (count = arp_cache_count(&arp_globals.cache) - 1; count >= 0;
-	    count--) {
-		arp_device_t *device = arp_cache_get_index(&arp_globals.cache,
-		    count);
-		
-		if (device)
-			arp_clear_device(device);
-	}
-	
-	arp_cache_clear(&arp_globals.cache, free);
-	fibril_mutex_unlock(&arp_globals.lock);
-	
-	return EOK;
-}
-
-static int arp_clear_address_req(nic_device_id_t device_id,
-    services_t protocol, measured_string_t *address)
-{
-	fibril_mutex_lock(&arp_globals.lock);
-	
-	arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
-	if (!device) {
-		fibril_mutex_unlock(&arp_globals.lock);
-		return ENOENT;
-	}
-	
-	arp_proto_t *proto = arp_protos_find(&device->protos, protocol);
-	if (!proto) {
-		fibril_mutex_unlock(&arp_globals.lock);
-		return ENOENT;
-	}
-	
-	arp_trans_t *trans = arp_addr_find(&proto->addresses, address->value,
-	    address->length);
-	if (trans)
-		arp_clear_trans(trans);
-	
-	arp_addr_exclude(&proto->addresses, address->value, address->length, free);
-	
-	fibril_mutex_unlock(&arp_globals.lock);
-	return EOK;
-}
-
-static int arp_clear_device_req(nic_device_id_t device_id)
-{
-	fibril_mutex_lock(&arp_globals.lock);
-	
-	arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
-	if (!device) {
-		fibril_mutex_unlock(&arp_globals.lock);
-		return ENOENT;
-	}
-	
-	arp_clear_device(device);
-	
-	fibril_mutex_unlock(&arp_globals.lock);
-	return EOK;
-}
-
-/** Create new protocol specific data.
- *
- * Allocate and return the needed memory block as the proto parameter.
- *
- * @param[out] proto   Allocated protocol specific data.
- * @param[in]  service Protocol module service.
- * @param[in]  address Actual protocol device address.
- *
- * @return EOK on success.
- * @return ENOMEM if there is not enough memory left.
- *
- */
-static int arp_proto_create(arp_proto_t **proto, services_t service,
-    measured_string_t *address)
-{
-	*proto = (arp_proto_t *) malloc(sizeof(arp_proto_t));
-	if (!*proto)
-		return ENOMEM;
-	
-	(*proto)->service = service;
-	(*proto)->addr = address;
-	(*proto)->addr_data = address->value;
-	
-	int rc = arp_addr_initialize(&(*proto)->addresses);
-	if (rc != EOK) {
-		free(*proto);
-		return rc;
-	}
-	
-	return EOK;
-}
-
-/** Process the received ARP packet.
- *
- * Update the source hardware address if the source entry exists or the packet
- * is targeted to my protocol address.
- *
- * Respond to the ARP request if the packet is the ARP request and is
- * targeted to my address.
- *
- * @param[in]     device_id Source device identifier.
- * @param[in,out] packet    Received packet.
- *
- * @return EOK on success and the packet is no longer needed.
- * @return One on success and the packet has been reused.
- * @return EINVAL if the packet is too small to carry an ARP
- *         packet.
- * @return EINVAL if the received address lengths differs from
- *         the registered values.
- * @return ENOENT if the device is not found in the cache.
- * @return ENOENT if the protocol for the device is not found in
- *         the cache.
- * @return ENOMEM if there is not enough memory left.
- *
- */
-static int arp_receive_message(nic_device_id_t device_id, packet_t *packet)
-{
-	int rc;
-	
-	size_t length = packet_get_data_length(packet);
-	if (length <= sizeof(arp_header_t))
-		return EINVAL;
-	
-	arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
-	if (!device)
-		return ENOENT;
-	
-	arp_header_t *header = (arp_header_t *) packet_get_data(packet);
-	if ((ntohs(header->hardware) != device->hardware) ||
-	    (length < sizeof(arp_header_t) + header->hardware_length * 2U +
-	    header->protocol_length * 2U)) {
-		return EINVAL;
-	}
-	
-	arp_proto_t *proto = arp_protos_find(&device->protos,
-	    protocol_unmap(device->service, ntohs(header->protocol)));
-	if (!proto)
-		return ENOENT;
-	
-	uint8_t *src_hw = ((uint8_t *) header) + sizeof(arp_header_t);
-	uint8_t *src_proto = src_hw + header->hardware_length;
-	uint8_t *des_hw = src_proto + header->protocol_length;
-	uint8_t *des_proto = des_hw + header->hardware_length;
-	
-	arp_trans_t *trans = arp_addr_find(&proto->addresses, src_proto,
-	    header->protocol_length);
-	
-	if ((trans) && (trans->hw_addr)) {
-		/* Translation exists */
-		if (trans->hw_addr->length != header->hardware_length)
-			return EINVAL;
-		
-		memcpy(trans->hw_addr->value, src_hw, trans->hw_addr->length);
-	}
-	
-	/* Is my protocol address? */
-	if (proto->addr->length != header->protocol_length)
-		return EINVAL;
-	
-	if (!bcmp(proto->addr->value, des_proto, proto->addr->length)) {
-		if (!trans) {
-			/* Update the translation */
-			trans = (arp_trans_t *) malloc(sizeof(arp_trans_t));
-			if (!trans)
-				return ENOMEM;
-			
-			trans->hw_addr = NULL;
-			fibril_condvar_initialize(&trans->cv);
-			rc = arp_addr_add(&proto->addresses, src_proto,
-			    header->protocol_length, trans);
-			if (rc != EOK) {
-				free(trans);
-				return rc;
-			}
-		}
-		
-		if (!trans->hw_addr) {
-			trans->hw_addr = measured_string_create_bulk(src_hw,
-			    header->hardware_length);
-			if (!trans->hw_addr)
-				return ENOMEM;
-			
-			/* Notify the fibrils that wait for the translation. */
-			fibril_condvar_broadcast(&trans->cv);
-		}
-		
-		if (ntohs(header->operation) == ARPOP_REQUEST) {
-			header->operation = htons(ARPOP_REPLY);
-			memcpy(des_proto, src_proto, header->protocol_length);
-			memcpy(src_proto, proto->addr->value,
-			    header->protocol_length);
-			memcpy(src_hw, device->addr,
-			    device->packet_dimension.addr_len);
-			memcpy(des_hw, trans->hw_addr->value,
-			    header->hardware_length);
-			
-			rc = packet_set_addr(packet, src_hw, des_hw,
-			    header->hardware_length);
-			if (rc != EOK)
-				return rc;
-			
-			nil_send_msg(device->sess, device_id, packet,
-			    SERVICE_ARP);
-			return 1;
-		}
-	}
-	
-	return EOK;
-}
-
-/** Update the device content length according to the new MTU value.
- *
- * @param[in] device_id Device identifier.
- * @param[in] mtu       New MTU value.
- *
- * @return ENOENT if device is not found.
- * @return EOK on success.
- *
- */
-static int arp_mtu_changed_message(nic_device_id_t device_id, size_t mtu)
-{
-	fibril_mutex_lock(&arp_globals.lock);
-	
-	arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
-	if (!device) {
-		fibril_mutex_unlock(&arp_globals.lock);
-		return ENOENT;
-	}
-	
-	device->packet_dimension.content = mtu;
-	
-	fibril_mutex_unlock(&arp_globals.lock);
-	
-	printf("%s: Device %d changed MTU to %zu\n", NAME, device_id, mtu);
-	
-	return EOK;
-}
-
-static int arp_addr_changed_message(nic_device_id_t device_id)
-{
-	uint8_t addr_buffer[NIC_MAX_ADDRESS_LENGTH];
-	size_t length;
-	ipc_callid_t data_callid;
-	if (!async_data_write_receive(&data_callid, &length)) {
-		async_answer_0(data_callid, EINVAL);
-		return EINVAL;
-	}
-	if (length > NIC_MAX_ADDRESS_LENGTH) {
-		async_answer_0(data_callid, ELIMIT);
-		return ELIMIT;
-	}
-	if (async_data_write_finalize(data_callid, addr_buffer, length) != EOK) {
-		return EINVAL;
-	}
-
-	fibril_mutex_lock(&arp_globals.lock);
-
-	arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
-	if (!device) {
-		fibril_mutex_unlock(&arp_globals.lock);
-		return ENOENT;
-	}
-
-	memcpy(device->addr, addr_buffer, length);
-	device->addr_len = length;
-
-	fibril_mutex_unlock(&arp_globals.lock);
-	return EOK;
-}
-
-/** Process IPC messages from the registered device driver modules
- *
- * @param[in]     iid   Message identifier.
- * @param[in,out] icall Message parameters.
- * @param[in]     arg   Local argument.
- *
- */
-static void arp_receiver(ipc_callid_t iid, ipc_call_t *icall, void *arg)
-{
-	packet_t *packet;
-	int rc;
-	
-	while (true) {
-		switch (IPC_GET_IMETHOD(*icall)) {
-		case NET_IL_DEVICE_STATE:
-			/* Do nothing - keep the cache */
-			async_answer_0(iid, (sysarg_t) EOK);
-			break;
-		
-		case NET_IL_RECEIVED:
-			rc = packet_translate_remote(arp_globals.net_sess, &packet,
-			    IPC_GET_PACKET(*icall));
-			if (rc == EOK) {
-				fibril_mutex_lock(&arp_globals.lock);
-				do {
-					packet_t *next = pq_detach(packet);
-					rc = arp_receive_message(IPC_GET_DEVICE(*icall), packet);
-					if (rc != 1) {
-						pq_release_remote(arp_globals.net_sess,
-						    packet_get_id(packet));
-					}
-					
-					packet = next;
-				} while (packet);
-				fibril_mutex_unlock(&arp_globals.lock);
-			}
-			async_answer_0(iid, (sysarg_t) rc);
-			break;
-		
-		case NET_IL_MTU_CHANGED:
-			rc = arp_mtu_changed_message(IPC_GET_DEVICE(*icall),
-			    IPC_GET_MTU(*icall));
-			async_answer_0(iid, (sysarg_t) rc);
-			break;
-		case NET_IL_ADDR_CHANGED:
-			rc = arp_addr_changed_message(IPC_GET_DEVICE(*icall));
-			async_answer_0(iid, (sysarg_t) rc);
-		
-		default:
-			async_answer_0(iid, (sysarg_t) ENOTSUP);
-		}
-		
-		iid = async_get_call(icall);
-	}
-}
-
-/** Register the device.
- *
- * Create new device entry in the cache or update the protocol address if the
- * device with the device identifier and the driver service exists.
- *
- * @param[in] device_id Device identifier.
- * @param[in] service   Device driver service.
- * @param[in] protocol  Protocol service.
- * @param[in] address   Actual device protocol address.
- *
- * @return EOK on success.
- * @return EEXIST if another device with the same device identifier
- *         and different driver service exists.
- * @return ENOMEM if there is not enough memory left.
- * @return Other error codes as defined for the
- *         measured_strings_return() function.
- *
- */
-static int arp_device_message(nic_device_id_t device_id, services_t service,
-    services_t protocol, measured_string_t *address)
-{
-	int index;
-	int rc;
-	
-	fibril_mutex_lock(&arp_globals.lock);
-	
-	/* An existing device? */
-	arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
-	if (device) {
-		if (device->service != service) {
-			printf("%s: Device %d already exists\n", NAME,
-			    device->device_id);
-			fibril_mutex_unlock(&arp_globals.lock);
-			return EEXIST;
-		}
-		
-		arp_proto_t *proto = arp_protos_find(&device->protos, protocol);
-		if (proto) {
-			free(proto->addr);
-			free(proto->addr_data);
-			proto->addr = address;
-			proto->addr_data = address->value;
-		} else {
-			rc = arp_proto_create(&proto, protocol, address);
-			if (rc != EOK) {
-				fibril_mutex_unlock(&arp_globals.lock);
-				return rc;
-			}
-			
-			index = arp_protos_add(&device->protos, proto->service,
-			    proto);
-			if (index < 0) {
-				fibril_mutex_unlock(&arp_globals.lock);
-				free(proto);
-				return index;
-			}
-			
-			printf("%s: New protocol added (id: %d, proto: %d)\n", NAME,
-			    device_id, protocol);
-		}
-	} else {
-		hw_type_t hardware = hardware_map(service);
-		if (!hardware)
-			return ENOENT;
-		
-		/* Create new device */
-		device = (arp_device_t *) malloc(sizeof(arp_device_t));
-		if (!device) {
-			fibril_mutex_unlock(&arp_globals.lock);
-			return ENOMEM;
-		}
-		
-		device->hardware = hardware;
-		device->device_id = device_id;
-		rc = arp_protos_initialize(&device->protos);
-		if (rc != EOK) {
-			fibril_mutex_unlock(&arp_globals.lock);
-			free(device);
-			return rc;
-		}
-		
-		arp_proto_t *proto;
-		rc = arp_proto_create(&proto, protocol, address);
-		if (rc != EOK) {
-			fibril_mutex_unlock(&arp_globals.lock);
-			free(device);
-			return rc;
-		}
-		
-		index = arp_protos_add(&device->protos, proto->service, proto);
-		if (index < 0) {
-			fibril_mutex_unlock(&arp_globals.lock);
-			arp_protos_destroy(&device->protos, free);
-			free(device);
-			return index;
-		}
-		
-		device->service = service;
-		
-		/* Bind */
-		device->sess = nil_bind_service(device->service,
-		    (sysarg_t) device->device_id, SERVICE_ARP,
-		    arp_receiver);
-		if (device->sess == NULL) {
-			fibril_mutex_unlock(&arp_globals.lock);
-			arp_protos_destroy(&device->protos, free);
-			free(device);
-			return EREFUSED;
-		}
-		
-		/* Get packet dimensions */
-		rc = nil_packet_size_req(device->sess, device_id,
-		    &device->packet_dimension);
-		if (rc != EOK) {
-			fibril_mutex_unlock(&arp_globals.lock);
-			arp_protos_destroy(&device->protos, free);
-			free(device);
-			return rc;
-		}
-		
-		/* Get hardware address */
-		int len = nil_get_addr_req(device->sess, device_id, device->addr,
-		    NIC_MAX_ADDRESS_LENGTH);
-		if (len < 0) {
-			fibril_mutex_unlock(&arp_globals.lock);
-			arp_protos_destroy(&device->protos, free);
-			free(device);
-			return len;
-		}
-		
-		device->addr_len = len;
-		
-		/* Get broadcast address */
-		len = nil_get_broadcast_addr_req(device->sess, device_id,
-		    device->broadcast_addr, NIC_MAX_ADDRESS_LENGTH);
-		if (len < 0) {
-			fibril_mutex_unlock(&arp_globals.lock);
-			arp_protos_destroy(&device->protos, free);
-			free(device);
-			return len;
-		}
-		
-		device->broadcast_addr_len = len;
-		
-		rc = arp_cache_add(&arp_globals.cache, device->device_id,
-		    device);
-		if (rc != EOK) {
-			fibril_mutex_unlock(&arp_globals.lock);
-			arp_protos_destroy(&device->protos, free);
-			free(device);
-			return rc;
-		}
-		printf("%s: Device registered (id: %d, type: 0x%x, service: %d,"
-		    " proto: %d)\n", NAME, device->device_id, device->hardware,
-		    device->service, protocol);
-	}
-	
-	fibril_mutex_unlock(&arp_globals.lock);
-	return EOK;
-}
-
-int il_initialize(async_sess_t *net_sess)
-{
-	fibril_mutex_initialize(&arp_globals.lock);
-	
-	fibril_mutex_lock(&arp_globals.lock);
-	arp_globals.net_sess = net_sess;
-	int rc = arp_cache_initialize(&arp_globals.cache);
-	fibril_mutex_unlock(&arp_globals.lock);
-	
-	return rc;
-}
-
-static int arp_send_request(nic_device_id_t device_id, services_t protocol,
-    measured_string_t *target, arp_device_t *device, arp_proto_t *proto)
-{
-	/* ARP packet content size = header + (address + translation) * 2 */
-	size_t length = 8 + 2 * (proto->addr->length + device->addr_len);
-	if (length > device->packet_dimension.content)
-		return ELIMIT;
-	
-	packet_t *packet = packet_get_4_remote(arp_globals.net_sess,
-	    device->packet_dimension.addr_len, device->packet_dimension.prefix,
-	    length, device->packet_dimension.suffix);
-	if (!packet)
-		return ENOMEM;
-	
-	arp_header_t *header = (arp_header_t *) packet_suffix(packet, length);
-	if (!header) {
-		pq_release_remote(arp_globals.net_sess, packet_get_id(packet));
-		return ENOMEM;
-	}
-	
-	header->hardware = htons(device->hardware);
-	header->hardware_length = (uint8_t) device->addr_len;
-	header->protocol = htons(protocol_map(device->service, protocol));
-	header->protocol_length = (uint8_t) proto->addr->length;
-	header->operation = htons(ARPOP_REQUEST);
-	
-	length = sizeof(arp_header_t);
-	memcpy(((uint8_t *) header) + length, device->addr,
-	    device->addr_len);
-	length += device->addr_len;
-	memcpy(((uint8_t *) header) + length, proto->addr->value,
-	    proto->addr->length);
-	length += proto->addr->length;
-	bzero(((uint8_t *) header) + length, device->addr_len);
-	length += device->addr_len;
-	memcpy(((uint8_t *) header) + length, target->value, target->length);
-	
-	int rc = packet_set_addr(packet, device->addr, device->broadcast_addr,
-	    device->addr_len);
-	if (rc != EOK) {
-		pq_release_remote(arp_globals.net_sess, packet_get_id(packet));
-		return rc;
-	}
-	
-	nil_send_msg(device->sess, device_id, packet, SERVICE_ARP);
-	return EOK;
-}
-
-/** Return the hardware address for the given protocol address.
- *
- * Send the ARP request packet if the hardware address is not found in the
- * cache.
- *
- * @param[in]  device_id   Device identifier.
- * @param[in]  protocol    Protocol service.
- * @param[in]  target      Target protocol address.
- * @param[out] translation Where the hardware address of the target is stored.
- *
- * @return EOK on success.
- * @return EAGAIN if the caller should try again.
- * @return Other error codes in case of error.
- *
- */
-static int arp_translate_message(nic_device_id_t device_id, services_t protocol,
-    measured_string_t *target, measured_string_t **translation)
-{
-	bool retry = false;
-	int rc;
-
-	assert(fibril_mutex_is_locked(&arp_globals.lock));
-	
-restart:
-	if ((!target) || (!translation))
-		return EBADMEM;
-	
-	arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
-	if (!device)
-		return ENOENT;
-	
-	arp_proto_t *proto = arp_protos_find(&device->protos, protocol);
-	if ((!proto) || (proto->addr->length != target->length))
-		return ENOENT;
-	
-	arp_trans_t *trans = arp_addr_find(&proto->addresses, target->value,
-	    target->length);
-	if (trans) {
-		if (trans->hw_addr) {
-			/* The translation is in place. */
-			*translation = trans->hw_addr;
-			return EOK;
-		}
-		
-		if (retry) {
-			/*
-			 * We may get here as a result of being signalled for
-			 * some reason while waiting for the translation (e.g.
-			 * translation becoming available, record being removed
-			 * from the table) and then losing the race for
-			 * the arp_globals.lock with someone else who modified
-			 * the table.
-			 *
-			 * Remove the incomplete record so that it is possible
-			 * to make new ARP requests.
-			 */
-			arp_clear_trans(trans);
-			arp_addr_exclude(&proto->addresses, target->value,
-			    target->length, free);
-			return EAGAIN;
-		}
-		
-		/*
-		 * We are a random passer-by who merely joins an already waiting
-		 * fibril in waiting for the translation.
-		 */
-		rc = fibril_condvar_wait_timeout(&trans->cv, &arp_globals.lock,
-		    ARP_TRANS_WAIT);
-		if (rc == ETIMEOUT)
-			return ENOENT;
-		
-		/*
-		 * Need to recheck because we did not hold the lock while
-		 * sleeping on the condition variable.
-		 */
-		retry = true;
-		goto restart;
-	}
-	
-	if (retry)
-		return EAGAIN;
-
-	/*
-	 * We are under the protection of arp_globals.lock, so we can afford to
-	 * first send the ARP request and then insert an incomplete ARP record.
-	 * The incomplete record is used to tell any other potential waiter
-	 * that this fibril has already sent the request and that it is waiting
-	 * for the answer. Lastly, any fibril which sees the incomplete request
-	 * can perform a timed wait on its condition variable to wait for the
-	 * ARP reply to arrive.
-	 */
-
-	rc = arp_send_request(device_id, protocol, target, device, proto);
-	if (rc != EOK)
-		return rc;
-	
-	trans = (arp_trans_t *) malloc(sizeof(arp_trans_t));
-	if (!trans)
-		return ENOMEM;
-	
-	trans->hw_addr = NULL;
-	fibril_condvar_initialize(&trans->cv);
-	
-	rc = arp_addr_add(&proto->addresses, target->value, target->length,
-	    trans);
-	if (rc != EOK) {
-		free(trans);
-		return rc;
-	}
-	
-	rc = fibril_condvar_wait_timeout(&trans->cv, &arp_globals.lock,
-	    ARP_TRANS_WAIT);
-	if (rc == ETIMEOUT) {
-		/*
-		 * Remove the incomplete record so that it is possible to make 
-		 * new ARP requests.
-		 */
-		arp_clear_trans(trans);
-		arp_addr_exclude(&proto->addresses, target->value,
-		    target->length, free);
-		return ENOENT;
-	}
-	
-	/*
-	 * We need to recheck that the translation has indeed become available,
-	 * because we dropped the arp_globals.lock while sleeping on the
-	 * condition variable and someone else might have e.g. removed the
-	 * translation before we managed to lock arp_globals.lock again.
-	 */
-
-	retry = true;
-	goto restart;
-}
-
-/** Process the ARP message.
- *
- * @param[in]  callid Message identifier.
- * @param[in]  call   Message parameters.
- * @param[out] answer Answer.
- * @param[out] count  Number of arguments of the answer.
- *
- * @return EOK on success.
- * @return ENOTSUP if the message is not known.
- *
- * @see arp_interface.h
- * @see IS_NET_ARP_MESSAGE()
- *
- */
-int il_module_message(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer,
-    size_t *count)
-{
-	measured_string_t *address;
-	measured_string_t *translation;
-	uint8_t *data;
-	int rc;
-	
-	*count = 0;
-	
-	if (!IPC_GET_IMETHOD(*call))
-		return EOK;
-	
-	switch (IPC_GET_IMETHOD(*call)) {
-	case NET_ARP_DEVICE:
-		rc = measured_strings_receive(&address, &data, 1);
-		if (rc != EOK)
-			return rc;
-		
-		rc = arp_device_message(IPC_GET_DEVICE(*call),
-		    IPC_GET_SERVICE(*call), ARP_GET_NETIF(*call), address);
-		if (rc != EOK) {
-			free(address);
-			free(data);
-		}
-		
-		return rc;
-	
-	case NET_ARP_TRANSLATE:
-		rc = measured_strings_receive(&address, &data, 1);
-		if (rc != EOK)
-			return rc;
-		
-		fibril_mutex_lock(&arp_globals.lock);
-		rc = arp_translate_message(IPC_GET_DEVICE(*call),
-		    IPC_GET_SERVICE(*call), address, &translation);
-		free(address);
-		free(data);
-		
-		if (rc != EOK) {
-			fibril_mutex_unlock(&arp_globals.lock);
-			return rc;
-		}
-		
-		if (!translation) {
-			fibril_mutex_unlock(&arp_globals.lock);
-			return ENOENT;
-		}
-		
-		rc = measured_strings_reply(translation, 1);
-		fibril_mutex_unlock(&arp_globals.lock);
-		return rc;
-	
-	case NET_ARP_CLEAR_DEVICE:
-		return arp_clear_device_req(IPC_GET_DEVICE(*call));
-	
-	case NET_ARP_CLEAR_ADDRESS:
-		rc = measured_strings_receive(&address, &data, 1);
-		if (rc != EOK)
-			return rc;
-		
-		arp_clear_address_req(IPC_GET_DEVICE(*call),
-		    IPC_GET_SERVICE(*call), address);
-		free(address);
-		free(data);
-		return EOK;
-	
-	case NET_ARP_CLEAN_CACHE:
-		return arp_clean_cache_req();
-	}
-	
-	return ENOTSUP;
-}
-
-int main(int argc, char *argv[])
-{
-	/* Start the module */
-	return il_module_start(SERVICE_ARP);
-}
-
-/** @}
- */
Index: pace/srv/net/il/arp/arp.h
===================================================================
--- uspace/srv/net/il/arp/arp.h	(revision bf31e3f1ebd6e88e0c8425f109e42ccd92b6c9b3)
+++ 	(revision )
@@ -1,159 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup arp
- * @{
- */
-
-/** @file
- * ARP module.
- */
-
-#ifndef NET_ARP_H_
-#define NET_ARP_H_
-
-#include <async.h>
-#include <fibril_synch.h>
-#include <ipc/services.h>
-#include <net/device.h>
-#include <net/packet.h>
-#include <net_hardware.h>
-#include <adt/generic_char_map.h>
-#include <adt/int_map.h>
-#include <adt/measured_strings.h>
-
-/** Type definition of the ARP device specific data.
- * @see arp_device
- */
-typedef struct arp_device arp_device_t;
-
-/** Type definition of the ARP global data.
- * @see arp_globals
- */
-typedef struct arp_globals arp_globals_t;
-
-/** Type definition of the ARP protocol specific data.
- * @see arp_proto
- */
-typedef struct arp_proto arp_proto_t;
-
-/** Type definition of the ARP address translation record.
- * @see arp_trans
- */
-typedef struct arp_trans arp_trans_t;
-
-/** ARP address map.
- *
- * Translates addresses.
- * @see generic_char_map.h
- */
-GENERIC_CHAR_MAP_DECLARE(arp_addr, arp_trans_t);
-
-/** ARP address cache.
- *
- * Maps devices to the ARP device specific data.
- * @see device.h
- */
-DEVICE_MAP_DECLARE(arp_cache, arp_device_t);
-
-/** ARP protocol map.
- *
- * Maps protocol identifiers to the ARP protocol specific data.
- * @see int_map.h
- */
-INT_MAP_DECLARE(arp_protos, arp_proto_t);
-
-/** ARP device specific data. */
-struct arp_device {
-	/** Actual device hardware address. */
-	uint8_t addr[NIC_MAX_ADDRESS_LENGTH];
-	/** Actual device hardware address length. */
-	size_t addr_len;
-	/** Broadcast device hardware address. */
-	uint8_t broadcast_addr[NIC_MAX_ADDRESS_LENGTH];
-	/** Broadcast device hardware address length. */
-	size_t broadcast_addr_len;
-	/** Device identifier. */
-	nic_device_id_t device_id;
-	/** Hardware type. */
-	hw_type_t hardware;
-	/** Packet dimension. */
-	packet_dimension_t packet_dimension;
-	/** Device module session. */
-	async_sess_t *sess;
-	
-	/**
-	 * Protocol map.
-	 * Address map for each protocol.
-	 */
-	arp_protos_t protos;
-	
-	/** Device module service. */
-	services_t service;
-};
-
-/** ARP global data. */
-struct arp_globals {
-	/** ARP address cache. */
-	arp_cache_t cache;
-	
-	/** Networking module session. */
-	async_sess_t *net_sess;
-	
-	/** Safety lock. */
-	fibril_mutex_t lock;
-};
-
-/** ARP protocol specific data. */
-struct arp_proto {
-	/** Actual device protocol address. */
-	measured_string_t *addr;
-	/** Actual device protocol address data. */
-	uint8_t *addr_data;
-	/** Address map. */
-	arp_addr_t addresses;
-	/** Protocol service. */
-	services_t service;
-};
-
-/** ARP address translation record. */
-struct arp_trans {
-	/**
-	 * Hardware address for the translation. NULL denotes an incomplete
-	 * record with possible waiters.
-	 */
-	measured_string_t *hw_addr;
-	/** Condition variable used for waiting for completion of the record. */
-	fibril_condvar_t cv;
-};
-
-#endif
-
-/** @}
- */
-
Index: pace/srv/net/il/ip/Makefile
===================================================================
--- uspace/srv/net/il/ip/Makefile	(revision bf31e3f1ebd6e88e0c8425f109e42ccd92b6c9b3)
+++ 	(revision )
@@ -1,38 +1,0 @@
-#
-# Copyright (c) 2005 Martin Decky
-# Copyright (c) 2007 Jakub Jermar
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# - Redistributions of source code must retain the above copyright
-#   notice, this list of conditions and the following disclaimer.
-# - Redistributions in binary form must reproduce the above copyright
-#   notice, this list of conditions and the following disclaimer in the
-#   documentation and/or other materials provided with the distribution.
-# - The name of the author may not be used to endorse or promote products
-#   derived from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-
-USPACE_PREFIX = ../../../..
-LIBS = $(LIBNET_PREFIX)/libnet.a
-EXTRA_CFLAGS = -I$(LIBNET_PREFIX)/include
-BINARY = ip
-
-SOURCES = \
-	ip.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/srv/net/il/ip/ip.c
===================================================================
--- uspace/srv/net/il/ip/ip.c	(revision bf31e3f1ebd6e88e0c8425f109e42ccd92b6c9b3)
+++ 	(revision )
@@ -1,2010 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup ip
- * @{
- */
-
-/** @file
- * IP module implementation.
- * @see arp.h
- */
-
-#include <async.h>
-#include <errno.h>
-#include <fibril_synch.h>
-#include <stdio.h>
-#include <str.h>
-#include <ipc/services.h>
-#include <ipc/net.h>
-#include <ipc/nil.h>
-#include <ipc/il.h>
-#include <ipc/ip.h>
-#include <sys/types.h>
-#include <byteorder.h>
-#include "ip.h"
-
-#include <adt/measured_strings.h>
-#include <adt/module_map.h>
-
-#include <packet_client.h>
-#include <net/socket_codes.h>
-#include <net/in.h>
-#include <net/in6.h>
-#include <net/inet.h>
-#include <net/modules.h>
-#include <net/device.h>
-#include <net/packet.h>
-#include <net/icmp_codes.h>
-
-#include <arp_interface.h>
-#include <net_checksum.h>
-#include <icmp_client.h>
-#include <icmp_remote.h>
-#include <ip_client.h>
-#include <ip_interface.h>
-#include <ip_header.h>
-#include <net_interface.h>
-#include <nil_remote.h>
-#include <tl_remote.h>
-#include <packet_remote.h>
-#include <il_remote.h>
-#include <il_skel.h>
-
-/** IP module name. */
-#define NAME			"ip"
-
-/** IP version 4. */
-#define IPV4			4
-
-/** Default network interface IP version. */
-#define NET_DEFAULT_IPV		IPV4
-
-/** Default network interface IP routing. */
-#define NET_DEFAULT_IP_ROUTING	false
-
-/** Minimum IP packet content. */
-#define IP_MIN_CONTENT		576
-
-/** ARP module name. */
-#define ARP_NAME		"arp"
-
-/** ARP module filename. */
-#define ARP_FILENAME		"/srv/arp"
-
-/** IP packet address length. */
-#define IP_ADDR			sizeof(struct sockaddr_in6)
-
-/** IP packet prefix length. */
-#define IP_PREFIX		sizeof(ip_header_t)
-
-/** IP packet suffix length. */
-#define IP_SUFFIX		0
-
-/** IP packet maximum content length. */
-#define IP_MAX_CONTENT		65535
-
-/** The IP localhost address. */
-#define IPV4_LOCALHOST_ADDRESS	htonl((127 << 24) + 1)
-
-/** IP global data. */
-ip_globals_t ip_globals;
-
-DEVICE_MAP_IMPLEMENT(ip_netifs, ip_netif_t);
-INT_MAP_IMPLEMENT(ip_protos, ip_proto_t);
-GENERIC_FIELD_IMPLEMENT(ip_routes, ip_route_t);
-
-static void ip_receiver(ipc_callid_t, ipc_call_t *, void *);
-
-/** Release the packet and returns the result.
- *
- * @param[in] packet Packet queue to be released.
- * @param[in] result Result to be returned.
- *
- * @return Result parameter.
- *
- */
-static int ip_release_and_return(packet_t *packet, int result)
-{
-	pq_release_remote(ip_globals.net_sess, packet_get_id(packet));
-	return result;
-}
-
-/** Return the ICMP session.
- *
- * Search the registered protocols.
- *
- * @return Found ICMP session.
- * @return NULL if the ICMP is not registered.
- *
- */
-static async_sess_t *ip_get_icmp_session(void)
-{
-	fibril_rwlock_read_lock(&ip_globals.protos_lock);
-	ip_proto_t *proto = ip_protos_find(&ip_globals.protos, IPPROTO_ICMP);
-	async_sess_t *sess = proto ? proto->sess : NULL;
-	fibril_rwlock_read_unlock(&ip_globals.protos_lock);
-	
-	return sess;
-}
-
-/** Prepares the ICMP notification packet.
- *
- * Releases additional packets and keeps only the first one.
- *
- * @param[in] packet	The packet or the packet queue to be reported as faulty.
- * @param[in] header	The first packet IP header. May be NULL.
- * @return		EOK on success.
- * @return		EINVAL if there are no data in the packet.
- * @return		EINVAL if the packet is a fragment.
- * @return		ENOMEM if the packet is too short to contain the IP
- *			header.
- * @return		EAFNOSUPPORT if the address family is not supported.
- * @return		EPERM if the protocol is not allowed to send ICMP
- *			notifications. The ICMP protocol itself.
- * @return		Other error codes as defined for the packet_set_addr().
- */
-static int ip_prepare_icmp(packet_t *packet, ip_header_t *header)
-{
-	packet_t *next;
-	struct sockaddr *dest;
-	struct sockaddr_in dest_in;
-	socklen_t addrlen;
-
-	/* Detach the first packet and release the others */
-	next = pq_detach(packet);
-	if (next)
-		pq_release_remote(ip_globals.net_sess, packet_get_id(next));
-
-	if (!header) {
-		if (packet_get_data_length(packet) <= sizeof(ip_header_t))
-			return ENOMEM;
-
-		/* Get header */
-		header = (ip_header_t *) packet_get_data(packet);
-		if (!header)
-			return EINVAL;
-
-	}
-
-	/* Only for the first fragment */
-	if (IP_FRAGMENT_OFFSET(header))
-		return EINVAL;
-
-	/* Not for the ICMP protocol */
-	if (header->protocol == IPPROTO_ICMP)
-		return EPERM;
-
-	/* Set the destination address */
-	switch (GET_IP_HEADER_VERSION(header)) {
-	case IPVERSION:
-		addrlen = sizeof(dest_in);
-		bzero(&dest_in, addrlen);
-		dest_in.sin_family = AF_INET;
-		memcpy(&dest_in.sin_addr.s_addr, &header->source_address,
-		    sizeof(header->source_address));
-		dest = (struct sockaddr *) &dest_in;
-		break;
-
-	default:
-		return EAFNOSUPPORT;
-	}
-
-	return packet_set_addr(packet, NULL, (uint8_t *) dest, addrlen);
-}
-
-/** Prepare the ICMP notification packet.
- *
- * Release additional packets and keep only the first one.
- * All packets are released on error.
- *
- * @param[in] error  Packet error service.
- * @param[in] packet Packet or the packet queue to be reported as faulty.
- * @param[in] header First packet IP header. May be NULL.
- *
- * @return Found ICMP session.
- * @return NULL if the error parameter is set.
- * @return NULL if the ICMP session is not found.
- * @return NULL if the ip_prepare_icmp() fails.
- *
- */
-static async_sess_t *ip_prepare_icmp_and_get_session(services_t error,
-    packet_t *packet, ip_header_t *header)
-{
-	async_sess_t *sess = ip_get_icmp_session();
-	
-	if ((error) || (!sess) || (ip_prepare_icmp(packet, header))) {
-		pq_release_remote(ip_globals.net_sess, packet_get_id(packet));
-		return NULL;
-	}
-	
-	return sess;
-}
-
-int il_initialize(async_sess_t *net_sess)
-{
-	fibril_rwlock_initialize(&ip_globals.lock);
-	fibril_rwlock_write_lock(&ip_globals.lock);
-	fibril_rwlock_initialize(&ip_globals.protos_lock);
-	fibril_rwlock_initialize(&ip_globals.netifs_lock);
-	
-	ip_globals.net_sess = net_sess;
-	ip_globals.packet_counter = 0;
-	ip_globals.gateway.address.s_addr = 0;
-	ip_globals.gateway.netmask.s_addr = 0;
-	ip_globals.gateway.gateway.s_addr = 0;
-	ip_globals.gateway.netif = NULL;
-	
-	int rc = ip_netifs_initialize(&ip_globals.netifs);
-	if (rc != EOK)
-		goto out;
-	rc = ip_protos_initialize(&ip_globals.protos);
-	if (rc != EOK)
-		goto out;
-	rc = modules_initialize(&ip_globals.modules);
-	if (rc != EOK)
-		goto out;
-	rc = add_module(NULL, &ip_globals.modules, (uint8_t *) ARP_NAME,
-	    (uint8_t *) ARP_FILENAME, SERVICE_ARP, 0, arp_connect_module);
-
-out:
-	fibril_rwlock_write_unlock(&ip_globals.lock);
-
-	return rc;
-}
-
-/** Initializes a new network interface specific data.
- *
- * Connects to the network interface layer module, reads the netif
- * configuration, starts an ARP module if needed and sets the netif routing
- * table.
- * 
- * The device identifier and the nil service has to be set.
- *
- * @param[in,out] ip_netif Network interface specific data.
- * @return		EOK on success.
- * @return		ENOTSUP if DHCP is configured.
- * @return		ENOTSUP if IPv6 is configured.
- * @return		EINVAL if any of the addresses is invalid.
- * @return		EINVAL if the used ARP module is not known.
- * @return		ENOMEM if there is not enough memory left.
- * @return		Other error codes as defined for the
- *			net_get_device_conf_req() function.
- * @return		Other error codes as defined for the bind_service()
- *			function.
- * @return		Other error codes as defined for the specific
- *			arp_device_req() function.
- * @return		Other error codes as defined for the
- *			nil_packet_size_req() function.
- */
-static int ip_netif_initialize(ip_netif_t *ip_netif)
-{
-	measured_string_t names[] = {
-		{
-			(uint8_t *) "IPV",
-			3
-		},
-		{
-			(uint8_t *) "IP_CONFIG",
-			9
-		},
-		{
-			(uint8_t *) "IP_ADDR",
-			7
-		},
-		{
-			(uint8_t *) "IP_NETMASK",
-			10
-		},
-		{
-			(uint8_t *) "IP_GATEWAY",
-			10
-		},
-		{
-			(uint8_t *) "IP_BROADCAST",
-			12
-		},
-		{
-			(uint8_t *) "ARP",
-			3
-		},
-		{
-			(uint8_t *) "IP_ROUTING",
-			10
-		}
-	};
-	measured_string_t *configuration;
-	size_t count = sizeof(names) / sizeof(measured_string_t);
-	uint8_t *data;
-	measured_string_t address;
-	ip_route_t *route;
-	in_addr_t gateway;
-	int index;
-	int rc;
-
-	ip_netif->arp = NULL;
-	route = NULL;
-	ip_netif->ipv = NET_DEFAULT_IPV;
-	ip_netif->dhcp = false;
-	ip_netif->routing = NET_DEFAULT_IP_ROUTING;
-	configuration = &names[0];
-	
-	/* Get configuration */
-	rc = net_get_device_conf_req(ip_globals.net_sess, ip_netif->device_id,
-	    &configuration, count, &data);
-	if (rc != EOK)
-		return rc;
-	
-	if (configuration) {
-		if (configuration[0].value)
-			ip_netif->ipv = strtol((char *) configuration[0].value, NULL, 0);
-		
-		ip_netif->dhcp = !str_lcmp((char *) configuration[1].value, "dhcp",
-		    configuration[1].length);
-		
-		if (ip_netif->dhcp) {
-			// TODO dhcp
-			net_free_settings(configuration, data);
-			return ENOTSUP;
-		} else if (ip_netif->ipv == IPV4) {
-			route = (ip_route_t *) malloc(sizeof(ip_route_t));
-			if (!route) {
-				net_free_settings(configuration, data);
-				return ENOMEM;
-			}
-			route->address.s_addr = 0;
-			route->netmask.s_addr = 0;
-			route->gateway.s_addr = 0;
-			route->netif = ip_netif;
-			index = ip_routes_add(&ip_netif->routes, route);
-			if (index < 0) {
-				net_free_settings(configuration, data);
-				free(route);
-				return index;
-			}
-			
-			if ((inet_pton(AF_INET, (char *) configuration[2].value,
-			    (uint8_t *) &route->address.s_addr) != EOK) ||
-			    (inet_pton(AF_INET, (char *) configuration[3].value,
-			    (uint8_t *) &route->netmask.s_addr) != EOK) ||
-			    (inet_pton(AF_INET, (char *) configuration[4].value,
-			    (uint8_t *) &gateway.s_addr) == EINVAL) ||
-			    (inet_pton(AF_INET, (char *) configuration[5].value,
-			    (uint8_t *) &ip_netif->broadcast.s_addr) == EINVAL))
-			    {
-				net_free_settings(configuration, data);
-				return EINVAL;
-			}
-		} else {
-			// TODO ipv6 in separate module
-			net_free_settings(configuration, data);
-			return ENOTSUP;
-		}
-		
-		if (configuration[6].value) {
-			ip_netif->arp = get_running_module(&ip_globals.modules,
-			    configuration[6].value);
-			if (!ip_netif->arp) {
-				printf("Failed to start the arp %s\n",
-				    configuration[6].value);
-				net_free_settings(configuration, data);
-				return EINVAL;
-			}
-		}
-		
-		if (configuration[7].value)
-			ip_netif->routing = (configuration[7].value[0] == 'y');
-		
-		net_free_settings(configuration, data);
-	}
-	
-	/* Bind netif service which also initializes the device */
-	ip_netif->sess = nil_bind_service(ip_netif->service,
-	    (sysarg_t) ip_netif->device_id, SERVICE_IP,
-	    ip_receiver);
-	if (ip_netif->sess == NULL) {
-		printf("Failed to contact the nil service %d\n",
-		    ip_netif->service);
-		return ENOENT;
-	}
-	
-	/* Has to be after the device netif module initialization */
-	if (ip_netif->arp) {
-		if (route) {
-			address.value = (uint8_t *) &route->address.s_addr;
-			address.length = sizeof(in_addr_t);
-			
-			rc = arp_device_req(ip_netif->arp->sess,
-			    ip_netif->device_id, SERVICE_IP, ip_netif->service,
-			    &address);
-			if (rc != EOK)
-				return rc;
-		} else {
-			ip_netif->arp = 0;
-		}
-	}
-	
-	/* Get packet dimensions */
-	rc = nil_packet_size_req(ip_netif->sess, ip_netif->device_id,
-	    &ip_netif->packet_dimension);
-	if (rc != EOK)
-		return rc;
-	
-	if (ip_netif->packet_dimension.content < IP_MIN_CONTENT) {
-		printf("Maximum transmission unit %zu bytes is too small, at "
-		    "least %d bytes are needed\n",
-		    ip_netif->packet_dimension.content, IP_MIN_CONTENT);
-		ip_netif->packet_dimension.content = IP_MIN_CONTENT;
-	}
-	
-	index = ip_netifs_add(&ip_globals.netifs, ip_netif->device_id, ip_netif);
-	if (index < 0)
-		return index;
-	
-	if (gateway.s_addr) {
-		/* The default gateway */
-		ip_globals.gateway.address.s_addr = 0;
-		ip_globals.gateway.netmask.s_addr = 0;
-		ip_globals.gateway.gateway.s_addr = gateway.s_addr;
-		ip_globals.gateway.netif = ip_netif;
-		
-		char defgateway[INET_ADDRSTRLEN];
-		inet_ntop(AF_INET, (uint8_t *) &gateway.s_addr,
-		    defgateway, INET_ADDRSTRLEN);
-		printf("%s: Default gateway (%s)\n", NAME, defgateway);
-	}
-	
-	return EOK;
-}
-
-static int ip_device_req_local(nic_device_id_t device_id, services_t netif)
-{
-	ip_netif_t *ip_netif;
-	ip_route_t *route;
-	int index;
-	int rc;
-
-	ip_netif = (ip_netif_t *) malloc(sizeof(ip_netif_t));
-	if (!ip_netif)
-		return ENOMEM;
-
-	rc = ip_routes_initialize(&ip_netif->routes);
-	if (rc != EOK) {
-		free(ip_netif);
-		return rc;
-	}
-	
-	ip_netif->device_id = device_id;
-	ip_netif->service = netif;
-	ip_netif->state = NIC_STATE_STOPPED;
-	
-	fibril_rwlock_write_lock(&ip_globals.netifs_lock);
-
-	rc = ip_netif_initialize(ip_netif);
-	if (rc != EOK) {
-		fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
-		ip_routes_destroy(&ip_netif->routes, free);
-		free(ip_netif);
-		return rc;
-	}
-	if (ip_netif->arp)
-		ip_netif->arp->usage++;
-
-	/* Print the settings */
-	printf("%s: Device registered (id: %d, ipv: %d, conf: %s)\n",
-	    NAME, ip_netif->device_id, ip_netif->ipv,
-	    ip_netif->dhcp ? "dhcp" : "static");
-	
-	// TODO ipv6 addresses
-	
-	char address[INET_ADDRSTRLEN];
-	char netmask[INET_ADDRSTRLEN];
-	char gateway[INET_ADDRSTRLEN];
-	
-	for (index = 0; index < ip_routes_count(&ip_netif->routes); index++) {
-		route = ip_routes_get_index(&ip_netif->routes, index);
-		if (route) {
-			inet_ntop(AF_INET, (uint8_t *) &route->address.s_addr,
-			    address, INET_ADDRSTRLEN);
-			inet_ntop(AF_INET, (uint8_t *) &route->netmask.s_addr,
-			    netmask, INET_ADDRSTRLEN);
-			inet_ntop(AF_INET, (uint8_t *) &route->gateway.s_addr,
-			    gateway, INET_ADDRSTRLEN);
-			printf("%s: Route %d (address: %s, netmask: %s, "
-			    "gateway: %s)\n", NAME, index, address, netmask,
-			    gateway);
-		}
-	}
-	
-	inet_ntop(AF_INET, (uint8_t *) &ip_netif->broadcast.s_addr, address,
-	    INET_ADDRSTRLEN);
-	fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
-
-	printf("%s: Broadcast (%s)\n", NAME, address);
-
-	return EOK;
-}
-
-/** Searches the network interfaces if there is a suitable route.
- *
- * @param[in] netif	The network interface to be searched for routes. May be
- *			NULL.
- * @param[in] destination The destination address.
- * @return		The found route.
- * @return		NULL if no route was found.
- */
-static ip_route_t *ip_netif_find_route(ip_netif_t *netif,
-    in_addr_t destination)
-{
-	int index;
-	ip_route_t *route;
-	
-	if (!netif)
-		return NULL;
-	
-	/* Start with the first one (the direct route) */
-	for (index = 0; index < ip_routes_count(&netif->routes); index++) {
-		route = ip_routes_get_index(&netif->routes, index);
-		if ((route) &&
-		    ((route->address.s_addr & route->netmask.s_addr) ==
-		    (destination.s_addr & route->netmask.s_addr)))
-			return route;
-	}
-
-	return NULL;
-}
-
-/** Searches all network interfaces if there is a suitable route.
- *
- * @param[in] destination The destination address.
- * @return		The found route.
- * @return		NULL if no route was found.
- */
-static ip_route_t *ip_find_route(in_addr_t destination) {
-	int index;
-	ip_route_t *route;
-	ip_netif_t *netif;
-
-	/* Start with the last netif - the newest one */
-	index = ip_netifs_count(&ip_globals.netifs) - 1;
-	while (index >= 0) {
-		netif = ip_netifs_get_index(&ip_globals.netifs, index);
-		if (netif && (netif->state == NIC_STATE_ACTIVE)) {
-			route = ip_netif_find_route(netif, destination);
-			if (route)
-				return route;
-		}
-		index--;
-	}
-
-	return &ip_globals.gateway;
-}
-
-/** Returns the network interface's IP address.
- *
- * @param[in] netif	The network interface.
- * @return		The IP address.
- * @return		NULL if no IP address was found.
- */
-static in_addr_t *ip_netif_address(ip_netif_t *netif)
-{
-	ip_route_t *route;
-
-	route = ip_routes_get_index(&netif->routes, 0);
-	return route ? &route->address : NULL;
-}
-
-/** Copies the fragment header.
- *
- * Copies only the header itself and relevant IP options.
- *
- * @param[out] last	The created header.
- * @param[in] first	The original header to be copied.
- */
-static void ip_create_last_header(ip_header_t *last, ip_header_t *first)
-{
-	ip_option_t *option;
-	size_t next;
-	size_t length;
-
-	/* Copy first itself */
-	memcpy(last, first, sizeof(ip_header_t));
-	length = sizeof(ip_header_t);
-	next = sizeof(ip_header_t);
-
-	/* Process all IP options */
-	while (next < GET_IP_HEADER_LENGTH(first)) {
-		option = (ip_option_t *) (((uint8_t *) first) + next);
-		/* Skip end or noop */
-		if ((option->type == IPOPT_END) ||
-		    (option->type == IPOPT_NOOP)) {
-			next++;
-		} else {
-			/* Copy if told so or skip */
-			if (IPOPT_COPIED(option->type)) {
-				memcpy(((uint8_t *) last) + length,
-				    ((uint8_t *) first) + next, option->length);
-				length += option->length;
-			}
-			/* Next option */
-			next += option->length;
-		}
-	}
-
-	/* Align 4 byte boundary */
-	if (length % 4) {
-		bzero(((uint8_t *) last) + length, 4 - (length % 4));
-		SET_IP_HEADER_LENGTH(last, (length / 4 + 1));
-	} else {
-		SET_IP_HEADER_LENGTH(last, (length / 4));
-	}
-
-	last->header_checksum = 0;
-}
-
-/** Prepares the outgoing packet or the packet queue.
- *
- * The packet queue is a fragmented packet
- * Updates the first packet's IP header.
- * Prefixes the additional packets with fragment headers.
- *
- * @param[in] source	The source address.
- * @param[in] dest	The destination address.
- * @param[in,out] packet The packet to be sent.
- * @param[in] destination The destination hardware address.
- * @return		EOK on success.
- * @return		EINVAL if the packet is too small to contain the IP
- *			header.
- * @return		EINVAL if the packet is too long than the IP allows.
- * @return		ENOMEM if there is not enough memory left.
- * @return		Other error codes as defined for the packet_set_addr()
- *			function.
- */
-static int ip_prepare_packet(in_addr_t *source, in_addr_t dest,
-    packet_t *packet, measured_string_t *destination)
-{
-	size_t length;
-	ip_header_t *header;
-	ip_header_t *last_header;
-	ip_header_t *middle_header;
-	packet_t *next;
-	int rc;
-
-	length = packet_get_data_length(packet);
-	if ((length < sizeof(ip_header_t)) || (length > IP_MAX_CONTENT))
-		return EINVAL;
-
-	header = (ip_header_t *) packet_get_data(packet);
-	if (destination) {
-		rc = packet_set_addr(packet, NULL, (uint8_t *) destination->value,
-		    destination->length);
-	} else {
-		rc = packet_set_addr(packet, NULL, NULL, 0);
-	}
-	if (rc != EOK)
-		return rc;
-	
-	SET_IP_HEADER_VERSION(header, IPV4);
-	SET_IP_HEADER_FRAGMENT_OFFSET_HIGH(header, 0);
-	header->fragment_offset_low = 0;
-	header->header_checksum = 0;
-	if (source)
-		header->source_address = source->s_addr;
-	header->destination_address = dest.s_addr;
-
-	fibril_rwlock_write_lock(&ip_globals.lock);
-	ip_globals.packet_counter++;
-	header->identification = htons(ip_globals.packet_counter);
-	fibril_rwlock_write_unlock(&ip_globals.lock);
-
-	if (pq_next(packet)) {
-		last_header = (ip_header_t *) malloc(IP_HEADER_LENGTH(header));
-		if (!last_header)
-			return ENOMEM;
-		ip_create_last_header(last_header, header);
-		next = pq_next(packet);
-		while (pq_next(next)) {
-			middle_header = (ip_header_t *) packet_prefix(next,
-			    IP_HEADER_LENGTH(last_header));
-			if (!middle_header) {
-				free(last_header);
-				return ENOMEM;
-			}
-
-			memcpy(middle_header, last_header,
-			    IP_HEADER_LENGTH(last_header));
-			SET_IP_HEADER_FLAGS(header,
-			    (GET_IP_HEADER_FLAGS(header) | IPFLAG_MORE_FRAGMENTS));
-			middle_header->total_length =
-			    htons(packet_get_data_length(next));
-			SET_IP_HEADER_FRAGMENT_OFFSET_HIGH(middle_header,
-			    IP_COMPUTE_FRAGMENT_OFFSET_HIGH(length));
-			middle_header->fragment_offset_low =
-			    IP_COMPUTE_FRAGMENT_OFFSET_LOW(length);
-			middle_header->header_checksum =
-			    IP_HEADER_CHECKSUM(middle_header);
-			if (destination) {
-				rc = packet_set_addr(next, NULL,
-				    (uint8_t *) destination->value,
-				    destination->length);
-				if (rc != EOK) {
-				    	free(last_header);
-					return rc;
-				}
-			}
-			length += packet_get_data_length(next);
-			next = pq_next(next);
-		}
-
-		middle_header = (ip_header_t *) packet_prefix(next,
-		    IP_HEADER_LENGTH(last_header));
-		if (!middle_header) {
-			free(last_header);
-			return ENOMEM;
-		}
-
-		memcpy(middle_header, last_header,
-		    IP_HEADER_LENGTH(last_header));
-		middle_header->total_length =
-		    htons(packet_get_data_length(next));
-		SET_IP_HEADER_FRAGMENT_OFFSET_HIGH(middle_header,
-		    IP_COMPUTE_FRAGMENT_OFFSET_HIGH(length));
-		middle_header->fragment_offset_low =
-		    IP_COMPUTE_FRAGMENT_OFFSET_LOW(length);
-		middle_header->header_checksum =
-		    IP_HEADER_CHECKSUM(middle_header);
-		if (destination) {
-			rc = packet_set_addr(next, NULL,
-			    (uint8_t *) destination->value,
-			    destination->length);
-			if (rc != EOK) {
-				free(last_header);
-				return rc;
-			}
-		}
-		length += packet_get_data_length(next);
-		free(last_header);
-		SET_IP_HEADER_FLAGS(header,
-		    (GET_IP_HEADER_FLAGS(header) | IPFLAG_MORE_FRAGMENTS));
-	}
-
-	header->total_length = htons(length);
-	/* Unnecessary for all protocols */
-	header->header_checksum = IP_HEADER_CHECKSUM(header);
-
-	return EOK;
-}
-
-/** Fragments the packet from the end.
- *
- * @param[in] packet	The packet to be fragmented.
- * @param[in,out] new_packet The new packet fragment.
- * @param[in,out] header The original packet header.
- * @param[in,out] new_header The new packet fragment header.
- * @param[in] length	The new fragment length.
- * @param[in] src	The source address.
- * @param[in] dest	The destiantion address.
- * @param[in] addrlen	The address length.
- * @return		EOK on success.
- * @return		ENOMEM if the target packet is too small.
- * @return		Other error codes as defined for the packet_set_addr()
- *			function.
- * @return		Other error codes as defined for the pq_insert_after()
- *			function.
- */
-static int ip_fragment_packet_data(packet_t *packet, packet_t *new_packet,
-    ip_header_t *header, ip_header_t *new_header, size_t length,
-    const struct sockaddr *src, const struct sockaddr *dest, socklen_t addrlen)
-{
-	void *data;
-	size_t offset;
-	int rc;
-
-	data = packet_suffix(new_packet, length);
-	if (!data)
-		return ENOMEM;
-
-	memcpy(data, ((void *) header) + IP_TOTAL_LENGTH(header) - length,
-	    length);
-	
-	rc = packet_trim(packet, 0, length);
-	if (rc != EOK)
-		return rc;
-	
-	header->total_length = htons(IP_TOTAL_LENGTH(header) - length);
-	new_header->total_length = htons(IP_HEADER_LENGTH(new_header) + length);
-	offset = IP_FRAGMENT_OFFSET(header) + IP_HEADER_DATA_LENGTH(header);
-	SET_IP_HEADER_FRAGMENT_OFFSET_HIGH(new_header,
-	    IP_COMPUTE_FRAGMENT_OFFSET_HIGH(offset));
-	new_header->fragment_offset_low =
-	    IP_COMPUTE_FRAGMENT_OFFSET_LOW(offset);
-	new_header->header_checksum = IP_HEADER_CHECKSUM(new_header);
-	
-	rc = packet_set_addr(new_packet, (const uint8_t *) src,
-	    (const uint8_t *) dest, addrlen);
-	if (rc != EOK)
-		return rc;
-
-	return pq_insert_after(packet, new_packet);
-}
-
-/** Prefixes a middle fragment header based on the last fragment header to the
- * packet.
- *
- * @param[in] packet	The packet to be prefixed.
- * @param[in] last	The last header to be copied.
- * @return		The prefixed middle header.
- * @return		NULL on error.
- */
-static ip_header_t *ip_create_middle_header(packet_t *packet,
-    ip_header_t *last)
-{
-	ip_header_t *middle;
-
-	middle = (ip_header_t *) packet_suffix(packet, IP_HEADER_LENGTH(last));
-	if (!middle)
-		return NULL;
-	memcpy(middle, last, IP_HEADER_LENGTH(last));
-	SET_IP_HEADER_FLAGS(middle,
-	    (GET_IP_HEADER_FLAGS(middle) | IPFLAG_MORE_FRAGMENTS));
-	return middle;
-}
-
-/** Checks the packet length and fragments it if needed.
- *
- * The new fragments are queued before the original packet.
- *
- * @param[in,out] packet The packet to be checked.
- * @param[in] length	The maximum packet length.
- * @param[in] prefix	The minimum prefix size.
- * @param[in] suffix	The minimum suffix size.
- * @param[in] addr_len	The minimum address length.
- * @return		EOK on success.
- * @return		EINVAL if the packet_get_addr() function fails.
- * @return		EINVAL if the packet does not contain the IP header.
- * @return		EPERM if the packet needs to be fragmented and the
- *			fragmentation is not allowed.
- * @return		ENOMEM if there is not enough memory left.
- * @return		ENOMEM if there is no packet available.
- * @return		ENOMEM if the packet is too small to contain the IP
- *			header.
- * @return		Other error codes as defined for the packet_trim()
- *			function.
- * @return		Other error codes as defined for the
- *			ip_create_middle_header() function.
- * @return		Other error codes as defined for the
- *			ip_fragment_packet_data() function.
- */
-static int
-ip_fragment_packet(packet_t *packet, size_t length, size_t prefix, size_t suffix,
-    socklen_t addr_len)
-{
-	packet_t *new_packet;
-	ip_header_t *header;
-	ip_header_t *middle_header;
-	ip_header_t *last_header;
-	struct sockaddr *src;
-	struct sockaddr *dest;
-	socklen_t addrlen;
-	int result;
-	int rc;
-
-	result = packet_get_addr(packet, (uint8_t **) &src, (uint8_t **) &dest);
-	if (result <= 0)
-		return EINVAL;
-
-	addrlen = (socklen_t) result;
-	if (packet_get_data_length(packet) <= sizeof(ip_header_t))
-		return ENOMEM;
-
-	/* Get header */
-	header = (ip_header_t *) packet_get_data(packet);
-	if (!header)
-		return EINVAL;
-
-	/* Fragmentation forbidden? */
-	if(GET_IP_HEADER_FLAGS(header) & IPFLAG_DONT_FRAGMENT)
-		return EPERM;
-
-	/* Create the last fragment */
-	new_packet = packet_get_4_remote(ip_globals.net_sess, prefix, length,
-	    suffix, ((addrlen > addr_len) ? addrlen : addr_len));
-	if (!new_packet)
-		return ENOMEM;
-
-	/* Allocate as much as originally */
-	last_header = (ip_header_t *) packet_suffix(new_packet,
-	    IP_HEADER_LENGTH(header));
-	if (!last_header)
-		return ip_release_and_return(packet, ENOMEM);
-
-	ip_create_last_header(last_header, header);
-
-	/* Trim the unused space */
-	rc = packet_trim(new_packet, 0,
-	    IP_HEADER_LENGTH(header) - IP_HEADER_LENGTH(last_header));
-	if (rc != EOK)
-		return ip_release_and_return(packet, rc);
-
-	/* Greatest multiple of 8 lower than content */
-	// TODO even fragmentation?
-	length = length & ~0x7;
-	
-	rc = ip_fragment_packet_data(packet, new_packet, header, last_header,
-	    ((IP_HEADER_DATA_LENGTH(header) -
-	    ((length - IP_HEADER_LENGTH(header)) & ~0x7)) %
-	    ((length - IP_HEADER_LENGTH(last_header)) & ~0x7)),
-	    src, dest, addrlen);
-	if (rc != EOK)
-		return ip_release_and_return(packet, rc);
-
-	/* Mark the first as fragmented */
-	SET_IP_HEADER_FLAGS(header,
-	    (GET_IP_HEADER_FLAGS(header) | IPFLAG_MORE_FRAGMENTS));
-
-	/* Create middle fragments */
-	while (IP_TOTAL_LENGTH(header) > length) {
-		new_packet = packet_get_4_remote(ip_globals.net_sess, prefix,
-		    length, suffix,
-		    ((addrlen >= addr_len) ? addrlen : addr_len));
-		if (!new_packet)
-			return ENOMEM;
-
-		middle_header = ip_create_middle_header(new_packet,
-		    last_header);
-		if (!middle_header)
-			return ip_release_and_return(packet, ENOMEM);
-
-		rc = ip_fragment_packet_data(packet, new_packet, header,
-		    middle_header,
-		    (length - IP_HEADER_LENGTH(middle_header)) & ~0x7,
-		    src, dest, addrlen);
-		if (rc != EOK)
-			return ip_release_and_return(packet, rc);
-	}
-
-	/* Finish the first fragment */
-	header->header_checksum = IP_HEADER_CHECKSUM(header);
-
-	return EOK;
-}
-
-/** Check the packet queue lengths and fragments the packets if needed.
- *
- * The ICMP_FRAG_NEEDED error notification may be sent if the packet needs to
- * be fragmented and the fragmentation is not allowed.
- *
- * @param[in,out] packet   Packet or the packet queue to be checked.
- * @param[in]     prefix   Minimum prefix size.
- * @param[in]     content  Maximum content size.
- * @param[in]     suffix   Minimum suffix size.
- * @param[in]     addr_len Minimum address length.
- * @param[in]     error    Error module service.
- *
- * @return The packet or the packet queue of the allowed length.
- * @return NULL if there are no packets left.
- *
- */
-static packet_t *ip_split_packet(packet_t *packet, size_t prefix, size_t content,
-    size_t suffix, socklen_t addr_len, services_t error)
-{
-	size_t length;
-	packet_t *next;
-	packet_t *new_packet;
-	int result;
-	async_sess_t *sess;
-	
-	next = packet;
-	/* Check all packets */
-	while (next) {
-		length = packet_get_data_length(next);
-		
-		if (length <= content) {
-			next = pq_next(next);
-			continue;
-		}
-
-		/* Too long */
-		result = ip_fragment_packet(next, content, prefix,
-		    suffix, addr_len);
-		if (result != EOK) {
-			new_packet = pq_detach(next);
-			if (next == packet) {
-				/* The new first packet of the queue */
-				packet = new_packet;
-			}
-			/* Fragmentation needed? */
-			if (result == EPERM) {
-				sess = ip_prepare_icmp_and_get_session(error, next, NULL);
-				if (sess) {
-					/* Fragmentation necessary ICMP */
-					icmp_destination_unreachable_msg(sess,
-					    ICMP_FRAG_NEEDED, content, next);
-				}
-			} else {
-				pq_release_remote(ip_globals.net_sess,
-				    packet_get_id(next));
-			}
-
-			next = new_packet;
-			continue;
-		}
-
-		next = pq_next(next);
-	}
-
-	return packet;
-}
-
-/** Send the packet or the packet queue via the specified route.
- *
- * The ICMP_HOST_UNREACH error notification may be sent if route hardware
- * destination address is found.
- *
- * @param[in,out] packet Packet to be sent.
- * @param[in]     netif  Target network interface.
- * @param[in]     route  Target route.
- * @param[in]     src    Source address.
- * @param[in]     dest   Destination address.
- * @param[in]     error  Error module service.
- *
- * @return EOK on success.
- * @return Other error codes as defined for arp_translate_req().
- * @return Other error codes as defined for ip_prepare_packet().
- *
- */
-static int ip_send_route(packet_t *packet, ip_netif_t *netif,
-    ip_route_t *route, in_addr_t *src, in_addr_t dest, services_t error)
-{
-	measured_string_t destination;
-	measured_string_t *translation;
-	uint8_t *data;
-	async_sess_t *sess;
-	int rc;
-
-	/* Get destination hardware address */
-	if (netif->arp && (route->address.s_addr != dest.s_addr)) {
-		destination.value = route->gateway.s_addr ?
-		    (uint8_t *) &route->gateway.s_addr : (uint8_t *) &dest.s_addr;
-		destination.length = sizeof(dest.s_addr);
-
-		rc = arp_translate_req(netif->arp->sess, netif->device_id,
-		    SERVICE_IP, &destination, &translation, &data);
-		if (rc != EOK) {
-			pq_release_remote(ip_globals.net_sess,
-			    packet_get_id(packet));
-			return rc;
-		}
-
-		if (!translation || !translation->value) {
-			if (translation) {
-				free(translation);
-				free(data);
-			}
-			sess = ip_prepare_icmp_and_get_session(error, packet,
-			    NULL);
-			if (sess) {
-				/* Unreachable ICMP if no routing */
-				icmp_destination_unreachable_msg(sess,
-				    ICMP_HOST_UNREACH, 0, packet);
-			}
-			return EINVAL;
-		}
-
-	} else {
-		translation = NULL;
-	}
-
-	rc = ip_prepare_packet(src, dest, packet, translation);
-	if (rc != EOK) {
-		pq_release_remote(ip_globals.net_sess, packet_get_id(packet));
-	} else {
-		packet = ip_split_packet(packet, netif->packet_dimension.prefix,
-		    netif->packet_dimension.content,
-		    netif->packet_dimension.suffix,
-		    netif->packet_dimension.addr_len, error);
-		if (packet) {
-			nil_send_msg(netif->sess, netif->device_id, packet,
-			    SERVICE_IP);
-		}
-	}
-
-	if (translation) {
-		free(translation);
-		free(data);
-	}
-
-	return rc;
-}
-
-static int ip_send_msg_local(nic_device_id_t device_id, packet_t *packet,
-    services_t sender, services_t error)
-{
-	int addrlen;
-	ip_netif_t *netif;
-	ip_route_t *route;
-	struct sockaddr *addr;
-	struct sockaddr_in *address_in;
-	in_addr_t *dest;
-	in_addr_t *src;
-	async_sess_t *sess;
-	int rc;
-
-	/*
-	 * Addresses in the host byte order
-	 * Should be the next hop address or the target destination address
-	 */
-	addrlen = packet_get_addr(packet, NULL, (uint8_t **) &addr);
-	if (addrlen < 0)
-		return ip_release_and_return(packet, addrlen);
-	if ((size_t) addrlen < sizeof(struct sockaddr))
-		return ip_release_and_return(packet, EINVAL);
-
-	switch (addr->sa_family) {
-	case AF_INET:
-		if (addrlen != sizeof(struct sockaddr_in))
-			return ip_release_and_return(packet, EINVAL);
-		address_in = (struct sockaddr_in *) addr;
-		dest = &address_in->sin_addr;
-		if (!dest->s_addr)
-			dest->s_addr = IPV4_LOCALHOST_ADDRESS;
-		break;
-	case AF_INET6:
-	default:
-		return ip_release_and_return(packet, EAFNOSUPPORT);
-	}
-
-	netif = NULL;
-	route = NULL;
-	fibril_rwlock_read_lock(&ip_globals.netifs_lock);
-
-	/* Device specified? */
-	if (device_id > 0) {
-		netif = ip_netifs_find(&ip_globals.netifs, device_id);
-		route = ip_netif_find_route(netif, *dest);
-		if (netif && !route && (ip_globals.gateway.netif == netif))
-			route = &ip_globals.gateway;
-	}
-
-	if (!route) {
-		route = ip_find_route(*dest);
-		netif = route ? route->netif : NULL;
-	}
-	if (!netif || !route) {
-		fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
-		sess = ip_prepare_icmp_and_get_session(error, packet, NULL);
-		if (sess) {
-			/* Unreachable ICMP if no routing */
-			icmp_destination_unreachable_msg(sess,
-			    ICMP_NET_UNREACH, 0, packet);
-		}
-		return ENOENT;
-	}
-
-	if (error) {
-		/*
-		 * Do not send for broadcast, anycast packets or network
-		 * broadcast.
-		 */
-		if (!dest->s_addr || !(~dest->s_addr) ||
-		    !(~((dest->s_addr & ~route->netmask.s_addr) |
-		    route->netmask.s_addr)) ||
-		    (!(dest->s_addr & ~route->netmask.s_addr))) {
-			return ip_release_and_return(packet, EINVAL);
-		}
-	}
-	
-	/* If the local host is the destination */
-	if ((route->address.s_addr == dest->s_addr) &&
-	    (dest->s_addr != IPV4_LOCALHOST_ADDRESS)) {
-		/* Find the loopback device to deliver */
-		dest->s_addr = IPV4_LOCALHOST_ADDRESS;
-		route = ip_find_route(*dest);
-		netif = route ? route->netif : NULL;
-		if (!netif || !route) {
-			fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
-			sess = ip_prepare_icmp_and_get_session(error, packet,
-			    NULL);
-			if (sess) {
-				/* Unreachable ICMP if no routing */
-				icmp_destination_unreachable_msg(sess,
-				    ICMP_HOST_UNREACH, 0, packet);
-			}
-			return ENOENT;
-		}
-	}
-	
-	src = ip_netif_address(netif);
-	if (!src) {
-		fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
-		return ip_release_and_return(packet, ENOENT);
-	}
-
-	rc = ip_send_route(packet, netif, route, src, *dest, error);
-	fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
-
-	return rc;
-}
-
-/** Updates the device state.
- *
- * @param[in] device_id	The device identifier.
- * @param[in] state	The new state value.
- * @return		EOK on success.
- * @return		ENOENT if device is not found.
- */
-static int ip_device_state_message(nic_device_id_t device_id,
-    nic_device_state_t state)
-{
-	ip_netif_t *netif;
-
-	fibril_rwlock_write_lock(&ip_globals.netifs_lock);
-	/* Find the device */
-	netif = ip_netifs_find(&ip_globals.netifs, device_id);
-	if (!netif) {
-		fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
-		return ENOENT;
-	}
-	netif->state = state;
-	fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
-
-	printf("%s: Device %d changed state to '%s'\n", NAME, device_id,
-	    nic_device_state_to_string(state));
-
-	return EOK;
-}
-
-/** Returns the packet destination address from the IP header.
- *
- * @param[in] header	The packet IP header to be read.
- * @return		The packet destination address.
- */
-static in_addr_t ip_get_destination(ip_header_t *header)
-{
-	in_addr_t destination;
-
-	// TODO search set ipopt route?
-	destination.s_addr = header->destination_address;
-	return destination;
-}
-
-/** Delivers the packet to the local host.
- *
- * The packet is either passed to another module or released on error.
- * The ICMP_PROT_UNREACH error notification may be sent if the protocol is not
- * found.
- *
- * @param[in] device_id	The source device identifier.
- * @param[in] packet	The packet to be delivered.
- * @param[in] header	The first packet IP header. May be NULL.
- * @param[in] error	The packet error service.
- * @return		EOK on success.
- * @return		ENOTSUP if the packet is a fragment.
- * @return		EAFNOSUPPORT if the address family is not supported.
- * @return		ENOENT if the target protocol is not found.
- * @return		Other error codes as defined for the packet_set_addr()
- *			function.
- * @return		Other error codes as defined for the packet_trim()
- *			function.
- * @return		Other error codes as defined for the protocol specific
- *			tl_received_msg() function.
- */
-static int ip_deliver_local(nic_device_id_t device_id, packet_t *packet,
-    ip_header_t *header, services_t error)
-{
-	ip_proto_t *proto;
-	async_sess_t *sess;
-	services_t service;
-	tl_received_msg_t received_msg;
-	struct sockaddr *src;
-	struct sockaddr *dest;
-	struct sockaddr_in src_in;
-	struct sockaddr_in dest_in;
-	socklen_t addrlen;
-	int rc;
-
-	if ((GET_IP_HEADER_FLAGS(header) & IPFLAG_MORE_FRAGMENTS) ||
-	    IP_FRAGMENT_OFFSET(header)) {
-		// TODO fragmented
-		return ENOTSUP;
-	}
-	
-	switch (GET_IP_HEADER_VERSION(header)) {
-	case IPVERSION:
-		addrlen = sizeof(src_in);
-		bzero(&src_in, addrlen);
-		src_in.sin_family = AF_INET;
-		memcpy(&dest_in, &src_in, addrlen);
-		memcpy(&src_in.sin_addr.s_addr, &header->source_address,
-		    sizeof(header->source_address));
-		memcpy(&dest_in.sin_addr.s_addr, &header->destination_address,
-		    sizeof(header->destination_address));
-		src = (struct sockaddr *) &src_in;
-		dest = (struct sockaddr *) &dest_in;
-		break;
-
-	default:
-		return ip_release_and_return(packet, EAFNOSUPPORT);
-	}
-
-	rc = packet_set_addr(packet, (uint8_t *) src, (uint8_t *) dest,
-	    addrlen);
-	if (rc != EOK)
-		return ip_release_and_return(packet, rc);
-
-	/* Trim padding if present */
-	if (!error &&
-	    (IP_TOTAL_LENGTH(header) < packet_get_data_length(packet))) {
-		rc = packet_trim(packet, 0,
-		    packet_get_data_length(packet) - IP_TOTAL_LENGTH(header));
-		if (rc != EOK)
-			return ip_release_and_return(packet, rc);
-	}
-
-	fibril_rwlock_read_lock(&ip_globals.protos_lock);
-
-	proto = ip_protos_find(&ip_globals.protos, header->protocol);
-	if (!proto) {
-		fibril_rwlock_read_unlock(&ip_globals.protos_lock);
-		sess = ip_prepare_icmp_and_get_session(error, packet, header);
-		if (sess) {
-			/* Unreachable ICMP */
-			icmp_destination_unreachable_msg(sess,
-			    ICMP_PROT_UNREACH, 0, packet);
-		}
-		return ENOENT;
-	}
-
-	if (proto->received_msg) {
-		service = proto->service;
-		received_msg = proto->received_msg;
-		fibril_rwlock_read_unlock(&ip_globals.protos_lock);
-		rc = received_msg(device_id, packet, service, error);
-	} else {
-		rc = tl_received_msg(proto->sess, device_id, packet,
-		    proto->service, error);
-		fibril_rwlock_read_unlock(&ip_globals.protos_lock);
-	}
-
-	return rc;
-}
-
-/** Processes the received packet.
- *
- * The packet is either passed to another module or released on error.
- *
- * The ICMP_PARAM_POINTER error notification may be sent if the checksum is
- * invalid.
- * The ICMP_EXC_TTL error notification may be sent if the TTL is less than two.
- * The ICMP_HOST_UNREACH error notification may be sent if no route was found.
- * The ICMP_HOST_UNREACH error notification may be sent if the packet is for
- * another host and the routing is disabled.
- *
- * @param[in] device_id	The source device identifier.
- * @param[in] packet	The received packet to be processed.
- * @return		EOK on success.
- * @return		EINVAL if the TTL is less than two.
- * @return		EINVAL if the checksum is invalid.
- * @return		EAFNOSUPPORT if the address family is not supported.
- * @return		ENOENT if no route was found.
- * @return		ENOENT if the packet is for another host and the routing
- *			is disabled.
- */
-static int ip_process_packet(nic_device_id_t device_id, packet_t *packet)
-{
-	ip_header_t *header;
-	in_addr_t dest;
-	ip_route_t *route;
-	async_sess_t *sess;
-	struct sockaddr *addr;
-	struct sockaddr_in addr_in;
-	socklen_t addrlen;
-	int rc;
-	
-	header = (ip_header_t *) packet_get_data(packet);
-	if (!header)
-		return ip_release_and_return(packet, ENOMEM);
-
-	/* Checksum */
-	if ((header->header_checksum) &&
-	    (IP_HEADER_CHECKSUM(header) != IP_CHECKSUM_ZERO)) {
-		sess = ip_prepare_icmp_and_get_session(0, packet, header);
-		if (sess) {
-			/* Checksum error ICMP */
-			icmp_parameter_problem_msg(sess, ICMP_PARAM_POINTER,
-			    ((size_t) ((void *) &header->header_checksum)) -
-			    ((size_t) ((void *) header)), packet);
-		}
-		return EINVAL;
-	}
-
-	if (header->ttl <= 1) {
-		sess = ip_prepare_icmp_and_get_session(0, packet, header);
-		if (sess) {
-			/* TTL exceeded ICMP */
-			icmp_time_exceeded_msg(sess, ICMP_EXC_TTL, packet);
-		}
-		return EINVAL;
-	}
-	
-	/* Process ipopt and get destination */
-	dest = ip_get_destination(header);
-
-	/* Set the destination address */
-	switch (GET_IP_HEADER_VERSION(header)) {
-	case IPVERSION:
-		addrlen = sizeof(addr_in);
-		bzero(&addr_in, addrlen);
-		addr_in.sin_family = AF_INET;
-		memcpy(&addr_in.sin_addr.s_addr, &dest, sizeof(dest));
-		addr = (struct sockaddr *) &addr_in;
-		break;
-
-	default:
-		return ip_release_and_return(packet, EAFNOSUPPORT);
-	}
-
-	rc = packet_set_addr(packet, NULL, (uint8_t *) &addr, addrlen);
-	if (rc != EOK)
-		return rc;
-	
-	route = ip_find_route(dest);
-	if (!route) {
-		sess = ip_prepare_icmp_and_get_session(0, packet, header);
-		if (sess) {
-			/* Unreachable ICMP */
-			icmp_destination_unreachable_msg(sess,
-			    ICMP_HOST_UNREACH, 0, packet);
-		}
-		return ENOENT;
-	}
-
-	if (route->address.s_addr == dest.s_addr) {
-		/* Local delivery */
-		return ip_deliver_local(device_id, packet, header, 0);
-	}
-
-	if (route->netif->routing) {
-		header->ttl--;
-		return ip_send_route(packet, route->netif, route, NULL, dest,
-		    0);
-	}
-
-	sess = ip_prepare_icmp_and_get_session(0, packet, header);
-	if (sess) {
-		/* Unreachable ICMP if no routing */
-		icmp_destination_unreachable_msg(sess, ICMP_HOST_UNREACH, 0,
-		    packet);
-	}
-	
-	return ENOENT;
-}
-
-/** Return the device packet dimensions for sending.
- *
- * @param[in]  device_id Device identifier.
- * @param[out] addr_len  Minimum reserved address length.
- * @param[out] prefix    Minimum reserved prefix size.
- * @param[out] content   Maximum content size.
- * @param[out] suffix    Minimum reserved suffix size.
- *
- * @return EOK on success.
- *
- */
-static int ip_packet_size_message(nic_device_id_t device_id, size_t *addr_len,
-    size_t *prefix, size_t *content, size_t *suffix)
-{
-	ip_netif_t *netif;
-	int index;
-
-	if (!addr_len || !prefix || !content || !suffix)
-		return EBADMEM;
-
-	*content = IP_MAX_CONTENT - IP_PREFIX;
-	fibril_rwlock_read_lock(&ip_globals.netifs_lock);
-	if (device_id < 0) {
-		*addr_len = IP_ADDR;
-		*prefix = 0;
-		*suffix = 0;
-
-		for (index = ip_netifs_count(&ip_globals.netifs) - 1;
-		    index >= 0; index--) {
-			netif = ip_netifs_get_index(&ip_globals.netifs, index);
-			if (!netif)
-				continue;
-			
-			if (netif->packet_dimension.addr_len > *addr_len)
-				*addr_len = netif->packet_dimension.addr_len;
-			
-			if (netif->packet_dimension.prefix > *prefix)
-				*prefix = netif->packet_dimension.prefix;
-				
-			if (netif->packet_dimension.suffix > *suffix)
-				*suffix = netif->packet_dimension.suffix;
-		}
-
-		*prefix = *prefix + IP_PREFIX;
-		*suffix = *suffix + IP_SUFFIX;
-	} else {
-		netif = ip_netifs_find(&ip_globals.netifs, device_id);
-		if (!netif) {
-			fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
-			return ENOENT;
-		}
-
-		*addr_len = (netif->packet_dimension.addr_len > IP_ADDR) ?
-		    netif->packet_dimension.addr_len : IP_ADDR;
-		*prefix = netif->packet_dimension.prefix + IP_PREFIX;
-		*suffix = netif->packet_dimension.suffix + IP_SUFFIX;
-	}
-	fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
-
-	return EOK;
-}
-
-/** Updates the device content length according to the new MTU value.
- *
- * @param[in] device_id	The device identifier.
- * @param[in] mtu	The new mtu value.
- * @return		EOK on success.
- * @return		ENOENT if device is not found.
- */
-static int ip_mtu_changed_message(nic_device_id_t device_id, size_t mtu)
-{
-	ip_netif_t *netif;
-
-	fibril_rwlock_write_lock(&ip_globals.netifs_lock);
-	netif = ip_netifs_find(&ip_globals.netifs, device_id);
-	if (!netif) {
-		fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
-		return ENOENT;
-	}
-	netif->packet_dimension.content = mtu;
-	fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
-
-	printf("%s: Device %d changed MTU to %zu\n", NAME, device_id, mtu);
-
-	return EOK;
-}
-
-/** Process IPC messages from the registered device driver modules
- *
- * @param[in]     iid   Message identifier.
- * @param[in,out] icall Message parameters.
- * @param[in]     arg   Local argument.
- *
- */
-static void ip_receiver(ipc_callid_t iid, ipc_call_t *icall, void *arg)
-{
-	packet_t *packet;
-	int rc;
-	
-	while (true) {
-		switch (IPC_GET_IMETHOD(*icall)) {
-		case NET_IL_DEVICE_STATE:
-			rc = ip_device_state_message(IPC_GET_DEVICE(*icall),
-			    IPC_GET_STATE(*icall));
-			async_answer_0(iid, (sysarg_t) rc);
-			break;
-		
-		case NET_IL_RECEIVED:
-			rc = packet_translate_remote(ip_globals.net_sess, &packet,
-			    IPC_GET_PACKET(*icall));
-			if (rc == EOK) {
-				do {
-					packet_t *next = pq_detach(packet);
-					ip_process_packet(IPC_GET_DEVICE(*icall), packet);
-					packet = next;
-				} while (packet);
-			}
-			
-			async_answer_0(iid, (sysarg_t) rc);
-			break;
-		
-		case NET_IL_MTU_CHANGED:
-			rc = ip_mtu_changed_message(IPC_GET_DEVICE(*icall),
-			    IPC_GET_MTU(*icall));
-			async_answer_0(iid, (sysarg_t) rc);
-			break;
-		case NET_IL_ADDR_CHANGED:
-			async_answer_0(iid, (sysarg_t) EOK);
-			break;
-
-		default:
-			async_answer_0(iid, (sysarg_t) ENOTSUP);
-		}
-		
-		iid = async_get_call(icall);
-	}
-}
-
-/** Register the transport layer protocol.
- *
- * The traffic of this protocol will be supplied using either the receive
- * function or IPC message.
- *
- * @param[in] protocol     Transport layer module protocol.
- * @param[in] service      Transport layer module service.
- * @param[in] sess         Transport layer module session.
- * @param[in] received_msg Receiving function.
- *
- * @return EOK on success.
- * @return EINVAL if the protocol parameter and/or the service
- *         parameter is zero.
- * @return EINVAL if the phone parameter is not a positive number
- *         and the tl_receive_msg is NULL.
- * @return ENOMEM if there is not enough memory left.
- *
- */
-static int ip_register(int protocol, services_t service, async_sess_t *sess,
-    tl_received_msg_t received_msg)
-{
-	ip_proto_t *proto;
-	int index;
-
-	if ((!protocol) || (!service) || ((!sess) && (!received_msg)))
-		return EINVAL;
-	
-	proto = (ip_proto_t *) malloc(sizeof(ip_protos_t));
-	if (!proto)
-		return ENOMEM;
-
-	proto->protocol = protocol;
-	proto->service = service;
-	proto->sess = sess;
-	proto->received_msg = received_msg;
-
-	fibril_rwlock_write_lock(&ip_globals.protos_lock);
-	index = ip_protos_add(&ip_globals.protos, proto->protocol, proto);
-	if (index < 0) {
-		fibril_rwlock_write_unlock(&ip_globals.protos_lock);
-		free(proto);
-		return index;
-	}
-	fibril_rwlock_write_unlock(&ip_globals.protos_lock);
-
-	printf("%s: Protocol registered (protocol: %d)\n",
-	    NAME, proto->protocol);
-
-	return EOK;
-}
-
-static int ip_add_route_req_local(nic_device_id_t device_id, in_addr_t address,
-    in_addr_t netmask, in_addr_t gateway)
-{
-	ip_route_t *route;
-	ip_netif_t *netif;
-	int index;
-
-	fibril_rwlock_write_lock(&ip_globals.netifs_lock);
-
-	netif = ip_netifs_find(&ip_globals.netifs, device_id);
-	if (!netif) {
-		fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
-		return ENOENT;
-	}
-
-	route = (ip_route_t *) malloc(sizeof(ip_route_t));
-	if (!route) {
-		fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
-		return ENOMEM;
-	}
-
-	route->address.s_addr = address.s_addr;
-	route->netmask.s_addr = netmask.s_addr;
-	route->gateway.s_addr = gateway.s_addr;
-	route->netif = netif;
-	index = ip_routes_add(&netif->routes, route);
-	if (index < 0)
-		free(route);
-
-	fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
-	
-	return index;
-}
-
-static int ip_set_gateway_req_local(nic_device_id_t device_id,
-    in_addr_t gateway)
-{
-	ip_netif_t *netif;
-
-	fibril_rwlock_write_lock(&ip_globals.netifs_lock);
-
-	netif = ip_netifs_find(&ip_globals.netifs, device_id);
-	if (!netif) {
-		fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
-		return ENOENT;
-	}
-
-	ip_globals.gateway.address.s_addr = 0;
-	ip_globals.gateway.netmask.s_addr = 0;
-	ip_globals.gateway.gateway.s_addr = gateway.s_addr;
-	ip_globals.gateway.netif = netif;
-	
-	fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
-	
-	return EOK;
-}
-
-/** Notify the IP module about the received error notification packet.
- *
- * @param[in] device_id Device identifier.
- * @param[in] packet    Received packet or the received packet queue.
- * @param[in] target    Target internetwork module service to be
- *                      delivered to.
- * @param[in] error     Packet error reporting service. Prefixes the
- *                      received packet.
- *
- * @return EOK on success.
- *
- */
-static int ip_received_error_msg_local(nic_device_id_t device_id,
-    packet_t *packet, services_t target, services_t error)
-{
-	uint8_t *data;
-	int offset;
-	icmp_type_t type;
-	icmp_code_t code;
-	ip_netif_t *netif;
-	measured_string_t address;
-	ip_route_t *route;
-	ip_header_t *header;
-
-	switch (error) {
-	case SERVICE_ICMP:
-		offset = icmp_client_process_packet(packet, &type, &code, NULL,
-		    NULL);
-		if (offset < 0)
-			return ip_release_and_return(packet, ENOMEM);
-
-		data = packet_get_data(packet);
-		header = (ip_header_t *)(data + offset);
-
-		/* Destination host unreachable? */
-		if ((type != ICMP_DEST_UNREACH) ||
-		    (code != ICMP_HOST_UNREACH)) {
-			/* No, something else */
-			break;
-		}
-
-		fibril_rwlock_read_lock(&ip_globals.netifs_lock);
-
-		netif = ip_netifs_find(&ip_globals.netifs, device_id);
-		if (!netif || !netif->arp) {
-			fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
-			break;
-		}
-
-		route = ip_routes_get_index(&netif->routes, 0);
-
-		/* From the same network? */
-		if (route && ((route->address.s_addr & route->netmask.s_addr) ==
-		    (header->destination_address & route->netmask.s_addr))) {
-			/* Clear the ARP mapping if any */
-			address.value = (uint8_t *) &header->destination_address;
-			address.length = sizeof(header->destination_address);
-			arp_clear_address_req(netif->arp->sess,
-			    netif->device_id, SERVICE_IP, &address);
-		}
-
-		fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
-		break;
-
-	default:
-		return ip_release_and_return(packet, ENOTSUP);
-	}
-
-	return ip_deliver_local(device_id, packet, header, error);
-}
-
-static int ip_get_route_req_local(ip_protocol_t protocol,
-    const struct sockaddr *destination, socklen_t addrlen,
-    nic_device_id_t *device_id, void **header, size_t *headerlen)
-{
-	struct sockaddr_in *address_in;
-	in_addr_t *dest;
-	in_addr_t *src;
-	ip_route_t *route;
-	ipv4_pseudo_header_t *header_in;
-
-	if (!destination || (addrlen <= 0))
-		return EINVAL;
-
-	if (!device_id || !header || !headerlen)
-		return EBADMEM;
-
-	if ((size_t) addrlen < sizeof(struct sockaddr))
-		return EINVAL;
-
-	switch (destination->sa_family) {
-	case AF_INET:
-		if (addrlen != sizeof(struct sockaddr_in))
-			return EINVAL;
-		address_in = (struct sockaddr_in *) destination;
-		dest = &address_in->sin_addr;
-		if (!dest->s_addr)
-			dest->s_addr = IPV4_LOCALHOST_ADDRESS;
-		break;
-
-	case AF_INET6:
-	default:
-		return EAFNOSUPPORT;
-	}
-
-	fibril_rwlock_read_lock(&ip_globals.lock);
-	route = ip_find_route(*dest);
-	/* If the local host is the destination */
-	if (route && (route->address.s_addr == dest->s_addr) &&
-	    (dest->s_addr != IPV4_LOCALHOST_ADDRESS)) {
-		/* Find the loopback device to deliver */
-		dest->s_addr = IPV4_LOCALHOST_ADDRESS;
-		route = ip_find_route(*dest);
-	}
-
-	if (!route || !route->netif) {
-		fibril_rwlock_read_unlock(&ip_globals.lock);
-		return ENOENT;
-	}
-
-	*device_id = route->netif->device_id;
-	src = ip_netif_address(route->netif);
-	fibril_rwlock_read_unlock(&ip_globals.lock);
-
-	*headerlen = sizeof(*header_in);
-	header_in = (ipv4_pseudo_header_t *) malloc(*headerlen);
-	if (!header_in)
-		return ENOMEM;
-
-	bzero(header_in, *headerlen);
-	header_in->destination_address = dest->s_addr;
-	header_in->source_address = src->s_addr;
-	header_in->protocol = protocol;
-	header_in->data_length = 0;
-	*header = header_in;
-
-	return EOK;
-}
-
-/** Processes the IP message.
- *
- * @param[in] callid	The message identifier.
- * @param[in] call	The message parameters.
- * @param[out] answer	The message answer parameters.
- * @param[out] answer_count The last parameter for the actual answer in the
- *			answer parameter.
- * @return		EOK on success.
- * @return		ENOTSUP if the message is not known.
- *
- * @see ip_interface.h
- * @see il_remote.h
- * @see IS_NET_IP_MESSAGE()
- */
-int il_module_message(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer,
-    size_t *answer_count)
-{
-	packet_t *packet;
-	struct sockaddr *addr;
-	void *header;
-	size_t headerlen;
-	size_t addrlen;
-	size_t prefix;
-	size_t suffix;
-	size_t content;
-	nic_device_id_t device_id;
-	int rc;
-	
-	*answer_count = 0;
-	
-	if (!IPC_GET_IMETHOD(*call))
-		return EOK;
-	
-	async_sess_t *callback =
-	    async_callback_receive_start(EXCHANGE_SERIALIZE, call);
-	if (callback)
-		return ip_register(IL_GET_PROTO(*call), IL_GET_SERVICE(*call),
-		    callback, NULL);
-	
-	switch (IPC_GET_IMETHOD(*call)) {
-	case NET_IP_DEVICE:
-		return ip_device_req_local(IPC_GET_DEVICE(*call),
-		    IPC_GET_SERVICE(*call));
-	
-	case NET_IP_RECEIVED_ERROR:
-		rc = packet_translate_remote(ip_globals.net_sess, &packet,
-		    IPC_GET_PACKET(*call));
-		if (rc != EOK)
-			return rc;
-		return ip_received_error_msg_local(IPC_GET_DEVICE(*call),
-		    packet, IPC_GET_TARGET(*call), IPC_GET_ERROR(*call));
-	
-	case NET_IP_ADD_ROUTE:
-		return ip_add_route_req_local(IPC_GET_DEVICE(*call),
-		    IP_GET_ADDRESS(*call), IP_GET_NETMASK(*call),
-		    IP_GET_GATEWAY(*call));
-
-	case NET_IP_SET_GATEWAY:
-		return ip_set_gateway_req_local(IPC_GET_DEVICE(*call),
-		    IP_GET_GATEWAY(*call));
-
-	case NET_IP_GET_ROUTE:
-		rc = async_data_write_accept((void **) &addr, false, 0, 0, 0,
-		    &addrlen);
-		if (rc != EOK)
-			return rc;
-		
-		rc = ip_get_route_req_local(IP_GET_PROTOCOL(*call), addr,
-		    (socklen_t) addrlen, &device_id, &header, &headerlen);
-		if (rc != EOK)
-			return rc;
-		
-		IPC_SET_DEVICE(*answer, device_id);
-		IP_SET_HEADERLEN(*answer, headerlen);
-		
-		*answer_count = 2;
-		
-		rc = data_reply(&headerlen, sizeof(headerlen));
-		if (rc == EOK)
-			rc = data_reply(header, headerlen);
-			
-		free(header);
-		return rc;
-	
-	case NET_IP_PACKET_SPACE:
-		rc = ip_packet_size_message(IPC_GET_DEVICE(*call), &addrlen,
-		    &prefix, &content, &suffix);
-		if (rc != EOK)
-			return rc;
-		
-		IPC_SET_ADDR(*answer, addrlen);
-		IPC_SET_PREFIX(*answer, prefix);
-		IPC_SET_CONTENT(*answer, content);
-		IPC_SET_SUFFIX(*answer, suffix);
-		*answer_count = 4;
-		return EOK;
-	
-	case NET_IP_SEND:
-		rc = packet_translate_remote(ip_globals.net_sess, &packet,
-		    IPC_GET_PACKET(*call));
-		if (rc != EOK)
-			return rc;
-		
-		return ip_send_msg_local(IPC_GET_DEVICE(*call), packet, 0,
-		    IPC_GET_ERROR(*call));
-	}
-	
-	return ENOTSUP;
-}
-
-int main(int argc, char *argv[])
-{
-	/* Start the module */
-	return il_module_start(SERVICE_IP);
-}
-
-/** @}
- */
Index: pace/srv/net/il/ip/ip.h
===================================================================
--- uspace/srv/net/il/ip/ip.h	(revision bf31e3f1ebd6e88e0c8425f109e42ccd92b6c9b3)
+++ 	(revision )
@@ -1,162 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup ip
- * @{
- */
-
-/** @file
- * IP module.
- */
-
-#ifndef NET_IP_H_
-#define NET_IP_H_
-
-#include <async.h>
-#include <fibril_synch.h>
-#include <ipc/services.h>
-#include <net/device.h>
-#include <net/inet.h>
-#include <ip_interface.h>
-#include <adt/int_map.h>
-#include <adt/generic_field.h>
-#include <adt/module_map.h>
-
-/** Type definition of the IP global data.
- * @see ip_globals
- */
-typedef struct ip_globals ip_globals_t;
-
-/** Type definition of the IP network interface specific data.
- * @see ip_netif
- */
-typedef struct ip_netif ip_netif_t;
-
-/** Type definition of the IP protocol specific data.
- * @see ip_proto
- */
-typedef struct ip_proto ip_proto_t;
-
-/** Type definition of the IP route specific data.
- *  @see ip_route
- */
-typedef struct ip_route	ip_route_t;
-
-/** IP network interfaces.
- * Maps devices to the IP network interface specific data.
- * @see device.h
- */
-DEVICE_MAP_DECLARE(ip_netifs, ip_netif_t);
-
-/** IP registered protocols.
- * Maps protocols to the IP protocol specific data.
- * @see int_map.h
- */
-INT_MAP_DECLARE(ip_protos, ip_proto_t);
-
-/** IP routing table.
- * @see generic_field.h
- */
-GENERIC_FIELD_DECLARE(ip_routes, ip_route_t);
-
-/** IP network interface specific data. */
-struct ip_netif {
-	/** ARP module. Assigned if using ARP. */
-	module_t *arp;
-	/** Broadcast address. */
-	in_addr_t broadcast;
-	/** Device identifier. */
-	nic_device_id_t device_id;
-	/** Indicates whether using DHCP. */
-	int dhcp;
-	/** IP version. */
-	int ipv;
-	/** Packet dimension. */
-	packet_dimension_t packet_dimension;
-	/** Netif module session. */
-	async_sess_t *sess;
-	/** Routing table. */
-	ip_routes_t routes;
-	/** Indicates whether IP routing is enabled. */
-	int routing;
-	/** Netif module service. */
-	services_t service;
-	/** Device state. */
-	nic_device_state_t state;
-};
-
-/** IP protocol specific data. */
-struct ip_proto {
-	/** Protocol module session. */
-	async_sess_t *sess;
-	/** Protocol number. */
-	int protocol;
-	/** Protocol packet receiving function. */
-	tl_received_msg_t received_msg;
-	/** Protocol module service. */
-	services_t service;
-};
-
-/** IP route specific data. */
-struct ip_route {
-	/** Target address. */
-	in_addr_t address;
-	/** Gateway. */
-	in_addr_t gateway;
-	/** Parent netif. */
-	ip_netif_t *netif;
-	/** Target network mask. */
-	in_addr_t netmask;
-};
-
-/** IP global data. */
-struct ip_globals {
-	/** Default gateway. */
-	ip_route_t gateway;
-	/** Safety lock. */
-	fibril_rwlock_t lock;
-	/** Known support modules. */
-	modules_t modules;
-	/** Networking module session. */
-	async_sess_t *net_sess;
-	/** Registered network interfaces. */
-	ip_netifs_t netifs;
-	/** Netifs safeyt lock. */
-	fibril_rwlock_t netifs_lock;
-	/** Packet counter. */
-	uint16_t packet_counter;
-	/** Registered protocols. */
-	ip_protos_t protos;
-	/** Protocols safety lock. */
-	fibril_rwlock_t protos_lock;
-};
-
-#endif
-
-/** @}
- */
Index: pace/srv/net/net/Makefile
===================================================================
--- uspace/srv/net/net/Makefile	(revision bf31e3f1ebd6e88e0c8425f109e42ccd92b6c9b3)
+++ 	(revision )
@@ -1,48 +1,0 @@
-#
-# Copyright (c) 2005 Martin Decky
-# Copyright (c) 2007 Jakub Jermar
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# - Redistributions of source code must retain the above copyright
-#   notice, this list of conditions and the following disclaimer.
-# - Redistributions in binary form must reproduce the above copyright
-#   notice, this list of conditions and the following disclaimer in the
-#   documentation and/or other materials provided with the distribution.
-# - The name of the author may not be used to endorse or promote products
-#   derived from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-
-USPACE_PREFIX = ../../..
-ROOT_PATH = $(USPACE_PREFIX)/..
-LIBS = $(LIBNET_PREFIX)/libnet.a
-EXTRA_CFLAGS = -I$(LIBNET_PREFIX)/include -I$(LIBNIC_PREFIX)/include \
-    -I$(LIBDRV_PREFIX)/include
-
-COMMON_MAKEFILE = $(ROOT_PATH)/Makefile.common
-CONFIG_MAKEFILE = $(ROOT_PATH)/Makefile.config
-
--include $(COMMON_MAKEFILE)
--include $(CONFIG_MAKEFILE)
-
-BINARY = net
-
-SOURCES = \
-	net.c \
-	packet_server.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/srv/net/net/net.c
===================================================================
--- uspace/srv/net/net/net.c	(revision bf31e3f1ebd6e88e0c8425f109e42ccd92b6c9b3)
+++ 	(revision )
@@ -1,777 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * Copyright (c) 2011 Radim Vansa
- * Copyright (c) 2011 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup net
- * @{
- */
-
-#include <assert.h>
-#include <async.h>
-#include <ctype.h>
-#include <ddi.h>
-#include <errno.h>
-#include <str_error.h>
-#include <malloc.h>
-#include <stdio.h>
-#include <str.h>
-#include <str_error.h>
-#include <ns.h>
-#include <ipc/services.h>
-#include <ipc/net.h>
-#include <ipc/net_net.h>
-#include <ipc/il.h>
-#include <ipc/ip.h>
-#include <ipc/nil.h>
-#include <net/packet.h>
-#include <net/device.h>
-#include <adt/char_map.h>
-#include <adt/generic_char_map.h>
-#include <adt/measured_strings.h>
-#include <adt/module_map.h>
-#include <fibril_synch.h>
-#include <loc.h>
-#include <nic.h>
-#include <nil_remote.h>
-#include <net_interface.h>
-#include <ip_interface.h>
-#include <device/nic.h>
-#include <dirent.h>
-#include <fcntl.h>
-#include <cfg.h>
-#include "net.h"
-#include "packet_server.h"
-
-#define MAX_PATH_LENGTH  1024
-
-/** Networking module global data. */
-net_globals_t net_globals;
-
-GENERIC_CHAR_MAP_IMPLEMENT(measured_strings, measured_string_t);
-DEVICE_MAP_IMPLEMENT(netifs, netif_t);
-LIST_INITIALIZE(netif_list);
-
-static FIBRIL_MUTEX_INITIALIZE(discovery_lock);
-
-/** Add the configured setting to the configuration map.
- *
- * @param[in] configuration The configuration map.
- * @param[in] name          The setting name.
- * @param[in] value         The setting value.
- *
- * @return EOK on success.
- * @return ENOMEM if there is not enough memory left.
- *
- */
-static int add_configuration(measured_strings_t *configuration,
-    const uint8_t *name, const uint8_t *value)
-{
-	int rc;
-	
-	measured_string_t *setting =
-	    measured_string_create_bulk(value, 0);
-	if (!setting)
-		return ENOMEM;
-	
-	/* Add the configuration setting */
-	rc = measured_strings_add(configuration, name, 0, setting);
-	if (rc != EOK) {
-		free(setting);
-		return rc;
-	}
-	
-	return EOK;
-}
-
-/** Generate new system-unique device identifier.
- *
- * @return The system-unique devic identifier.
- *
- */
-static nic_device_id_t generate_new_device_id(void)
-{
-	return device_assign_devno();
-}
-
-static int read_configuration_file(const char *directory, const char *filename,
-    measured_strings_t *configuration)
-{
-	printf("%s: Reading configuration file %s/%s\n", NAME, directory, filename);
-	
-	cfg_file_t cfg;
-	int rc = cfg_load_path(directory, filename, &cfg);
-	if (rc != EOK)
-		return rc;
-	
-	if (cfg_anonymous(&cfg) == NULL) {
-		cfg_unload(&cfg);
-		return ENOENT;
-	}
-	
-	cfg_section_foreach(cfg_anonymous(&cfg), link) {
-		const cfg_entry_t *entry = cfg_entry_instance(link);
-		
-		rc = add_configuration(configuration,
-		    (uint8_t *) entry->key, (uint8_t *) entry->value);
-		if (rc != EOK) {
-			cfg_unload(&cfg);
-			return rc;
-		}
-	}
-	
-	cfg_unload(&cfg);
-	return EOK;
-}
-
-/** Read the network interface specific configuration.
- *
- * @param[in]     name  The network interface name.
- * @param[in,out] netif The network interface structure.
- *
- * @return EOK on success.
- * @return Other error codes as defined for the add_configuration() function.
- *
- */
-static int read_netif_configuration(const char *name, netif_t *netif)
-{
-	return read_configuration_file(CONF_DIR, name, &netif->configuration);
-}
-
-/** Read the networking subsystem global configuration.
- *
- * @return EOK on success.
- * @return Other error codes as defined for the add_configuration() function.
- *
- */
-static int read_configuration(void)
-{
-	return read_configuration_file(CONF_DIR, CONF_GENERAL_FILE,
-	    &net_globals.configuration);
-}
-
-/** Return the configured values.
- *
- * The network interface configuration is searched first.
- *
- * @param[in]  netif_conf    The network interface configuration setting.
- * @param[out] configuration The found configured values.
- * @param[in]  count         The desired settings count.
- * @param[out] data          The found configuration settings data.
- *
- * @return EOK.
- *
- */
-static int net_get_conf(measured_strings_t *netif_conf,
-    measured_string_t *configuration, size_t count)
-{
-	if ((!configuration) || (count <= 0))
-			return EINVAL;
-	
-	size_t index;
-	for (index = 0; index < count; index++) {
-		measured_string_t *setting =
-		    measured_strings_find(netif_conf, configuration[index].value, 0);
-		if (!setting)
-			setting = measured_strings_find(&net_globals.configuration,
-			    configuration[index].value, 0);
-		
-		if (setting) {
-			configuration[index].length = setting->length;
-			configuration[index].value = setting->value;
-		} else {
-			configuration[index].length = 0;
-			configuration[index].value = NULL;
-		}
-	}
-	
-	return EOK;
-}
-
-static int net_get_device_conf(nic_device_id_t device_id,
-    measured_string_t *configuration, size_t count)
-{
-	netif_t *netif = netifs_find(&net_globals.netifs, device_id);
-	if (netif)
-		return net_get_conf(&netif->configuration, configuration, count);
-	else
-		return net_get_conf(NULL, configuration, count);
-}
-
-static int net_get_devices(measured_string_t **devices, size_t *dev_count)
-{
-	if (!devices)
-		return EBADMEM;
-	
-	size_t max_count = netifs_count(&net_globals.netifs);
-	*devices = malloc(max_count * sizeof(measured_string_t));
-	if (*devices == NULL)
-		return ENOMEM;
-	
-	size_t count = 0;
-	for (size_t i = 0; i < max_count; i++) {
-		netif_t *item = netifs_get_index(&net_globals.netifs, i);
-		if (item->sess != NULL) {
-			/* 
-			 * Use format "device_id:device_name"
-			 * FIXME: This typecasting looks really ugly
-			 */
-			(*devices)[count].length = asprintf(
-			    (char **) &((*devices)[count].value),
-			    NIC_DEVICE_PRINT_FMT ":%s", item->id,
-			    (const char *) item->name);
-			count++;
-		}
-	}
-	
-	*dev_count = (size_t) count;
-	return EOK;
-}
-
-static int net_get_devices_count()
-{
-	size_t max_count = netifs_count(&net_globals.netifs);
-	
-	size_t count = 0;
-	for (size_t i = 0; i < max_count; i++) {
-		netif_t *item = netifs_get_index(&net_globals.netifs, i);
-		if (item->sess != NULL)
-			count++;
-	}
-	
-	return count;
-}
-
-static void net_free_devices(measured_string_t *devices, size_t count)
-{
-	size_t i;
-	for (i = 0; i < count; ++i)
-		free(devices[i].value);
-	
-	free(devices);
-}
-
-/** Start the network interface according to its configuration.
- *
- * Register the network interface with the subsystem modules.
- * Start the needed subsystem modules.
- *
- * @param[in] netif The network interface specific data.
- *
- * @return EOK on success.
- * @return EINVAL if there are some settings missing.
- * @return ENOENT if the internet protocol module is not known.
- * @return Other error codes as defined for the netif_probe_req() function.
- * @return Other error codes as defined for the nil_device_req() function.
- * @return Other error codes as defined for the needed internet layer
- *         registering function.
- *
- */
-static int init_device(netif_t *netif, service_id_t sid)
-{
-	printf("%s: Initializing device '%s'\n", NAME, netif->name);
-	
-	netif->sid = sid;
-	netif->sess = loc_service_connect(EXCHANGE_SERIALIZE, netif->sid,
-	    IPC_FLAG_BLOCKING);
-	if (netif->sess == NULL) {
-		printf("%s: Unable to connect to device\n", NAME);
-		return EREFUSED;
-	}
-	
-	/* Optional network interface layer */
-	measured_string_t *setting = measured_strings_find(&netif->configuration,
-	    (uint8_t *) CONF_NIL, 0);
-	if (setting) {
-		netif->nil = get_running_module(&net_globals.modules,
-		    setting->value);
-		if (!netif->nil) {
-			printf("%s: Unable to connect to network interface layer '%s'\n",
-			    NAME, setting->value);
-			return EINVAL;
-		}
-	} else
-		netif->nil = NULL;
-	
-	/* Mandatory internet layer */
-	setting = measured_strings_find(&netif->configuration,
-	    (uint8_t *) CONF_IL, 0);
-	netif->il = get_running_module(&net_globals.modules,
-	    setting->value);
-	if (!netif->il) {
-		printf("%s: Unable to connect to internet layer '%s'\n",
-		    NAME, setting->value);
-		return EINVAL;
-	}
-	
-	/* Network interface layer startup */
-	int rc;
-	services_t nil_service;
-	if (netif->nil) {
-		setting = measured_strings_find(&netif->configuration,
-		    (uint8_t *) CONF_MTU, 0);
-		if (!setting)
-			setting = measured_strings_find(&net_globals.configuration,
-			    (uint8_t *) CONF_MTU, 0);
-		
-		int mtu = setting ?
-		    strtol((const char *) setting->value, NULL, 10) : 0;
-		rc = nil_device_req(netif->nil->sess, netif->id,
-		    netif->sid, mtu);
-		if (rc != EOK) {
-			printf("%s: Unable to start network interface layer\n",
-			    NAME);
-			return rc;
-		}
-		
-		nil_service = netif->nil->service;
-	} else
-		nil_service = -1;
-	
-	/* Inter-network layer startup */
-	switch (netif->il->service) {
-	case SERVICE_IP:
-		rc = ip_device_req(netif->il->sess, netif->id, nil_service);
-		if (rc != EOK) {
-			printf("%s: Unable to start internet layer\n", NAME);
-			return rc;
-		}
-		
-		break;
-	default:
-		printf("%s: Unknown service\n", NAME);
-		return ENOENT;
-	}
-	
-	printf("%s: Activating device '%s'\n", NAME, netif->name);
-	list_append(&netif->netif_list, &netif_list);
-	return nic_set_state(netif->sess, NIC_STATE_ACTIVE);
-}
-
-static int net_nic_ready(service_id_t sid)
-{
-	int rc;
-	char *hwpath;
-	
-	rc = loc_service_get_name(sid, &hwpath);
-	if (rc != EOK) {
-		printf("%s: Failed getting name of service '%u'\n",
-		    NAME, (unsigned) sid);
-		return EINVAL;
-	}
-	
-	int index = char_map_find(&net_globals.netif_hwpaths,
-	    (uint8_t *) hwpath, 0);
-	
-	if (index == CHAR_MAP_NULL) {
-		printf("%s: Service '%s' not found in map.\n", NAME, hwpath);
-		free(hwpath);
-		return ENOENT;
-	}
-	
-	free(hwpath);
-	
-	netif_t *netif = netifs_get_index(&net_globals.netifs, index);
-	if (netif == NULL)
-		return ENOENT;
-	
-	rc = init_device(netif, sid);
-	if (rc != EOK)
-		return rc;
-	
-	/* Increment module usage */
-	if (netif->nil)
-		netif->nil->usage++;
-	
-	netif->il->usage++;
-	
-	return EOK;
-}
-
-/** Process the networking message.
- *
- * @param[in]  callid       The message identifier.
- * @param[in]  call         The message parameters.
- * @param[out] answer       The message answer parameters.
- * @param[out] answer_count The last parameter for the actual answer
- *                          in the answer parameter.
- *
- * @return EOK on success.
- * @return ENOTSUP if the message is not known.
- *
- * @see net_interface.h
- * @see IS_NET_NET_MESSAGE()
- *
- */
-static int net_message(ipc_callid_t callid, ipc_call_t *call,
-    ipc_call_t *answer, size_t *answer_count)
-{
-	measured_string_t *strings;
-	uint8_t *data;
-	int rc;
-	size_t count;
-	
-	*answer_count = 0;
-	
-	if (!IPC_GET_IMETHOD(*call))
-		return EOK;
-	
-	switch (IPC_GET_IMETHOD(*call)) {
-	case NET_NET_GET_DEVICE_CONF:
-		rc = measured_strings_receive(&strings, &data,
-		    IPC_GET_COUNT(*call));
-		if (rc != EOK)
-			return rc;
-		
-		net_get_device_conf(IPC_GET_DEVICE(*call), strings,
-		    IPC_GET_COUNT(*call));
-		
-		rc = measured_strings_reply(strings, IPC_GET_COUNT(*call));
-		free(strings);
-		free(data);
-		return rc;
-	case NET_NET_GET_CONF:
-		rc = measured_strings_receive(&strings, &data,
-		    IPC_GET_COUNT(*call));
-		if (rc != EOK)
-			return rc;
-		
-		net_get_conf(NULL, strings, IPC_GET_COUNT(*call));
-		
-		rc = measured_strings_reply(strings, IPC_GET_COUNT(*call));
-		free(strings);
-		free(data);
-		return rc;
-	case NET_NET_GET_DEVICES_COUNT:
-		count = (size_t) net_get_devices_count();
-		IPC_SET_ARG1(*answer, count);
-		*answer_count = 1;
-		return EOK;
-	case NET_NET_GET_DEVICES:
-		rc = net_get_devices(&strings, &count);
-		if (rc != EOK)
-			return rc;
-		
-		rc = measured_strings_reply(strings, count);
-		net_free_devices(strings, count);
-		return rc;
-	default:
-		return ENOTSUP;
-	}
-}
-
-/** Default thread for new connections.
- *
- * @param[in] iid   The initial message identifier.
- * @param[in] icall The initial message call structure.
- * @param[in] arg   Local argument.
- *
- */
-static void net_client_connection(ipc_callid_t iid, ipc_call_t *icall,
-    void *arg)
-{
-	/*
-	 * Accept the connection
-	 *  - Answer the first IPC_M_CONNECT_ME_TO call.
-	 */
-	async_answer_0(iid, EOK);
-	
-	while (true) {
-		/* Clear the answer structure */
-		ipc_call_t answer;
-		size_t count;
-		refresh_answer(&answer, &count);
-		
-		/* Fetch the next message */
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-		
-		/* Process the message */
-		int res;
-		if (IS_NET_PACKET_MESSAGE(call))
-			res = packet_server_message(callid, &call, &answer, &count);
-		else
-			res = net_message(callid, &call, &answer, &count);
-		
-		/* End if told to either by the message or the processing result */
-		if ((!IPC_GET_IMETHOD(call)) || (res == EHANGUP))
-			return;
-		
-		/* Answer the message */
-		answer_call(callid, res, &answer, count);
-	}
-}
-
-static int nic_check_new(void)
-{
-	category_id_t nic_cat;
-	service_id_t *svcs;
-	size_t count, i;
-	bool already_known;
-	int rc;
-
-	fibril_mutex_lock(&discovery_lock);
-
-	rc = loc_category_get_id(DEVICE_CATEGORY_NIC, &nic_cat, IPC_FLAG_BLOCKING);
-	if (rc != EOK) {
-		printf("%s: Failed resolving category '%s'.\n", NAME,
-		    DEVICE_CATEGORY_NIC);
-		return ENOENT;
-	}
-
-	rc = loc_category_get_svcs(nic_cat, &svcs, &count);
-	if (rc != EOK) {
-		printf("%s: Failed getting list of NIC devices.\n", NAME);
-		return EIO;
-	}
-
-	for (i = 0; i < count; i++) {
-		already_known = false;
-
-		list_foreach(netif_list, link) {
-			netif_t *netif = list_get_instance(link, netif_t, netif_list);
-			if (netif->sid == svcs[i]) {
-				already_known = true;
-				break;
-			}
-		}
-
-		if (!already_known) {
-			rc = net_nic_ready(svcs[i]);
-			if (rc != EOK) {
-				printf("%s: Failed adding NIC device #%u.\n",
-				    NAME, (unsigned) svcs[i]);
-			}
-		}
-	}
-
-	free(svcs);
-	fibril_mutex_unlock(&discovery_lock);
-	return EOK;
-}
-
-static void cat_change_cb(void)
-{
-	(void) nic_check_new();
-}
-
-static int net_start_nic_discovery(void)
-{
-	int rc;
-
-	rc = loc_register_cat_change_cb(cat_change_cb);
-	if (rc != EOK) {
-		printf("%s: Failed registering callback for device discovery (%d).\n",
-		    NAME, rc);
-		return rc;
-	}
-
-	return nic_check_new();
-}
-
-int main(int argc, char *argv[])
-{
-	netifs_initialize(&net_globals.netifs);
-	char_map_initialize(&net_globals.netif_hwpaths);
-	modules_initialize(&net_globals.modules);
-	measured_strings_initialize(&net_globals.configuration);
-	async_set_client_connection(net_client_connection);
-	
-	int rc = pm_init();
-	if (rc != EOK) {
-		printf("%s: Unable to initialize packet management\n", NAME);
-		return rc;
-	}
-	
-	rc = packet_server_init();
-	if (rc != EOK) {
-		printf("%s: Unable to initialize packet server\n", NAME);
-		pm_destroy();
-		return rc;
-	}
-	
-	rc = read_configuration();
-	if (rc != EOK) {
-		printf("%s: Error reading configuration\n", NAME);
-		pm_destroy();
-		return rc;
-	}
-	
-	DIR *config_dir = opendir(CONF_DIR);
-	if (config_dir != NULL) {
-		struct dirent *dir_entry;
-		while ((dir_entry = readdir(config_dir))) {
-			/* Ignore files without the CONF_EXT extension */
-			if ((str_size(dir_entry->d_name) < str_size(CONF_EXT)) ||
-			    (str_cmp(dir_entry->d_name + str_size(dir_entry->d_name) -
-			    str_size(CONF_EXT), CONF_EXT) != 0))
-				continue;
-			
-			
-			netif_t *netif = (netif_t *) malloc(sizeof(netif_t));
-			if (!netif)
-				continue;
-			
-			netif->sid = -1;
-			netif->sess = NULL;
-			
-			netif->id = generate_new_device_id();
-			if (!netif->id) {
-				free(netif);
-				continue;
-			}
-			
-			rc = measured_strings_initialize(&netif->configuration);
-			if (rc != EOK) {
-				free(netif);
-				continue;
-			}
-			
-			rc = read_netif_configuration(dir_entry->d_name, netif);
-			if (rc != EOK) {
-				printf("%s: Error reading configuration %s\n", NAME,
-				    dir_entry->d_name);
-				free(netif);
-				continue;
-			}
-			
-			measured_string_t *name = measured_strings_find(&netif->configuration,
-			    (uint8_t *) CONF_NAME, 0);
-			if (!name) {
-				printf("%s: Network interface name is missing in %s\n",
-				    NAME, dir_entry->d_name);
-				measured_strings_destroy(&netif->configuration, free);
-				free(netif);
-				continue;
-			}
-			
-			netif->name = name->value;
-			
-			/* Mandatory hardware path */
-			measured_string_t *hwpath = measured_strings_find(
-			    &netif->configuration, (const uint8_t *) CONF_HWPATH, 0);
-			if (!hwpath) {
-				printf("%s: Hardware path is missing in %s\n",
-				    NAME, dir_entry->d_name);
-				measured_strings_destroy(&netif->configuration, free);
-				free(netif);
-				continue;
-			}
-			
-			int index = netifs_add(&net_globals.netifs, netif->id, netif);
-			if (index < 0) {
-				measured_strings_destroy(&netif->configuration, free);
-				free(netif);
-				continue;
-			}
-			
-			/*
-			 * Add to the hardware paths map and init network interfaces
-			 * and needed modules.
-			 */
-			rc = char_map_add(&net_globals.netif_hwpaths, hwpath->value, 0, index);
-			if (rc != EOK) {
-				measured_strings_destroy(&netif->configuration, free);
-				netifs_exclude_index(&net_globals.netifs, index, free);
-				continue;
-			}
-		}
-		
-		closedir(config_dir);
-	}
-	
-	rc = add_module(NULL, &net_globals.modules, (uint8_t *) ETHERNET_NAME,
-	    (uint8_t *) ETHERNET_FILENAME, SERVICE_ETHERNET, 0, connect_to_service);
-	if (rc != EOK) {
-		printf("%s: Error adding module '%s'\n", NAME, ETHERNET_NAME);
-		pm_destroy();
-		return rc;
-	}
-	
-	rc = add_module(NULL, &net_globals.modules, (uint8_t *) NILDUMMY_NAME,
-	    (uint8_t *) NILDUMMY_FILENAME, SERVICE_NILDUMMY, 0, connect_to_service);
-	if (rc != EOK) {
-		printf("%s: Error adding module '%s'\n", NAME, NILDUMMY_NAME);
-		pm_destroy();
-		return rc;
-	}
-	
-	task_id_t task_id = net_spawn((uint8_t *) IP_FILENAME);
-	if (!task_id) {
-		printf("%s: Error spawning IP module\n", NAME);
-		pm_destroy();
-		return EINVAL;
-	}
-	
-	rc = add_module(NULL, &net_globals.modules, (uint8_t *) IP_NAME,
-	    (uint8_t *) IP_FILENAME, SERVICE_IP, task_id, ip_connect_module);
-	if (rc != EOK) {
-		printf("%s: Error adding module '%s'\n", NAME, IP_NAME);
-		pm_destroy();
-		return rc;
-	}
-	
-	if (!net_spawn((uint8_t *) "/srv/icmp")) {
-		printf("%s: Error spawning ICMP module\n", NAME);
-		pm_destroy();
-		return EINVAL;
-	}
-	
-	if (!net_spawn((uint8_t *) "/srv/udp")) {
-		printf("%s: Error spawning UDP module\n", NAME);
-		pm_destroy();
-		return EINVAL;
-	}
-	
-	if (!net_spawn((uint8_t *) "/srv/tcp")) {
-		printf("%s: Error spawning TCP module\n", NAME);
-		pm_destroy();
-		return EINVAL;
-	}
-	
-	rc = service_register(SERVICE_NETWORKING);
-	if (rc != EOK) {
-		printf("%s: Error registering service\n", NAME);
-		pm_destroy();
-		return rc;
-	}
-	
-	rc = net_start_nic_discovery();
-	if (rc != EOK) {
-		printf("%s: Error starting NIC discovery\n", NAME);
-		pm_destroy();
-		return rc;
-	}
-	
-	task_retval(0);
-	async_manager();
-	return 0;
-}
-
-/** @}
- */
Index: pace/srv/net/net/net.h
===================================================================
--- uspace/srv/net/net/net.h	(revision bf31e3f1ebd6e88e0c8425f109e42ccd92b6c9b3)
+++ 	(revision )
@@ -1,132 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * Copyright (c) 2011 Radim Vansa
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup net
- * @{
- */
-
-#ifndef NET_NET_H_
-#define NET_NET_H_
-
-#include <ipc/loc.h>
-#include <net/device.h>
-#include <adt/char_map.h>
-#include <adt/generic_char_map.h>
-#include <adt/measured_strings.h>
-#include <adt/module_map.h>
-#include <net/packet.h>
-
-#define NAME  "net"
-
-#define ETHERNET_FILENAME  "/srv/eth"
-#define ETHERNET_NAME      "eth"
-
-#define IP_FILENAME  "/srv/ip"
-#define IP_NAME      "ip"
-
-#define NILDUMMY_FILENAME  "/srv/nildummy"
-#define NILDUMMY_NAME      "nildummy"
-
-/** @}
- */
-
-/** @name Configuration setting names definitions
- * @{
- */
-
-#define CONF_IL     "IL"     /**< Internet protocol module name configuration label. */
-#define CONF_IO     "IO"     /**< Device input/output address configuration label. */
-#define CONF_IRQ    "IRQ"    /**< Interrupt number configuration label. */
-#define CONF_MTU    "MTU"    /**< Maximum transmission unit configuration label. */
-#define CONF_NAME   "NAME"   /**< Network interface name configuration label. */
-#define CONF_HWPATH "HWPATH" /**< Network interface hardware pathname label. */
-#define CONF_NIL    "NIL"    /**< Network interface layer module name configuration label. */
-
-/** @}
- */
-
-#define CONF_DIR           "/cfg/net"  /**< Configuration directory. */
-#define CONF_GENERAL_FILE  "general"   /**< General configuration file. */
-#define CONF_EXT           ".nic"      /**< Extension for NIC's configuration files. */
-
-/** Configuration settings.
- *
- * Maps setting names to the values.
- * @see generic_char_map.h
- *
- */
-GENERIC_CHAR_MAP_DECLARE(measured_strings, measured_string_t);
-
-/** Present network interface device.
- *
- */
-typedef struct {
-	/** System-unique network interface name. */
-	uint8_t *name;
-	/** System-unique network interface identifier. */
-	nic_device_id_t id;
-	/** Configuration. */
-	measured_strings_t configuration;
-	
-	/** Serving network interface driver module index. */
-	service_id_t sid;    /**< Service ID */
-	async_sess_t *sess;  /**< Driver session. */
-	
-	module_t *nil;  /**< Serving link layer module index. */
-	module_t *il;   /**< Serving internet layer module index. */
-	
-	link_t netif_list;
-} netif_t;
-
-/** Present network interfaces.
- *
- * Maps devices to the networking device specific data.
- * @see device.h
- *
- */
-DEVICE_MAP_DECLARE(netifs, netif_t);
-
-/** Networking module global data.
- *
- */
-typedef struct {
-	measured_strings_t configuration;  /**< Global configuration. */
-	modules_t modules;                 /**< Available modules. */
-	
-	/** Network interface structure indices by hardware path. */
-	char_map_t netif_hwpaths;
-	
-	/** Present network interfaces. */
-	netifs_t netifs;
-} net_globals_t;
-
-#endif
-
-/** @}
- */
Index: pace/srv/net/net/packet_server.c
===================================================================
--- uspace/srv/net/net/packet_server.c	(revision bf31e3f1ebd6e88e0c8425f109e42ccd92b6c9b3)
+++ 	(revision )
@@ -1,402 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * Copyright (c) 2011 Radim Vansa
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup libpacket
- *  @{
- */
-
-/** @file
- * Packet server implementation.
- */
-
-#include <align.h>
-#include <assert.h>
-#include <async.h>
-#include <errno.h>
-#include <str_error.h>
-#include <stdio.h>
-#include <fibril_synch.h>
-#include <unistd.h>
-#include <sys/mman.h>
-#include <ipc/packet.h>
-#include <ipc/net.h>
-#include <net/packet.h>
-#include <net/packet_header.h>
-
-#include "packet_server.h"
-
-#define PACKET_SERVER_PROFILE 1
-
-/** Number of queues cacheing the unused packets */
-#define FREE_QUEUES_COUNT	7
-/** Maximum number of packets in each queue */
-#define FREE_QUEUE_MAX_LENGTH	16
-
-/** The default address length reserved for new packets. */
-#define DEFAULT_ADDR_LEN	32
-
-/** The default prefix reserved for new packets. */
-#define DEFAULT_PREFIX		64
-
-/** The default suffix reserved for new packets. */
-#define DEFAULT_SUFFIX		64
-
-/** The queue with unused packets */
-typedef struct packet_queue {
-	packet_t *first;	/**< First packet in the queue */
-	size_t packet_size; /**< Maximal size of the packets in this queue */
-	int count;			/**< Length of the queue */
-} packet_queue_t;
-
-/** Packet server global data. */
-static struct {
-	/** Safety lock. */
-	fibril_mutex_t lock;
-	/** Free packet queues. */
-	packet_queue_t free_queues[FREE_QUEUES_COUNT];
-	
-	/** Total packets allocated. */
-	packet_id_t next_id;
-} ps_globals = {
-	.lock = FIBRIL_MUTEX_INITIALIZER(ps_globals.lock),
-	.free_queues = {
-		{ NULL, PAGE_SIZE, 0},
-		{ NULL, PAGE_SIZE * 2, 0},
-		{ NULL, PAGE_SIZE * 4, 0},
-		{ NULL, PAGE_SIZE * 8, 0},
-		{ NULL, PAGE_SIZE * 16, 0},
-		{ NULL, PAGE_SIZE * 32, 0},
-		{ NULL, PAGE_SIZE * 64, 0},
-	},
-	.next_id = 1
-};
-
-/** Clears and initializes the packet according to the given dimensions.
- *
- * @param[in] packet	The packet to be initialized.
- * @param[in] addr_len	The source and destination addresses maximal length in
- *			bytes.
- * @param[in] max_prefix The maximal prefix length in bytes.
- * @param[in] max_content The maximal content length in bytes.
- * @param[in] max_suffix The maximal suffix length in bytes.
- */
-static void packet_init(packet_t *packet,
-	size_t addr_len, size_t max_prefix, size_t max_content, size_t max_suffix)
-{
-	/* Clear the packet content */
-	bzero(((void *) packet) + sizeof(packet_t),
-	    packet->length - sizeof(packet_t));
-	
-	/* Clear the packet header */
-	packet->order = 0;
-	packet->metric = 0;
-	packet->previous = 0;
-	packet->next = 0;
-	packet->offload_info = 0;
-	packet->offload_mask = 0;
-	packet->addr_len = 0;
-	packet->src_addr = sizeof(packet_t);
-	packet->dest_addr = packet->src_addr + addr_len;
-	packet->max_prefix = max_prefix;
-	packet->max_content = max_content;
-	packet->data_start = packet->dest_addr + addr_len + packet->max_prefix;
-	packet->data_end = packet->data_start;
-}
-
-/**
- * Releases the memory allocated for the packet
- *
- * @param[in] packet Pointer to the memory where the packet was allocated
- */
-static void packet_dealloc(packet_t *packet)
-{
-	pm_remove(packet);
-	munmap(packet, packet->length);
-}
-
-/** Creates a new packet of dimensions at least as given.
- *
- * @param[in] length	The total length of the packet, including the header,
- *			the addresses and the data of the packet.
- * @param[in] addr_len	The source and destination addresses maximal length in
- *			bytes.
- * @param[in] max_prefix The maximal prefix length in bytes.
- * @param[in] max_content The maximal content length in bytes.
- * @param[in] max_suffix The maximal suffix length in bytes.
- * @return		The packet of dimensions at least as given.
- * @return		NULL if there is not enough memory left.
- */
-static packet_t *packet_alloc(size_t length, size_t addr_len,
-	size_t max_prefix, size_t max_content, size_t max_suffix)
-{
-	packet_t *packet;
-	int rc;
-
-	/* Global lock is locked */
-	assert(fibril_mutex_is_locked(&ps_globals.lock));
-	/* The length is some multiple of PAGE_SIZE */
-	assert(!(length & (PAGE_SIZE - 1)));
-
-	packet = (packet_t *) mmap(NULL, length, PROTO_READ | PROTO_WRITE,
-		MAP_SHARED | MAP_ANONYMOUS, 0, 0);
-	if (packet == MAP_FAILED)
-		return NULL;
-	
-	/* Using 32bit packet_id the id could overflow */
-	packet_id_t pid;
-	do {
-		pid = ps_globals.next_id;
-		ps_globals.next_id++;
-	} while (!pid || pm_find(pid));
-	packet->packet_id = pid;
-
-	packet->length = length;
-	packet_init(packet, addr_len, max_prefix, max_content, max_suffix);
-	packet->magic_value = PACKET_MAGIC_VALUE;
-	rc = pm_add(packet);
-	if (rc != EOK) {
-		packet_dealloc(packet);
-		return NULL;
-	}
-	
-	return packet;
-}
-
-/** Return the packet of dimensions at least as given.
- *
- * Try to reuse free packets first.
- * Create a new packet aligned to the memory page size if none available.
- * Lock the global data during its processing.
- *
- * @param[in] addr_len	The source and destination addresses maximal length in
- *			bytes.
- * @param[in] max_prefix The maximal prefix length in bytes.
- * @param[in] max_content The maximal content length in bytes.
- * @param[in] max_suffix The maximal suffix length in bytes.
- * @return		The packet of dimensions at least as given.
- * @return		NULL if there is not enough memory left.
- */
-static packet_t *packet_get_local(size_t addr_len,
-	size_t max_prefix, size_t max_content, size_t max_suffix)
-{
-	size_t length = ALIGN_UP(sizeof(packet_t) + 2 * addr_len
-		+ max_prefix + max_content + max_suffix, PAGE_SIZE);
-	
-	if (length > PACKET_MAX_LENGTH)
-		return NULL;
-
-	fibril_mutex_lock(&ps_globals.lock);
-	
-	packet_t *packet;
-	unsigned int index;
-	
-	for (index = 0; index < FREE_QUEUES_COUNT; index++) {
-		if ((length > ps_globals.free_queues[index].packet_size) &&
-			(index < FREE_QUEUES_COUNT - 1))
-			continue;
-		
-		packet = ps_globals.free_queues[index].first;
-		while (packet_is_valid(packet) && (packet->length < length))
-			packet = pm_find(packet->next);
-		
-		if (packet_is_valid(packet)) {
-			ps_globals.free_queues[index].count--;
-			if (packet == ps_globals.free_queues[index].first) {
-				ps_globals.free_queues[index].first = pq_detach(packet);
-			} else {
-				pq_detach(packet);
-			}
-			
-			packet_init(packet, addr_len, max_prefix, max_content, max_suffix);
-			fibril_mutex_unlock(&ps_globals.lock);
-			
-			return packet;
-		}
-	}
-	
-	packet = packet_alloc(length, addr_len,
-		max_prefix, max_content, max_suffix);
-	
-	fibril_mutex_unlock(&ps_globals.lock);
-	
-	return packet;
-}
-
-/** Release the packet and returns it to the appropriate free packet queue.
- *
- * @param[in] packet	The packet to be released.
- *
- */
-static void packet_release(packet_t *packet)
-{
-	int index;
-	int result;
-
-	assert(fibril_mutex_is_locked(&ps_globals.lock));
-
-	for (index = 0; (index < FREE_QUEUES_COUNT - 1) &&
-	    (packet->length > ps_globals.free_queues[index].packet_size); index++) {
-		;
-	}
-	
-	ps_globals.free_queues[index].count++;
-	result = pq_add(&ps_globals.free_queues[index].first, packet,
-		packet->length,	packet->length);
-	assert(result == EOK);
-}
-
-/** Releases the packet queue.
- *
- * @param[in] packet_id	The first packet identifier.
- * @return		EOK on success.
- * @return		ENOENT if there is no such packet.
- */
-static int packet_release_wrapper(packet_id_t packet_id)
-{
-	packet_t *packet;
-
-	packet = pm_find(packet_id);
-	if (!packet_is_valid(packet))
-		return ENOENT;
-
-	fibril_mutex_lock(&ps_globals.lock);
-	pq_destroy(packet, packet_release);
-	fibril_mutex_unlock(&ps_globals.lock);
-
-	return EOK;
-}
-
-/** Shares the packet memory block.
- * @param[in] packet	The packet to be shared.
- * @return		EOK on success.
- * @return		EINVAL if the packet is not valid.
- * @return		EINVAL if the calling module does not accept the memory.
- * @return		ENOMEM if the desired and actual sizes differ.
- * @return		Other error codes as defined for the
- *			async_share_in_finalize() function.
- */
-static int packet_reply(packet_t *packet)
-{
-	if (!packet_is_valid(packet))
-		return EINVAL;
-	
-	ipc_callid_t callid;
-	size_t size;
-	if (!async_share_in_receive(&callid, &size)) {
-		async_answer_0(callid, EINVAL);
-		return EINVAL;
-	}
-	
-	if (size != packet->length) {
-		async_answer_0(callid, ENOMEM);
-		return ENOMEM;
-	}
-	
-	return async_share_in_finalize(callid, packet,
-	    PROTO_READ | PROTO_WRITE);
-}
-
-/** Processes the packet server message.
- *
- * @param[in] callid	The message identifier.
- * @param[in] call	The message parameters.
- * @param[out] answer	The message answer parameters.
- * @param[out] answer_count The last parameter for the actual answer in the
- *			answer parameter.
- * @return		EOK on success.
- * @return		ENOMEM if there is not enough memory left.
- * @return		ENOENT if there is no such packet as in the packet
- *			message parameter.
- * @return		ENOTSUP if the message is not known.
- * @return		Other error codes as defined for the
- *			packet_release_wrapper() function.
- */
-int packet_server_message(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer,
-    size_t *answer_count)
-{
-	packet_t *packet;
-	
-	if (!IPC_GET_IMETHOD(*call))
-		return EOK;
-	
-	*answer_count = 0;
-	switch (IPC_GET_IMETHOD(*call)) {
-	case NET_PACKET_CREATE_1:
-		packet = packet_get_local(DEFAULT_ADDR_LEN, DEFAULT_PREFIX,
-			IPC_GET_CONTENT(*call), DEFAULT_SUFFIX);
-		if (!packet)
-			return ENOMEM;
-		*answer_count = 2;
-		IPC_SET_ARG1(*answer, (sysarg_t) packet->packet_id);
-		IPC_SET_ARG2(*answer, (sysarg_t) packet->length);
-		return EOK;
-	
-	case NET_PACKET_CREATE_4:
-		packet = packet_get_local(
-			((DEFAULT_ADDR_LEN < IPC_GET_ADDR_LEN(*call)) ?
-		    IPC_GET_ADDR_LEN(*call) : DEFAULT_ADDR_LEN),
-		    DEFAULT_PREFIX + IPC_GET_PREFIX(*call),
-		    IPC_GET_CONTENT(*call),
-		    DEFAULT_SUFFIX + IPC_GET_SUFFIX(*call));
-		if (!packet)
-			return ENOMEM;
-		*answer_count = 2;
-		IPC_SET_ARG1(*answer, (sysarg_t) packet->packet_id);
-		IPC_SET_ARG2(*answer, (sysarg_t) packet->length);
-		return EOK;
-	
-	case NET_PACKET_GET:
-		packet = pm_find(IPC_GET_ID(*call));
-		if (!packet_is_valid(packet))
-			return ENOENT;
-		
-		return packet_reply(packet);
-	
-	case NET_PACKET_GET_SIZE:
-		packet = pm_find(IPC_GET_ID(*call));
-		if (!packet_is_valid(packet))
-			return ENOENT;
-		IPC_SET_ARG1(*answer, (sysarg_t) packet->length);
-		*answer_count = 1;
-		return EOK;
-	
-	case NET_PACKET_RELEASE:
-		return packet_release_wrapper(IPC_GET_ID(*call));
-	}
-	
-	return ENOTSUP;
-}
-
-int packet_server_init()
-{
-	return EOK;
-}
-
-/** @}
- */
Index: pace/srv/net/net/packet_server.h
===================================================================
--- uspace/srv/net/net/packet_server.h	(revision bf31e3f1ebd6e88e0c8425f109e42ccd92b6c9b3)
+++ 	(revision )
@@ -1,57 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * Copyright (c) 2011 Radim Vansa
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup libpacket
- * @{
- */
-
-/** @file
- * Packet server.
- * The hosting module has to be compiled with both the packet.c and the
- * packet_server.c source files. To function correctly, initialization of the
- * packet map by the pm_init() function has to happen at the first place. Then
- * the packet messages have to be processed by the packet_server_message()
- * function. The packet map should be released by the pm_destroy() function
- * during the module termination.
- * @see IS_NET_PACKET_MESSAGE()
- */
-
-#ifndef NET_PACKET_SERVER_H_
-#define NET_PACKET_SERVER_H_
-
-#include <ipc/common.h>
-
-extern int packet_server_init(void);
-extern int packet_server_message(ipc_callid_t, ipc_call_t *, ipc_call_t *,
-    size_t *);
-
-#endif
-
-/** @}
- */
Index: pace/srv/net/nil/eth/Makefile
===================================================================
--- uspace/srv/net/nil/eth/Makefile	(revision bf31e3f1ebd6e88e0c8425f109e42ccd92b6c9b3)
+++ 	(revision )
@@ -1,46 +1,0 @@
-#
-# Copyright (c) 2005 Martin Decky
-# Copyright (c) 2007 Jakub Jermar
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# - Redistributions of source code must retain the above copyright
-#   notice, this list of conditions and the following disclaimer.
-# - Redistributions in binary form must reproduce the above copyright
-#   notice, this list of conditions and the following disclaimer in the
-#   documentation and/or other materials provided with the distribution.
-# - The name of the author may not be used to endorse or promote products
-#   derived from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-
-USPACE_PREFIX = ../../../..
-ROOT_PATH = $(USPACE_PREFIX)/..
-LIBS = $(LIBNET_PREFIX)/libnet.a
-EXTRA_CFLAGS = -I$(LIBNET_PREFIX)/include
-
-COMMON_MAKEFILE = $(ROOT_PATH)/Makefile.common
-CONFIG_MAKEFILE = $(ROOT_PATH)/Makefile.config
-
--include $(COMMON_MAKEFILE)
--include $(CONFIG_MAKEFILE)
-
-BINARY = eth
-
-SOURCES = \
-	eth.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/srv/net/nil/eth/eth.c
===================================================================
--- uspace/srv/net/nil/eth/eth.c	(revision bf31e3f1ebd6e88e0c8425f109e42ccd92b6c9b3)
+++ 	(revision )
@@ -1,997 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * Copyright (c) 2011 Radim Vansa
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup eth
- *  @{
- */
-
-/** @file
- *  Ethernet module implementation.
- *  @see eth.h
- */
-
-#include <assert.h>
-#include <async.h>
-#include <malloc.h>
-#include <mem.h>
-#include <stdio.h>
-#include <byteorder.h>
-#include <str.h>
-#include <errno.h>
-#include <ipc/nil.h>
-#include <ipc/net.h>
-#include <ipc/services.h>
-#include <loc.h>
-#include <net/modules.h>
-#include <net_checksum.h>
-#include <ethernet_lsap.h>
-#include <ethernet_protocols.h>
-#include <protocol_map.h>
-#include <net/device.h>
-#include <net_interface.h>
-#include <il_remote.h>
-#include <adt/measured_strings.h>
-#include <packet_client.h>
-#include <packet_remote.h>
-#include <device/nic.h>
-#include <nil_skel.h>
-#include "eth.h"
-
-/** The module name. */
-#define NAME  "eth"
-
-/** Reserved packet prefix length. */
-#define ETH_PREFIX \
-	(sizeof(eth_header_t) + sizeof(eth_header_lsap_t) + \
-	    sizeof(eth_header_snap_t))
-
-/** Reserved packet suffix length. */
-#define ETH_SUFFIX  (sizeof(eth_fcs_t))
-
-/** Maximum packet content length. */
-#define ETH_MAX_CONTENT  1500u
-
-/** Minimum packet content length. */
-#define ETH_MIN_CONTENT  46u
-
-/** Maximum tagged packet content length. */
-#define ETH_MAX_TAGGED_CONTENT(flags) \
-	(ETH_MAX_CONTENT - \
-	    ((IS_8023_2_LSAP(flags) || IS_8023_2_SNAP(flags)) ? \
-	    sizeof(eth_header_lsap_t) : 0) - \
-	    (IS_8023_2_SNAP(flags) ? sizeof(eth_header_snap_t) : 0))
-
-/** Minimum tagged packet content length. */
-#define ETH_MIN_TAGGED_CONTENT(flags) \
-	(ETH_MIN_CONTENT - \
-	    ((IS_8023_2_LSAP(flags) || IS_8023_2_SNAP(flags)) ? \
-	    sizeof(eth_header_lsap_t) : 0) - \
-	    (IS_8023_2_SNAP(flags) ? sizeof(eth_header_snap_t) : 0))
-
-/** Dummy flag shift value. */
-#define ETH_DUMMY_SHIFT  0
-
-/** Mode flag shift value. */
-#define ETH_MODE_SHIFT  1
-
-/** Dummy device flag.
- * Preamble and FCS are mandatory part of the packets.
- */
-#define ETH_DUMMY  (1 << ETH_DUMMY_SHIFT)
-
-/** Returns the dummy flag.
- * @see ETH_DUMMY
- */
-#define IS_DUMMY(flags)  ((flags) & ETH_DUMMY)
-
-/** Device mode flags.
- * @see ETH_DIX
- * @see ETH_8023_2_LSAP
- * @see ETH_8023_2_SNAP
- */
-#define ETH_MODE_MASK  (3 << ETH_MODE_SHIFT)
-
-/** DIX Ethernet mode flag. */
-#define ETH_DIX  (1 << ETH_MODE_SHIFT)
-
-/** Return whether the DIX Ethernet mode flag is set.
- *
- * @param[in] flags Ethernet flags.
- * @see ETH_DIX
- *
- */
-#define IS_DIX(flags)  (((flags) & ETH_MODE_MASK) == ETH_DIX)
-
-/** 802.3 + 802.2 + LSAP mode flag. */
-#define ETH_8023_2_LSAP  (2 << ETH_MODE_SHIFT)
-
-/** Return whether the 802.3 + 802.2 + LSAP mode flag is set.
- *
- * @param[in] flags Ethernet flags.
- * @see ETH_8023_2_LSAP
- *
- */
-#define IS_8023_2_LSAP(flags)  (((flags) & ETH_MODE_MASK) == ETH_8023_2_LSAP)
-
-/** 802.3 + 802.2 + LSAP + SNAP mode flag. */
-#define ETH_8023_2_SNAP  (3 << ETH_MODE_SHIFT)
-
-/** Return whether the 802.3 + 802.2 + LSAP + SNAP mode flag is set.
- *
- * @param[in] flags Ethernet flags.
- * @see ETH_8023_2_SNAP
- *
- */
-#define IS_8023_2_SNAP(flags)  (((flags) & ETH_MODE_MASK) == ETH_8023_2_SNAP)
-
-/** Type definition of the ethernet address type.
- * @see eth_addr_type
- */
-typedef enum eth_addr_type eth_addr_type_t;
-
-/** Ethernet address type. */
-enum eth_addr_type {
-	/** Local address. */
-	ETH_LOCAL_ADDR,
-	/** Broadcast address. */
-	ETH_BROADCAST_ADDR
-};
-
-/** Ethernet module global data. */
-eth_globals_t eth_globals;
-
-DEVICE_MAP_IMPLEMENT(eth_devices, eth_device_t);
-INT_MAP_IMPLEMENT(eth_protos, eth_proto_t);
-
-static void eth_nic_cb_connection(ipc_callid_t iid, ipc_call_t *icall,
-    void *arg);
-
-static int eth_device_state(eth_device_t *device, sysarg_t state)
-{
-	int index;
-	eth_proto_t *proto;
-
-	fibril_rwlock_read_lock(&eth_globals.protos_lock);
-	for (index = eth_protos_count(&eth_globals.protos) - 1; index >= 0;
-	    index--) {
-		proto = eth_protos_get_index(&eth_globals.protos, index);
-		if ((proto) && (proto->sess)) {
-			il_device_state_msg(proto->sess, device->device_id,
-			    state, proto->service);
-		}
-	}
-	fibril_rwlock_read_unlock(&eth_globals.protos_lock);
-	
-	return EOK;
-}
-
-int nil_initialize(async_sess_t *sess)
-{
-	int rc;
-
-	fibril_rwlock_initialize(&eth_globals.devices_lock);
-	fibril_rwlock_initialize(&eth_globals.protos_lock);
-	
-	fibril_rwlock_write_lock(&eth_globals.devices_lock);
-	fibril_rwlock_write_lock(&eth_globals.protos_lock);
-	
-	eth_globals.net_sess = sess;
-	memcpy(eth_globals.broadcast_addr, "\xFF\xFF\xFF\xFF\xFF\xFF",
-			ETH_ADDR);
-
-	rc = eth_devices_initialize(&eth_globals.devices);
-	if (rc != EOK) {
-		free(eth_globals.broadcast_addr);
-		goto out;
-	}
-
-	rc = eth_protos_initialize(&eth_globals.protos);
-	if (rc != EOK) {
-		free(eth_globals.broadcast_addr);
-		eth_devices_destroy(&eth_globals.devices, free);
-	}
-	
-out:
-	fibril_rwlock_write_unlock(&eth_globals.protos_lock);
-	fibril_rwlock_write_unlock(&eth_globals.devices_lock);
-	
-	return rc;
-}
-
-/** Register new device or updates the MTU of an existing one.
- *
- * Determine the device local hardware address.
- *
- * @param[in] device_id New device identifier.
- * @param[in] sid       NIC service ID.
- * @param[in] mtu       Device maximum transmission unit.
- *
- * @return EOK on success.
- * @return EEXIST if the device with the different service exists.
- * @return ENOMEM if there is not enough memory left.
- *
- */
-static int eth_device_message(nic_device_id_t device_id, service_id_t sid,
-    size_t mtu)
-{
-	eth_device_t *device;
-	int index;
-	measured_string_t names[2] = {
-		{
-			(uint8_t *) "ETH_MODE",
-			8
-		},
-		{
-			(uint8_t *) "ETH_DUMMY",
-			9
-		}
-	};
-	measured_string_t *configuration;
-	size_t count = sizeof(names) / sizeof(measured_string_t);
-	uint8_t *data;
-	eth_proto_t *proto;
-	int rc;
-
-	fibril_rwlock_write_lock(&eth_globals.devices_lock);
-	/* An existing device? */
-	device = eth_devices_find(&eth_globals.devices, device_id);
-	if (device) {
-		if (device->sid != sid) {
-			printf("Device %d already exists\n", device->device_id);
-			fibril_rwlock_write_unlock(&eth_globals.devices_lock);
-			return EEXIST;
-		}
-		
-		/* Update mtu */
-		if ((mtu > 0) && (mtu <= ETH_MAX_TAGGED_CONTENT(device->flags)))
-			device->mtu = mtu;
-		else
-			device->mtu = ETH_MAX_TAGGED_CONTENT(device->flags);
-		
-		printf("Device %d already exists:\tMTU\t= %zu\n",
-		    device->device_id, device->mtu);
-		fibril_rwlock_write_unlock(&eth_globals.devices_lock);
-		
-		/* Notify all upper layer modules */
-		fibril_rwlock_read_lock(&eth_globals.protos_lock);
-		for (index = 0; index < eth_protos_count(&eth_globals.protos);
-		    index++) {
-			proto = eth_protos_get_index(&eth_globals.protos,
-			    index);
-			if (proto->sess) {
-				il_mtu_changed_msg(proto->sess,
-				    device->device_id, device->mtu,
-				    proto->service);
-			}
-		}
-
-		fibril_rwlock_read_unlock(&eth_globals.protos_lock);
-		return EOK;
-	}
-	
-	/* Create a new device */
-	device = (eth_device_t *) malloc(sizeof(eth_device_t));
-	if (!device)
-		return ENOMEM;
-
-	device->device_id = device_id;
-	device->sid = sid;
-	device->flags = 0;
-	if ((mtu > 0) && (mtu <= ETH_MAX_TAGGED_CONTENT(device->flags)))
-		device->mtu = mtu;
-	else
-		device->mtu = ETH_MAX_TAGGED_CONTENT(device->flags);
-
-	configuration = &names[0];
-	rc = net_get_device_conf_req(eth_globals.net_sess, device->device_id,
-	    &configuration, count, &data);
-	if (rc != EOK) {
-		fibril_rwlock_write_unlock(&eth_globals.devices_lock);
-		free(device);
-		return rc;
-	}
-
-	if (configuration) {
-		if (!str_lcmp((char *) configuration[0].value, "DIX",
-		    configuration[0].length)) {
-			device->flags |= ETH_DIX;
-		} else if(!str_lcmp((char *) configuration[0].value, "8023_2_LSAP",
-		    configuration[0].length)) {
-			device->flags |= ETH_8023_2_LSAP;
-		} else {
-			device->flags |= ETH_8023_2_SNAP;
-		}
-		
-		if (configuration[1].value &&
-		    (configuration[1].value[0] == 'y')) {
-			device->flags |= ETH_DUMMY;
-		}
-		net_free_settings(configuration, data);
-	} else {
-		device->flags |= ETH_8023_2_SNAP;
-	}
-	
-	/* Bind the device driver */
-	device->sess = loc_service_connect(EXCHANGE_SERIALIZE, sid,
-	    IPC_FLAG_BLOCKING);
-	if (device->sess == NULL) {
-		fibril_rwlock_write_unlock(&eth_globals.devices_lock);
-		free(device);
-		return ENOENT;
-	}
-	
-	rc = nic_callback_create(device->sess, eth_nic_cb_connection, device);
-	if (rc != EOK) {
-		fibril_rwlock_write_unlock(&eth_globals.devices_lock);
-		async_hangup(device->sess);
-		free(device);
-		return EIO;
-	}
-	
-	/* Get hardware address */
-	rc = nic_get_address(device->sess, &device->addr);
-	if (rc != EOK) {
-		fibril_rwlock_write_unlock(&eth_globals.devices_lock);
-		free(device);
-		return rc;
-	}
-	
-	/* Add to the cache */
-	index = eth_devices_add(&eth_globals.devices, device->device_id,
-	    device);
-	if (index < 0) {
-		fibril_rwlock_write_unlock(&eth_globals.devices_lock);
-		free(device);
-		return index;
-	}
-	
-	printf("%s: Device registered (id: %d, sid: %zu: mtu: %zu, "
-	    "mac: " PRIMAC ", flags: 0x%x)\n", NAME,
-	    device->device_id, device->sid, device->mtu,
-	    ARGSMAC(device->addr.address), device->flags);
-
-	fibril_rwlock_write_unlock(&eth_globals.devices_lock);
-	return EOK;
-}
-
-/** Processes the received packet and chooses the target registered module.
- *
- * @param[in] flags	The device flags.
- * @param[in] packet	The packet.
- * @return		The target registered module.
- * @return		NULL if the packet is not long enough.
- * @return		NULL if the packet is too long.
- * @return		NULL if the raw ethernet protocol is used.
- * @return		NULL if the dummy device FCS checksum is invalid.
- * @return		NULL if the packet address length is not big enough.
- */
-static eth_proto_t *eth_process_packet(int flags, packet_t *packet)
-{
-	eth_header_snap_t *header;
-	size_t length;
-	eth_type_t type;
-	size_t prefix;
-	size_t suffix;
-	eth_fcs_t *fcs;
-	uint8_t *data;
-	int rc;
-
-	length = packet_get_data_length(packet);
-	
-	if (IS_DUMMY(flags))
-		packet_trim(packet, sizeof(eth_preamble_t), 0);
-	if (length < sizeof(eth_header_t) + ETH_MIN_CONTENT +
-	    (IS_DUMMY(flags) ? ETH_SUFFIX : 0))
-		return NULL;
-	
-	data = packet_get_data(packet);
-	header = (eth_header_snap_t *) data;
-	type = ntohs(header->header.ethertype);
-	
-	if (type >= ETH_MIN_PROTO) {
-		/* DIX Ethernet */
-		prefix = sizeof(eth_header_t);
-		suffix = 0;
-		fcs = (eth_fcs_t *) data + length - sizeof(eth_fcs_t);
-		length -= sizeof(eth_fcs_t);
-	} else if (type <= ETH_MAX_CONTENT) {
-		/* Translate "LSAP" values */
-		if ((header->lsap.dsap == ETH_LSAP_GLSAP) &&
-		    (header->lsap.ssap == ETH_LSAP_GLSAP)) {
-			/* Raw packet -- discard */
-			return NULL;
-		} else if ((header->lsap.dsap == ETH_LSAP_SNAP) &&
-		    (header->lsap.ssap == ETH_LSAP_SNAP)) {
-			/*
-			 * IEEE 802.3 + 802.2 + LSAP + SNAP
-			 * organization code not supported
-			 */
-			type = ntohs(header->snap.ethertype);
-			prefix = sizeof(eth_header_t) + sizeof(eth_header_lsap_t) +
-			    sizeof(eth_header_snap_t);
-		} else {
-			/* IEEE 802.3 + 802.2 LSAP */
-			type = lsap_map(header->lsap.dsap);
-			prefix = sizeof(eth_header_t) + sizeof(eth_header_lsap_t);
-		}
-
-		suffix = (type < ETH_MIN_CONTENT) ? ETH_MIN_CONTENT - type : 0U;
-		fcs = (eth_fcs_t *) data + prefix + type + suffix;
-		suffix += length - prefix - type;
-		length = prefix + type + suffix;
-	} else {
-		/* Invalid length/type, should not occur */
-		return NULL;
-	}
-	
-	if (IS_DUMMY(flags)) {
-		if (~compute_crc32(~0U, data, length * 8) != ntohl(*fcs))
-			return NULL;
-		suffix += sizeof(eth_fcs_t);
-	}
-	
-	rc = packet_set_addr(packet, header->header.source_address,
-	    header->header.destination_address, ETH_ADDR);
-	if (rc != EOK)
-		return NULL;
-
-	rc = packet_trim(packet, prefix, suffix);
-	if (rc != EOK)
-		return NULL;
-	
-	return eth_protos_find(&eth_globals.protos, type);
-}
-
-int nil_received_msg_local(nic_device_id_t device_id, packet_t *packet)
-{
-	eth_proto_t *proto;
-	packet_t *next;
-	eth_device_t *device;
-	int flags;
-
-	fibril_rwlock_read_lock(&eth_globals.devices_lock);
-	device = eth_devices_find(&eth_globals.devices, device_id);
-	if (!device) {
-		fibril_rwlock_read_unlock(&eth_globals.devices_lock);
-		return ENOENT;
-	}
-
-	flags = device->flags;
-	fibril_rwlock_read_unlock(&eth_globals.devices_lock);
-	fibril_rwlock_read_lock(&eth_globals.protos_lock);
-	
-	do {
-		next = pq_detach(packet);
-		proto = eth_process_packet(flags, packet);
-		if (proto) {
-			il_received_msg(proto->sess, device_id, packet,
-			    proto->service);
-		} else {
-			/* Drop invalid/unknown */
-			pq_release_remote(eth_globals.net_sess,
-			    packet_get_id(packet));
-		}
-		packet = next;
-	} while (packet);
-
-	fibril_rwlock_read_unlock(&eth_globals.protos_lock);
-	return EOK;
-}
-
-/** Returns the device packet dimensions for sending.
- *
- * @param[in] device_id	The device identifier.
- * @param[out] addr_len	The minimum reserved address length.
- * @param[out] prefix	The minimum reserved prefix size.
- * @param[out] content	The maximum content size.
- * @param[out] suffix	The minimum reserved suffix size.
- * @return		EOK on success.
- * @return		EBADMEM if either one of the parameters is NULL.
- * @return		ENOENT if there is no such device.
- */
-static int eth_packet_space_message(nic_device_id_t device_id, size_t *addr_len,
-    size_t *prefix, size_t *content, size_t *suffix)
-{
-	eth_device_t *device;
-
-	if (!addr_len || !prefix || !content || !suffix)
-		return EBADMEM;
-	
-	fibril_rwlock_read_lock(&eth_globals.devices_lock);
-	device = eth_devices_find(&eth_globals.devices, device_id);
-	if (!device) {
-		fibril_rwlock_read_unlock(&eth_globals.devices_lock);
-		return ENOENT;
-	}
-
-	*content = device->mtu;
-	fibril_rwlock_read_unlock(&eth_globals.devices_lock);
-	
-	*addr_len = ETH_ADDR;
-	*prefix = ETH_PREFIX;
-	*suffix = ETH_MIN_CONTENT + ETH_SUFFIX;
-
-	return EOK;
-}
-
-/** Send the device hardware address.
- *
- * @param[in] device_id	The device identifier.
- * @param[in] type	Type of the desired address.
- * @return		EOK on success.
- * @return		EBADMEM if the address parameter is NULL.
- * @return		ENOENT if there no such device.
- */
-static int eth_addr_message(nic_device_id_t device_id, eth_addr_type_t type)
-{
-	eth_device_t *device = NULL;
-	uint8_t *address;
-	size_t max_len;
-	ipc_callid_t callid;
-	
-	if (type == ETH_BROADCAST_ADDR)
-		address = eth_globals.broadcast_addr;
-	else {
-		fibril_rwlock_read_lock(&eth_globals.devices_lock);
-		device = eth_devices_find(&eth_globals.devices, device_id);
-		if (!device) {
-			fibril_rwlock_read_unlock(&eth_globals.devices_lock);
-			return ENOENT;
-		}
-		
-		address = (uint8_t *) &device->addr.address;
-	}
-	
-	int rc = EOK;
-	if (!async_data_read_receive(&callid, &max_len)) {
-		rc = EREFUSED;
-		goto end;
-	}
-	
-	if (max_len < ETH_ADDR) {
-		async_data_read_finalize(callid, NULL, 0);
-		rc = ELIMIT;
-		goto end;
-	}
-	
-	rc = async_data_read_finalize(callid, address, ETH_ADDR);
-	if (rc != EOK)
-		goto end;
-	
-end:
-	
-	if (type == ETH_LOCAL_ADDR)
-		fibril_rwlock_read_unlock(&eth_globals.devices_lock);
-	
-	return rc;
-}
-
-/** Register receiving module service.
- *
- * Pass received packets for this service.
- *
- * @param[in] service Module service.
- * @param[in] sess    Service session.
- *
- * @return EOK on success.
- * @return ENOENT if the service is not known.
- * @return ENOMEM if there is not enough memory left.
- *
- */
-static int eth_register_message(services_t service, async_sess_t *sess)
-{
-	eth_proto_t *proto;
-	int protocol;
-	int index;
-
-	protocol = protocol_map(SERVICE_ETHERNET, service);
-	if (!protocol)
-		return ENOENT;
-
-	fibril_rwlock_write_lock(&eth_globals.protos_lock);
-	proto = eth_protos_find(&eth_globals.protos, protocol);
-	if (proto) {
-		proto->sess = sess;
-		fibril_rwlock_write_unlock(&eth_globals.protos_lock);
-		return EOK;
-	} else {
-		proto = (eth_proto_t *) malloc(sizeof(eth_proto_t));
-		if (!proto) {
-			fibril_rwlock_write_unlock(&eth_globals.protos_lock);
-			return ENOMEM;
-		}
-
-		proto->service = service;
-		proto->protocol = protocol;
-		proto->sess = sess;
-
-		index = eth_protos_add(&eth_globals.protos, protocol, proto);
-		if (index < 0) {
-			fibril_rwlock_write_unlock(&eth_globals.protos_lock);
-			free(proto);
-			return index;
-		}
-	}
-	
-	printf("%s: Protocol registered (protocol: %d, service: %#x)\n",
-	    NAME, proto->protocol, proto->service);
-	
-	fibril_rwlock_write_unlock(&eth_globals.protos_lock);
-	return EOK;
-}
-
-/** Prepares the packet for sending.
- *
- * @param[in] flags	The device flags.
- * @param[in] packet	The packet.
- * @param[in] src_addr	The source hardware address.
- * @param[in] ethertype	The ethernet protocol type.
- * @param[in] mtu	The device maximum transmission unit.
- * @return		EOK on success.
- * @return		EINVAL if the packet addresses length is not long
- *			enough.
- * @return		EINVAL if the packet is bigger than the device MTU.
- * @return		ENOMEM if there is not enough memory in the packet.
- */
-static int
-eth_prepare_packet(int flags, packet_t *packet, uint8_t *src_addr, int ethertype,
-    size_t mtu)
-{
-	eth_header_snap_t *header;
-	eth_header_lsap_t *header_lsap;
-	eth_header_t *header_dix;
-	eth_fcs_t *fcs;
-	uint8_t *src;
-	uint8_t *dest;
-	size_t length;
-	int i;
-	void *padding;
-	eth_preamble_t *preamble;
-
-	i = packet_get_addr(packet, &src, &dest);
-	if (i < 0)
-		return i;
-	
-	if (i != ETH_ADDR)
-		return EINVAL;
-	
-	for (i = 0; i < ETH_ADDR; i++) {
-		if (src[i]) {
-			src_addr = src;
-			break;
-		}
-	}
-
-	length = packet_get_data_length(packet);
-	if (length > mtu)
-		return EINVAL;
-	
-	if (length < ETH_MIN_TAGGED_CONTENT(flags)) {
-		padding = packet_suffix(packet,
-		    ETH_MIN_TAGGED_CONTENT(flags) - length);
-		if (!padding)
-			return ENOMEM;
-
-		bzero(padding, ETH_MIN_TAGGED_CONTENT(flags) - length);
-	}
-	
-	if (IS_DIX(flags)) {
-		header_dix = PACKET_PREFIX(packet, eth_header_t);
-		if (!header_dix)
-			return ENOMEM;
-		
-		header_dix->ethertype = (uint16_t) ethertype;
-		memcpy(header_dix->source_address, src_addr, ETH_ADDR);
-		memcpy(header_dix->destination_address, dest, ETH_ADDR);
-		src = &header_dix->destination_address[0];
-	} else if (IS_8023_2_LSAP(flags)) {
-		header_lsap = PACKET_PREFIX(packet, eth_header_lsap_t);
-		if (!header_lsap)
-			return ENOMEM;
-		
-		header_lsap->header.ethertype = htons(length +
-		    sizeof(eth_header_lsap_t));
-		header_lsap->lsap.dsap = lsap_unmap(ntohs(ethertype));
-		header_lsap->lsap.ssap = header_lsap->lsap.dsap;
-		header_lsap->lsap.ctrl = IEEE_8023_2_UI;
-		memcpy(header_lsap->header.source_address, src_addr, ETH_ADDR);
-		memcpy(header_lsap->header.destination_address, dest, ETH_ADDR);
-		src = &header_lsap->header.destination_address[0];
-	} else if (IS_8023_2_SNAP(flags)) {
-		header = PACKET_PREFIX(packet, eth_header_snap_t);
-		if (!header)
-			return ENOMEM;
-		
-		header->header.ethertype = htons(length +
-		    sizeof(eth_header_lsap_t) + sizeof(eth_header_snap_t));
-		header->lsap.dsap = (uint16_t) ETH_LSAP_SNAP;
-		header->lsap.ssap = header->lsap.dsap;
-		header->lsap.ctrl = IEEE_8023_2_UI;
-		
-		for (i = 0; i < 3; i++)
-			header->snap.protocol[i] = 0;
-		
-		header->snap.ethertype = (uint16_t) ethertype;
-		memcpy(header->header.source_address, src_addr, ETH_ADDR);
-		memcpy(header->header.destination_address, dest, ETH_ADDR);
-		src = &header->header.destination_address[0];
-	}
-	
-	if (IS_DUMMY(flags)) {
-		preamble = PACKET_PREFIX(packet, eth_preamble_t);
-		if (!preamble)
-			return ENOMEM;
-		
-		for (i = 0; i < 7; i++)
-			preamble->preamble[i] = ETH_PREAMBLE;
-		
-		preamble->sfd = ETH_SFD;
-		
-		fcs = PACKET_SUFFIX(packet, eth_fcs_t);
-		if (!fcs)
-			return ENOMEM;
-
-		*fcs = htonl(~compute_crc32(~0U, src, length * 8));
-	}
-	
-	return EOK;
-}
-
-/** Sends the packet queue.
- *
- * Sends only packet successfully processed by the eth_prepare_packet()
- * function.
- *
- * @param[in] device_id	The device identifier.
- * @param[in] packet	The packet queue.
- * @param[in] sender	The sending module service.
- * @return		EOK on success.
- * @return		ENOENT if there no such device.
- * @return		EINVAL if the service parameter is not known.
- */
-static int eth_send_message(nic_device_id_t device_id, packet_t *packet,
-    services_t sender)
-{
-	eth_device_t *device;
-	packet_t *next;
-	packet_t *tmp;
-	int ethertype;
-	int rc;
-
-	ethertype = htons(protocol_map(SERVICE_ETHERNET, sender));
-	if (!ethertype) {
-		pq_release_remote(eth_globals.net_sess, packet_get_id(packet));
-		return EINVAL;
-	}
-	
-	fibril_rwlock_read_lock(&eth_globals.devices_lock);
-	device = eth_devices_find(&eth_globals.devices, device_id);
-	if (!device) {
-		fibril_rwlock_read_unlock(&eth_globals.devices_lock);
-		return ENOENT;
-	}
-	
-	/* Process packet queue */
-	next = packet;
-	do {
-		rc = eth_prepare_packet(device->flags, next,
-		    (uint8_t *) &device->addr.address, ethertype, device->mtu);
-		if (rc != EOK) {
-			/* Release invalid packet */
-			tmp = pq_detach(next);
-			if (next == packet)
-				packet = tmp;
-			pq_release_remote(eth_globals.net_sess,
-			    packet_get_id(next));
-			next = tmp;
-		} else {
-			nic_send_frame(device->sess, packet_get_data(next),
-			    packet_get_data_length(next));
-			next = pq_next(next);
-		}
-	} while (next);
-	
-	pq_release_remote(eth_globals.net_sess, packet_get_id(packet));
-	
-	fibril_rwlock_read_unlock(&eth_globals.devices_lock);
-	return EOK;
-}
-
-static int eth_received(eth_device_t *device)
-{
-	void *data;
-	size_t size;
-	int rc;
-	
-	rc = async_data_write_accept(&data, false, 0, 0, 0, &size);
-	if (rc != EOK) {
-		printf("%s: data_write_accept() failed\n", NAME);
-		return rc;
-	}
-	
-	packet_t *packet = packet_get_1_remote(eth_globals.net_sess, size);
-	if (packet == NULL)
-		return ENOMEM;
-	
-	void *pdata = packet_suffix(packet, size);
-	memcpy(pdata, data, size);
-	free(data);
-	
-	return nil_received_msg_local(device->device_id, packet);
-}
-
-static int eth_addr_changed(eth_device_t *device)
-{
-	nic_address_t address;
-	size_t length;
-	ipc_callid_t data_callid;
-	if (!async_data_write_receive(&data_callid, &length)) {
-		async_answer_0(data_callid, EINVAL);
-		return EINVAL;
-	}
-	if (length > sizeof (nic_address_t)) {
-		async_answer_0(data_callid, ELIMIT);
-		return ELIMIT;
-	}
-	if (async_data_write_finalize(data_callid, &address, length) != EOK) {
-		return EINVAL;
-	}
-
-	fibril_rwlock_write_lock(&eth_globals.devices_lock);
-
-	printf("Device %d changing address from " PRIMAC " to " PRIMAC "\n",
-		device->device_id, ARGSMAC(device->addr.address),
-		ARGSMAC(address.address));
-	memcpy(&device->addr, &address, sizeof (nic_address_t));
-	fibril_rwlock_write_unlock(&eth_globals.devices_lock);
-
-	/* Notify all upper layer modules */
-	fibril_rwlock_read_lock(&eth_globals.protos_lock);
-	int index;
-	for (index = 0; index < eth_protos_count(&eth_globals.protos); index++) {
-		eth_proto_t *proto = eth_protos_get_index(&eth_globals.protos, index);
-		if (proto->sess != NULL) {
-			il_addr_changed_msg(proto->sess, device->device_id,
-					ETH_ADDR, address.address);
-		}
-	}
-
-	fibril_rwlock_read_unlock(&eth_globals.protos_lock);
-	return EOK;
-}
-
-int nil_module_message(ipc_callid_t callid, ipc_call_t *call,
-    ipc_call_t *answer, size_t *answer_count)
-{
-	packet_t *packet;
-	size_t addrlen;
-	size_t prefix;
-	size_t suffix;
-	size_t content;
-	int rc;
-	
-	*answer_count = 0;
-	
-	if (!IPC_GET_IMETHOD(*call))
-		return EOK;
-	
-	async_sess_t *callback =
-	    async_callback_receive_start(EXCHANGE_SERIALIZE, call);
-	if (callback)
-		return eth_register_message(NIL_GET_PROTO(*call), callback);
-	
-	switch (IPC_GET_IMETHOD(*call)) {
-	case NET_NIL_DEVICE:
-		return eth_device_message(IPC_GET_DEVICE(*call),
-		    IPC_GET_DEVICE_HANDLE(*call), IPC_GET_MTU(*call));
-	case NET_NIL_SEND:
-		rc = packet_translate_remote(eth_globals.net_sess, &packet,
-		    IPC_GET_PACKET(*call));
-		if (rc != EOK)
-			return rc;
-		
-		return eth_send_message(IPC_GET_DEVICE(*call), packet,
-		    IPC_GET_SERVICE(*call));
-	case NET_NIL_PACKET_SPACE:
-		rc = eth_packet_space_message(IPC_GET_DEVICE(*call), &addrlen,
-		    &prefix, &content, &suffix);
-		if (rc != EOK)
-			return rc;
-		
-		IPC_SET_ADDR(*answer, addrlen);
-		IPC_SET_PREFIX(*answer, prefix);
-		IPC_SET_CONTENT(*answer, content);
-		IPC_SET_SUFFIX(*answer, suffix);
-		*answer_count = 4;
-		
-		return EOK;
-	case NET_NIL_ADDR:
-		rc = eth_addr_message(IPC_GET_DEVICE(*call), ETH_LOCAL_ADDR);
-		if (rc != EOK)
-			return rc;
-		
-		IPC_SET_ADDR(*answer, ETH_ADDR);
-		*answer_count = 1;
-		
-		return EOK;
-	case NET_NIL_BROADCAST_ADDR:
-		rc = eth_addr_message(IPC_GET_DEVICE(*call), ETH_BROADCAST_ADDR);
-		if (rc != EOK)
-			return rc;
-		
-		IPC_SET_ADDR(*answer, ETH_ADDR);
-		*answer_count = 1;
-		
-		return EOK;
-	}
-	
-	return ENOTSUP;
-}
-
-static void eth_nic_cb_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
-{
-	eth_device_t *device = (eth_device_t *)arg;
-	int rc;
-	
-	async_answer_0(iid, EOK);
-	
-	while (true) {
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-		
-		if (!IPC_GET_IMETHOD(call))
-			break;
-		
-		switch (IPC_GET_IMETHOD(call)) {
-		case NIC_EV_DEVICE_STATE:
-			rc = eth_device_state(device, IPC_GET_ARG1(call));
-			async_answer_0(callid, (sysarg_t) rc);
-			break;
-		case NIC_EV_RECEIVED:
-			rc = eth_received(device);
-			async_answer_0(callid, (sysarg_t) rc);
-			break;
-		case NIC_EV_ADDR_CHANGED:
-			rc = eth_addr_changed(device);
-			async_answer_0(callid, (sysarg_t) rc);
-			break;
-		default:
-			async_answer_0(callid, ENOTSUP);
-		}
-	}
-}
-
-int main(int argc, char *argv[])
-{
-	/* Start the module */
-	return nil_module_start(SERVICE_ETHERNET);
-}
-
-/** @}
- */
Index: pace/srv/net/nil/eth/eth.h
===================================================================
--- uspace/srv/net/nil/eth/eth.h	(revision bf31e3f1ebd6e88e0c8425f109e42ccd92b6c9b3)
+++ 	(revision )
@@ -1,277 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * Copyright (c) 2011 Radim Vansa
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup eth
- *  @{
- */
-
-/** @file
- * Ethernet module.
- */
-
-#ifndef NET_ETH_H_
-#define NET_ETH_H_
-
-#include <async.h>
-#include <fibril_synch.h>
-#include <ipc/loc.h>
-#include <ipc/services.h>
-#include <net/device.h>
-#include <adt/measured_strings.h>
-
-/** Ethernet address length. */
-#define ETH_ADDR  6
-
-/** Ethernet header preamble value. */
-#define ETH_PREAMBLE  0x55
-
-/** Ethernet header start of frame value. */
-#define ETH_SFD  0xD5
-
-/** IEEE 802.2 unordered information control field. */
-#define IEEE_8023_2_UI  0x03
-
-/** Type definition of the Ethernet header IEEE 802.3 + 802.2 + SNAP extensions.
- * @see eth_header_snap
- */
-typedef struct eth_header_snap eth_header_snap_t;
-
-/** Type definition of the Ethernet header IEEE 802.3 + 802.2 + SNAP extensions.
- * @see eth_header_lsap
- */
-typedef struct eth_header_lsap eth_header_lsap_t;
-
-/** Type definition of the Ethernet header LSAP extension.
- * @see eth_ieee_lsap
- */
-typedef struct eth_ieee_lsap eth_ieee_lsap_t;
-
-/** Type definition of the Ethernet header SNAP extension.
- * @see eth_snap
- */
-typedef struct eth_snap eth_snap_t;
-
-/** Type definition of the Ethernet header preamble.
- * @see preamble
- */
-typedef struct eth_preamble eth_preamble_t;
-
-/** Type definition of the Ethernet header.
- * @see eth_header
- */
-typedef struct eth_header eth_header_t;
-
-/** Ethernet header Link Service Access Point extension. */
-struct eth_ieee_lsap {
-	/**
-	 * Destination Service Access Point identifier.
-	 * The possible values are assigned by an IEEE committee.
-	 */
-	uint8_t dsap;
-	
-	/**
-	 * Source Service Access Point identifier.
-	 * The possible values are assigned by an IEEE committee.
-	 */
-	uint8_t ssap;
-	
-	/**
-	 * Control parameter.
-	 * The possible values are assigned by an IEEE committee.
-	 */
-	uint8_t ctrl;
-} __attribute__ ((packed));
-
-/** Ethernet header SNAP extension. */
-struct eth_snap {
-	/** Protocol identifier or organization code. */
-	uint8_t protocol[3];
-	
-	/**
-	 * Ethernet protocol identifier in the network byte order (big endian).
-	 * @see ethernet_protocols.h
-	 */
-	uint16_t ethertype;
-} __attribute__ ((packed));
-
-/** Ethernet header preamble.
- *
- * Used for dummy devices.
- */
-struct eth_preamble {
-	/**
-	 * Controlling preamble used for the frame transmission synchronization.
-	 * All should be set to ETH_PREAMBLE.
-	 */
-	uint8_t preamble[7];
-	
-	/**
-	 * Start of Frame Delimiter used for the frame transmission
-	 * synchronization.
-	 * Should be set to ETH_SFD.
-	 */
-	uint8_t sfd;
-} __attribute__ ((packed));
-
-/** Ethernet header. */
-struct eth_header {
-	/** Destination host Ethernet address (MAC address). */
-	uint8_t destination_address[ETH_ADDR];
-	/** Source host Ethernet address (MAC address). */
-	uint8_t source_address[ETH_ADDR];
-	
-	/**
-	 * Ethernet protocol identifier in the network byte order (big endian).
-	 * @see ethernet_protocols.h
-	 */
-	uint16_t ethertype;
-} __attribute__ ((packed));
-
-/** Ethernet header IEEE 802.3 + 802.2 extension. */
-struct eth_header_lsap {
-	/** Ethernet header. */
-	eth_header_t header;
-	
-	/**
-	 * LSAP extension.
-	 * If DSAP and SSAP are set to ETH_LSAP_SNAP the SNAP extension is being
-	 * used.
-	 * If DSAP and SSAP fields are equal to ETH_RAW the raw Ethernet packet
-	 * without any extensions is being used and the frame content starts
-	 * rigth after the two fields.
-	 */
-	eth_ieee_lsap_t lsap;
-} __attribute__ ((packed));
-
-/** Ethernet header IEEE 802.3 + 802.2 + SNAP extensions. */
-struct eth_header_snap {
-	/** Ethernet header. */
-	eth_header_t header;
-	
-	/**
-	 * LSAP extension.
-	 * If DSAP and SSAP are set to ETH_LSAP_SNAP the SNAP extension is being
-	 * used.
-	 * If DSAP and SSAP fields are equal to ETH_RAW the raw Ethernet packet
-	 * without any extensions is being used and the frame content starts
-	 * rigth after the two fields.
-	 */
-	eth_ieee_lsap_t lsap;
-	
-	/** SNAP extension. */
-	eth_snap_t snap;
-} __attribute__ ((packed));
-
-/** Ethernet Frame Check Sequence. */
-typedef uint32_t eth_fcs_t;
-
-/** Type definition of the Ethernet global data.
- * @see eth_globals
- */
-typedef struct eth_globals eth_globals_t;
-
-/** Type definition of the Ethernet device specific data.
- * @see eth_device
- */
-typedef struct eth_device eth_device_t;
-
-/** Type definition of the Ethernet protocol specific data.
- * @see eth_proto
- */
-typedef struct eth_proto eth_proto_t;
-
-/** Ethernet device map.
- * Maps devices to the Ethernet device specific data.
- * @see device.h
- */
-DEVICE_MAP_DECLARE(eth_devices, eth_device_t);
-
-/** Ethernet protocol map.
- * Maps protocol identifiers to the Ethernet protocol specific data.
- * @see int_map.h
- */
-INT_MAP_DECLARE(eth_protos, eth_proto_t);
-
-/** Ethernet device specific data. */
-struct eth_device {
-	/** Device identifier. */
-	nic_device_id_t device_id;
-	/** Device handle */
-	service_id_t sid;
-	/** Driver session. */
-	async_sess_t *sess;
-	/** Maximal transmission unit. */
-	size_t mtu;
-	
-	/**
-	 * Various device flags.
-	 * @see ETH_DUMMY
-	 * @see ETH_MODE_MASK
-	 */
-	int flags;
-	
-	/** Actual device hardware address. */
-	nic_address_t addr;
-};
-
-/** Ethernet protocol specific data. */
-struct eth_proto {
-	/** Protocol service. */
-	services_t service;
-	/** Protocol identifier. */
-	int protocol;
-	/** Protocol module session. */
-	async_sess_t *sess;
-};
-
-/** Ethernet global data. */
-struct eth_globals {
-	/** Networking module session. */
-	async_sess_t *net_sess;
-	/** Safety lock for devices. */
-	fibril_rwlock_t devices_lock;
-	/** All known Ethernet devices. */
-	eth_devices_t devices;
-	/** Safety lock for protocols. */
-	fibril_rwlock_t protos_lock;
-	
-	/**
-	 * Protocol map.
-	 * Service map for each protocol.
-	 */
-	eth_protos_t protos;
-	
-	/** Broadcast device hardware address. */
-	uint8_t broadcast_addr[ETH_ADDR];
-};
-
-#endif
-
-/** @}
- */
Index: pace/srv/net/nil/nildummy/Makefile
===================================================================
--- uspace/srv/net/nil/nildummy/Makefile	(revision bf31e3f1ebd6e88e0c8425f109e42ccd92b6c9b3)
+++ 	(revision )
@@ -1,46 +1,0 @@
-#
-# Copyright (c) 2005 Martin Decky
-# Copyright (c) 2007 Jakub Jermar
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# - Redistributions of source code must retain the above copyright
-#   notice, this list of conditions and the following disclaimer.
-# - Redistributions in binary form must reproduce the above copyright
-#   notice, this list of conditions and the following disclaimer in the
-#   documentation and/or other materials provided with the distribution.
-# - The name of the author may not be used to endorse or promote products
-#   derived from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-
-USPACE_PREFIX = ../../../..
-ROOT_PATH = $(USPACE_PREFIX)/..
-LIBS = $(LIBNET_PREFIX)/libnet.a
-EXTRA_CFLAGS = -I$(LIBNET_PREFIX)/include
-
-COMMON_MAKEFILE = $(ROOT_PATH)/Makefile.common
-CONFIG_MAKEFILE = $(ROOT_PATH)/Makefile.config
-
--include $(COMMON_MAKEFILE)
--include $(CONFIG_MAKEFILE)
-
-BINARY = nildummy
-
-SOURCES = \
-	nildummy.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/srv/net/nil/nildummy/nildummy.c
===================================================================
--- uspace/srv/net/nil/nildummy/nildummy.c	(revision bf31e3f1ebd6e88e0c8425f109e42ccd92b6c9b3)
+++ 	(revision )
@@ -1,506 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * Copyright (c) 2011 Radim Vansa
- * Copyright (c) 2011 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup nildummy
- * @{
- */
-
-/** @file
- * Dummy network interface layer module implementation.
- * @see nildummy.h
- */
-
-#include <assert.h>
-#include <async.h>
-#include <malloc.h>
-#include <mem.h>
-#include <stdio.h>
-#include <str.h>
-#include <ipc/nil.h>
-#include <ipc/net.h>
-#include <ipc/services.h>
-#include <net/modules.h>
-#include <net/device.h>
-#include <il_remote.h>
-#include <adt/measured_strings.h>
-#include <net/packet.h>
-#include <packet_remote.h>
-#include <packet_client.h>
-#include <device/nic.h>
-#include <loc.h>
-#include <nil_skel.h>
-#include "nildummy.h"
-
-/** The module name. */
-#define NAME  "nildummy"
-
-/** Default maximum transmission unit. */
-#define NET_DEFAULT_MTU  1500
-
-/** Network interface layer module global data. */
-nildummy_globals_t nildummy_globals;
-
-DEVICE_MAP_IMPLEMENT(nildummy_devices, nildummy_device_t);
-
-static void nildummy_nic_cb_conn(ipc_callid_t iid, ipc_call_t *icall,
-    void *arg);
-
-static int nildummy_device_state(nildummy_device_t *device, sysarg_t state)
-{
-	fibril_rwlock_read_lock(&nildummy_globals.protos_lock);
-	if (nildummy_globals.proto.sess)
-		il_device_state_msg(nildummy_globals.proto.sess,
-		    device->device_id, state, nildummy_globals.proto.service);
-	fibril_rwlock_read_unlock(&nildummy_globals.protos_lock);
-	
-	return EOK;
-}
-
-static int nildummy_addr_changed(nildummy_device_t *device)
-{
-	return ENOTSUP;
-}
-
-int nil_initialize(async_sess_t *sess)
-{
-	fibril_rwlock_initialize(&nildummy_globals.devices_lock);
-	fibril_rwlock_initialize(&nildummy_globals.protos_lock);
-	fibril_rwlock_write_lock(&nildummy_globals.devices_lock);
-	fibril_rwlock_write_lock(&nildummy_globals.protos_lock);
-	
-	nildummy_globals.net_sess = sess;
-	nildummy_globals.proto.sess = NULL;
-	int rc = nildummy_devices_initialize(&nildummy_globals.devices);
-	
-	fibril_rwlock_write_unlock(&nildummy_globals.protos_lock);
-	fibril_rwlock_write_unlock(&nildummy_globals.devices_lock);
-	
-	return rc;
-}
-
-/** Register new device or updates the MTU of an existing one.
- *
- * Determine the device local hardware address.
- *
- * @param[in] device_id New device identifier.
- * @param[in] service   Device driver service.
- * @param[in] mtu       Device maximum transmission unit.
- *
- * @return EOK on success.
- * @return EEXIST if the device with the different service exists.
- * @return ENOMEM if there is not enough memory left.
- * @return Other error codes as defined for the
- *         netif_bind_service() function.
- * @return Other error codes as defined for the
- *         netif_get_addr_req() function.
- *
- */
-static int nildummy_device_message(nic_device_id_t device_id,
-    service_id_t sid, size_t mtu)
-{
-	fibril_rwlock_write_lock(&nildummy_globals.devices_lock);
-	
-	/* An existing device? */
-	nildummy_device_t *device =
-	    nildummy_devices_find(&nildummy_globals.devices, device_id);
-	if (device) {
-		if (device->sid != sid) {
-			printf("Device %d exists, handles do not match\n",
-			    device->device_id);
-			fibril_rwlock_write_unlock(&nildummy_globals.devices_lock);
-			return EEXIST;
-		}
-		
-		/* Update MTU */
-		if (mtu > 0)
-			device->mtu = mtu;
-		else
-			device->mtu = NET_DEFAULT_MTU;
-		
-		printf("Device %d already exists (mtu: %zu)\n", device->device_id,
-		    device->mtu);
-		fibril_rwlock_write_unlock(&nildummy_globals.devices_lock);
-		
-		/* Notify the upper layer module */
-		fibril_rwlock_read_lock(&nildummy_globals.protos_lock);
-		if (nildummy_globals.proto.sess) {
-			il_mtu_changed_msg(nildummy_globals.proto.sess,
-			    device->device_id, device->mtu,
-			    nildummy_globals.proto.service);
-		}
-		fibril_rwlock_read_unlock(&nildummy_globals.protos_lock);
-		
-		return EOK;
-	}
-	
-	/* Create a new device */
-	device = (nildummy_device_t *) malloc(sizeof(nildummy_device_t));
-	if (!device)
-		return ENOMEM;
-	
-	device->device_id = device_id;
-	device->sid = sid;
-	if (mtu > 0)
-		device->mtu = mtu;
-	else
-		device->mtu = NET_DEFAULT_MTU;
-	
-	/* Bind the device driver */
-	device->sess = loc_service_connect(EXCHANGE_SERIALIZE, sid,
-	    IPC_FLAG_BLOCKING);
-	if (device->sess == NULL) {
-		fibril_rwlock_write_unlock(&nildummy_globals.devices_lock);
-		free(device);
-		return ENOENT;
-	}
-	
-	int rc = nic_callback_create(device->sess, nildummy_nic_cb_conn,
-	    device);
-	if (rc != EOK) {
-		async_hangup(device->sess);
-		
-		return ENOENT;
-	}
-	
-	/* Get hardware address */
-	rc = nic_get_address(device->sess, &device->addr);
-	if (rc != EOK) {
-		fibril_rwlock_write_unlock(&nildummy_globals.devices_lock);
-		free(device);
-		return rc;
-	}
-	
-	device->addr_len = ETH_ADDR;
-	
-	/* Add to the cache */
-	int index = nildummy_devices_add(&nildummy_globals.devices,
-	    device->device_id, device);
-	if (index < 0) {
-		fibril_rwlock_write_unlock(&nildummy_globals.devices_lock);
-		free(device);
-		return index;
-	}
-	
-	printf("%s: Device registered (id: %d, mtu: %zu)\n", NAME,
-	    device->device_id, device->mtu);
-	fibril_rwlock_write_unlock(&nildummy_globals.devices_lock);
-	return EOK;
-}
-
-/** Return the device hardware address.
- *
- * @param[in]  device_id Device identifier.
- * @param[out] address   Device hardware address.
- *
- * @return EOK on success.
- * @return EBADMEM if the address parameter is NULL.
- * @return ENOENT if there no such device.
- *
- */
-static int nildummy_addr_message(nic_device_id_t device_id, size_t *addrlen)
-{
-	if (!addrlen)
-		return EBADMEM;
-	
-	fibril_rwlock_read_lock(&nildummy_globals.devices_lock);
-	
-	nildummy_device_t *device =
-	    nildummy_devices_find(&nildummy_globals.devices, device_id);
-	if (!device) {
-		fibril_rwlock_read_unlock(&nildummy_globals.devices_lock);
-		return ENOENT;
-	}
-	
-	ipc_callid_t callid;
-	size_t max_len;
-	if (!async_data_read_receive(&callid, &max_len)) {
-		fibril_rwlock_read_unlock(&nildummy_globals.devices_lock);
-		return EREFUSED;
-	}
-	
-	if (max_len < device->addr_len) {
-		fibril_rwlock_read_unlock(&nildummy_globals.devices_lock);
-		async_data_read_finalize(callid, NULL, 0);
-		return ELIMIT;
-	}
-	
-	int rc = async_data_read_finalize(callid,
-	    (uint8_t *) &device->addr.address, device->addr_len);
-	if (rc != EOK) {
-		fibril_rwlock_read_unlock(&nildummy_globals.devices_lock);
-		return rc;
-	}
-	
-	*addrlen = device->addr_len;
-	
-	fibril_rwlock_read_unlock(&nildummy_globals.devices_lock);
-	return EOK;
-}
-
-/** Return the device packet dimensions for sending.
- *
- * @param[in]  device_id Device identifier.
- * @param[out] addr_len  Minimum reserved address length.
- * @param[out] prefix    Minimum reserved prefix size.
- * @param[out] content   Maximum content size.
- * @param[out] suffix    Minimum reserved suffix size.
- *
- * @return EOK on success.
- * @return EBADMEM if either one of the parameters is NULL.
- * @return ENOENT if there is no such device.
- *
- */
-static int nildummy_packet_space_message(nic_device_id_t device_id,
-    size_t *addr_len, size_t *prefix, size_t *content, size_t *suffix)
-{
-	if ((!addr_len) || (!prefix) || (!content) || (!suffix))
-		return EBADMEM;
-	
-	fibril_rwlock_read_lock(&nildummy_globals.devices_lock);
-	
-	nildummy_device_t *device =
-	    nildummy_devices_find(&nildummy_globals.devices, device_id);
-	if (!device) {
-		fibril_rwlock_read_unlock(&nildummy_globals.devices_lock);
-		return ENOENT;
-	}
-	
-	*content = device->mtu;
-	
-	fibril_rwlock_read_unlock(&nildummy_globals.devices_lock);
-	
-	*addr_len = 0;
-	*prefix = 0;
-	*suffix = 0;
-	return EOK;
-}
-
-int nil_received_msg_local(nic_device_id_t device_id, packet_t *packet)
-{
-	fibril_rwlock_read_lock(&nildummy_globals.protos_lock);
-	
-	if (nildummy_globals.proto.sess) {
-		do {
-			packet_t *next = pq_detach(packet);
-			il_received_msg(nildummy_globals.proto.sess, device_id,
-			    packet, nildummy_globals.proto.service);
-			packet = next;
-		} while (packet);
-	}
-	
-	fibril_rwlock_read_unlock(&nildummy_globals.protos_lock);
-	
-	return EOK;
-}
-
-/** Register receiving module service.
- *
- * Pass received packets for this service.
- *
- * @param[in] service Module service.
- * @param[in] sess    Service session.
- *
- * @return EOK on success.
- * @return ENOENT if the service is not known.
- * @return ENOMEM if there is not enough memory left.
- *
- */
-static int nildummy_register_message(services_t service, async_sess_t *sess)
-{
-	fibril_rwlock_write_lock(&nildummy_globals.protos_lock);
-	nildummy_globals.proto.service = service;
-	nildummy_globals.proto.sess = sess;
-	
-	printf("%s: Protocol registered (service: %#x)\n",
-	    NAME, nildummy_globals.proto.service);
-	
-	fibril_rwlock_write_unlock(&nildummy_globals.protos_lock);
-	return EOK;
-}
-
-/** Send the packet queue.
- *
- * @param[in] device_id Device identifier.
- * @param[in] packet    Packet queue.
- * @param[in] sender    Sending module service.
- *
- * @return EOK on success.
- * @return ENOENT if there no such device.
- * @return EINVAL if the service parameter is not known.
- *
- */
-static int nildummy_send_message(nic_device_id_t device_id, packet_t *packet,
-    services_t sender)
-{
-	fibril_rwlock_read_lock(&nildummy_globals.devices_lock);
-	
-	nildummy_device_t *device =
-	    nildummy_devices_find(&nildummy_globals.devices, device_id);
-	if (!device) {
-		fibril_rwlock_read_unlock(&nildummy_globals.devices_lock);
-		return ENOENT;
-	}
-	
-	packet_t *p = packet;
-	do {
-		nic_send_frame(device->sess, packet_get_data(p),
-		    packet_get_data_length(p));
-		p = pq_next(p);
-	} while (p != NULL);
-	
-	pq_release_remote(nildummy_globals.net_sess, packet_get_id(packet));
-	
-	fibril_rwlock_read_unlock(&nildummy_globals.devices_lock);
-	
-	return EOK;
-}
-
-static int nildummy_received(nildummy_device_t *device)
-{
-	void *data;
-	size_t size;
-	int rc;
-
-	rc = async_data_write_accept(&data, false, 0, 0, 0, &size);
-	if (rc != EOK)
-		return rc;
-
-	packet_t *packet = packet_get_1_remote(nildummy_globals.net_sess, size);
-	if (packet == NULL)
-		return ENOMEM;
-
-	void *pdata = packet_suffix(packet, size);
-	memcpy(pdata, data, size);
-	free(pdata);
-
-	return nil_received_msg_local(device->device_id, packet);
-}
-
-int nil_module_message(ipc_callid_t callid, ipc_call_t *call,
-    ipc_call_t *answer, size_t *answer_count)
-{
-	packet_t *packet;
-	size_t addrlen;
-	size_t prefix;
-	size_t suffix;
-	size_t content;
-	int rc;
-	
-	*answer_count = 0;
-	
-	if (!IPC_GET_IMETHOD(*call))
-		return EOK;
-	
-	async_sess_t *callback =
-	    async_callback_receive_start(EXCHANGE_SERIALIZE, call);
-	if (callback)
-		return nildummy_register_message(NIL_GET_PROTO(*call), callback);
-	
-	switch (IPC_GET_IMETHOD(*call)) {
-	case NET_NIL_DEVICE:
-		return nildummy_device_message(IPC_GET_DEVICE(*call),
-		    IPC_GET_DEVICE_HANDLE(*call), IPC_GET_MTU(*call));
-	
-	case NET_NIL_SEND:
-		rc = packet_translate_remote(nildummy_globals.net_sess,
-		    &packet, IPC_GET_PACKET(*call));
-		if (rc != EOK)
-			return rc;
-		return nildummy_send_message(IPC_GET_DEVICE(*call), packet,
-		    IPC_GET_SERVICE(*call));
-	
-	case NET_NIL_PACKET_SPACE:
-		rc = nildummy_packet_space_message(IPC_GET_DEVICE(*call),
-		    &addrlen, &prefix, &content, &suffix);
-		if (rc != EOK)
-			return rc;
-		IPC_SET_ADDR(*answer, addrlen);
-		IPC_SET_PREFIX(*answer, prefix);
-		IPC_SET_CONTENT(*answer, content);
-		IPC_SET_SUFFIX(*answer, suffix);
-		*answer_count = 4;
-		return EOK;
-	
-	case NET_NIL_ADDR:
-	case NET_NIL_BROADCAST_ADDR:
-		rc = nildummy_addr_message(IPC_GET_DEVICE(*call), &addrlen);
-		if (rc != EOK)
-			return rc;
-		
-		IPC_SET_ADDR(*answer, addrlen);
-		*answer_count = 1;
-		return rc;
-	}
-	
-	return ENOTSUP;
-}
-
-static void nildummy_nic_cb_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
-{
-	nildummy_device_t *device = (nildummy_device_t *)arg;
-	int rc;
-	
-	async_answer_0(iid, EOK);
-	
-	while (true) {
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-		
-		if (!IPC_GET_IMETHOD(call))
-			break;
-		
-		switch (IPC_GET_IMETHOD(call)) {
-		case NIC_EV_DEVICE_STATE:
-			rc = nildummy_device_state(device, IPC_GET_ARG1(call));
-			async_answer_0(callid, (sysarg_t) rc);
-			break;
-		case NIC_EV_RECEIVED:
-			rc = nildummy_received(device);
-			async_answer_0(callid, (sysarg_t) rc);
-			break;
-		case NIC_EV_ADDR_CHANGED:
-			rc = nildummy_addr_changed(device);
-			async_answer_0(callid, (sysarg_t) rc);
-			break;
-		default:
-			async_answer_0(callid, ENOTSUP);
-		}
-	}
-}
-
-
-int main(int argc, char *argv[])
-{
-	/* Start the module */
-	return nil_module_start(SERVICE_NILDUMMY);
-}
-
-/** @}
- */
Index: pace/srv/net/nil/nildummy/nildummy.h
===================================================================
--- uspace/srv/net/nil/nildummy/nildummy.h	(revision bf31e3f1ebd6e88e0c8425f109e42ccd92b6c9b3)
+++ 	(revision )
@@ -1,124 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * Copyright (c) 2011 Radim Vansa
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup nildummy
- * @{
- */
-
-/** @file
- * Dummy network interface layer module.
- */
-
-#ifndef NET_NILDUMMY_H_
-#define NET_NILDUMMY_H_
-
-#include <async.h>
-#include <fibril_synch.h>
-#include <ipc/loc.h>
-#include <ipc/services.h>
-#include <net/device.h>
-
-/** Type definition of the dummy nil global data.
- *
- * @see nildummy_globals
- *
- */
-typedef struct nildummy_globals nildummy_globals_t;
-
-/** Type definition of the dummy nil device specific data.
- *
- * @see nildummy_device
- *
- */
-typedef struct nildummy_device nildummy_device_t;
-
-/** Type definition of the dummy nil protocol specific data.
- *
- * @see nildummy_proto
- *
- */
-typedef struct nildummy_proto nildummy_proto_t;
-
-/** Dummy nil device map.
- *
- * Map devices to the dummy nil device specific data.
- * @see device.h
- *
- */
-DEVICE_MAP_DECLARE(nildummy_devices, nildummy_device_t);
-
-/** Dummy nil device specific data. */
-struct nildummy_device {
-	/** Device identifier. */
-	nic_device_id_t device_id;
-	/** Device service ID. */
-	service_id_t sid;
-	/** Driver session. */
-	async_sess_t *sess;
-	
-	/** Maximal transmission unit. */
-	size_t mtu;
-	
-	/** Actual device hardware address. */
-	nic_address_t addr;
-	/** Actual device hardware address length. */
-	size_t addr_len;
-};
-
-/** Dummy nil protocol specific data. */
-struct nildummy_proto {
-	/** Protocol service. */
-	services_t service;
-	
-	/** Protocol module session. */
-	async_sess_t *sess;
-};
-
-/** Dummy nil global data. */
-struct nildummy_globals {
-	/** Networking module session. */
-	async_sess_t *net_sess;
-	
-	/** Lock for devices. */
-	fibril_rwlock_t devices_lock;
-	
-	/** All known Ethernet devices. */
-	nildummy_devices_t devices;
-	
-	/** Safety lock for protocols. */
-	fibril_rwlock_t protos_lock;
-	
-	/** Default protocol. */
-	nildummy_proto_t proto;
-};
-
-#endif
-
-/** @}
- */
Index: pace/srv/net/tl/icmp/Makefile
===================================================================
--- uspace/srv/net/tl/icmp/Makefile	(revision bf31e3f1ebd6e88e0c8425f109e42ccd92b6c9b3)
+++ 	(revision )
@@ -1,39 +1,0 @@
-#
-# Copyright (c) 2005 Martin Decky
-# Copyright (c) 2007 Jakub Jermar
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# - Redistributions of source code must retain the above copyright
-#   notice, this list of conditions and the following disclaimer.
-# - Redistributions in binary form must reproduce the above copyright
-#   notice, this list of conditions and the following disclaimer in the
-#   documentation and/or other materials provided with the distribution.
-# - The name of the author may not be used to endorse or promote products
-#   derived from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-
-USPACE_PREFIX = ../../../..
-LIBS = $(LIBNET_PREFIX)/libnet.a
-EXTRA_CFLAGS = -I$(LIBNET_PREFIX)/include
-BINARY = icmp
-STATIC_ONLY = y
-
-SOURCES = \
-	icmp.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/srv/net/tl/icmp/icmp.c
===================================================================
--- uspace/srv/net/tl/icmp/icmp.c	(revision bf31e3f1ebd6e88e0c8425f109e42ccd92b6c9b3)
+++ 	(revision )
@@ -1,809 +1,0 @@
-/*
- * Copyright (c) 2008 Lukas Mejdrech
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup icmp
- * @{
- */
-
-/** @file
- * ICMP module implementation.
- */
-
-#include <async.h>
-#include <atomic.h>
-#include <fibril.h>
-#include <fibril_synch.h>
-#include <stdint.h>
-#include <str.h>
-#include <ipc/services.h>
-#include <ipc/net.h>
-#include <ipc/tl.h>
-#include <ipc/icmp.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <byteorder.h>
-#include <errno.h>
-#include <adt/hash_table.h>
-
-#include <net/socket_codes.h>
-#include <net/ip_protocols.h>
-#include <net/inet.h>
-#include <net/modules.h>
-#include <net/icmp_api.h>
-#include <net/icmp_codes.h>
-#include <net/icmp_common.h>
-
-#include <packet_client.h>
-#include <packet_remote.h>
-#include <net_checksum.h>
-#include <icmp_client.h>
-#include <icmp_remote.h>
-#include <il_remote.h>
-#include <ip_client.h>
-#include <ip_interface.h>
-#include <net_interface.h>
-#include <tl_remote.h>
-#include <tl_skel.h>
-#include <icmp_header.h>
-
-/** ICMP module name */
-#define NAME  "icmp"
-
-/** Number of replies hash table keys */
-#define REPLY_KEYS  2
-
-/** Number of replies hash table buckets */
-#define REPLY_BUCKETS  1024
-
-/**
- * Original datagram length in bytes transfered to the error
- * notification message.
- */
-#define ICMP_KEEP_LENGTH  8
-
-/** Compute the ICMP datagram checksum.
- *
- * @param[in,out] header ICMP datagram header.
- * @param[in]     length Total datagram length.
- *
- * @return Computed checksum.
- *
- */
-#define ICMP_CHECKSUM(header, length) \
-	htons(ip_checksum((uint8_t *) (header), (length)))
-
-/** An echo request datagrams pattern. */
-#define ICMP_ECHO_TEXT  "ICMP hello from HelenOS."
-
-/** ICMP reply data. */
-typedef struct {
-	/** Hash table link */
-	link_t link;
-	
-	/** Reply identification and sequence */
-	icmp_param_t id;
-	icmp_param_t sequence;
-	
-	/** Reply signaling */
-	fibril_condvar_t condvar;
-	
-	/** Reply result */
-	int result;
-} icmp_reply_t;
-
-/** Global data */
-static async_sess_t *net_sess = NULL;
-static async_sess_t *ip_sess = NULL;
-static bool error_reporting = true;
-static bool echo_replying = true;
-static packet_dimension_t icmp_dimension;
-
-/** ICMP client identification counter */
-static atomic_t icmp_client;
-
-/** ICMP identifier and sequence number (client-specific) */
-static fibril_local icmp_param_t icmp_id;
-static fibril_local icmp_param_t icmp_seq;
-
-/** Reply hash table */
-static fibril_mutex_t reply_lock;
-static hash_table_t replies;
-
-static hash_index_t replies_hash(unsigned long key[])
-{
-	/*
-	 * ICMP identifier and sequence numbers
-	 * are 16-bit values.
-	 */
-	hash_index_t index = ((key[0] & 0xffff) << 16) | (key[1] & 0xffff);
-	return (index % REPLY_BUCKETS);
-}
-
-static int replies_compare(unsigned long key[], hash_count_t keys, link_t *item)
-{
-	icmp_reply_t *reply =
-	    hash_table_get_instance(item, icmp_reply_t, link);
-	
-	if (keys == 1)
-		return (reply->id == key[0]);
-	else
-		return ((reply->id == key[0]) && (reply->sequence == key[1]));
-}
-
-static void replies_remove_callback(link_t *item)
-{
-}
-
-static hash_table_operations_t reply_ops = {
-	.hash = replies_hash,
-	.compare = replies_compare,
-	.remove_callback = replies_remove_callback
-};
-
-/** Release the packet and return the result.
- *
- * @param[in] packet Packet queue to be released.
- *
- */
-static void icmp_release(packet_t *packet)
-{
-	pq_release_remote(net_sess, packet_get_id(packet));
-}
-
-/** Send the ICMP message.
- *
- * Set the message type and code and compute the checksum.
- * Error messages are sent only if allowed in the configuration.
- * Release the packet on errors.
- *
- * @param[in] type          Message type.
- * @param[in] code          Message code.
- * @param[in] packet        Message packet to be sent.
- * @param[in] header        ICMP header.
- * @param[in] error         Error service to be announced. Should be
- *                          SERVICE_ICMP or zero.
- * @param[in] ttl           Time to live.
- * @param[in] tos           Type of service.
- * @param[in] dont_fragment Disable fragmentation.
- *
- * @return EOK on success.
- * @return EPERM if the error message is not allowed.
- *
- */
-static int icmp_send_packet(icmp_type_t type, icmp_code_t code,
-    packet_t *packet, icmp_header_t *header, services_t error, ip_ttl_t ttl,
-    ip_tos_t tos, bool dont_fragment)
-{
-	/* Do not send an error if disabled */
-	if ((error) && (!error_reporting)) {
-		icmp_release(packet);
-		return EPERM;
-	}
-	
-	header->type = type;
-	header->code = code;
-	
-	/*
-	 * The checksum needs to be calculated
-	 * with a virtual checksum field set to
-	 * zero.
-	 */
-	header->checksum = 0;
-	header->checksum = ICMP_CHECKSUM(header,
-	    packet_get_data_length(packet));
-	
-	int rc = ip_client_prepare_packet(packet, IPPROTO_ICMP, ttl, tos,
-	    dont_fragment, 0);
-	if (rc != EOK) {
-		icmp_release(packet);
-		return rc;
-	}
-	
-	return ip_send_msg(ip_sess, -1, packet, SERVICE_ICMP, error);
-}
-
-/** Prepare the ICMP error packet.
- *
- * Truncate the original packet if longer than ICMP_KEEP_LENGTH bytes.
- * Prefix and return the ICMP header.
- *
- * @param[in,out] packet Original packet.
- *
- * @return The prefixed ICMP header.
- * @return NULL on errors.
- *
- */
-static icmp_header_t *icmp_prepare_packet(packet_t *packet)
-{
-	size_t total_length = packet_get_data_length(packet);
-	if (total_length <= 0)
-		return NULL;
-	
-	size_t header_length = ip_client_header_length(packet);
-	if (header_length <= 0)
-		return NULL;
-	
-	/* Truncate if longer than 64 bits (without the IP header) */
-	if ((total_length > header_length + ICMP_KEEP_LENGTH) &&
-	    (packet_trim(packet, 0,
-	    total_length - header_length - ICMP_KEEP_LENGTH) != EOK))
-		return NULL;
-	
-	icmp_header_t *header = PACKET_PREFIX(packet, icmp_header_t);
-	if (!header)
-		return NULL;
-	
-	bzero(header, sizeof(*header));
-	return header;
-}
-
-/** Request an echo message.
- *
- * Send a packet with specified parameters to the target host
- * and wait for the reply upto the given timeout.
- * Block the caller until the reply or the timeout occurs.
- *
- * @param[in] id            Message identifier.
- * @param[in] sequence      Message sequence parameter.
- * @param[in] size          Message data length in bytes.
- * @param[in] timeout       Timeout in miliseconds.
- * @param[in] ttl           Time to live.
- * @param[in] tos           Type of service.
- * @param[in] dont_fragment Disable fragmentation.
- * @param[in] addr          Target host address.
- * @param[in] addrlen       Torget host address length.
- *
- * @return ICMP_ECHO on success.
- * @return ETIMEOUT if the reply has not arrived before the
- *         timeout.
- * @return ICMP type of the received error notification.
- * @return EINVAL if the addrlen parameter is less or equal to
- *         zero.
- * @return ENOMEM if there is not enough memory left.
- *
- */
-static int icmp_echo(icmp_param_t id, icmp_param_t sequence, size_t size,
-    mseconds_t timeout, ip_ttl_t ttl, ip_tos_t tos, bool dont_fragment,
-    const struct sockaddr *addr, socklen_t addrlen)
-{
-	if (addrlen <= 0)
-		return EINVAL;
-	
-	size_t length = (size_t) addrlen;
-	
-	packet_t *packet = packet_get_4_remote(net_sess, size,
-	    icmp_dimension.addr_len, ICMP_HEADER_SIZE + icmp_dimension.prefix,
-	    icmp_dimension.suffix);
-	if (!packet)
-		return ENOMEM;
-	
-	/* Prepare the requesting packet, set the destination address. */
-	int rc = packet_set_addr(packet, NULL, (const uint8_t *) addr, length);
-	if (rc != EOK) {
-		icmp_release(packet);
-		return rc;
-	}
-	
-	/* Allocate space in the packet */
-	uint8_t *data = (uint8_t *) packet_suffix(packet, size);
-	if (!data) {
-		icmp_release(packet);
-		return ENOMEM;
-	}
-	
-	/* Fill the data */
-	length = 0;
-	while (size > length + sizeof(ICMP_ECHO_TEXT)) {
-		memcpy(data + length, ICMP_ECHO_TEXT, sizeof(ICMP_ECHO_TEXT));
-		length += sizeof(ICMP_ECHO_TEXT);
-	}
-	memcpy(data + length, ICMP_ECHO_TEXT, size - length);
-	
-	/* Prefix the header */
-	icmp_header_t *header = PACKET_PREFIX(packet, icmp_header_t);
-	if (!header) {
-		icmp_release(packet);
-		return ENOMEM;
-	}
-	
-	bzero(header, sizeof(icmp_header_t));
-	header->un.echo.identifier = id;
-	header->un.echo.sequence_number = sequence;
-	
-	/* Prepare the reply structure */
-	icmp_reply_t *reply = malloc(sizeof(icmp_reply_t));
-	if (!reply) {
-		icmp_release(packet);
-		return ENOMEM;
-	}
-	
-	reply->id = id;
-	reply->sequence = sequence;
-	fibril_condvar_initialize(&reply->condvar);
-	
-	/* Add the reply to the replies hash table */
-	fibril_mutex_lock(&reply_lock);
-	
-	unsigned long key[REPLY_KEYS] = {id, sequence};
-	hash_table_insert(&replies, key, &reply->link);
-	
-	/* Send the request */
-	icmp_send_packet(ICMP_ECHO, 0, packet, header, 0, ttl, tos,
-	    dont_fragment);
-	
-	/* Wait for the reply. Timeout in microseconds. */
-	rc = fibril_condvar_wait_timeout(&reply->condvar, &reply_lock,
-	    timeout * 1000);
-	if (rc == EOK)
-		rc = reply->result;
-	
-	/* Remove the reply from the replies hash table */
-	hash_table_remove(&replies, key, REPLY_KEYS);
-	
-	fibril_mutex_unlock(&reply_lock);
-	
-	free(reply);
-	
-	return rc;
-}
-
-static int icmp_destination_unreachable(icmp_code_t code, icmp_param_t mtu,
-    packet_t *packet)
-{
-	icmp_header_t *header = icmp_prepare_packet(packet);
-	if (!header) {
-		icmp_release(packet);
-		return ENOMEM;
-	}
-	
-	if (mtu)
-		header->un.frag.mtu = mtu;
-	
-	return icmp_send_packet(ICMP_DEST_UNREACH, code, packet, header,
-	    SERVICE_ICMP, 0, 0, false);
-}
-
-static int icmp_source_quench(packet_t *packet)
-{
-	icmp_header_t *header = icmp_prepare_packet(packet);
-	if (!header) {
-		icmp_release(packet);
-		return ENOMEM;
-	}
-	
-	return icmp_send_packet(ICMP_SOURCE_QUENCH, 0, packet, header,
-	    SERVICE_ICMP, 0, 0, false);
-}
-
-static int icmp_time_exceeded(icmp_code_t code, packet_t *packet)
-{
-	icmp_header_t *header = icmp_prepare_packet(packet);
-	if (!header) {
-		icmp_release(packet);
-		return ENOMEM;
-	}
-	
-	return icmp_send_packet(ICMP_TIME_EXCEEDED, code, packet, header,
-	    SERVICE_ICMP, 0, 0, false);
-}
-
-static int icmp_parameter_problem(icmp_code_t code, icmp_param_t pointer,
-    packet_t *packet)
-{
-	icmp_header_t *header = icmp_prepare_packet(packet);
-	if (!header) {
-		icmp_release(packet);
-		return ENOMEM;
-	}
-	
-	header->un.param.pointer = pointer;
-	return icmp_send_packet(ICMP_PARAMETERPROB, code, packet, header,
-	    SERVICE_ICMP, 0, 0, false);
-}
-
-/** Try to set the pending reply result as the received message type.
- *
- * If the reply data is not present, the reply timed out and the other fibril
- * is already awake. The packet is released.
- *
- * @param[in] packet The received reply message.
- * @param[in] header The ICMP message header.
- * @param[in] type   The received reply message type.
- * @param[in] code   The received reply message code.
- *
- */
-static void icmp_process_echo_reply(packet_t *packet, icmp_header_t *header,
-    icmp_type_t type, icmp_code_t code)
-{
-	unsigned long key[REPLY_KEYS] =
-	    {header->un.echo.identifier, header->un.echo.sequence_number};
-	
-	/* The packet is no longer needed */
-	icmp_release(packet);
-	
-	/* Find the pending reply */
-	fibril_mutex_lock(&reply_lock);
-	
-	link_t *link = hash_table_find(&replies, key);
-	if (link != NULL) {
-		icmp_reply_t *reply =
-		   hash_table_get_instance(link, icmp_reply_t, link);
-		
-		reply->result = type;
-		fibril_condvar_signal(&reply->condvar);
-	}
-	
-	fibril_mutex_unlock(&reply_lock);
-}
-
-/** Process the received ICMP packet.
- *
- * Notify the destination socket application.
- *
- * @param[in,out] packet Received packet.
- * @param[in]     error  Packet error reporting service to prefix
- *                       the received packet.
- *
- * @return EOK on success.
- * @return EINVAL if the packet is not valid.
- * @return EINVAL if the stored packet address is not the an_addr_t.
- * @return EINVAL if the packet does not contain any data.
- * @return NO_DATA if the packet content is shorter than the user
- *         datagram header.
- * @return ENOMEM if there is not enough memory left.
- * @return EADDRNOTAVAIL if the destination socket does not exist.
- * @return Other error codes as defined for the
- *         ip_client_process_packet() function.
- *
- */
-static int icmp_process_packet(packet_t *packet, services_t error)
-{
-	icmp_type_t type;
-	icmp_code_t code;
-	int rc;
-	
-	switch (error) {
-	case SERVICE_NONE:
-		break;
-	case SERVICE_ICMP:
-		/* Process error */
-		rc = icmp_client_process_packet(packet, &type, &code, NULL, NULL);
-		if (rc < 0)
-			return rc;
-		
-		/* Remove the error header */
-		rc = packet_trim(packet, (size_t) rc, 0);
-		if (rc != EOK)
-			return rc;
-		
-		break;
-	default:
-		return ENOTSUP;
-	}
-	
-	/* Get rid of the IP header */
-	size_t length = ip_client_header_length(packet);
-	rc = packet_trim(packet, length, 0);
-	if (rc != EOK)
-		return rc;
-	
-	length = packet_get_data_length(packet);
-	if (length <= 0)
-		return EINVAL;
-	
-	if (length < ICMP_HEADER_SIZE)
-		return EINVAL;
-	
-	void *data = packet_get_data(packet);
-	if (!data)
-		return EINVAL;
-	
-	/* Get ICMP header */
-	icmp_header_t *header = (icmp_header_t *) data;
-	
-	if (header->checksum) {
-		while (ICMP_CHECKSUM(header, length) != IP_CHECKSUM_ZERO) {
-			/*
-			 * Set the original message type on error notification.
-			 * Type swap observed in Qemu.
-			 */
-			if (error) {
-				switch (header->type) {
-				case ICMP_ECHOREPLY:
-					header->type = ICMP_ECHO;
-					continue;
-				}
-			}
-			
-			return EINVAL;
-		}
-	}
-	
-	switch (header->type) {
-	case ICMP_ECHOREPLY:
-		if (error)
-			icmp_process_echo_reply(packet, header, type, code);
-		else
-			icmp_process_echo_reply(packet, header, ICMP_ECHO, 0);
-		
-		return EOK;
-	
-	case ICMP_ECHO:
-		if (error) {
-			icmp_process_echo_reply(packet, header, type, code);
-			return EOK;
-		}
-		
-		/* Do not send a reply if disabled */
-		if (echo_replying) {
-			uint8_t *src;
-			int addrlen = packet_get_addr(packet, &src, NULL);
-			
-			/*
-			 * Set both addresses to the source one (avoid the
-			 * source address deletion before setting the
-			 * destination one).
-			 */
-			if ((addrlen > 0) && (packet_set_addr(packet, src, src,
-			    (size_t) addrlen) == EOK)) {
-				/* Send the reply */
-				icmp_send_packet(ICMP_ECHOREPLY, 0, packet,
-				    header, 0, 0, 0, 0);
-				return EOK;
-			}
-			
-			return EINVAL;
-		}
-		
-		return EPERM;
-	
-	case ICMP_DEST_UNREACH:
-	case ICMP_SOURCE_QUENCH:
-	case ICMP_REDIRECT:
-	case ICMP_ALTERNATE_ADDR:
-	case ICMP_ROUTER_ADV:
-	case ICMP_ROUTER_SOL:
-	case ICMP_TIME_EXCEEDED:
-	case ICMP_PARAMETERPROB:
-	case ICMP_CONVERSION_ERROR:
-	case ICMP_REDIRECT_MOBILE:
-	case ICMP_SKIP:
-	case ICMP_PHOTURIS:
-		ip_received_error_msg(ip_sess, -1, packet,
-		    SERVICE_IP, SERVICE_ICMP);
-		return EOK;
-	
-	default:
-		return ENOTSUP;
-	}
-}
-
-/** Process IPC messages from the IP module
- *
- * @param[in]     iid   Message identifier.
- * @param[in,out] icall Message parameters.
- * @param[in]     arg   Local argument.
- *
- */
-static void icmp_receiver(ipc_callid_t iid, ipc_call_t *icall, void *arg)
-{
-	packet_t *packet;
-	int rc;
-	
-	while (true) {
-		if (!IPC_GET_IMETHOD(*icall))
-			break;
-		
-		switch (IPC_GET_IMETHOD(*icall)) {
-		case NET_TL_RECEIVED:
-			rc = packet_translate_remote(net_sess, &packet,
-			    IPC_GET_PACKET(*icall));
-			if (rc == EOK) {
-				rc = icmp_process_packet(packet, IPC_GET_ERROR(*icall));
-				if (rc != EOK)
-					icmp_release(packet);
-			}
-			
-			async_answer_0(iid, (sysarg_t) rc);
-			break;
-		default:
-			async_answer_0(iid, (sysarg_t) ENOTSUP);
-		}
-		
-		iid = async_get_call(icall);
-	}
-}
-
-/** Initialize the ICMP module.
- *
- * @param[in] sess Network module session.
- *
- * @return EOK on success.
- * @return ENOMEM if there is not enough memory left.
- *
- */
-int tl_initialize(async_sess_t *sess)
-{
-	measured_string_t names[] = {
-		{
-			(uint8_t *) "ICMP_ERROR_REPORTING",
-			20
-		},
-		{
-			(uint8_t *) "ICMP_ECHO_REPLYING",
-			18
-		}
-	};
-	measured_string_t *configuration;
-	size_t count = sizeof(names) / sizeof(measured_string_t);
-	uint8_t *data;
-	
-	if (!hash_table_create(&replies, REPLY_BUCKETS, REPLY_KEYS, &reply_ops))
-		return ENOMEM;
-	
-	fibril_mutex_initialize(&reply_lock);
-	atomic_set(&icmp_client, 0);
-	
-	net_sess = sess;
-	ip_sess = ip_bind_service(SERVICE_IP, IPPROTO_ICMP, SERVICE_ICMP,
-	    icmp_receiver);
-	if (ip_sess == NULL)
-		return ENOENT;
-	
-	int rc = ip_packet_size_req(ip_sess, -1, &icmp_dimension);
-	if (rc != EOK)
-		return rc;
-	
-	icmp_dimension.prefix += ICMP_HEADER_SIZE;
-	icmp_dimension.content -= ICMP_HEADER_SIZE;
-	
-	/* Get configuration */
-	configuration = &names[0];
-	rc = net_get_conf_req(net_sess, &configuration, count, &data);
-	if (rc != EOK)
-		return rc;
-	
-	if (configuration) {
-		if (configuration[0].value)
-			error_reporting = (configuration[0].value[0] == 'y');
-		
-		if (configuration[1].value)
-			echo_replying = (configuration[1].value[0] == 'y');
-		
-		net_free_settings(configuration, data);
-	}
-	
-	return EOK;
-}
-
-/** Per-connection initialization
- *
- * Initialize client-specific global variables.
- *
- */
-void tl_connection(void)
-{
-	icmp_id = (icmp_param_t) atomic_postinc(&icmp_client);
-	icmp_seq = 1;
-}
-
-/** Process the ICMP message.
- *
- * @param[in]  callid Message identifier.
- * @param[in]  call   Message parameters.
- * @param[out] answer Answer.
- * @param[out] count  Number of arguments of the answer.
- *
- * @return EOK on success.
- * @return ENOTSUP if the message is not known.
- * @return Other error codes as defined for the packet_translate()
- *         function.
- * @return Other error codes as defined for the
- *         icmp_destination_unreachable() function.
- * @return Other error codes as defined for the
- *         icmp_source_quench() function.
- * @return Other error codes as defined for the
- *         icmp_time_exceeded() function.
- * @return Other error codes as defined for the
- *         icmp_parameter_problem() function.
- *
- * @see icmp_remote.h
- * @see IS_NET_ICMP_MESSAGE()
- *
- */
-int tl_message(ipc_callid_t callid, ipc_call_t *call,
-    ipc_call_t *answer, size_t *count)
-{
-	struct sockaddr *addr;
-	size_t size;
-	packet_t *packet;
-	int rc;
-	
-	*count = 0;
-	
-	switch (IPC_GET_IMETHOD(*call)) {
-	case NET_ICMP_ECHO:
-		rc = async_data_write_accept((void **) &addr, false, 0, 0, 0, &size);
-		if (rc != EOK)
-			return rc;
-		
-		rc = icmp_echo(icmp_id, icmp_seq, ICMP_GET_SIZE(*call),
-		    ICMP_GET_TIMEOUT(*call), ICMP_GET_TTL(*call),
-		    ICMP_GET_TOS(*call), ICMP_GET_DONT_FRAGMENT(*call),
-		    addr, (socklen_t) size);
-		
-		free(addr);
-		icmp_seq++;
-		return rc;
-	
-	case NET_ICMP_DEST_UNREACH:
-		rc = packet_translate_remote(net_sess, &packet,
-		    IPC_GET_PACKET(*call));
-		if (rc != EOK)
-			return rc;
-		
-		return icmp_destination_unreachable(ICMP_GET_CODE(*call),
-		    ICMP_GET_MTU(*call), packet);
-	
-	case NET_ICMP_SOURCE_QUENCH:
-		rc = packet_translate_remote(net_sess, &packet,
-		    IPC_GET_PACKET(*call));
-		if (rc != EOK)
-			return rc;
-		
-		return icmp_source_quench(packet);
-	
-	case NET_ICMP_TIME_EXCEEDED:
-		rc = packet_translate_remote(net_sess, &packet,
-		    IPC_GET_PACKET(*call));
-		if (rc != EOK)
-			return rc;
-		
-		return icmp_time_exceeded(ICMP_GET_CODE(*call), packet);
-	
-	case NET_ICMP_PARAMETERPROB:
-		rc = packet_translate_remote(net_sess, &packet,
-		    IPC_GET_PACKET(*call));
-		if (rc != EOK)
-			return rc;
-		
-		return icmp_parameter_problem(ICMP_GET_CODE(*call),
-		    ICMP_GET_POINTER(*call), packet);
-	}
-	
-	return ENOTSUP;
-}
-
-int main(int argc, char *argv[])
-{
-	/* Start the module */
-	return tl_module_start(SERVICE_ICMP);
-}
-
-/** @}
- */
Index: pace/srv/net/tl/tcp/Makefile
===================================================================
--- uspace/srv/net/tl/tcp/Makefile	(revision bf31e3f1ebd6e88e0c8425f109e42ccd92b6c9b3)
+++ 	(revision )
@@ -1,48 +1,0 @@
-#
-# Copyright (c) 2011 Jiri Svoboda
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# - Redistributions of source code must retain the above copyright
-#   notice, this list of conditions and the following disclaimer.
-# - Redistributions in binary form must reproduce the above copyright
-#   notice, this list of conditions and the following disclaimer in the
-#   documentation and/or other materials provided with the distribution.
-# - The name of the author may not be used to endorse or promote products
-#   derived from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-
-USPACE_PREFIX = ../../../..
-LIBS = $(LIBNET_PREFIX)/libnet.a
-EXTRA_CFLAGS = -I$(LIBNET_PREFIX)/include
-BINARY = tcp
-
-SOURCES = \
-	conn.c \
-	iqueue.c \
-	ncsim.c \
-	pdu.c \
-	rqueue.c \
-	segment.c \
-	seq_no.c \
-	sock.c \
-	tcp.c \
-	test.c \
-	tqueue.c \
-	ucall.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/srv/net/tl/tcp/conn.c
===================================================================
--- uspace/srv/net/tl/tcp/conn.c	(revision bf31e3f1ebd6e88e0c8425f109e42ccd92b6c9b3)
+++ 	(revision )
@@ -1,1282 +1,0 @@
-/*
- * Copyright (c) 2011 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup tcp
- * @{
- */
-
-/**
- * @file TCP connection processing and state machine
- */
-
-#include <adt/list.h>
-#include <bool.h>
-#include <errno.h>
-#include <io/log.h>
-#include <macros.h>
-#include <stdlib.h>
-#include "conn.h"
-#include "iqueue.h"
-#include "segment.h"
-#include "seq_no.h"
-#include "tcp_type.h"
-#include "tqueue.h"
-#include "ucall.h"
-
-#define RCV_BUF_SIZE 4096/*2*/
-#define SND_BUF_SIZE 4096
-
-#define MAX_SEGMENT_LIFETIME	(15*1000*1000) //(2*60*1000*1000)
-#define TIME_WAIT_TIMEOUT	(2*MAX_SEGMENT_LIFETIME)
-
-LIST_INITIALIZE(conn_list);
-FIBRIL_MUTEX_INITIALIZE(conn_list_lock);
-
-static void tcp_conn_seg_process(tcp_conn_t *conn, tcp_segment_t *seg);
-static void tcp_conn_tw_timer_set(tcp_conn_t *conn);
-static void tcp_conn_tw_timer_clear(tcp_conn_t *conn);
-
-/** Create new connection structure.
- *
- * @param lsock		Local socket (will be deeply copied)
- * @param fsock		Foreign socket (will be deeply copied)
- * @return		New connection or NULL
- */
-tcp_conn_t *tcp_conn_new(tcp_sock_t *lsock, tcp_sock_t *fsock)
-{
-	tcp_conn_t *conn = NULL;
-	bool tqueue_inited = false;
-
-	/* Allocate connection structure */
-	conn = calloc(1, sizeof(tcp_conn_t));
-	if (conn == NULL)
-		goto error;
-
-	conn->tw_timer = fibril_timer_create();
-	if (conn->tw_timer == NULL)
-		goto error;
-
-	fibril_mutex_initialize(&conn->lock);
-
-	/* One for the user, one for not being in closed state */
-	atomic_set(&conn->refcnt, 2);
-
-	/* Allocate receive buffer */
-	fibril_condvar_initialize(&conn->rcv_buf_cv);
-	conn->rcv_buf_size = RCV_BUF_SIZE;
-	conn->rcv_buf_used = 0;
-	conn->rcv_buf_fin = false;
-
-	conn->rcv_buf = calloc(1, conn->rcv_buf_size);
-	if (conn->rcv_buf == NULL)
-		goto error;
-
-	/** Allocate send buffer */
-	fibril_condvar_initialize(&conn->snd_buf_cv);
-	conn->snd_buf_size = SND_BUF_SIZE;
-	conn->snd_buf_used = 0;
-	conn->snd_buf_fin = false;
-	conn->snd_buf = calloc(1, conn->snd_buf_size);
-	if (conn->snd_buf == NULL)
-		goto error;
-
-	/* Set up receive window. */
-	conn->rcv_wnd = conn->rcv_buf_size;
-
-	/* Initialize incoming segment queue */
-	tcp_iqueue_init(&conn->incoming, conn);
-
-	/* Initialize retransmission queue */
-	if (tcp_tqueue_init(&conn->retransmit, conn) != EOK)
-		goto error;
-
-	tqueue_inited = true;
-
-	/* Connection state change signalling */
-	fibril_condvar_initialize(&conn->cstate_cv);
-
-	conn->cstate_cb = NULL;
-
-	conn->cstate = st_listen;
-	conn->reset = false;
-	conn->deleted = false;
-	conn->ap = ap_passive;
-	conn->fin_is_acked = false;
-	conn->ident.local = *lsock;
-	if (fsock != NULL)
-		conn->ident.foreign = *fsock;
-
-	return conn;
-
-error:
-	if (tqueue_inited)
-		tcp_tqueue_fini(&conn->retransmit);
-	if (conn != NULL && conn->rcv_buf != NULL)
-		free(conn->rcv_buf);
-	if (conn != NULL && conn->snd_buf != NULL)
-		free(conn->snd_buf);
-	if (conn != NULL && conn->tw_timer != NULL)
-		fibril_timer_destroy(conn->tw_timer);
-	if (conn != NULL)
-		free(conn);
-
-	return NULL;
-}
-
-/** Destroy connection structure.
- *
- * Connection structure should be destroyed when the folowing condtitions
- * are met:
- * (1) user has deleted the connection
- * (2) the connection has entered closed state
- * (3) nobody is holding references to the connection
- *
- * This happens when @a conn->refcnt is zero as we count (1) and (2)
- * as special references.
- *
- * @param conn		Connection
- */
-static void tcp_conn_free(tcp_conn_t *conn)
-{
-	log_msg(LVL_DEBUG, "%s: tcp_conn_free(%p)", conn->name, conn);
-	tcp_tqueue_fini(&conn->retransmit);
-
-	if (conn->rcv_buf != NULL)
-		free(conn->rcv_buf);
-	if (conn->snd_buf != NULL)
-		free(conn->snd_buf);
-	if (conn->tw_timer != NULL)
-		fibril_timer_destroy(conn->tw_timer);
-	free(conn);
-}
-
-/** Add reference to connection.
- *
- * Increase connection reference count by one.
- *
- * @param conn		Connection
- */
-void tcp_conn_addref(tcp_conn_t *conn)
-{
-	log_msg(LVL_DEBUG, "%s: tcp_conn_addref(%p)", conn->name, conn);
-	atomic_inc(&conn->refcnt);
-}
-
-/** Remove reference from connection.
- *
- * Decrease connection reference count by one.
- *
- * @param conn		Connection
- */
-void tcp_conn_delref(tcp_conn_t *conn)
-{
-	log_msg(LVL_DEBUG, "%s: tcp_conn_delref(%p)", conn->name, conn);
-
-	if (atomic_predec(&conn->refcnt) == 0)
-		tcp_conn_free(conn);
-}
-
-/** Delete connection.
- *
- * The caller promises not make no further references to @a conn.
- * TCP will free @a conn eventually.
- *
- * @param conn		Connection
- */
-void tcp_conn_delete(tcp_conn_t *conn)
-{
-	log_msg(LVL_DEBUG, "%s: tcp_conn_delete(%p)", conn->name, conn);
-
-	assert(conn->deleted == false);
-	tcp_conn_delref(conn);
-}
-
-/** Enlist connection.
- *
- * Add connection to the connection map.
- */
-void tcp_conn_add(tcp_conn_t *conn)
-{
-	tcp_conn_addref(conn);
-	fibril_mutex_lock(&conn_list_lock);
-	list_append(&conn->link, &conn_list);
-	fibril_mutex_unlock(&conn_list_lock);
-}
-
-/** Delist connection.
- *
- * Remove connection from the connection map.
- */
-void tcp_conn_remove(tcp_conn_t *conn)
-{
-	fibril_mutex_lock(&conn_list_lock);
-	list_remove(&conn->link);
-	fibril_mutex_unlock(&conn_list_lock);
-	tcp_conn_delref(conn);
-}
-
-static void tcp_conn_state_set(tcp_conn_t *conn, tcp_cstate_t nstate)
-{
-	tcp_cstate_t old_state;
-
-	log_msg(LVL_DEBUG, "tcp_conn_state_set(%p)", conn);
-
-	old_state = conn->cstate;
-	conn->cstate = nstate;
-	fibril_condvar_broadcast(&conn->cstate_cv);
-
-	/* Run user callback function */
-	if (conn->cstate_cb != NULL) {
-		log_msg(LVL_DEBUG, "tcp_conn_state_set() - run user CB");
-		conn->cstate_cb(conn, conn->cstate_cb_arg);
-	} else {
-		log_msg(LVL_DEBUG, "tcp_conn_state_set() - no user CB");
-	}
-
-	assert(old_state != st_closed);
-	if (nstate == st_closed) {
-		/* Drop one reference for now being in closed state */
-		tcp_conn_delref(conn);
-	}
-}
-
-/** Synchronize connection.
- *
- * This is the first step of an active connection attempt,
- * sends out SYN and sets up ISS and SND.xxx.
- */
-void tcp_conn_sync(tcp_conn_t *conn)
-{
-	/* XXX select ISS */
-	conn->iss = 1;
-	conn->snd_nxt = conn->iss;
-	conn->snd_una = conn->iss;
-	conn->ap = ap_active;
-
-	tcp_tqueue_ctrl_seg(conn, CTL_SYN);
-	tcp_conn_state_set(conn, st_syn_sent);
-}
-
-/** FIN has been sent.
- *
- * This function should be called when FIN is sent over the connection,
- * as a result the connection state is changed appropriately.
- */
-void tcp_conn_fin_sent(tcp_conn_t *conn)
-{
-	switch (conn->cstate) {
-	case st_syn_received:
-	case st_established:
-		log_msg(LVL_DEBUG, "%s: FIN sent -> Fin-Wait-1", conn->name);
-		tcp_conn_state_set(conn, st_fin_wait_1);
-		break;
-	case st_close_wait:
-		log_msg(LVL_DEBUG, "%s: FIN sent -> Last-Ack", conn->name);
-		tcp_conn_state_set(conn, st_last_ack);
-		break;
-	default:
-		log_msg(LVL_ERROR, "%s: Connection state %d", conn->name,
-		    conn->cstate);
-		assert(false);
-	}
-
-	conn->fin_is_acked = false;
-}
-
-/** Compare two sockets.
- *
- * Two sockets are equal if the address is equal and the port number
- * is equal.
- */
-static bool tcp_socket_match(tcp_sock_t *sock, tcp_sock_t *patt)
-{
-	log_msg(LVL_DEBUG, "tcp_socket_match(sock=(%x,%u), pat=(%x,%u))",
-	    sock->addr.ipv4, sock->port, patt->addr.ipv4, patt->port);
-
-	if (patt->addr.ipv4 != TCP_IPV4_ANY &&
-	    patt->addr.ipv4 != sock->addr.ipv4)
-		return false;
-
-	if (patt->port != TCP_PORT_ANY &&
-	    patt->port != sock->port)
-		return false;
-
-	log_msg(LVL_DEBUG, " -> match");
-
-	return true;
-}
-
-/** Match socket with pattern. */
-static bool tcp_sockpair_match(tcp_sockpair_t *sp, tcp_sockpair_t *pattern)
-{
-	log_msg(LVL_DEBUG, "tcp_sockpair_match(%p, %p)", sp, pattern);
-
-	if (!tcp_socket_match(&sp->local, &pattern->local))
-		return false;
-
-	if (!tcp_socket_match(&sp->foreign, &pattern->foreign))
-		return false;
-
-	return true;
-}
-
-/** Find connection structure for specified socket pair.
- *
- * A connection is uniquely identified by a socket pair. Look up our
- * connection map and return connection structure based on socket pair.
- * The connection reference count is bumped by one.
- *
- * @param sp	Socket pair
- * @return	Connection structure or NULL if not found.
- */
-tcp_conn_t *tcp_conn_find_ref(tcp_sockpair_t *sp)
-{
-	log_msg(LVL_DEBUG, "tcp_conn_find(%p)", sp);
-
-	fibril_mutex_lock(&conn_list_lock);
-
-	list_foreach(conn_list, link) {
-		tcp_conn_t *conn = list_get_instance(link, tcp_conn_t, link);
-		tcp_sockpair_t *csp = &conn->ident;
-		log_msg(LVL_DEBUG, "compare with conn (f:(%x,%u), l:(%x,%u))",
-		    csp->foreign.addr.ipv4, csp->foreign.port,
-		    csp->local.addr.ipv4, csp->local.port);
-		if (tcp_sockpair_match(sp, csp)) {
-			tcp_conn_addref(conn);
-			fibril_mutex_unlock(&conn_list_lock);
-			return conn;
-		}
-	}
-
-	fibril_mutex_unlock(&conn_list_lock);
-	return NULL;
-}
-
-/** Reset connection.
- *
- * @param conn	Connection
- */
-static void tcp_conn_reset(tcp_conn_t *conn)
-{
-	log_msg(LVL_DEBUG, "%s: tcp_conn_reset()", conn->name);
-	tcp_conn_state_set(conn, st_closed);
-	conn->reset = true;
-
-	tcp_conn_tw_timer_clear(conn);
-	tcp_tqueue_clear(&conn->retransmit);
-
-	fibril_condvar_broadcast(&conn->rcv_buf_cv);
-	fibril_condvar_broadcast(&conn->snd_buf_cv);
-}
-
-/** Signal to the user that connection has been reset.
- *
- * Send an out-of-band signal to the user.
- */
-static void tcp_reset_signal(tcp_conn_t *conn)
-{
-	/* TODO */
-	log_msg(LVL_DEBUG, "%s: tcp_reset_signal()", conn->name);
-}
-
-/** Determine if SYN has been received.
- *
- * @param conn	Connection
- * @return	@c true if SYN has been received, @c false otherwise.
- */
-bool tcp_conn_got_syn(tcp_conn_t *conn)
-{
-	switch (conn->cstate) {
-	case st_listen:
-	case st_syn_sent:
-		return false;
-	case st_syn_received:
-	case st_established:
-	case st_fin_wait_1:
-	case st_fin_wait_2:
-	case st_close_wait:
-	case st_closing:
-	case st_last_ack:
-	case st_time_wait:
-		return true;
-	case st_closed:
-		log_msg(LVL_WARN, "state=%d", (int) conn->cstate);
-		assert(false);
-	}
-
-	assert(false);
-}
-
-/** Segment arrived in Listen state.
- *
- * @param conn		Connection
- * @param seg		Segment
- */
-static void tcp_conn_sa_listen(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	log_msg(LVL_DEBUG, "tcp_conn_sa_listen(%p, %p)", conn, seg);
-
-	if ((seg->ctrl & CTL_RST) != 0) {
-		log_msg(LVL_DEBUG, "Ignoring incoming RST.");
-		return;
-	}
-
-	if ((seg->ctrl & CTL_ACK) != 0) {
-		log_msg(LVL_DEBUG, "Incoming ACK, send acceptable RST.");
-		tcp_reply_rst(&conn->ident, seg);
-		return;
-	}
-
-	if ((seg->ctrl & CTL_SYN) == 0) {
-		log_msg(LVL_DEBUG, "SYN not present. Ignoring segment.");
-		return;
-	}
-
-	log_msg(LVL_DEBUG, "Got SYN, sending SYN, ACK.");
-
-	conn->rcv_nxt = seg->seq + 1;
-	conn->irs = seg->seq;
-
-
-	log_msg(LVL_DEBUG, "rcv_nxt=%u", conn->rcv_nxt);
-
-	if (seg->len > 1)
-		log_msg(LVL_WARN, "SYN combined with data, ignoring data.");
-
-	/* XXX select ISS */
-	conn->iss = 1;
-	conn->snd_nxt = conn->iss;
-	conn->snd_una = conn->iss;
-
-	/*
-	 * Surprisingly the spec does not deal with initial window setting.
-	 * Set SND.WND = SEG.WND and set SND.WL1 so that next segment
-	 * will always be accepted as new window setting.
-	 */
-	conn->snd_wnd = seg->wnd;
-	conn->snd_wl1 = seg->seq;
-	conn->snd_wl2 = seg->seq;
-
-	tcp_conn_state_set(conn, st_syn_received);
-
-	tcp_tqueue_ctrl_seg(conn, CTL_SYN | CTL_ACK /* XXX */);
-
-	tcp_segment_delete(seg);
-}
-
-/** Segment arrived in Syn-Sent state.
- *
- * @param conn		Connection
- * @param seg		Segment
- */
-static void tcp_conn_sa_syn_sent(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	log_msg(LVL_DEBUG, "tcp_conn_sa_syn_sent(%p, %p)", conn, seg);
-
-	if ((seg->ctrl & CTL_ACK) != 0) {
-		log_msg(LVL_DEBUG, "snd_una=%u, seg.ack=%u, snd_nxt=%u",
-		    conn->snd_una, seg->ack, conn->snd_nxt);
-		if (!seq_no_ack_acceptable(conn, seg->ack)) {
-			if ((seg->ctrl & CTL_RST) == 0) {
-				log_msg(LVL_WARN, "ACK not acceptable, send RST");
-				tcp_reply_rst(&conn->ident, seg);
-			} else {
-				log_msg(LVL_WARN, "RST,ACK not acceptable, drop");
-			}
-			return;
-		}
-	}
-
-	if ((seg->ctrl & CTL_RST) != 0) {
-		/* If we get here, we have either an acceptable ACK or no ACK */
-		if ((seg->ctrl & CTL_ACK) != 0) {
-			log_msg(LVL_DEBUG, "%s: Connection reset. -> Closed",
-			    conn->name);
-			/* Reset connection */
-			tcp_conn_reset(conn);
-			return;
-		} else {
-			log_msg(LVL_DEBUG, "%s: RST without ACK, drop",
-			    conn->name);
-			return;
-		}
-	}
-
-	/* XXX precedence */
-
-	if ((seg->ctrl & CTL_SYN) == 0) {
-		log_msg(LVL_DEBUG, "No SYN bit, ignoring segment.");
-		return;
-	}
-
-	conn->rcv_nxt = seg->seq + 1;
-	conn->irs = seg->seq;
-
-	if ((seg->ctrl & CTL_ACK) != 0) {
-		conn->snd_una = seg->ack;
-
-		/*
-		 * Prune acked segments from retransmission queue and
-		 * possibly transmit more data.
-		 */
-		tcp_tqueue_ack_received(conn);
-	}
-
-	log_msg(LVL_DEBUG, "Sent SYN, got SYN.");
-
-	/*
-	 * Surprisingly the spec does not deal with initial window setting.
-	 * Set SND.WND = SEG.WND and set SND.WL1 so that next segment
-	 * will always be accepted as new window setting.
-	 */
-	log_msg(LVL_DEBUG, "SND.WND := %" PRIu32 ", SND.WL1 := %" PRIu32 ", "
-	    "SND.WL2 = %" PRIu32, seg->wnd, seg->seq, seg->seq);
-	conn->snd_wnd = seg->wnd;
-	conn->snd_wl1 = seg->seq;
-	conn->snd_wl2 = seg->seq;
-
-	if (seq_no_syn_acked(conn)) {
-		log_msg(LVL_DEBUG, "%s: syn acked -> Established", conn->name);
-		tcp_conn_state_set(conn, st_established);
-		tcp_tqueue_ctrl_seg(conn, CTL_ACK /* XXX */);
-	} else {
-		log_msg(LVL_DEBUG, "%s: syn not acked -> Syn-Received",
-		    conn->name);
-		tcp_conn_state_set(conn, st_syn_received);
-		tcp_tqueue_ctrl_seg(conn, CTL_SYN | CTL_ACK /* XXX */);
-	}
-
-	tcp_segment_delete(seg);
-}
-
-/** Segment arrived in state where segments are processed in sequence order.
- *
- * Queue segment in incoming segments queue for processing.
- *
- * @param conn		Connection
- * @param seg		Segment
- */
-static void tcp_conn_sa_queue(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	tcp_segment_t *pseg;
-
-	log_msg(LVL_DEBUG, "tcp_conn_sa_seq(%p, %p)", conn, seg);
-
-	/* Discard unacceptable segments ("old duplicates") */
-	if (!seq_no_segment_acceptable(conn, seg)) {
-		log_msg(LVL_DEBUG, "Replying ACK to unacceptable segment.");
-		tcp_tqueue_ctrl_seg(conn, CTL_ACK);
-		tcp_segment_delete(seg);
-		return;
-	}
-
-	/* Queue for processing */
-	tcp_iqueue_insert_seg(&conn->incoming, seg);
-
-	/*
-	 * Process all segments from incoming queue that are ready.
-	 * Unacceptable segments are discarded by tcp_iqueue_get_ready_seg().
-	 *
-	 * XXX Need to return ACK for unacceptable segments
-	 */
-	while (tcp_iqueue_get_ready_seg(&conn->incoming, &pseg) == EOK)
-		tcp_conn_seg_process(conn, pseg);
-}
-
-/** Process segment RST field.
- *
- * @param conn		Connection
- * @param seg		Segment
- * @return		cp_done if we are done with this segment, cp_continue
- *			if not
- */
-static cproc_t tcp_conn_seg_proc_rst(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	if ((seg->ctrl & CTL_RST) == 0)
-		return cp_continue;
-
-	switch (conn->cstate) {
-	case st_syn_received:
-		/* XXX In case of passive open, revert to Listen state */
-		if (conn->ap == ap_passive) {
-			tcp_conn_state_set(conn, st_listen);
-			/* XXX Revert conn->ident */
-			tcp_conn_tw_timer_clear(conn);
-			tcp_tqueue_clear(&conn->retransmit);
-		} else {
-			tcp_conn_reset(conn);
-		}
-		break;
-	case st_established:
-	case st_fin_wait_1:
-	case st_fin_wait_2:
-	case st_close_wait:
-		/* General "connection reset" signal */
-		tcp_reset_signal(conn);
-		tcp_conn_reset(conn);
-		break;
-	case st_closing:
-	case st_last_ack:
-	case st_time_wait:
-		tcp_conn_reset(conn);
-		break;
-	case st_listen:
-	case st_syn_sent:
-	case st_closed:
-		assert(false);
-	}
-
-	return cp_done;
-}
-
-/** Process segment security and precedence fields.
- *
- * @param conn		Connection
- * @param seg		Segment
- * @return		cp_done if we are done with this segment, cp_continue
- *			if not
- */
-static cproc_t tcp_conn_seg_proc_sp(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	/* TODO */
-	return cp_continue;
-}
-
-/** Process segment SYN field.
- *
- * @param conn		Connection
- * @param seg		Segment
- * @return		cp_done if we are done with this segment, cp_continue
- *			if not
- */
-static cproc_t tcp_conn_seg_proc_syn(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	if ((seg->ctrl & CTL_SYN) == 0)
-		return cp_continue;
-
-	/*
-	 * Assert SYN is in receive window, otherwise this step should not
-	 * be reached.
-	 */
-	assert(seq_no_in_rcv_wnd(conn, seg->seq));
-
-	log_msg(LVL_WARN, "SYN is in receive window, should send reset. XXX");
-
-	/*
-	 * TODO
-	 *
-	 * Send a reset, resond "reset" to all outstanding RECEIVEs and SEND,
-	 * flush segment queues. Send unsolicited "connection reset" signal
-	 * to user, connection -> closed state, delete TCB, return.
-	 */
-	return cp_done;
-}
-
-/** Process segment ACK field in Syn-Received state.
- *
- * @param conn		Connection
- * @param seg		Segment
- * @return		cp_done if we are done with this segment, cp_continue
- *			if not
- */
-static cproc_t tcp_conn_seg_proc_ack_sr(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	if (!seq_no_ack_acceptable(conn, seg->ack)) {
-		/* ACK is not acceptable, send RST. */
-		log_msg(LVL_WARN, "Segment ACK not acceptable, sending RST.");
-		tcp_reply_rst(&conn->ident, seg);
-		tcp_segment_delete(seg);
-		return cp_done;
-	}
-
-	log_msg(LVL_DEBUG, "%s: SYN ACKed -> Established", conn->name);
-
-	tcp_conn_state_set(conn, st_established);
-
-	/* XXX Not mentioned in spec?! */
-	conn->snd_una = seg->ack;
-
-	return cp_continue;
-}
-
-/** Process segment ACK field in Established state.
- *
- * @param conn		Connection
- * @param seg		Segment
- * @return		cp_done if we are done with this segment, cp_continue
- *			if not
- */
-static cproc_t tcp_conn_seg_proc_ack_est(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	log_msg(LVL_DEBUG, "tcp_conn_seg_proc_ack_est(%p, %p)", conn, seg);
-
-	log_msg(LVL_DEBUG, "SEG.ACK=%u, SND.UNA=%u, SND.NXT=%u",
-	    (unsigned)seg->ack, (unsigned)conn->snd_una,
-	    (unsigned)conn->snd_nxt);
-
-	if (!seq_no_ack_acceptable(conn, seg->ack)) {
-		log_msg(LVL_DEBUG, "ACK not acceptable.");
-		if (!seq_no_ack_duplicate(conn, seg->ack)) {
-			log_msg(LVL_WARN, "Not acceptable, not duplicate. "
-			    "Send ACK and drop.");
-			/* Not acceptable, not duplicate. Send ACK and drop. */
-			tcp_tqueue_ctrl_seg(conn, CTL_ACK);
-			tcp_segment_delete(seg);
-			return cp_done;
-		} else {
-			log_msg(LVL_DEBUG, "Ignoring duplicate ACK.");
-		}
-	} else {
-		/* Update SND.UNA */
-		conn->snd_una = seg->ack;
-	}
-
-	if (seq_no_new_wnd_update(conn, seg)) {
-		conn->snd_wnd = seg->wnd;
-		conn->snd_wl1 = seg->seq;
-		conn->snd_wl2 = seg->ack;
-
-		log_msg(LVL_DEBUG, "Updating send window, SND.WND=%" PRIu32
-		    ", SND.WL1=%" PRIu32 ", SND.WL2=%" PRIu32,
-		    conn->snd_wnd, conn->snd_wl1, conn->snd_wl2);
-	}
-
-	/*
-	 * Prune acked segments from retransmission queue and
-	 * possibly transmit more data.
-	 */
-	tcp_tqueue_ack_received(conn);
-
-	return cp_continue;
-}
-
-/** Process segment ACK field in Fin-Wait-1 state.
- *
- * @param conn		Connection
- * @param seg		Segment
- * @return		cp_done if we are done with this segment, cp_continue
- *			if not
- */
-static cproc_t tcp_conn_seg_proc_ack_fw1(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	if (tcp_conn_seg_proc_ack_est(conn, seg) == cp_done)
-		return cp_done;
-
-	if (conn->fin_is_acked) {
-		log_msg(LVL_DEBUG, "%s: FIN acked -> Fin-Wait-2", conn->name);
-		tcp_conn_state_set(conn, st_fin_wait_2);
-	}
-
-	return cp_continue;
-}
-
-/** Process segment ACK field in Fin-Wait-2 state.
- *
- * @param conn		Connection
- * @param seg		Segment
- * @return		cp_done if we are done with this segment, cp_continue
- *			if not
- */
-static cproc_t tcp_conn_seg_proc_ack_fw2(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	if (tcp_conn_seg_proc_ack_est(conn, seg) == cp_done)
-		return cp_done;
-
-	/* TODO */
-	return cp_continue;
-}
-
-/** Process segment ACK field in Close-Wait state.
- *
- * @param conn		Connection
- * @param seg		Segment
- * @return		cp_done if we are done with this segment, cp_continue
- *			if not
- */
-static cproc_t tcp_conn_seg_proc_ack_cw(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	/* The same processing as in Established state */
-	return tcp_conn_seg_proc_ack_est(conn, seg);
-}
-
-/** Process segment ACK field in Closing state.
- *
- * @param conn		Connection
- * @param seg		Segment
- * @return		cp_done if we are done with this segment, cp_continue
- *			if not
- */
-static cproc_t tcp_conn_seg_proc_ack_cls(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	if (tcp_conn_seg_proc_ack_est(conn, seg) == cp_done)
-		return cp_done;
-
-	/* TODO */
-	return cp_continue;
-}
-
-/** Process segment ACK field in Last-Ack state.
- *
- * @param conn		Connection
- * @param seg		Segment
- * @return		cp_done if we are done with this segment, cp_continue
- *			if not
- */
-static cproc_t tcp_conn_seg_proc_ack_la(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	if (tcp_conn_seg_proc_ack_est(conn, seg) == cp_done)
-		return cp_done;
-
-	if (conn->fin_is_acked) {
-		log_msg(LVL_DEBUG, "%s: FIN acked -> Closed", conn->name);
-		tcp_conn_remove(conn);
-		tcp_conn_state_set(conn, st_closed);
-		return cp_done;
-	}
-
-	return cp_continue;
-}
-
-/** Process segment ACK field in Time-Wait state.
- *
- * @param conn		Connection
- * @param seg		Segment
- * @return		cp_done if we are done with this segment, cp_continue
- *			if not
- */
-static cproc_t tcp_conn_seg_proc_ack_tw(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	/* Nothing to do */
-	return cp_continue;
-}
-
-/** Process segment ACK field.
- *
- * @param conn		Connection
- * @param seg		Segment
- * @return		cp_done if we are done with this segment, cp_continue
- *			if not
- */
-static cproc_t tcp_conn_seg_proc_ack(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	log_msg(LVL_DEBUG, "%s: tcp_conn_seg_proc_ack(%p, %p)",
-	    conn->name, conn, seg);
-
-	if ((seg->ctrl & CTL_ACK) == 0) {
-		log_msg(LVL_WARN, "Segment has no ACK. Dropping.");
-		tcp_segment_delete(seg);
-		return cp_done;
-	}
-
-	switch (conn->cstate) {
-	case st_syn_received:
-		return tcp_conn_seg_proc_ack_sr(conn, seg);
-	case st_established:
-		return tcp_conn_seg_proc_ack_est(conn, seg);
-	case st_fin_wait_1:
-		return tcp_conn_seg_proc_ack_fw1(conn, seg);
-	case st_fin_wait_2:
-		return tcp_conn_seg_proc_ack_fw2(conn, seg);
-	case st_close_wait:
-		return tcp_conn_seg_proc_ack_cw(conn, seg);
-	case st_closing:
-		return tcp_conn_seg_proc_ack_cls(conn, seg);
-	case st_last_ack:
-		return tcp_conn_seg_proc_ack_la(conn, seg);
-	case st_time_wait:
-		return tcp_conn_seg_proc_ack_tw(conn, seg);
-	case st_listen:
-	case st_syn_sent:
-	case st_closed:
-		assert(false);
-	}
-
-	assert(false);
-}
-
-/** Process segment URG field.
- *
- * @param conn		Connection
- * @param seg		Segment
- * @return		cp_done if we are done with this segment, cp_continue
- *			if not
- */
-static cproc_t tcp_conn_seg_proc_urg(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	return cp_continue;
-}
-
-/** Process segment text.
- *
- * @param conn		Connection
- * @param seg		Segment
- * @return		cp_done if we are done with this segment, cp_continue
- *			if not
- */
-static cproc_t tcp_conn_seg_proc_text(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	size_t text_size;
-	size_t xfer_size;
-
-	log_msg(LVL_DEBUG, "%s: tcp_conn_seg_proc_text(%p, %p)",
-	    conn->name, conn, seg);
-
-	switch (conn->cstate) {
-	case st_established:
-	case st_fin_wait_1:
-	case st_fin_wait_2:
-		/* OK */
-		break;
-	case st_close_wait:
-	case st_closing:
-	case st_last_ack:
-	case st_time_wait:
-		/* Invalid since FIN has been received. Ignore text. */
-		return cp_continue;
-	case st_listen:
-	case st_syn_sent:
-	case st_syn_received:
-	case st_closed:
-		assert(false);
-	}
-
-	/*
-	 * Process segment text
-	 */
-	assert(seq_no_segment_ready(conn, seg));
-
-	/* Trim anything outside our receive window */
-	tcp_conn_trim_seg_to_wnd(conn, seg);
-
-	/* Determine how many bytes to copy */
-	text_size = tcp_segment_text_size(seg);
-	xfer_size = min(text_size, conn->rcv_buf_size - conn->rcv_buf_used);
-
-	/* Copy data to receive buffer */
-	tcp_segment_text_copy(seg, conn->rcv_buf + conn->rcv_buf_used,
-	    xfer_size);
-	conn->rcv_buf_used += xfer_size;
-
-	/* Signal to the receive function that new data has arrived */
-	fibril_condvar_broadcast(&conn->rcv_buf_cv);
-
-	log_msg(LVL_DEBUG, "Received %zu bytes of data.", xfer_size);
-
-	/* Advance RCV.NXT */
-	conn->rcv_nxt += xfer_size;
-
-	/* Update receive window. XXX Not an efficient strategy. */
-	conn->rcv_wnd -= xfer_size;
-
-	/* Send ACK */
-	if (xfer_size > 0)
-		tcp_tqueue_ctrl_seg(conn, CTL_ACK);
-
-	if (xfer_size < seg->len) {
-		/* Trim part of segment which we just received */
-		tcp_conn_trim_seg_to_wnd(conn, seg);
-	} else {
-		log_msg(LVL_DEBUG, "%s: Nothing left in segment, dropping "
-		    "(xfer_size=%zu, SEG.LEN=%zu, seg->ctrl=%u)",
-		    conn->name, xfer_size, seg->len, (unsigned)seg->ctrl);
-		/* Nothing left in segment */
-		tcp_segment_delete(seg);
-		return cp_done;
-	}
-
-	return cp_continue;
-}
-
-/** Process segment FIN field.
- *
- * @param conn		Connection
- * @param seg		Segment
- * @return		cp_done if we are done with this segment, cp_continue
- *			if not
- */
-static cproc_t tcp_conn_seg_proc_fin(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	log_msg(LVL_DEBUG, "%s: tcp_conn_seg_proc_fin(%p, %p)",
-	    conn->name, conn, seg);
-	log_msg(LVL_DEBUG, " seg->len=%zu, seg->ctl=%u", (size_t) seg->len,
-	    (unsigned) seg->ctrl);
-
-	/* Only process FIN if no text is left in segment. */
-	if (tcp_segment_text_size(seg) == 0 && (seg->ctrl & CTL_FIN) != 0) {
-		log_msg(LVL_DEBUG, " - FIN found in segment.");
-
-		/* Send ACK */
-		tcp_tqueue_ctrl_seg(conn, CTL_ACK);
-
-		conn->rcv_nxt++;
-		conn->rcv_wnd--;
-
-		/* Change connection state */
-		switch (conn->cstate) {
-		case st_listen:
-		case st_syn_sent:
-		case st_closed:
-			/* Connection not synchronized */
-			assert(false);
-		case st_syn_received:
-		case st_established:
-			log_msg(LVL_DEBUG, "%s: FIN received -> Close-Wait",
-			    conn->name);
-			tcp_conn_state_set(conn, st_close_wait);
-			break;
-		case st_fin_wait_1:
-			log_msg(LVL_DEBUG, "%s: FIN received -> Closing",
-			    conn->name);
-			tcp_conn_state_set(conn, st_closing);
-			break;
-		case st_fin_wait_2:
-			log_msg(LVL_DEBUG, "%s: FIN received -> Time-Wait",
-			    conn->name);
-			tcp_conn_state_set(conn, st_time_wait);
-			/* Start the Time-Wait timer */
-			tcp_conn_tw_timer_set(conn);
-			break;
-		case st_close_wait:
-		case st_closing:
-		case st_last_ack:
-			/* Do nothing */
-			break;
-		case st_time_wait:
-			/* Restart the Time-Wait timer */
-			tcp_conn_tw_timer_set(conn);
-			break;
-		}
-
-		/* Add FIN to the receive buffer */
-		conn->rcv_buf_fin = true;
-		fibril_condvar_broadcast(&conn->rcv_buf_cv);
-
-		tcp_segment_delete(seg);
-		return cp_done;
-	}
-
-	return cp_continue;
-}
-
-/** Process incoming segment.
- *
- * We are in connection state where segments are processed in order
- * of sequence number. This processes one segment taken from the
- * connection incoming segments queue.
- *
- * @param conn		Connection
- * @param seg		Segment
- */
-static void tcp_conn_seg_process(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	log_msg(LVL_DEBUG, "tcp_conn_seg_process(%p, %p)", conn, seg);
-	tcp_segment_dump(seg);
-
-	/* Check whether segment is acceptable */
-	/* XXX Permit valid ACKs, URGs and RSTs */
-/*	if (!seq_no_segment_acceptable(conn, seg)) {
-		log_msg(LVL_WARN, "Segment not acceptable, dropping.");
-		if ((seg->ctrl & CTL_RST) == 0) {
-			tcp_tqueue_ctrl_seg(conn, CTL_ACK);
-		}
-		return;
-	}
-*/
-
-	if (tcp_conn_seg_proc_rst(conn, seg) == cp_done)
-		return;
-
-	if (tcp_conn_seg_proc_sp(conn, seg) == cp_done)
-		return;
-
-	if (tcp_conn_seg_proc_syn(conn, seg) == cp_done)
-		return;
-
-	if (tcp_conn_seg_proc_ack(conn, seg) == cp_done)
-		return;
-
-	if (tcp_conn_seg_proc_urg(conn, seg) == cp_done)
-		return;
-
-	if (tcp_conn_seg_proc_text(conn, seg) == cp_done)
-		return;
-
-	if (tcp_conn_seg_proc_fin(conn, seg) == cp_done)
-		return;
-
-	/*
-	 * If anything is left from the segment, insert it back into the
-	 * incoming segments queue.
-	 */
-	if (seg->len > 0) {
-		log_msg(LVL_DEBUG, "Re-insert segment %p. seg->len=%zu",
-		    seg, (size_t) seg->len);
-		tcp_iqueue_insert_seg(&conn->incoming, seg);
-	} else {
-		tcp_segment_delete(seg);
-	}
-}
-
-/** Segment arrived on a connection.
- *
- * @param conn		Connection
- * @param seg		Segment
- */
-void tcp_conn_segment_arrived(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	log_msg(LVL_DEBUG, "%c: tcp_conn_segment_arrived(%p)",
-	    conn->name, seg);
-
-	switch (conn->cstate) {
-	case st_listen:
-		tcp_conn_sa_listen(conn, seg); break;
-	case st_syn_sent:
-		tcp_conn_sa_syn_sent(conn, seg); break;
-	case st_syn_received:
-	case st_established:
-	case st_fin_wait_1:
-	case st_fin_wait_2:
-	case st_close_wait:
-	case st_closing:
-	case st_last_ack:
-	case st_time_wait:
-		/* Process segments in order of sequence number */
-		tcp_conn_sa_queue(conn, seg); break;
-	case st_closed:
-		log_msg(LVL_DEBUG, "state=%d", (int) conn->cstate);
-		assert(false);
-	}
-}
-
-/** Time-Wait timeout handler.
- *
- * @param arg	Connection
- */
-static void tw_timeout_func(void *arg)
-{
-	tcp_conn_t *conn = (tcp_conn_t *) arg;
-
-	log_msg(LVL_DEBUG, "tw_timeout_func(%p)", conn);
-
-	fibril_mutex_lock(&conn->lock);
-
-	if (conn->cstate == st_closed) {
-		log_msg(LVL_DEBUG, "Connection already closed.");
-		fibril_mutex_unlock(&conn->lock);
-		tcp_conn_delref(conn);
-		return;
-	}
-
-	log_msg(LVL_DEBUG, "%s: TW Timeout -> Closed", conn->name);
-	tcp_conn_remove(conn);
-	tcp_conn_state_set(conn, st_closed);
-
-	fibril_mutex_unlock(&conn->lock);
-	tcp_conn_delref(conn);
-}
-
-/** Start or restart the Time-Wait timeout.
- *
- * @param conn		Connection
- */
-void tcp_conn_tw_timer_set(tcp_conn_t *conn)
-{
-	tcp_conn_addref(conn);
-	fibril_timer_set(conn->tw_timer, TIME_WAIT_TIMEOUT, tw_timeout_func,
-	    (void *)conn);
-}
-
-/** Clear the Time-Wait timeout.
- *
- * @param conn		Connection
- */
-void tcp_conn_tw_timer_clear(tcp_conn_t *conn)
-{
-	if (fibril_timer_clear(conn->tw_timer) == fts_active)
-		tcp_conn_delref(conn);
-}
-
-/** Trim segment to the receive window.
- *
- * @param conn		Connection
- * @param seg		Segment
- */
-void tcp_conn_trim_seg_to_wnd(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	uint32_t left, right;
-
-	seq_no_seg_trim_calc(conn, seg, &left, &right);
-	tcp_segment_trim(seg, left, right);
-}
-
-/** Handle unexpected segment received on a socket pair.
- *
- * We reply with an RST unless the received segment has RST.
- *
- * @param sp		Socket pair which received the segment
- * @param seg		Unexpected segment
- */
-void tcp_unexpected_segment(tcp_sockpair_t *sp, tcp_segment_t *seg)
-{
-	log_msg(LVL_DEBUG, "tcp_unexpected_segment(%p, %p)", sp, seg);
-
-	if ((seg->ctrl & CTL_RST) == 0)
-		tcp_reply_rst(sp, seg);
-}
-
-/** Compute flipped socket pair for response.
- *
- * Flipped socket pair has local and foreign sockets exchanged.
- *
- * @param sp		Socket pair
- * @param fsp		Place to store flipped socket pair
- */
-void tcp_sockpair_flipped(tcp_sockpair_t *sp, tcp_sockpair_t *fsp)
-{
-	fsp->local = sp->foreign;
-	fsp->foreign = sp->local;
-}
-
-/** Send RST in response to an incoming segment.
- *
- * @param sp		Socket pair which received the segment
- * @param seg		Incoming segment
- */
-void tcp_reply_rst(tcp_sockpair_t *sp, tcp_segment_t *seg)
-{
-	tcp_segment_t *rseg;
-
-	log_msg(LVL_DEBUG, "tcp_reply_rst(%p, %p)", sp, seg);
-
-	rseg = tcp_segment_make_rst(seg);
-	tcp_transmit_segment(sp, rseg);
-}
-
-/**
- * @}
- */
Index: pace/srv/net/tl/tcp/conn.h
===================================================================
--- uspace/srv/net/tl/tcp/conn.h	(revision bf31e3f1ebd6e88e0c8425f109e42ccd92b6c9b3)
+++ 	(revision )
@@ -1,61 +1,0 @@
-/*
- * Copyright (c) 2011 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup tcp
- * @{
- */
-/** @file TCP connection processing and state machine
- */
-
-#ifndef CONN_H
-#define CONN_H
-
-#include <bool.h>
-#include "tcp_type.h"
-
-extern tcp_conn_t *tcp_conn_new(tcp_sock_t *, tcp_sock_t *);
-extern void tcp_conn_delete(tcp_conn_t *);
-extern void tcp_conn_add(tcp_conn_t *);
-extern void tcp_conn_remove(tcp_conn_t *);
-extern void tcp_conn_sync(tcp_conn_t *);
-extern void tcp_conn_fin_sent(tcp_conn_t *);
-extern void tcp_conn_ack_of_fin_rcvd(tcp_conn_t *);
-extern tcp_conn_t *tcp_conn_find_ref(tcp_sockpair_t *);
-extern void tcp_conn_addref(tcp_conn_t *);
-extern void tcp_conn_delref(tcp_conn_t *);
-extern bool tcp_conn_got_syn(tcp_conn_t *);
-extern void tcp_conn_segment_arrived(tcp_conn_t *, tcp_segment_t *);
-extern void tcp_conn_trim_seg_to_wnd(tcp_conn_t *, tcp_segment_t *);
-extern void tcp_unexpected_segment(tcp_sockpair_t *, tcp_segment_t *);
-extern void tcp_sockpair_flipped(tcp_sockpair_t *, tcp_sockpair_t *);
-extern void tcp_reply_rst(tcp_sockpair_t *, tcp_segment_t *);
-
-#endif
-
-/** @}
- */
Index: pace/srv/net/tl/tcp/iqueue.c
===================================================================
--- uspace/srv/net/tl/tcp/iqueue.c	(revision bf31e3f1ebd6e88e0c8425f109e42ccd92b6c9b3)
+++ 	(revision )
@@ -1,156 +1,0 @@
-/*
- * Copyright (c) 2011 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup tcp
- * @{
- */
-
-/**
- * @file Connection incoming segments queue
- *
- * Segments are sorted in order of their sequence number.
- */
-
-#include <adt/list.h>
-#include <errno.h>
-#include <io/log.h>
-#include <stdlib.h>
-#include "iqueue.h"
-#include "segment.h"
-#include "seq_no.h"
-#include "tcp_type.h"
-
-/** Initialize incoming segments queue.
- *
- * @param iqueue	Incoming queue
- * @param conn		Connection the queue is associated with
- */
-void tcp_iqueue_init(tcp_iqueue_t *iqueue, tcp_conn_t *conn)
-{
-	list_initialize(&iqueue->list);
-	iqueue->conn = conn;
-}
-
-/** Insert segment into incoming queue.
- *
- * @param iqueue	Incoming queue
- * @param seg		Segment
- */
-void tcp_iqueue_insert_seg(tcp_iqueue_t *iqueue, tcp_segment_t *seg)
-{
-	tcp_iqueue_entry_t *iqe;
-	tcp_iqueue_entry_t *qe;
-	link_t *link;
-	log_msg(LVL_DEBUG, "tcp_iqueue_insert_seg()");
-
-	iqe = calloc(1, sizeof(tcp_iqueue_entry_t));
-	if (iqe == NULL) {
-		log_msg(LVL_ERROR, "Failed allocating IQE.");
-		return;
-	}
-
-	iqe->seg = seg;
-
-	/* Sort by sequence number */
-
-	link = list_first(&iqueue->list);
-	while (link != NULL) {
-		qe = list_get_instance(link,
-		    tcp_iqueue_entry_t, link);
-
-		if (seq_no_seg_cmp(iqueue->conn, iqe->seg, qe->seg) >= 0)
-			break;
-	}
-
-	if (link != NULL)
-		list_insert_before(&iqe->link, &qe->link);
-	else
-		list_append(&iqe->link, &iqueue->list);
-}
-
-/** Get next ready segment from incoming queue.
- *
- * Return the segment with the earliest sequence number if it is ready.
- * A segment is ready if its SEG.SEQ is earlier or equal to RCV.NXT.
- *
- * @param iqueue	Incoming queue
- * @param seg		Place to store pointer to segment
- * @return		EOK on success, ENOENT if no segment is ready
- */
-int tcp_iqueue_get_ready_seg(tcp_iqueue_t *iqueue, tcp_segment_t **seg)
-{
-	tcp_iqueue_entry_t *iqe;
-	link_t *link;
-
-	log_msg(LVL_DEBUG, "tcp_get_ready_seg()");
-
-	link = list_first(&iqueue->list);
-	if (link == NULL) {
-		log_msg(LVL_DEBUG, "iqueue is empty");
-		return ENOENT;
-	}
-
-	iqe = list_get_instance(link, tcp_iqueue_entry_t, link);
-
-	while (!seq_no_segment_acceptable(iqueue->conn, iqe->seg)) {
-		log_msg(LVL_DEBUG, "Skipping unacceptable segment (RCV.NXT=%"
-		    PRIu32 ", RCV.NXT+RCV.WND=%" PRIu32 ", SEG.SEQ=%" PRIu32
-		    ", SEG.LEN=%" PRIu32 ")", iqueue->conn->rcv_nxt,
-		    iqueue->conn->rcv_nxt + iqueue->conn->rcv_wnd,
-		    iqe->seg->seq, iqe->seg->len);
-
-		list_remove(&iqe->link);
-		tcp_segment_delete(iqe->seg);
-
-         	link = list_first(&iqueue->list);
-		if (link == NULL) {
-			log_msg(LVL_DEBUG, "iqueue is empty");
-			return ENOENT;
-		}
-
-		iqe = list_get_instance(link, tcp_iqueue_entry_t, link);
-	}
-
-	/* Do not return segments that are not ready for processing */
-	if (!seq_no_segment_ready(iqueue->conn, iqe->seg)) {
-		log_msg(LVL_DEBUG, "Next segment not ready: SEG.SEQ=%u, "
-		    "RCV.NXT=%u, SEG.LEN=%u", iqe->seg->seq,
-		    iqueue->conn->rcv_nxt, iqe->seg->len);
-		return ENOENT;
-	}
-
-	log_msg(LVL_DEBUG, "Returning ready segment %p", iqe->seg);
-	list_remove(&iqe->link);
-	*seg = iqe->seg;
-
-	return EOK;
-}
-
-/**
- * @}
- */
Index: pace/srv/net/tl/tcp/iqueue.h
===================================================================
--- uspace/srv/net/tl/tcp/iqueue.h	(revision bf31e3f1ebd6e88e0c8425f109e42ccd92b6c9b3)
+++ 	(revision )
@@ -1,47 +1,0 @@
-/*
- * Copyright (c) 2011 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup tcp
- * @{
- */
-/** @file Connection incoming segments queue
- */
-
-#ifndef IQUEUE_H
-#define IQUEUE_H
-
-#include "tcp_type.h"
-
-extern void tcp_iqueue_init(tcp_iqueue_t *, tcp_conn_t *);
-extern void tcp_iqueue_insert_seg(tcp_iqueue_t *, tcp_segment_t *);
-extern int tcp_iqueue_get_ready_seg(tcp_iqueue_t *, tcp_segment_t **);
-
-#endif
-
-/** @}
- */
Index: pace/srv/net/tl/tcp/ncsim.c
===================================================================
--- uspace/srv/net/tl/tcp/ncsim.c	(revision bf31e3f1ebd6e88e0c8425f109e42ccd92b6c9b3)
+++ 	(revision )
@@ -1,172 +1,0 @@
-/*
- * Copyright (c) 2011 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup tcp
- * @{
- */
-
-/**
- * @file Network condition simulator
- *
- * Simulate network conditions for testing the reliability implementation:
- *    - variable latency
- *    - frame drop
- */
-
-#include <adt/list.h>
-#include <async.h>
-#include <errno.h>
-#include <io/log.h>
-#include <stdlib.h>
-#include <thread.h>
-#include "conn.h"
-#include "ncsim.h"
-#include "rqueue.h"
-#include "segment.h"
-#include "tcp_type.h"
-
-static list_t sim_queue;
-static fibril_mutex_t sim_queue_lock;
-static fibril_condvar_t sim_queue_cv;
-
-/** Initialize segment receive queue. */
-void tcp_ncsim_init(void)
-{
-	list_initialize(&sim_queue);
-	fibril_mutex_initialize(&sim_queue_lock);
-	fibril_condvar_initialize(&sim_queue_cv);
-}
-
-/** Bounce segment through simulator into receive queue.
- *
- * @param sp	Socket pair, oriented for transmission
- * @param seg	Segment
- */
-void tcp_ncsim_bounce_seg(tcp_sockpair_t *sp, tcp_segment_t *seg)
-{
-	tcp_squeue_entry_t *sqe;
-	tcp_squeue_entry_t *old_qe;
-	link_t *link;
-
-	log_msg(LVL_DEBUG, "tcp_ncsim_bounce_seg()");
-	tcp_rqueue_bounce_seg(sp, seg);
-	return;
-
-	if (0 /*random() % 4 == 3*/) {
-		/* Drop segment */
-		log_msg(LVL_ERROR, "NCSim dropping segment");
-		tcp_segment_delete(seg);
-		return;
-	}
-
-	sqe = calloc(1, sizeof(tcp_squeue_entry_t));
-	if (sqe == NULL) {
-		log_msg(LVL_ERROR, "Failed allocating SQE.");
-		return;
-	}
-
-	sqe->delay = random() % (1000 * 1000);
-	sqe->sp = *sp;
-	sqe->seg = seg;
-
-	fibril_mutex_lock(&sim_queue_lock);
-
-	link = list_first(&sim_queue);
-	while (link != NULL && sqe->delay > 0) {
-		old_qe = list_get_instance(link, tcp_squeue_entry_t, link);
-		if (sqe->delay < old_qe->delay)
-			break;
-
-		sqe->delay -= old_qe->delay;
-
-		link = link->next;
-		if (link == &sim_queue.head)
-			link = NULL;
-	}
-
-	if (link != NULL)
-		list_insert_after(&sqe->link, link);
-	else
-		list_append(&sqe->link, &sim_queue);
-
-	fibril_condvar_broadcast(&sim_queue_cv);
-	fibril_mutex_unlock(&sim_queue_lock);
-}
-
-/** Network condition simulator handler thread. */
-static void tcp_ncsim_thread(void *arg)
-{
-	link_t *link;
-	tcp_squeue_entry_t *sqe;
-	int rc;
-
-	log_msg(LVL_DEBUG, "tcp_ncsim_thread()");
-
-
-	while (true) {
-		fibril_mutex_lock(&sim_queue_lock);
-
-		while (list_empty(&sim_queue))
-			fibril_condvar_wait(&sim_queue_cv, &sim_queue_lock);
-
-		do {
-			link = list_first(&sim_queue);
-			sqe = list_get_instance(link, tcp_squeue_entry_t, link);
-
-			log_msg(LVL_DEBUG, "NCSim - Sleep");
-			rc = fibril_condvar_wait_timeout(&sim_queue_cv,
-			    &sim_queue_lock, sqe->delay);
-		} while (rc != ETIMEOUT);
-
-		list_remove(link);
-		fibril_mutex_unlock(&sim_queue_lock);
-
-		log_msg(LVL_DEBUG, "NCSim - End Sleep");
-		tcp_rqueue_bounce_seg(&sqe->sp, sqe->seg);
-		free(sqe);
-	}
-}
-
-/** Start simulator handler thread. */
-void tcp_ncsim_thread_start(void)
-{
-	thread_id_t tid;
-        int rc;
-
-	log_msg(LVL_DEBUG, "tcp_ncsim_thread_start()");
-
-	rc = thread_create(tcp_ncsim_thread, NULL, "ncsim", &tid);
-	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed creating ncsim thread.");
-		return;
-	}
-}
-
-/**
- * @}
- */
Index: pace/srv/net/tl/tcp/ncsim.h
===================================================================
--- uspace/srv/net/tl/tcp/ncsim.h	(revision bf31e3f1ebd6e88e0c8425f109e42ccd92b6c9b3)
+++ 	(revision )
@@ -1,48 +1,0 @@
-/*
- * Copyright (c) 2011 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup tcp
- * @{
- */
-/** @file Network condition simulator
- */
-
-#ifndef NCSIM_H
-#define NCSIM_H
-
-#include "tcp_type.h"
-
-extern void tcp_ncsim_init(void);
-extern void tcp_ncsim_bounce_seg(tcp_sockpair_t *, tcp_segment_t *);
-extern void tcp_ncsim_thread_start(void);
-
-
-#endif
-
-/** @}
- */
Index: pace/srv/net/tl/tcp/pdu.c
===================================================================
--- uspace/srv/net/tl/tcp/pdu.c	(revision bf31e3f1ebd6e88e0c8425f109e42ccd92b6c9b3)
+++ 	(revision )
@@ -1,314 +1,0 @@
-/*
- * Copyright (c) 2011 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup tcp
- * @{
- */
-
-/**
- * @file TCP header encoding and decoding
- */
-
-#include <bitops.h>
-#include <byteorder.h>
-#include <errno.h>
-#include <mem.h>
-#include <stdlib.h>
-#include "pdu.h"
-#include "segment.h"
-#include "seq_no.h"
-#include "std.h"
-#include "tcp_type.h"
-
-#define TCP_CHECKSUM_INIT 0xffff
-
-/** One's complement addition.
- *
- * Result is a + b + carry.
- */
-static uint16_t tcp_ocadd16(uint16_t a, uint16_t b)
-{
-	uint32_t s;
-
-	s = (uint32_t)a + (uint32_t)b;
-	return (s & 0xffff) + (s >> 16);
-}
-
-static uint16_t tcp_checksum_calc(uint16_t ivalue, void *data, size_t size)
-{
-	uint16_t sum;
-	uint16_t w;
-	size_t words, i;
-	uint8_t *bdata;
-
-	sum = ~ivalue;
-	words = size / 2;
-	bdata = (uint8_t *)data;
-
-	for (i = 0; i < words; i++) {
-		w = ((uint16_t)bdata[2*i] << 8) | bdata[2*i + 1];
-		sum = tcp_ocadd16(sum, w);
-	}
-
-	if (size % 2 != 0) {
-		w = ((uint16_t)bdata[2*words] << 8);
-		sum = tcp_ocadd16(sum, w);
-	}
-
-	return ~sum;
-}
-
-static void tcp_header_decode_flags(uint16_t doff_flags, tcp_control_t *rctl)
-{
-	tcp_control_t ctl;
-
-	ctl = 0;
-
-	if ((doff_flags & BIT_V(uint16_t, DF_URG)) != 0)
-		ctl |= 0 /* XXX */;
-	if ((doff_flags & BIT_V(uint16_t, DF_ACK)) != 0)
-		ctl |= CTL_ACK;
-	if ((doff_flags & BIT_V(uint16_t, DF_PSH)) != 0)
-		ctl |= 0 /* XXX */;
-	if ((doff_flags & BIT_V(uint16_t, DF_RST)) != 0)
-		ctl |= CTL_RST;
-	if ((doff_flags & BIT_V(uint16_t, DF_SYN)) != 0)
-		ctl |= CTL_SYN;
-	if ((doff_flags & BIT_V(uint16_t, DF_FIN)) != 0)
-		ctl |= CTL_FIN;
-
-	*rctl = ctl;
-}
-
-static void tcp_header_encode_flags(tcp_control_t ctl, uint16_t doff_flags0,
-    uint16_t *rdoff_flags)
-{
-	uint16_t doff_flags;
-
-	doff_flags = doff_flags0;
-
-	if ((ctl & CTL_ACK) != 0)
-		doff_flags |= BIT_V(uint16_t, DF_ACK);
-	if ((ctl & CTL_RST) != 0)
-		doff_flags |= BIT_V(uint16_t, DF_RST);
-	if ((ctl & CTL_SYN) != 0)
-		doff_flags |= BIT_V(uint16_t, DF_SYN);
-	if ((ctl & CTL_FIN) != 0)
-		doff_flags |= BIT_V(uint16_t, DF_FIN);
-
-	*rdoff_flags = doff_flags;
-}
-
-static void tcp_header_setup(tcp_sockpair_t *sp, tcp_segment_t *seg, tcp_header_t *hdr)
-{
-	uint16_t doff_flags;
-	uint16_t doff;
-
-	hdr->src_port = host2uint16_t_be(sp->local.port);
-	hdr->dest_port = host2uint16_t_be(sp->foreign.port);
-	hdr->seq = host2uint32_t_be(seg->seq);
-	hdr->ack = host2uint32_t_be(seg->ack);
-
-	doff = (sizeof(tcp_header_t) / sizeof(uint32_t)) << DF_DATA_OFFSET_l;
-	tcp_header_encode_flags(seg->ctrl, doff, &doff_flags);
-
-	hdr->doff_flags = host2uint16_t_be(doff_flags);
-	hdr->window = host2uint16_t_be(seg->wnd);
-	hdr->checksum = 0;
-	hdr->urg_ptr = host2uint16_t_be(seg->up);
-}
-
-static void tcp_phdr_setup(tcp_pdu_t *pdu, tcp_phdr_t *phdr)
-{
-	phdr->src_addr = host2uint32_t_be(pdu->src_addr.ipv4);
-	phdr->dest_addr = host2uint32_t_be(pdu->dest_addr.ipv4);
-	phdr->zero = 0;
-	phdr->protocol = 6; /* XXX Magic number */
-	phdr->tcp_length = host2uint16_t_be(pdu->header_size + pdu->text_size);
-}
-
-static void tcp_header_decode(tcp_header_t *hdr, tcp_segment_t *seg)
-{
-	tcp_header_decode_flags(uint16_t_be2host(hdr->doff_flags), &seg->ctrl);
-	seg->seq = uint32_t_be2host(hdr->seq);
-	seg->ack = uint32_t_be2host(hdr->ack);
-	seg->wnd = uint16_t_be2host(hdr->window);
-	seg->up = uint16_t_be2host(hdr->urg_ptr);
-}
-
-static int tcp_header_encode(tcp_sockpair_t *sp, tcp_segment_t *seg,
-    void **header, size_t *size)
-{
-	tcp_header_t *hdr;
-
-	hdr = calloc(1, sizeof(tcp_header_t));
-	if (hdr == NULL)
-		return ENOMEM;
-
-	tcp_header_setup(sp, seg, hdr);
-	*header = hdr;
-	*size = sizeof(tcp_header_t);
-
-	return EOK;
-}
-
-static tcp_pdu_t *tcp_pdu_new(void)
-{
-	return calloc(1, sizeof(tcp_pdu_t));
-}
-
-/** Create PDU with the specified header and text data.
- *
- * Note that you still need to set addresses in the returned PDU.
- *
- * @param hdr		Header data
- * @param hdr_size      Header size in bytes
- * @param text		Text data
- * @param text_size	Text size in bytes
- * @return		New PDU
- */
-tcp_pdu_t *tcp_pdu_create(void *hdr, size_t hdr_size, void *text,
-    size_t text_size)
-{
-	tcp_pdu_t *pdu;
-
-	pdu = tcp_pdu_new();
-	if (pdu == NULL)
-		return NULL;
-
-	pdu->header = malloc(hdr_size);
-	pdu->text = malloc(text_size);
-	if (pdu->header == NULL || pdu->text == NULL)
-		goto error;
-
-	memcpy(pdu->header, hdr, hdr_size);
-	memcpy(pdu->text, text, text_size);
-
-	pdu->header_size = hdr_size;
-	pdu->text_size = text_size;
-
-	return pdu;
-
-error:
-	if (pdu->header != NULL)
-		free(pdu->header);
-	if (pdu->text != NULL)
-		free(pdu->text);
-
-	return NULL;
-}
-
-void tcp_pdu_delete(tcp_pdu_t *pdu)
-{
-	free(pdu->header);
-	free(pdu->text);
-	free(pdu);
-}
-
-static uint16_t tcp_pdu_checksum_calc(tcp_pdu_t *pdu)
-{
-	uint16_t cs_phdr;
-	uint16_t cs_headers;
-	uint16_t cs_all;
-	tcp_phdr_t phdr;
-
-	tcp_phdr_setup(pdu, &phdr);
-	cs_phdr = tcp_checksum_calc(TCP_CHECKSUM_INIT, (void *)&phdr,
-	    sizeof(tcp_phdr_t));
-	cs_headers = tcp_checksum_calc(cs_phdr, pdu->header, pdu->header_size);
-	cs_all = tcp_checksum_calc(cs_headers, pdu->text, pdu->text_size);
-
-	return cs_all;
-}
-
-static void tcp_pdu_set_checksum(tcp_pdu_t *pdu, uint16_t checksum)
-{
-	tcp_header_t *hdr;
-
-	hdr = (tcp_header_t *)pdu->header;
-	hdr->checksum = host2uint16_t_be(checksum);
-}
-
-/** Encode outgoing PDU */
-int tcp_pdu_decode(tcp_pdu_t *pdu, tcp_sockpair_t *sp, tcp_segment_t **seg)
-{
-	tcp_segment_t *nseg;
-	tcp_header_t *hdr;
-
-	nseg = tcp_segment_make_data(0, pdu->text, pdu->text_size);
-	if (nseg == NULL)
-		return ENOMEM;
-
-	tcp_header_decode(pdu->header, nseg);
-	nseg->len += seq_no_control_len(nseg->ctrl);
-
-	hdr = (tcp_header_t *)pdu->header;
-
-	sp->local.port = uint16_t_be2host(hdr->dest_port);
-	sp->local.addr = pdu->dest_addr;
-	sp->foreign.port = uint16_t_be2host(hdr->src_port);
-	sp->foreign.addr = pdu->src_addr;
-
-	*seg = nseg;
-	return EOK;
-}
-
-/** Decode incoming PDU */
-int tcp_pdu_encode(tcp_sockpair_t *sp, tcp_segment_t *seg, tcp_pdu_t **pdu)
-{
-	tcp_pdu_t *npdu;
-	size_t text_size;
-	uint16_t checksum;
-
-	npdu = tcp_pdu_new();
-	if (npdu == NULL)
-		return ENOMEM;
-
-	npdu->src_addr = sp->local.addr;
-	npdu->dest_addr = sp->foreign.addr;
-	tcp_header_encode(sp, seg, &npdu->header, &npdu->header_size);
-
-	text_size = tcp_segment_text_size(seg);
-	npdu->text = calloc(1, text_size);
-	if (npdu->text == NULL)
-		return ENOMEM;
-
-	npdu->text_size = text_size;
-	memcpy(npdu->text, seg->data, text_size);
-
-	/* Checksum calculation */
-	checksum = tcp_pdu_checksum_calc(npdu);
-	tcp_pdu_set_checksum(npdu, checksum);
-
-	*pdu = npdu;
-	return EOK;
-}
-
-/**
- * @}
- */
Index: pace/srv/net/tl/tcp/pdu.h
===================================================================
--- uspace/srv/net/tl/tcp/pdu.h	(revision bf31e3f1ebd6e88e0c8425f109e42ccd92b6c9b3)
+++ 	(revision )
@@ -1,50 +1,0 @@
-/*
- * Copyright (c) 2011 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup tcp
- * @{
- */
-/** @file TCP PDU (encoded Protocol Data Unit) handling
- */
-
-#ifndef PDU_H
-#define PDU_H
-
-#include <sys/types.h>
-#include "std.h"
-#include "tcp_type.h"
-
-extern tcp_pdu_t *tcp_pdu_create(void *, size_t, void *, size_t);
-extern void tcp_pdu_delete(tcp_pdu_t *);
-extern int tcp_pdu_decode(tcp_pdu_t *, tcp_sockpair_t *, tcp_segment_t **);
-extern int tcp_pdu_encode(tcp_sockpair_t *, tcp_segment_t *, tcp_pdu_t **);
-
-#endif
-
-/** @}
- */
Index: pace/srv/net/tl/tcp/rqueue.c
===================================================================
--- uspace/srv/net/tl/tcp/rqueue.c	(revision bf31e3f1ebd6e88e0c8425f109e42ccd92b6c9b3)
+++ 	(revision )
@@ -1,163 +1,0 @@
-/*
- * Copyright (c) 2011 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup tcp
- * @{
- */
-
-/**
- * @file Global segment receive queue
- */
-
-#include <adt/prodcons.h>
-#include <errno.h>
-#include <io/log.h>
-#include <stdlib.h>
-#include <thread.h>
-#include "conn.h"
-#include "pdu.h"
-#include "rqueue.h"
-#include "segment.h"
-#include "tcp_type.h"
-#include "ucall.h"
-
-/** Transcode bounced segments.
- *
- * If defined, segments bounced via the internal debugging loopback will
- * be encoded to a PDU and the decoded. Otherwise they will be bounced back
- * directly without passing the encoder-decoder.
- */
-#define BOUNCE_TRANSCODE
-
-static prodcons_t rqueue;
-
-/** Initialize segment receive queue. */
-void tcp_rqueue_init(void)
-{
-	prodcons_initialize(&rqueue);
-}
-
-/** Bounce segment directy into receive queue without constructing the PDU.
- *
- * This is for testing purposes only.
- *
- * @param sp	Socket pair, oriented for transmission
- * @param seg	Segment
- */
-void tcp_rqueue_bounce_seg(tcp_sockpair_t *sp, tcp_segment_t *seg)
-{
-	tcp_sockpair_t rident;
-
-	log_msg(LVL_DEBUG, "tcp_rqueue_bounce_seg()");
-
-#ifdef BOUNCE_TRANSCODE
-	tcp_pdu_t *pdu;
-	tcp_segment_t *dseg;
-
-	if (tcp_pdu_encode(sp, seg, &pdu) != EOK) {
-		log_msg(LVL_WARN, "Not enough memory. Segment dropped.");
-		return;
-	}
-
-	if (tcp_pdu_decode(pdu, &rident, &dseg) != EOK) {
-		log_msg(LVL_WARN, "Not enough memory. Segment dropped.");
-		return;
-	}
-
-	tcp_pdu_delete(pdu);
-
-	/** Insert decoded segment into rqueue */
-	tcp_rqueue_insert_seg(&rident, dseg);
-	tcp_segment_delete(seg);
-#else
-	/* Reverse the identification */
-	tcp_sockpair_flipped(sp, &rident);
-
-	/* Insert segment back into rqueue */
-	tcp_rqueue_insert_seg(&rident, seg);
-#endif
-}
-
-/** Insert segment into receive queue.
- *
- * @param sp	Socket pair, oriented for reception
- * @param seg	Segment
- */
-void tcp_rqueue_insert_seg(tcp_sockpair_t *sp, tcp_segment_t *seg)
-{
-	tcp_rqueue_entry_t *rqe;
-	log_msg(LVL_DEBUG, "tcp_rqueue_insert_seg()");
-
-	tcp_segment_dump(seg);
-
-	rqe = calloc(1, sizeof(tcp_rqueue_entry_t));
-	if (rqe == NULL) {
-		log_msg(LVL_ERROR, "Failed allocating RQE.");
-		return;
-	}
-
-	rqe->sp = *sp;
-	rqe->seg = seg;
-
-	prodcons_produce(&rqueue, &rqe->link);
-}
-
-/** Receive queue handler thread. */
-static void tcp_rqueue_thread(void *arg)
-{
-	link_t *link;
-	tcp_rqueue_entry_t *rqe;
-
-	log_msg(LVL_DEBUG, "tcp_rqueue_thread()");
-
-	while (true) {
-		link = prodcons_consume(&rqueue);
-		rqe = list_get_instance(link, tcp_rqueue_entry_t, link);
-
-		tcp_as_segment_arrived(&rqe->sp, rqe->seg);
-	}
-}
-
-/** Start receive queue handler thread. */
-void tcp_rqueue_thread_start(void)
-{
-	thread_id_t tid;
-        int rc;
-
-	log_msg(LVL_DEBUG, "tcp_rqueue_thread_start()");
-
-	rc = thread_create(tcp_rqueue_thread, NULL, "rqueue", &tid);
-	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed creating rqueue thread.");
-		return;
-	}
-}
-
-/**
- * @}
- */
Index: pace/srv/net/tl/tcp/rqueue.h
===================================================================
--- uspace/srv/net/tl/tcp/rqueue.h	(revision bf31e3f1ebd6e88e0c8425f109e42ccd92b6c9b3)
+++ 	(revision )
@@ -1,50 +1,0 @@
-/*
- * Copyright (c) 2011 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup tcp
- * @{
- */
-/** @file Global segment receive queue
- */
-
-#ifndef RQUEUE_H
-#define RQUEUE_H
-
-#include "tcp_type.h"
-
-extern void tcp_rqueue_init(void);
-extern void tcp_rqueue_bounce_seg(tcp_sockpair_t *, tcp_segment_t *);
-extern void tcp_rqueue_insert_seg(tcp_sockpair_t *, tcp_segment_t *);
-extern void tcp_rqueue_handler(void *);
-extern void tcp_rqueue_thread_start(void);
-
-
-#endif
-
-/** @}
- */
Index: pace/srv/net/tl/tcp/segment.c
===================================================================
--- uspace/srv/net/tl/tcp/segment.c	(revision bf31e3f1ebd6e88e0c8425f109e42ccd92b6c9b3)
+++ 	(revision )
@@ -1,261 +1,0 @@
-/*
- * Copyright (c) 2011 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup tcp
- * @{
- */
-
-/**
- * @file Segment processing
- */
-
-#include <io/log.h>
-#include <mem.h>
-#include <stdlib.h>
-#include "segment.h"
-#include "seq_no.h"
-#include "tcp_type.h"
-
-/** Alocate new segment structure. */
-tcp_segment_t *tcp_segment_new(void)
-{
-	return calloc(1, sizeof(tcp_segment_t));
-}
-
-/** Delete segment. */
-void tcp_segment_delete(tcp_segment_t *seg)
-{
-	free(seg);
-}
-
-/** Create duplicate of segment.
- *
- * @param seg	Segment
- * @return 	Duplicate segment
- */
-tcp_segment_t *tcp_segment_dup(tcp_segment_t *seg)
-{
-	tcp_segment_t *scopy;
-	size_t tsize;
-
-	scopy = tcp_segment_new();
-	if (scopy == NULL)
-		return NULL;
-
-	scopy->ctrl = seg->ctrl;
-	scopy->seq = seg->seq;
-	scopy->ack = seg->ack;
-	scopy->len = seg->len;
-	scopy->wnd = seg->wnd;
-	scopy->up = seg->up;
-
-	tsize = tcp_segment_text_size(seg);
-	scopy->data = calloc(tsize, 1);
-	if (scopy->data == NULL) {
-		free(scopy);
-		return NULL;
-	}
-
-	memcpy(scopy->data, seg->data, tsize);
-	scopy->dfptr = scopy->data;
-
-	return scopy;
-}
-
-/** Create a control-only segment.
- *
-  * @return	Segment
- */
-tcp_segment_t *tcp_segment_make_ctrl(tcp_control_t ctrl)
-{
-	tcp_segment_t *seg;
-
-	seg = tcp_segment_new();
-	if (seg == NULL)
-		return NULL;
-
-	seg->ctrl = ctrl;
-	seg->len = seq_no_control_len(ctrl);
-
-	return seg;
-}
-
-/** Create an RST segment.
- *
- * @param seg	Segment we are replying to
- * @return	RST segment
- */
-tcp_segment_t *tcp_segment_make_rst(tcp_segment_t *seg)
-{
-	tcp_segment_t *rseg;
-
-	rseg = tcp_segment_new();
-	if (rseg == NULL)
-		return NULL;
-
-	if ((seg->ctrl & CTL_ACK) == 0) {
-		rseg->ctrl = CTL_RST | CTL_ACK;
-		rseg->seq = 0;
-		rseg->ack = seg->seq + seg->len;
-	} else {
-		rseg->ctrl = CTL_RST;
-		rseg->seq = seg->ack;
-	}
-
-	return rseg;
-}
-
-/** Create a control segment.
- *
-  * @return	Segment
- */
-tcp_segment_t *tcp_segment_make_data(tcp_control_t ctrl, void *data,
-    size_t size)
-{
-	tcp_segment_t *seg;
-
-	seg = tcp_segment_new();
-	if (seg == NULL)
-		return NULL;
-
-	seg->ctrl = ctrl;
-	seg->len = seq_no_control_len(ctrl) + size;
-
-	seg->dfptr = seg->data = malloc(size);
-	if (seg->dfptr == NULL) {
-		free(seg);
-		return NULL;
-	}
-
-	memcpy(seg->data, data, size);
-
-	return seg;
-}
-
-
-/** Trim segment from left and right by the specified amount.
- *
- * Trim any text or control to remove the specified amount of sequence
- * numbers from the left (lower sequence numbers) and right side
- * (higher sequence numbers) of the segment.
- *
- * @param seg		Segment, will be modified in place
- * @param left		Amount of sequence numbers to trim from the left
- * @param right		Amount of sequence numbers to trim from the right
- */
-void tcp_segment_trim(tcp_segment_t *seg, uint32_t left, uint32_t right)
-{
-	uint32_t t_size;
-
-	assert(left + right <= seg->len);
-
-	/* Special case, entire segment trimmed from left */
-	if (left == seg->len) {
-		seg->seq = seg->seq + seg->len;
-		seg->len = 0;
-		return;
-	}
-
-	/* Special case, entire segment trimmed from right */
-	if (right == seg->len) {
-		seg->len = 0;
-		return;
-	}
-
-	/* General case */
-
-	t_size = tcp_segment_text_size(seg);
-
-	if (left > 0 && (seg->ctrl & CTL_SYN) != 0) {
-		/* Trim SYN */
-		seg->ctrl &= ~CTL_SYN;
-		seg->seq++;
-		seg->len--;
-		left--;
-	}
-
-	if (right > 0 && (seg->ctrl & CTL_FIN) != 0) {
-		/* Trim FIN */
-		seg->ctrl &= ~CTL_FIN;
-		seg->len--;
-		right--;
-	}
-
-	if (left > 0 || right > 0) {
-		/* Trim segment text */
-		assert(left + right <= t_size);
-
-		seg->data += left;
-		seg->len -= left + right;
-	}
-}
-
-/** Copy out text data from segment.
- *
- * Data is copied from the beginning of the segment text up to @a size bytes.
- * @a size must not be greater than the size of the segment text, but
- * it can be less.
- *
- * @param seg	Segment
- * @param buf	Destination buffer
- * @param size	Size of destination buffer
- */
-void tcp_segment_text_copy(tcp_segment_t *seg, void *buf, size_t size)
-{
-	assert(size <= tcp_segment_text_size(seg));
-	memcpy(buf, seg->data, size);
-}
-
-/** Return number of bytes in segment text.
- *
- * @param seg	Segment
- * @return	Number of bytes in segment text
- */
-size_t tcp_segment_text_size(tcp_segment_t *seg)
-{
-	return seg->len - seq_no_control_len(seg->ctrl);
-}
-
-/** Dump segment contents to log.
- *
- * @param seg	Segment
- */
-void tcp_segment_dump(tcp_segment_t *seg)
-{
-	log_msg(LVL_DEBUG, "Segment dump:");
-	log_msg(LVL_DEBUG, " - ctrl = %u", (unsigned)seg->ctrl);
-	log_msg(LVL_DEBUG, " - seq = % " PRIu32, seg->seq);
-	log_msg(LVL_DEBUG, " - ack = % " PRIu32, seg->ack);
-	log_msg(LVL_DEBUG, " - len = % " PRIu32, seg->len);
-	log_msg(LVL_DEBUG, " - wnd = % " PRIu32, seg->wnd);
-	log_msg(LVL_DEBUG, " - up = % " PRIu32, seg->up);
-}
-
-/**
- * @}
- */
Index: pace/srv/net/tl/tcp/segment.h
===================================================================
--- uspace/srv/net/tl/tcp/segment.h	(revision bf31e3f1ebd6e88e0c8425f109e42ccd92b6c9b3)
+++ 	(revision )
@@ -1,57 +1,0 @@
-/*
- * Copyright (c) 2011 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup tcp
- * @{
- */
-/** @file Segment processing
- */
-
-#ifndef SEGMENT_H
-#define SEGMENT_H
-
-#include <sys/types.h>
-#include "tcp_type.h"
-
-extern tcp_segment_t *tcp_segment_new(void);
-extern void tcp_segment_delete(tcp_segment_t *);
-extern tcp_segment_t *tcp_segment_dup(tcp_segment_t *);
-extern tcp_segment_t *tcp_segment_make_ctrl(tcp_control_t);
-extern tcp_segment_t *tcp_segment_make_rst(tcp_segment_t *);
-extern tcp_segment_t *tcp_segment_make_data(tcp_control_t, void *, size_t);
-extern void tcp_segment_trim(tcp_segment_t *, uint32_t, uint32_t);
-extern void tcp_segment_text_copy(tcp_segment_t *, void *, size_t);
-extern size_t tcp_segment_text_size(tcp_segment_t *);
-extern void tcp_segment_dump(tcp_segment_t *);
-
-
-
-#endif
-
-/** @}
- */
Index: pace/srv/net/tl/tcp/seq_no.c
===================================================================
--- uspace/srv/net/tl/tcp/seq_no.c	(revision bf31e3f1ebd6e88e0c8425f109e42ccd92b6c9b3)
+++ 	(revision )
@@ -1,243 +1,0 @@
-/*
- * Copyright (c) 2011 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup tcp
- * @{
- */
-
-/**
- * @file Sequence number computations
- */
-
-#include <assert.h>
-#include <bool.h>
-#include <sys/types.h>
-#include "seq_no.h"
-#include "tcp_type.h"
-
-/** a <= b < c modulo sequence space */
-static bool seq_no_le_lt(uint32_t a, uint32_t b, uint32_t c)
-{
-	if (a <= c) {
-		return (a <= b) && (b < c);
-	} else {
-		return (b < c) || (a <= b);
-	}
-}
-
-/** a < b <= c modulo sequence space */
-static bool seq_no_lt_le(uint32_t a, uint32_t b, uint32_t c)
-{
-	if (a <= c) {
-		return (a < b) && (b <= c);
-	} else {
-		return (b <= c) || (a < b);
-	}
-}
-
-/** Determine wheter ack is acceptable (new acknowledgement) */
-bool seq_no_ack_acceptable(tcp_conn_t *conn, uint32_t seg_ack)
-{
-	/* SND.UNA < SEG.ACK <= SND.NXT */
-	return seq_no_lt_le(conn->snd_una, seg_ack, conn->snd_nxt);
-}
-
-/** Determine wheter ack is duplicate.
- *
- * ACK is duplicate if it refers to a sequence number that has
- * aleady been acked (SEG.ACK <= SND.UNA).
- */
-bool seq_no_ack_duplicate(tcp_conn_t *conn, uint32_t seg_ack)
-{
-	uint32_t diff;
-
-	/*
-	 * There does not seem to be a three-point comparison
-	 * equivalent of SEG.ACK < SND.UNA. Thus we do it
-	 * on a best-effort basis, based on the difference.
-	 * [-2^31, 0) means less-than, 0 means equal, [0, 2^31)
-	 * means greater-than. Less-than or equal means duplicate.
-	 */
-	diff = seg_ack - conn->snd_una;
-	return diff == 0 || (diff & (0x1 << 31)) != 0;
-}
-
-/** Determine if sequence number is in receive window. */
-bool seq_no_in_rcv_wnd(tcp_conn_t *conn, uint32_t sn)
-{
-	return seq_no_le_lt(conn->rcv_nxt, sn, conn->rcv_nxt + conn->rcv_wnd);
-}
-
-/** Determine segment has new window update.
- *
- * Window update is new if either SND.WL1 < SEG.SEQ or
- * (SND.WL1 = SEG.SEQ and SND.WL2 <= SEG.ACK).
- */
-bool seq_no_new_wnd_update(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	bool n_seq, n_ack;
-
-	assert(seq_no_segment_acceptable(conn, seg));
-
-	/*
-	 * We make use of the fact that the peer should not ACK anything
-	 * beyond our send window (we surely haven't sent that yet)
-	 * as we should have filtered those acks out.
-	 * We use SND.UNA+SND.WND as the third point of comparison.
-	 */
-
-	n_seq = seq_no_lt_le(conn->snd_wl1, seg->seq,
-	    conn->snd_una + conn->snd_wnd);
-
-	n_ack = conn->snd_wl1 == seg->seq &&
-	    seq_no_le_lt(conn->snd_wl2, seg->ack,
-	    conn->snd_una + conn->snd_wnd + 1);
-
-	return n_seq || n_ack;
-}
-
-/** Determine if segment is ready for processing.
- *
- * Assuming segment is acceptable, a segment is ready if it intersects
- * RCV.NXT, that is we can process it immediately.
- */
-bool seq_no_segment_ready(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	assert(seq_no_segment_acceptable(conn, seg));
-
-	return seq_no_le_lt(seg->seq, conn->rcv_nxt, seg->seq + seg->len + 1);
-}
-
-/** Determine whether segment is fully acked */
-bool seq_no_segment_acked(tcp_conn_t *conn, tcp_segment_t *seg, uint32_t ack)
-{
-	assert(seg->len > 0);
-	return seq_no_lt_le(seg->seq, seg->seq + seg->len, ack);
-}
-
-/** Determine whether initial SYN is acked */
-bool seq_no_syn_acked(tcp_conn_t *conn)
-{
-	return seq_no_lt_le(conn->iss, conn->snd_una, conn->snd_nxt);
-}
-
-/** Determine whether segment overlaps the receive window */
-bool seq_no_segment_acceptable(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	bool b_in, e_in;
-
-	b_in = seq_no_le_lt(conn->rcv_nxt, seg->seq, conn->rcv_nxt
-	    + conn->rcv_wnd);
-
-	e_in = seq_no_le_lt(conn->rcv_nxt, seg->seq + seg->len - 1,
-	    conn->rcv_nxt + conn->rcv_wnd);
-
-	if (seg->len == 0 && conn->rcv_wnd == 0) {
-		return seg->seq == conn->rcv_nxt;
-	} else if (seg->len == 0 && conn->rcv_wnd != 0) {
-		return b_in;
-	} else if (seg->len > 0 && conn->rcv_wnd == 0) {
-		return false;
-	} else {
-		return b_in || e_in;
-	}
-}
-
-/** Determine size that control bits occupy in sequence space. */
-uint32_t seq_no_control_len(tcp_control_t ctrl)
-{
-	uint32_t len = 0;
-
-	if ((ctrl & CTL_SYN) != 0)
-		++len;
-
-	if ((ctrl & CTL_FIN) != 0)
-		++len;
-
-	return len;
-}
-
-/** Calculate the amount of trim needed to fit segment in receive window. */
-void seq_no_seg_trim_calc(tcp_conn_t *conn, tcp_segment_t *seg,
-    uint32_t *left, uint32_t *right)
-{
-	assert(seq_no_segment_acceptable(conn, seg));
-
-	/*
-	 * If RCV.NXT is between SEG.SEQ and RCV.NXT+RCV.WND, then
-	 * left trim amount is positive
-	 */
-	if (seq_no_lt_le(seg->seq, conn->rcv_nxt,
-	    conn->rcv_nxt + conn->rcv_wnd)) {
-		*left = conn->rcv_nxt - seg->seq;
-	} else {
-		*left = 0;
-	}
-
-	/*
-	 * If SEG.SEQ+SEG.LEN is between SEG.SEQ and RCV.NXT+RCV.WND,
-	 * then right trim is zero.
-	 */
-	if (seq_no_lt_le(seg->seq - 1, seg->seq + seg->len,
-	    conn->rcv_nxt + conn->rcv_wnd)) {
-		*right = 0;
-	} else {
-		*right = (seg->seq + seg->len) -
-		    (conn->rcv_nxt + conn->rcv_wnd);
-	}
-}
-
-/** Segment order comparison.
- *
- * Compare sequence order of two acceptable segments.
- *
- * @param conn		Connection
- * @param sa		Segment A
- * @param sb		Segment B
- *
- * @return		-1, 0, 1, resp. if A < B, A == B, A > B in terms
- *			of sequence order of the beginning of the segment.
- */
-int seq_no_seg_cmp(tcp_conn_t *conn, tcp_segment_t *sa, tcp_segment_t *sb)
-{
-	assert(seq_no_segment_acceptable(conn, sa));
-	assert(seq_no_segment_acceptable(conn, sb));
-
-	if (seq_no_lt_le(sa->seq, sb->seq, conn->rcv_nxt + conn->rcv_wnd))
-		return -1;
-
-	if (seq_no_lt_le(sb->seq, sa->seq, conn->rcv_nxt + conn->rcv_wnd))
-		return +1;
-
-	assert(sa->seq == sb->seq);
-	return 0;
-}
-
-/**
- * @}
- */
Index: pace/srv/net/tl/tcp/seq_no.h
===================================================================
--- uspace/srv/net/tl/tcp/seq_no.h	(revision bf31e3f1ebd6e88e0c8425f109e42ccd92b6c9b3)
+++ 	(revision )
@@ -1,58 +1,0 @@
-/*
- * Copyright (c) 2011 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup tcp
- * @{
- */
-/** @file Sequence number computations
- */
-
-#ifndef SEQ_NO_H
-#define SEQ_NO_H
-
-#include <sys/types.h>
-#include "tcp_type.h"
-
-extern bool seq_no_ack_acceptable(tcp_conn_t *, uint32_t);
-extern bool seq_no_ack_duplicate(tcp_conn_t *, uint32_t);
-extern bool seq_no_in_rcv_wnd(tcp_conn_t *, uint32_t);
-extern bool seq_no_new_wnd_update(tcp_conn_t *, tcp_segment_t *);
-extern bool seq_no_segment_acked(tcp_conn_t *, tcp_segment_t *, uint32_t);
-extern bool seq_no_syn_acked(tcp_conn_t *);
-extern bool seq_no_segment_ready(tcp_conn_t *, tcp_segment_t *);
-extern bool seq_no_segment_acceptable(tcp_conn_t *, tcp_segment_t *);
-extern void seq_no_seg_trim_calc(tcp_conn_t *, tcp_segment_t *, uint32_t *,
-    uint32_t *);
-extern int seq_no_seg_cmp(tcp_conn_t *, tcp_segment_t *, tcp_segment_t *);
-
-extern uint32_t seq_no_control_len(tcp_control_t);
-
-#endif
-
-/** @}
- */
Index: pace/srv/net/tl/tcp/sock.c
===================================================================
--- uspace/srv/net/tl/tcp/sock.c	(revision bf31e3f1ebd6e88e0c8425f109e42ccd92b6c9b3)
+++ 	(revision )
@@ -1,832 +1,0 @@
-/*
- * Copyright (c) 2008 Lukas Mejdrech
- * Copyright (c) 2011 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup tcp
- * @{
- */
-
-/**
- * @file Socket provider
- */
-
-#include <async.h>
-#include <errno.h>
-#include <io/log.h>
-#include <ip_client.h>
-#include <ipc/socket.h>
-#include <net/modules.h>
-#include <net/socket.h>
-
-#include "sock.h"
-#include "std.h"
-#include "tcp.h"
-#include "tcp_type.h"
-#include "ucall.h"
-
-#define FRAGMENT_SIZE 1024
-
-#define MAX_BACKLOG 128
-
-/** Free ports pool start. */
-#define TCP_FREE_PORTS_START		1025
-
-/** Free ports pool end. */
-#define TCP_FREE_PORTS_END		65535
-
-static int last_used_port = TCP_FREE_PORTS_START - 1;
-static socket_ports_t gsock;
-
-static void tcp_sock_cstate_cb(tcp_conn_t *conn, void *arg);
-
-void tcp_sock_init(void)
-{
-	socket_ports_initialize(&gsock);
-}
-
-static void tcp_free_sock_data(socket_core_t *sock_core)
-{
-	tcp_sockdata_t *socket;
-
-	socket = (tcp_sockdata_t *)sock_core->specific_data;
-	(void)socket;
-}
-
-static void tcp_sock_notify_data(socket_core_t *sock_core)
-{
-	log_msg(LVL_DEBUG, "tcp_sock_notify_data(%d)", sock_core->socket_id);
-	async_exch_t *exch = async_exchange_begin(sock_core->sess);
-	async_msg_5(exch, NET_SOCKET_RECEIVED, (sysarg_t)sock_core->socket_id,
-	    FRAGMENT_SIZE, 0, 0, 1);
-	async_exchange_end(exch);
-}
-
-static void tcp_sock_notify_aconn(socket_core_t *lsock_core)
-{
-	log_msg(LVL_DEBUG, "tcp_sock_notify_aconn(%d)", lsock_core->socket_id);
-	async_exch_t *exch = async_exchange_begin(lsock_core->sess);
-	async_msg_5(exch, NET_SOCKET_ACCEPTED, (sysarg_t)lsock_core->socket_id,
-	    FRAGMENT_SIZE, 0, 0, 0);
-	async_exchange_end(exch);
-}
-
-static void tcp_sock_socket(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
-{
-	tcp_sockdata_t *sock;
-	socket_core_t *sock_core;
-	int sock_id;
-	int rc;
-	ipc_call_t answer;
-
-	log_msg(LVL_DEBUG, "tcp_sock_socket()");
-	sock = calloc(sizeof(tcp_sockdata_t), 1);
-	if (sock == NULL) {
-		async_answer_0(callid, ENOMEM);
-		return;
-	}
-
-	fibril_mutex_initialize(&sock->lock);
-	sock->client = client;
-	sock->laddr.ipv4 = TCP_IPV4_ANY;
-	sock->lconn = NULL;
-	sock->backlog = 0;
-	list_initialize(&sock->ready);
-
-	sock_id = SOCKET_GET_SOCKET_ID(call);
-	rc = socket_create(&client->sockets, client->sess, sock, &sock_id);
-	if (rc != EOK) {
-		async_answer_0(callid, rc);
-		return;
-	}
-
-	sock_core = socket_cores_find(&client->sockets, sock_id);
-	assert(sock_core != NULL);
-	sock->sock_core = sock_core;
-
-	refresh_answer(&answer, NULL);
-	SOCKET_SET_SOCKET_ID(answer, sock_id);
-
-	SOCKET_SET_DATA_FRAGMENT_SIZE(answer, FRAGMENT_SIZE);
-	SOCKET_SET_HEADER_SIZE(answer, sizeof(tcp_header_t));
-	answer_call(callid, EOK, &answer, 3);
-}
-
-static void tcp_sock_bind(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
-{
-	int rc;
-	struct sockaddr *addr;
-	size_t addr_len;
-	socket_core_t *sock_core;
-	tcp_sockdata_t *socket;
-
-	log_msg(LVL_DEBUG, "tcp_sock_bind()");
-	log_msg(LVL_DEBUG, " - async_data_write_accept");
-	rc = async_data_write_accept((void **) &addr, false, 0, 0, 0, &addr_len);
-	if (rc != EOK) {
-		async_answer_0(callid, rc);
-		return;
-	}
-
-	log_msg(LVL_DEBUG, " - call socket_bind");
-	rc = socket_bind(&client->sockets, &gsock, SOCKET_GET_SOCKET_ID(call),
-	    addr, addr_len, TCP_FREE_PORTS_START, TCP_FREE_PORTS_END,
-	    last_used_port);
-	if (rc != EOK) {
-		async_answer_0(callid, rc);
-		return;
-	}
-
-	log_msg(LVL_DEBUG, " - call socket_cores_find");
-	sock_core = socket_cores_find(&client->sockets, SOCKET_GET_SOCKET_ID(call));
-	if (sock_core != NULL) {
-		socket = (tcp_sockdata_t *)sock_core->specific_data;
-		/* XXX Anything to do? */
-		(void) socket;
-	}
-
-	log_msg(LVL_DEBUG, " - success");
-	async_answer_0(callid, EOK);
-}
-
-static void tcp_sock_listen(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
-{
-	int socket_id;
-	int backlog;
-	socket_core_t *sock_core;
-	tcp_sockdata_t *socket;
-	tcp_error_t trc;
-	tcp_sock_t lsocket;
-	tcp_sock_t fsocket;
-	tcp_conn_t *conn;
-	tcp_sock_lconn_t *lconn;
-	int i;
-
-	log_msg(LVL_DEBUG, "tcp_sock_listen()");
-
-	socket_id = SOCKET_GET_SOCKET_ID(call);
-	backlog = SOCKET_GET_BACKLOG(call);
-
-	if (backlog < 0) {
-		async_answer_0(callid, EINVAL);
-		return;
-	}
-
-	if (backlog > MAX_BACKLOG)
-		backlog = MAX_BACKLOG;
-
-	sock_core = socket_cores_find(&client->sockets, socket_id);
-	if (sock_core == NULL) {
-		async_answer_0(callid, ENOTSOCK);
-		return;
-	}
-
-	socket = (tcp_sockdata_t *)sock_core->specific_data;
-
-	/*
-	 * Prepare @c backlog listening connections.
-	 */
-	fibril_mutex_lock(&socket->lock);
-
-	socket->backlog = backlog;
-	socket->lconn = calloc(sizeof(tcp_conn_t *), backlog);
-	if (socket->lconn == NULL) {
-		fibril_mutex_unlock(&socket->lock);
-		async_answer_0(callid, ENOMEM);
-		return;
-	}
-
-	log_msg(LVL_DEBUG, " - open connections");
-
-	lsocket.addr.ipv4 = TCP_IPV4_ANY;
-	lsocket.port = sock_core->port;
-	fsocket.addr.ipv4 = TCP_IPV4_ANY;
-	fsocket.port = TCP_PORT_ANY;
-
-	for (i = 0; i < backlog; i++) {
-
-		lconn = calloc(sizeof(tcp_sock_lconn_t), 1);
-		if (lconn == NULL) {
-			/* XXX Clean up */
-			fibril_mutex_unlock(&socket->lock);
-			async_answer_0(callid, ENOMEM);
-			return;
-		}
-
-		trc = tcp_uc_open(&lsocket, &fsocket, ap_passive,
-		    tcp_open_nonblock, &conn);
-		if (conn == NULL) {
-			/* XXX Clean up */
-			fibril_mutex_unlock(&socket->lock);
-			async_answer_0(callid, ENOMEM);
-			return;
-		}
-
-		tcp_uc_set_cstate_cb(conn, tcp_sock_cstate_cb, lconn);
-
-		assert(trc == TCP_EOK);
-		conn->name = (char *)"S";
-
-		lconn->conn = conn;
-		lconn->socket = socket;
-		link_initialize(&lconn->ready_list);
-		socket->lconn[i] = lconn;
-	}
-
-	fibril_mutex_unlock(&socket->lock);
-	async_answer_0(callid, EOK);
-}
-
-static void tcp_sock_connect(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
-{
-	int rc;
-	struct sockaddr_in *addr;
-	int socket_id;
-	size_t addr_len;
-	socket_core_t *sock_core;
-	tcp_sockdata_t *socket;
-	tcp_error_t trc;
-	tcp_sock_t lsocket;
-	tcp_sock_t fsocket;
-	nic_device_id_t dev_id;
-	tcp_phdr_t *phdr;
-	size_t phdr_len;
-
-	log_msg(LVL_DEBUG, "tcp_sock_connect()");
-
-	rc = async_data_write_accept((void **) &addr, false, 0, 0, 0, &addr_len);
-	if (rc != EOK || addr_len != sizeof(struct sockaddr_in)) {
-		async_answer_0(callid, rc);
-		return;
-	}
-
-	socket_id = SOCKET_GET_SOCKET_ID(call);
-
-	sock_core = socket_cores_find(&client->sockets, socket_id);
-	if (sock_core == NULL) {
-		async_answer_0(callid, ENOTSOCK);
-		return;
-	}
-
-	socket = (tcp_sockdata_t *)sock_core->specific_data;
-	if (sock_core->port <= 0) {
-		rc = socket_bind_free_port(&gsock, sock_core,
-		    TCP_FREE_PORTS_START, TCP_FREE_PORTS_END,
-		    last_used_port);
-		if (rc != EOK) {
-			async_answer_0(callid, rc);
-			return;
-		}
-
-		last_used_port = sock_core->port;
-	}
-
-	fibril_mutex_lock(&socket->lock);
-
-	if (socket->laddr.ipv4 == TCP_IPV4_ANY) {
-		/* Find route to determine local IP address. */
-		rc = ip_get_route_req(ip_sess, IPPROTO_TCP,
-		    (struct sockaddr *)addr, sizeof(*addr), &dev_id,
-		    (void **)&phdr, &phdr_len);
-		if (rc != EOK) {
-			fibril_mutex_unlock(&socket->lock);
-			async_answer_0(callid, rc);
-			log_msg(LVL_DEBUG, "tcp_transmit_connect: Failed to find route.");
-			return;
-		}
-
-		socket->laddr.ipv4 = uint32_t_be2host(phdr->src_addr);
-		log_msg(LVL_DEBUG, "Local IP address is %x", socket->laddr.ipv4);
-		free(phdr);
-	}
-
-	lsocket.addr.ipv4 = socket->laddr.ipv4;
-	lsocket.port = sock_core->port;
-	fsocket.addr.ipv4 = uint32_t_be2host(addr->sin_addr.s_addr);
-	fsocket.port = uint16_t_be2host(addr->sin_port);
-
-	trc = tcp_uc_open(&lsocket, &fsocket, ap_active, 0, &socket->conn);
-
-	if (socket->conn != NULL)
-		socket->conn->name = (char *)"C";
-
-	fibril_mutex_unlock(&socket->lock);
-
-	switch (trc) {
-	case TCP_EOK:
-		rc = EOK;
-		break;
-	case TCP_ERESET:
-		rc = ECONNREFUSED;
-		break;
-	default:
-		assert(false);
-	}
-
-	async_answer_0(callid, rc);
-
-	/* Push one fragment notification to client's queue */
-	tcp_sock_notify_data(sock_core);
-	log_msg(LVL_DEBUG, "tcp_sock_connect(): notify conn\n");
-}
-
-static void tcp_sock_accept(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
-{
-	ipc_call_t answer;
-	int socket_id;
-	int asock_id;
-	socket_core_t *sock_core;
-	socket_core_t *asock_core;
-	tcp_sockdata_t *socket;
-	tcp_sockdata_t *asocket;
-	tcp_error_t trc;
-	tcp_sock_t lsocket;
-	tcp_sock_t fsocket;
-	tcp_conn_t *conn;
-	tcp_conn_t *rconn;
-	tcp_sock_lconn_t *lconn;
-	int rc;
-
-	log_msg(LVL_DEBUG, "tcp_sock_accept()");
-
-	socket_id = SOCKET_GET_SOCKET_ID(call);
-	asock_id = SOCKET_GET_NEW_SOCKET_ID(call);
-
-	sock_core = socket_cores_find(&client->sockets, socket_id);
-	if (sock_core == NULL) {
-		async_answer_0(callid, ENOTSOCK);
-		return;
-	}
-
-	socket = (tcp_sockdata_t *)sock_core->specific_data;
-	fibril_mutex_lock(&socket->lock);
-
-	log_msg(LVL_DEBUG, " - verify socket->conn");
-	if (socket->conn != NULL) {
-		fibril_mutex_unlock(&socket->lock);
-		async_answer_0(callid, EINVAL);
-		return;
-	}
-
-	if (list_empty(&socket->ready)) {
-		fibril_mutex_unlock(&socket->lock);
-		async_answer_0(callid, ENOENT);
-		return;
-	}
-
-	lconn = list_get_instance(list_first(&socket->ready),
-	    tcp_sock_lconn_t, ready_list);
-	list_remove(&lconn->ready_list);
-
-	conn = lconn->conn;
-	tcp_uc_set_cstate_cb(conn, NULL, NULL);
-
-	/* Replenish listening connection */
-
-	lsocket.addr.ipv4 = TCP_IPV4_ANY;
-	lsocket.port = sock_core->port;
-	fsocket.addr.ipv4 = TCP_IPV4_ANY;
-	fsocket.port = TCP_PORT_ANY;
-
-	trc = tcp_uc_open(&lsocket, &fsocket, ap_passive, tcp_open_nonblock,
-	    &rconn);
-	if (rconn == NULL) {
-		/* XXX Clean up */
-		fibril_mutex_unlock(&socket->lock);
-		async_answer_0(callid, ENOMEM);
-		return;
-	}
-
-	tcp_uc_set_cstate_cb(rconn, tcp_sock_cstate_cb, lconn);
-
-	assert(trc == TCP_EOK);
-	rconn->name = (char *)"S";
-
-	lconn->conn = rconn;
-
-	/* Allocate socket for accepted connection */
-
-	log_msg(LVL_DEBUG, "tcp_sock_accept(): allocate asocket\n");
-	asocket = calloc(sizeof(tcp_sockdata_t), 1);
-	if (asocket == NULL) {
-		fibril_mutex_unlock(&socket->lock);
-		async_answer_0(callid, ENOMEM);
-		return;
-	}
-
-	fibril_mutex_initialize(&asocket->lock);
-	asocket->client = client;
-	asocket->conn = conn;
-	log_msg(LVL_DEBUG, "tcp_sock_accept():create asocket\n");
-
-	rc = socket_create(&client->sockets, client->sess, asocket, &asock_id);
-	if (rc != EOK) {
-		fibril_mutex_unlock(&socket->lock);
-		async_answer_0(callid, rc);
-		return;
-	}
-	log_msg(LVL_DEBUG, "tcp_sock_accept(): find acore\n");
-
-	asock_core = socket_cores_find(&client->sockets, asock_id);
-	assert(asock_core != NULL);
-
-	refresh_answer(&answer, NULL);
-
-	SOCKET_SET_DATA_FRAGMENT_SIZE(answer, FRAGMENT_SIZE);
-	SOCKET_SET_SOCKET_ID(answer, asock_id);
-	SOCKET_SET_ADDRESS_LENGTH(answer, sizeof(struct sockaddr_in));
-
-	answer_call(callid, asock_core->socket_id, &answer, 3);
-
-	/* Push one fragment notification to client's queue */
-	log_msg(LVL_DEBUG, "tcp_sock_accept(): notify data\n");
-	tcp_sock_notify_data(asock_core);
-	fibril_mutex_unlock(&socket->lock);
-}
-
-static void tcp_sock_send(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
-{
-	int socket_id;
-	int fragments;
-	int index;
-	socket_core_t *sock_core;
-	tcp_sockdata_t *socket;
-	ipc_call_t answer;
-	ipc_callid_t wcallid;
-	size_t length;
-	uint8_t buffer[FRAGMENT_SIZE];
-	tcp_error_t trc;
-	int rc;
-
-	log_msg(LVL_DEBUG, "tcp_sock_send()");
-	socket_id = SOCKET_GET_SOCKET_ID(call);
-	fragments = SOCKET_GET_DATA_FRAGMENTS(call);
-	SOCKET_GET_FLAGS(call);
-
-	sock_core = socket_cores_find(&client->sockets, socket_id);
-	if (sock_core == NULL) {
-		async_answer_0(callid, ENOTSOCK);
-		return;
-	}
-
-	socket = (tcp_sockdata_t *)sock_core->specific_data;
-	fibril_mutex_lock(&socket->lock);
-
-	if (socket->conn == NULL) {
-		fibril_mutex_unlock(&socket->lock);
-		async_answer_0(callid, ENOTCONN);
-		return;
-	}
-
-	for (index = 0; index < fragments; index++) {
-		if (!async_data_write_receive(&wcallid, &length)) {
-			fibril_mutex_unlock(&socket->lock);
-			async_answer_0(callid, EINVAL);
-			return;
-		}
-
-		if (length > FRAGMENT_SIZE)
-			length = FRAGMENT_SIZE;
-
-		rc = async_data_write_finalize(wcallid, buffer, length);
-		if (rc != EOK) {
-			fibril_mutex_unlock(&socket->lock);
-			async_answer_0(callid, rc);
-			return;
-		}
-
-		trc = tcp_uc_send(socket->conn, buffer, length, 0);
-
-		switch (trc) {
-		case TCP_EOK:
-			rc = EOK;
-			break;
-		case TCP_ENOTEXIST:
-			rc = ENOTCONN;
-			break;
-		case TCP_ECLOSING:
-			rc = ENOTCONN;
-			break;
-		case TCP_ERESET:
-			rc = ECONNABORTED;
-			break;
-		default:
-			assert(false);
-		}
-
-		if (rc != EOK) {
-			fibril_mutex_unlock(&socket->lock);
-			async_answer_0(callid, rc);
-			return;
-		}
-	}
-
-	refresh_answer(&answer, NULL);
-	SOCKET_SET_DATA_FRAGMENT_SIZE(answer, FRAGMENT_SIZE);
-	answer_call(callid, EOK, &answer, 2);
-	fibril_mutex_unlock(&socket->lock);
-}
-
-static void tcp_sock_sendto(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
-{
-	log_msg(LVL_DEBUG, "tcp_sock_sendto()");
-	async_answer_0(callid, ENOTSUP);
-}
-
-static void tcp_sock_recvfrom(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
-{
-	int socket_id;
-	int flags;
-	size_t addr_length, length;
-	socket_core_t *sock_core;
-	tcp_sockdata_t *socket;
-	ipc_call_t answer;
-	ipc_callid_t rcallid;
-	uint8_t buffer[FRAGMENT_SIZE];
-	size_t data_len;
-	xflags_t xflags;
-	tcp_error_t trc;
-	struct sockaddr_in addr;
-	tcp_sock_t *rsock;
-	int rc;
-
-	log_msg(LVL_DEBUG, "%p: tcp_sock_recv[from]()", client);
-
-	socket_id = SOCKET_GET_SOCKET_ID(call);
-	flags = SOCKET_GET_FLAGS(call);
-
-	sock_core = socket_cores_find(&client->sockets, socket_id);
-	if (sock_core == NULL) {
-		async_answer_0(callid, ENOTSOCK);
-		return;
-	}
-
-	socket = (tcp_sockdata_t *)sock_core->specific_data;
-	fibril_mutex_lock(&socket->lock);
-
-	if (socket->conn == NULL) {
-		fibril_mutex_unlock(&socket->lock);
-		async_answer_0(callid, ENOTCONN);
-		return;
-	}
-
-	(void)flags;
-
-	trc = tcp_uc_receive(socket->conn, buffer, FRAGMENT_SIZE, &data_len,
-	    &xflags);
-	log_msg(LVL_DEBUG, "**** tcp_uc_receive done");
-
-	switch (trc) {
-	case TCP_EOK:
-		rc = EOK;
-		break;
-	case TCP_ENOTEXIST:
-	case TCP_ECLOSING:
-		rc = ENOTCONN;
-		break;
-	case TCP_ERESET:
-		rc = ECONNABORTED;
-		break;
-	default:
-		assert(false);
-	}
-
-	log_msg(LVL_DEBUG, "**** tcp_uc_receive -> %d", rc);
-	if (rc != EOK) {
-		fibril_mutex_unlock(&socket->lock);
-		async_answer_0(callid, rc);
-		return;
-	}
-
-	if (IPC_GET_IMETHOD(call) == NET_SOCKET_RECVFROM) {
-		/* Fill addr */
-		rsock = &socket->conn->ident.foreign;
-		addr.sin_family = AF_INET;
-		addr.sin_addr.s_addr = host2uint32_t_be(rsock->addr.ipv4);
-		addr.sin_port = host2uint16_t_be(rsock->port);
-
-		log_msg(LVL_DEBUG, "addr read receive");
-		if (!async_data_read_receive(&rcallid, &addr_length)) {
-			fibril_mutex_unlock(&socket->lock);
-			async_answer_0(callid, EINVAL);
-			return;
-		}
-
-		if (addr_length > sizeof(addr))
-			addr_length = sizeof(addr);
-
-		log_msg(LVL_DEBUG, "addr read finalize");
-		rc = async_data_read_finalize(rcallid, &addr, addr_length);
-		if (rc != EOK) {
-			fibril_mutex_unlock(&socket->lock);
-			async_answer_0(callid, EINVAL);
-			return;
-		}
-	}
-
-	log_msg(LVL_DEBUG, "data read receive");
-	if (!async_data_read_receive(&rcallid, &length)) {
-		fibril_mutex_unlock(&socket->lock);
-		async_answer_0(callid, EINVAL);
-		return;
-	}
-
-	if (length > data_len)
-		length = data_len;
-
-	log_msg(LVL_DEBUG, "data read finalize");
-	rc = async_data_read_finalize(rcallid, buffer, length);
-
-	if (length < data_len && rc == EOK)
-		rc = EOVERFLOW;
-
-	SOCKET_SET_READ_DATA_LENGTH(answer, length);
-	answer_call(callid, EOK, &answer, 1);
-
-	/* Push one fragment notification to client's queue */
-	tcp_sock_notify_data(sock_core);
-	fibril_mutex_unlock(&socket->lock);
-}
-
-static void tcp_sock_close(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
-{
-	int socket_id;
-	socket_core_t *sock_core;
-	tcp_sockdata_t *socket;
-	tcp_error_t trc;
-	int rc;
-	uint8_t buffer[FRAGMENT_SIZE];
-	size_t data_len;
-	xflags_t xflags;
-
-	log_msg(LVL_DEBUG, "tcp_sock_close()");
-	socket_id = SOCKET_GET_SOCKET_ID(call);
-
-	sock_core = socket_cores_find(&client->sockets, socket_id);
-	if (sock_core == NULL) {
-		async_answer_0(callid, ENOTSOCK);
-		return;
-	}
-
-	socket = (tcp_sockdata_t *)sock_core->specific_data;
-	fibril_mutex_lock(&socket->lock);
-
-	if (socket->conn != NULL) {
-		trc = tcp_uc_close(socket->conn);
-		if (trc != TCP_EOK && trc != TCP_ENOTEXIST) {
-			fibril_mutex_unlock(&socket->lock);
-			async_answer_0(callid, EBADF);
-			return;
-		}
-
-		/* Drain incoming data. This should really be done in the background. */
-		do {
-			trc = tcp_uc_receive(socket->conn, buffer,
-			    FRAGMENT_SIZE, &data_len, &xflags);
-		} while (trc == TCP_EOK);
-
-		tcp_uc_delete(socket->conn);
-	}
-
-	rc = socket_destroy(net_sess, socket_id, &client->sockets, &gsock,
-	    tcp_free_sock_data);
-	if (rc != EOK) {
-		fibril_mutex_unlock(&socket->lock);
-		async_answer_0(callid, rc);
-		return;
-	}
-
-	fibril_mutex_unlock(&socket->lock);
-	async_answer_0(callid, EOK);
-}
-
-static void tcp_sock_getsockopt(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
-{
-	log_msg(LVL_DEBUG, "tcp_sock_getsockopt()");
-	async_answer_0(callid, ENOTSUP);
-}
-
-static void tcp_sock_setsockopt(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
-{
-	log_msg(LVL_DEBUG, "tcp_sock_setsockopt()");
-	async_answer_0(callid, ENOTSUP);
-}
-
-/** Called when connection state changes. */
-static void tcp_sock_cstate_cb(tcp_conn_t *conn, void *arg)
-{
-	tcp_conn_status_t cstatus;
-	tcp_sock_lconn_t *lconn = (tcp_sock_lconn_t *)arg;
-	tcp_sockdata_t *socket = lconn->socket;
-
-	log_msg(LVL_DEBUG, "tcp_sock_cstate_cb()");
-	fibril_mutex_lock(&socket->lock);
-	assert(conn == lconn->conn);
-
-	tcp_uc_status(conn, &cstatus);
-	if (cstatus.cstate != st_established) {
-		fibril_mutex_unlock(&socket->lock);
-		return;
-	}
-
-	assert_link_not_used(&lconn->ready_list);
-	list_append(&lconn->ready_list, &socket->ready);
-
-	log_msg(LVL_DEBUG, "tcp_sock_cstate_cb(): notify accept");
-
-	/* Push one accept notification to client's queue */
-	tcp_sock_notify_aconn(socket->sock_core);
-	fibril_mutex_unlock(&socket->lock);
-}
-
-int tcp_sock_connection(async_sess_t *sess, ipc_callid_t iid, ipc_call_t icall)
-{
-	ipc_callid_t callid;
-	ipc_call_t call;
-	tcp_client_t client;
-
-	/* Accept the connection */
-	async_answer_0(iid, EOK);
-
-	client.sess = sess;
-	socket_cores_initialize(&client.sockets);
-
-	while (true) {
-		callid = async_get_call(&call);
-		if (!IPC_GET_IMETHOD(call))
-			break;
-
-		log_msg(LVL_DEBUG, "tcp_sock_connection: METHOD=%d\n",
-		    (int)IPC_GET_IMETHOD(call));
-
-		switch (IPC_GET_IMETHOD(call)) {
-		case NET_SOCKET:
-			tcp_sock_socket(&client, callid, call);
-			break;
-		case NET_SOCKET_BIND:
-			tcp_sock_bind(&client, callid, call);
-			break;
-		case NET_SOCKET_LISTEN:
-			tcp_sock_listen(&client, callid, call);
-			break;
-		case NET_SOCKET_CONNECT:
-			tcp_sock_connect(&client, callid, call);
-			break;
-		case NET_SOCKET_ACCEPT:
-			tcp_sock_accept(&client, callid, call);
-			break;
-		case NET_SOCKET_SEND:
-			tcp_sock_send(&client, callid, call);
-			break;
-		case NET_SOCKET_SENDTO:
-			tcp_sock_sendto(&client, callid, call);
-			break;
-		case NET_SOCKET_RECV:
-		case NET_SOCKET_RECVFROM:
-			tcp_sock_recvfrom(&client, callid, call);
-			break;
-		case NET_SOCKET_CLOSE:
-			tcp_sock_close(&client, callid, call);
-			break;
-		case NET_SOCKET_GETSOCKOPT:
-			tcp_sock_getsockopt(&client, callid, call);
-			break;
-		case NET_SOCKET_SETSOCKOPT:
-			tcp_sock_setsockopt(&client, callid, call);
-			break;
-		default:
-			async_answer_0(callid, ENOTSUP);
-			break;
-		}
-	}
-
-	return EOK;
-}
-
-/**
- * @}
- */
Index: pace/srv/net/tl/tcp/sock.h
===================================================================
--- uspace/srv/net/tl/tcp/sock.h	(revision bf31e3f1ebd6e88e0c8425f109e42ccd92b6c9b3)
+++ 	(revision )
@@ -1,46 +1,0 @@
-/*
- * Copyright (c) 2011 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup tcp
- * @{
- */
-/** @file Socket provider
- */
-
-#ifndef SOCK_H
-#define SOCK_H
-
-#include <async.h>
-
-extern void tcp_sock_init(void);
-extern int tcp_sock_connection(async_sess_t *, ipc_callid_t, ipc_call_t);
-
-#endif
-
-/** @}
- */
Index: pace/srv/net/tl/tcp/std.h
===================================================================
--- uspace/srv/net/tl/tcp/std.h	(revision bf31e3f1ebd6e88e0c8425f109e42ccd92b6c9b3)
+++ 	(revision )
@@ -1,101 +1,0 @@
-/*
- * Copyright (c) 2011 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup tcp
- * @{
- */
-/** @file TCP header definitions
- *
- * Based on IETF RFC 793
- */
-
-#ifndef STD_H
-#define STD_H
-
-#include <sys/types.h>
-
-/** TCP Header (fixed part) */
-typedef struct {
-	/** Source port */
-	uint16_t src_port;
-	/** Destination port */
-	uint16_t dest_port;
-	/** Sequence number */
-	uint32_t seq;
-	/** Acknowledgement number */
-	uint32_t ack;
-	/** Data Offset, Reserved, Flags */
-	uint16_t doff_flags;
-	/** Window */
-	uint16_t window;
-	/* Checksum */
-	uint16_t checksum;
-	/** Urgent pointer */
-	uint16_t urg_ptr;
-} tcp_header_t;
-
-/** Bits in tcp_header_t.doff_flags */
-enum doff_flags_bits {
-	DF_DATA_OFFSET_h	= 15,
-	DF_DATA_OFFSET_l	= 12,
-	DF_URG			= 5,
-	DF_ACK			= 4,
-	DF_PSH			= 3,
-	DF_RST			= 2,
-	DF_SYN			= 1,
-	DF_FIN			= 0
-};
-
-/** TCP pseudo header */
-typedef struct {
-	/** Source address */
-	uint32_t src_addr;
-	/** Destination address */
-	uint32_t dest_addr;
-	/** Zero */
-	uint8_t zero;
-	/** Protocol */
-	uint8_t protocol;
-	/** TCP length */
-	uint16_t tcp_length;
-} tcp_phdr_t;
-
-/** Option kind */
-enum opt_kind {
-	/** End of option list */
-	OPT_END_LIST		= 0,
-	/** No-operation */
-	OPT_NOP			= 1,
-	/** Maximum segment size */
-	OPT_MAX_SEG_SIZE	= 2
-};
-
-#endif
-
-/** @}
- */
Index: pace/srv/net/tl/tcp/tcp.c
===================================================================
--- uspace/srv/net/tl/tcp/tcp.c	(revision bf31e3f1ebd6e88e0c8425f109e42ccd92b6c9b3)
+++ 	(revision )
@@ -1,446 +1,0 @@
-/*
- * Copyright (c) 2011 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup tcp
- * @{
- */
-
-/**
- * @file TCP (Transmission Control Protocol) network module
- */
-
-#include <async.h>
-#include <bitops.h>
-#include <byteorder.h>
-#include <errno.h>
-#include <io/log.h>
-#include <stdio.h>
-#include <task.h>
-
-#include <icmp_remote.h>
-#include <ip_client.h>
-#include <ip_interface.h>
-#include <ipc/services.h>
-#include <ipc/tl.h>
-#include <tl_common.h>
-#include <tl_skel.h>
-#include <packet_client.h>
-#include <packet_remote.h>
-
-#include "ncsim.h"
-#include "pdu.h"
-#include "rqueue.h"
-#include "sock.h"
-#include "std.h"
-#include "tcp.h"
-#include "test.h"
-
-#define NAME       "tcp"
-
-async_sess_t *net_sess;
-static async_sess_t *icmp_sess;
-async_sess_t *ip_sess;
-packet_dimensions_t pkt_dims;
-
-static void tcp_received_pdu(tcp_pdu_t *pdu);
-
-/* Pull up packets into a single memory block. */
-static int pq_pullup(packet_t *packet, void **data, size_t *dsize)
-{
-	packet_t *npacket;
-	size_t tot_len;
-	int length;
-
-	npacket = packet;
-	tot_len = 0;
-	do {
-		length = packet_get_data_length(packet);
-		if (length <= 0)
-			return EINVAL;
-
-		tot_len += length;
-	} while ((npacket = pq_next(npacket)) != NULL);
-
-	uint8_t *buf;
-	uint8_t *dp;
-
-	buf = calloc(tot_len, 1);
-	if (buf == NULL) {
-		free(buf);
-		return ENOMEM;
-	}
-
-	npacket = packet;
-	dp = buf;
-	do {
-		length = packet_get_data_length(packet);
-		if (length <= 0) {
-			free(buf);
-			return EINVAL;
-		}
-
-		memcpy(dp, packet_get_data(packet), length);
-		dp += length;
-	} while ((npacket = pq_next(npacket)) != NULL);
-
-	*data = buf;
-	*dsize = tot_len;
-	return EOK;
-}
-
-/** Process packet received from network layer. */
-static int tcp_received_msg(nic_device_id_t device_id, packet_t *packet,
-    services_t error)
-{
-	int rc;
-	size_t offset;
-	int length;
-	struct sockaddr_in *src_addr;
-	struct sockaddr_in *dest_addr;
-	size_t addr_len;
-
-	log_msg(LVL_DEBUG, "tcp_received_msg()");
-
-	switch (error) {
-	case SERVICE_NONE:
-		break;
-	case SERVICE_ICMP:
-	default:
-		log_msg(LVL_WARN, "Unsupported service number %u",
-		    (unsigned)error);
-		pq_release_remote(net_sess, packet_get_id(packet));
-		return ENOTSUP;
-	}
-
-	/* Process and trim off IP header */
-	log_msg(LVL_DEBUG, "tcp_received_msg() - IP header");
-
-	rc = ip_client_process_packet(packet, NULL, NULL, NULL, NULL, NULL);
-	if (rc < 0) {
-		log_msg(LVL_WARN, "ip_client_process_packet() failed");
-		pq_release_remote(net_sess, packet_get_id(packet));
-		return rc;
-	}
-
-	offset = (size_t)rc;
-	length = packet_get_data_length(packet);
-
-	if (length < 0 || (size_t)length < offset) {
-		log_msg(LVL_WARN, "length=%d, dropping.", length);
-		pq_release_remote(net_sess, packet_get_id(packet));
-		return EINVAL;
-	}
-
-	addr_len = packet_get_addr(packet, (uint8_t **)&src_addr,
-	    (uint8_t **)&dest_addr);
-	if (addr_len <= 0) {
-		log_msg(LVL_WARN, "Failed to get packet address.");
-		pq_release_remote(net_sess, packet_get_id(packet));
-		return EINVAL;
-	}
-
-	if (addr_len != sizeof(struct sockaddr_in)) {
-		log_msg(LVL_WARN, "Unsupported address size %zu (!= %zu)",
-		    addr_len, sizeof(struct sockaddr_in));
-		pq_release_remote(net_sess, packet_get_id(packet));
-		return EINVAL;
-	}
-
-	rc = packet_trim(packet, offset, 0);
-	if (rc != EOK) {
-		log_msg(LVL_WARN, "Failed to trim packet.");
-		pq_release_remote(net_sess, packet_get_id(packet));
-		return rc;
-	}
-
-	/* Pull up packets into a single memory block, pdu_raw. */
-	log_msg(LVL_DEBUG, "tcp_received_msg() - pull up");
-	uint8_t *pdu_raw;
-	size_t pdu_raw_size = 0;
-
-	pq_pullup(packet, (void **)&pdu_raw, &pdu_raw_size);
-
-	/* Split into header and payload. */
-
-	log_msg(LVL_DEBUG, "tcp_received_msg() - split header/payload");
-
-	tcp_pdu_t *pdu;
-	size_t hdr_size;
-	tcp_header_t *hdr;
-	uint32_t data_offset;
-
-	if (pdu_raw_size < sizeof(tcp_header_t)) {
-		log_msg(LVL_WARN, "pdu_raw_size = %zu < sizeof(tcp_header_t) = %zu",
-		    pdu_raw_size, sizeof(tcp_header_t));
-		pq_release_remote(net_sess, packet_get_id(packet));
-		return EINVAL;
-	}
-
-	hdr = (tcp_header_t *)pdu_raw;
-	data_offset = BIT_RANGE_EXTRACT(uint32_t, DF_DATA_OFFSET_h, DF_DATA_OFFSET_l,
-	    uint16_t_be2host(hdr->doff_flags));
-
-	hdr_size = sizeof(uint32_t) * data_offset;
-
-	if (pdu_raw_size < hdr_size) {
-		log_msg(LVL_WARN, "pdu_raw_size = %zu < hdr_size = %zu",
-		    pdu_raw_size, hdr_size);
-		pq_release_remote(net_sess, packet_get_id(packet));
-		return EINVAL;
-	}
-
-	if (hdr_size < sizeof(tcp_header_t)) {
-		log_msg(LVL_WARN, "hdr_size = %zu < sizeof(tcp_header_t) = %zu",
-		    hdr_size, sizeof(tcp_header_t));
-		pq_release_remote(net_sess, packet_get_id(packet));
-		return EINVAL;
-	}
-
-	log_msg(LVL_DEBUG, "pdu_raw_size=%zu, hdr_size=%zu",
-	    pdu_raw_size, hdr_size);
-	pdu = tcp_pdu_create(pdu_raw, hdr_size, pdu_raw + hdr_size,
-	    pdu_raw_size - hdr_size);
-	if (pdu == NULL) {
-		log_msg(LVL_WARN, "Failed creating PDU. Dropped.");
-		return ENOMEM;
-	}
-
-	free(pdu_raw);
-
-	pdu->src_addr.ipv4 = uint32_t_be2host(src_addr->sin_addr.s_addr);
-	pdu->dest_addr.ipv4 = uint32_t_be2host(dest_addr->sin_addr.s_addr);
-	log_msg(LVL_DEBUG, "src: 0x%08x, dest: 0x%08x",
-	    pdu->src_addr.ipv4, pdu->dest_addr.ipv4);
-
-	tcp_received_pdu(pdu);
-	tcp_pdu_delete(pdu);
-
-	return EOK;
-}
-
-/** Receive packets from network layer. */
-static void tcp_receiver(ipc_callid_t iid, ipc_call_t *icall, void *arg)
-{
-	packet_t *packet;
-	int rc;
-
-	log_msg(LVL_DEBUG, "tcp_receiver()");
-
-	while (true) {
-		switch (IPC_GET_IMETHOD(*icall)) {
-		case NET_TL_RECEIVED:
-			log_msg(LVL_DEBUG, "method = NET_TL_RECEIVED");
-			rc = packet_translate_remote(net_sess, &packet,
-			    IPC_GET_PACKET(*icall));
-			if (rc != EOK) {
-				log_msg(LVL_DEBUG, "Error %d translating packet.", rc);
-				async_answer_0(iid, (sysarg_t)rc);
-				break;
-			}
-			rc = tcp_received_msg(IPC_GET_DEVICE(*icall), packet,
-			    IPC_GET_ERROR(*icall));
-			async_answer_0(iid, (sysarg_t)rc);
-			break;
-		default:
-			log_msg(LVL_DEBUG, "method = %u",
-			    (unsigned)IPC_GET_IMETHOD(*icall));
-			async_answer_0(iid, ENOTSUP);
-			break;
-		}
-
-		iid = async_get_call(icall);
-	}
-}
-
-/** Transmit PDU over network layer. */
-void tcp_transmit_pdu(tcp_pdu_t *pdu)
-{
-	struct sockaddr_in dest;
-	nic_device_id_t dev_id;
-	void *phdr;
-	size_t phdr_len;
-	packet_dimension_t *pkt_dim;
-	int rc;
-	packet_t *packet;
-	void *pkt_data;
-	size_t pdu_size;
-
-	dest.sin_family = AF_INET;
-	dest.sin_port = 0; /* not needed */
-	dest.sin_addr.s_addr = host2uint32_t_be(pdu->dest_addr.ipv4);
-
-	/* Find route. Obtained pseudo-header is not used. */
-	rc = ip_get_route_req(ip_sess, IPPROTO_TCP, (struct sockaddr *)&dest,
-	    sizeof(dest), &dev_id, &phdr, &phdr_len);
-	if (rc != EOK) {
-		log_msg(LVL_DEBUG, "tcp_transmit_pdu: Failed to find route.");
-		return;
-	}
-
-	rc = tl_get_ip_packet_dimension(ip_sess, &pkt_dims, dev_id, &pkt_dim);
-	if (rc != EOK) {
-		log_msg(LVL_DEBUG, "tcp_transmit_pdu: Failed to get dimension.");
-		return;
-	}
-
-	pdu_size = pdu->header_size + pdu->text_size;
-
-	packet = packet_get_4_remote(net_sess, pdu_size, pkt_dim->addr_len,
-	    pkt_dim->prefix, pkt_dim->suffix);
-	if (!packet) {
-		log_msg(LVL_DEBUG, "tcp_transmit_pdu: Failed to get packet.");
-		return;
-	}
-
-	pkt_data = packet_suffix(packet, pdu_size);
-	if (!pkt_data) {
-		log_msg(LVL_DEBUG, "tcp_transmit_pdu: Failed to get pkt_data ptr.");
-		pq_release_remote(net_sess, packet_get_id(packet));
-		return;
-	}
-
-	rc = ip_client_prepare_packet(packet, IPPROTO_TCP, 0, 0, 0, 0);
-	if (rc != EOK) {
-		log_msg(LVL_DEBUG, "tcp_transmit_pdu: Failed to prepare IP packet part.");
-		pq_release_remote(net_sess, packet_get_id(packet));
-		return;
-	}
-
-	rc = packet_set_addr(packet, NULL, (uint8_t *)&dest, sizeof(dest));
-	if (rc != EOK) {
-		log_msg(LVL_DEBUG, "tcp_transmit_pdu: Failed to set packet address.");
-		pq_release_remote(net_sess, packet_get_id(packet));
-		return;
-	}
-
-	/* Copy PDU data to packet */
-	memcpy(pkt_data, pdu->header, pdu->header_size);
-	memcpy((uint8_t *)pkt_data + pdu->header_size, pdu->text,
-	    pdu->text_size);
-
-	/* Transmit packet. XXX Transfers packet ownership to IP? */
-	ip_send_msg(ip_sess, dev_id, packet, SERVICE_TCP, 0);
-}
-
-/** Process received PDU. */
-static void tcp_received_pdu(tcp_pdu_t *pdu)
-{
-	tcp_segment_t *dseg;
-	tcp_sockpair_t rident;
-
-	log_msg(LVL_DEBUG, "tcp_received_pdu()");
-
-	if (tcp_pdu_decode(pdu, &rident, &dseg) != EOK) {
-		log_msg(LVL_WARN, "Not enough memory. PDU dropped.");
-		return;
-	}
-
-	/* Insert decoded segment into rqueue */
-	tcp_rqueue_insert_seg(&rident, dseg);
-}
-
-/* Called from libnet */
-void tl_connection(void)
-{
-	log_msg(LVL_DEBUG, "tl_connection()");
-}
-
-/* Called from libnet */
-int tl_message(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer,
-    size_t *answer_count)
-{
-	async_sess_t *callback;
-
-	log_msg(LVL_DEBUG, "tl_message()");
-
-	*answer_count = 0;
-	callback = async_callback_receive_start(EXCHANGE_SERIALIZE, call);
-	if (callback)
-		return tcp_sock_connection(callback, callid, *call);
-
-	return ENOTSUP;
-}
-
-/* Called from libnet */
-int tl_initialize(async_sess_t *sess)
-{
-	int rc;
-
-	net_sess = sess;
-	icmp_sess = icmp_connect_module();
-
-	log_msg(LVL_DEBUG, "tl_initialize()");
-
-	tcp_sock_init();
-
-	ip_sess = ip_bind_service(SERVICE_IP, IPPROTO_TCP, SERVICE_TCP,
-	    tcp_receiver);
-	if (ip_sess == NULL)
-		return ENOENT;
-
-	rc = packet_dimensions_initialize(&pkt_dims);
-	if (rc != EOK)
-		return rc;
-
-	return EOK;
-}
-
-int main(int argc, char **argv)
-{
-	int rc;
-
-	printf(NAME ": TCP (Transmission Control Protocol) network module\n");
-
-	rc = log_init(NAME, LVL_ERROR);
-	if (rc != EOK) {
-		printf(NAME ": Failed to initialize log.\n");
-		return 1;
-	}
-
-//	printf(NAME ": Accepting connections\n");
-//	task_retval(0);
-
-	tcp_rqueue_init();
-	tcp_rqueue_thread_start();
-
-	tcp_ncsim_init();
-	tcp_ncsim_thread_start();
-
-	if (0) tcp_test();
-/*
-	async_manager();
-*/
-	tl_module_start(SERVICE_TCP);
-
-	/* Not reached */
-	return 0;
-}
-
-/**
- * @}
- */
Index: pace/srv/net/tl/tcp/tcp.h
===================================================================
--- uspace/srv/net/tl/tcp/tcp.h	(revision bf31e3f1ebd6e88e0c8425f109e42ccd92b6c9b3)
+++ 	(revision )
@@ -1,49 +1,0 @@
-/*
- * Copyright (c) 2011 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup tcp
- * @{
- */
-/** @file TCP (Transmission Control Protocol) network module
- */
-
-#ifndef TCP_H
-#define TCP_H
-
-#include <async.h>
-#include <packet_remote.h>
-#include "tcp_type.h"
-
-extern async_sess_t *net_sess;
-extern async_sess_t *ip_sess;
-extern void tcp_transmit_pdu(tcp_pdu_t *);
-
-#endif
-
-/** @}
- */
Index: pace/srv/net/tl/tcp/tcp_type.h
===================================================================
--- uspace/srv/net/tl/tcp/tcp_type.h	(revision bf31e3f1ebd6e88e0c8425f109e42ccd92b6c9b3)
+++ 	(revision )
@@ -1,363 +1,0 @@
-/*
- * Copyright (c) 2011 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup tcp
- * @{
- */
-/** @file TCP type definitions
- */
-
-#ifndef TCP_TYPE_H
-#define TCP_TYPE_H
-
-#include <adt/list.h>
-#include <async.h>
-#include <bool.h>
-#include <fibril_synch.h>
-#include <socket_core.h>
-#include <sys/types.h>
-
-struct tcp_conn;
-
-typedef enum {
-	/** Listen */
-	st_listen,
-	/** Syn-sent */
-	st_syn_sent,
-	/** Syn-received */
-	st_syn_received,
-	/** Established */
-	st_established,
-	/** Fin-wait-1 */
-	st_fin_wait_1,
-	/** Fin-wait-2 */
-	st_fin_wait_2,
-	/** Close-wait */
-	st_close_wait,
-	/** Closing */
-	st_closing,
-	/** Last-ack */
-	st_last_ack,
-	/** Time-wait */
-	st_time_wait,
-	/** Closed */
-	st_closed
-} tcp_cstate_t;
-
-/** Error codes returned by TCP user calls (per the spec). */
-typedef enum {
-	/* OK */
-	TCP_EOK,
-	/* Connection aborted due to user timeout */
-	TCP_EABORTED,
-	/* Connection already exists */
-	TCP_EEXISTS,
-	/* Connection closing */
-	TCP_ECLOSING,
-	/* Connection does not exist */
-	TCP_ENOTEXIST,
-	/* Connection illegal for this process */
-	TCP_EILLEGAL,
-	/* Connection not open */
-	TCP_ENOTOPEN,
-	/* Connection reset */
-	TCP_ERESET,
-	/* Foreign socket unspecified */
-	TCP_EUNSPEC,
-	/* Insufficient resources */
-	TCP_ENORES,
-	/* Precedence not allowed */
-	TCP_EINVPREC,
-	/* Security/compartment not allowed */
-	TCP_EINVCOMP
-} tcp_error_t;
-
-typedef enum {
-	XF_PUSH		= 0x1,
-	XF_URGENT	= 0x2
-} xflags_t;
-
-typedef enum {
-	CTL_SYN		= 0x1,
-	CTL_FIN		= 0x2,
-	CTL_RST		= 0x4,
-	CTL_ACK		= 0x8
-} tcp_control_t;
-
-typedef struct {
-	uint32_t ipv4;
-} netaddr_t;
-
-typedef struct {
-	netaddr_t addr;
-	uint16_t port;
-} tcp_sock_t;
-
-enum netaddr {
-	TCP_IPV4_ANY = 0
-};
-
-enum tcp_port {
-	TCP_PORT_ANY = 0
-};
-
-typedef struct {
-	tcp_sock_t local;
-	tcp_sock_t foreign;
-} tcp_sockpair_t;
-
-/** Connection incoming segments queue */
-typedef struct {
-	struct tcp_conn *conn;
-	list_t list;
-} tcp_iqueue_t;
-
-/** Retransmission queue */
-typedef struct {
-	struct tcp_conn *conn;
-	list_t list;
-
-	/** Retransmission timer */
-	fibril_timer_t *timer;
-} tcp_tqueue_t;
-
-typedef enum {
-	ap_active,
-	ap_passive
-} acpass_t;
-
-typedef enum {
-	tcp_open_nonblock = 1
-} tcp_open_flags_t;
-
-typedef struct tcp_conn tcp_conn_t;
-
-/** Connection state change callback function */
-typedef void (*tcp_cstate_cb_t)(tcp_conn_t *, void *);
-
-/** Connection */
-struct tcp_conn {
-	char *name;
-	link_t link;
-
-	/** Connection state change callback function */
-	tcp_cstate_cb_t cstate_cb;
-	/** Argument to @c cstate_cb */
-	void *cstate_cb_arg;
-
-	/** Connection identification (local and foreign socket) */
-	tcp_sockpair_t ident;
-
-	/** Active or passive connection */
-	acpass_t ap;
-
-	/** Protects access to connection structure */
-	fibril_mutex_t lock;
-	/** Reference count */
-	atomic_t refcnt;
-
-	/** Connection state */
-	tcp_cstate_t cstate;
-	/** True if connection was reset */
-	bool reset;
-	/** True if connection was deleted by user */
-	bool deleted;
-	/** Signalled when @c cstate changes */
-	fibril_condvar_t cstate_cv;
-
-	/** Set when FIN is removed from the retransmission queue */
-	bool fin_is_acked;
-
-	/** Queue of incoming segments */
-	tcp_iqueue_t incoming;
-
-	/** Retransmission queue */
-	tcp_tqueue_t retransmit;
-
-	/** Time-Wait timeout timer */
-	fibril_timer_t *tw_timer;
-
-	/** Receive buffer */
-	uint8_t *rcv_buf;
-	/** Receive buffer size */
-	size_t rcv_buf_size;
-	/** Receive buffer number of bytes used */
-	size_t rcv_buf_used;
-	/** Receive buffer contains FIN */
-	bool rcv_buf_fin;
-	/** Receive buffer CV. Broadcast when new data is inserted */
-	fibril_condvar_t rcv_buf_cv;
-
-	/** Send buffer */
-	uint8_t *snd_buf;
-	/** Send buffer size */
-	size_t snd_buf_size;
-	/** Send buffer number of bytes used */
-	size_t snd_buf_used;
-	/** Send buffer contains FIN */
-	bool snd_buf_fin;
-	/** Send buffer CV. Broadcast when space is made available in buffer */
-	fibril_condvar_t snd_buf_cv;
-
-	/** Send unacknowledged */
-	uint32_t snd_una;
-	/** Send next */
-	uint32_t snd_nxt;
-	/** Send window */
-	uint32_t snd_wnd;
-	/** Send urgent pointer */
-	uint32_t snd_up;
-	/** Segment sequence number used for last window update */
-	uint32_t snd_wl1;
-	/** Segment acknowledgement number used for last window update */
-	uint32_t snd_wl2;
-	/** Initial send sequence number */
-	uint32_t iss;
-
-	/** Receive next */
-	uint32_t rcv_nxt;
-	/** Receive window */
-	uint32_t rcv_wnd;
-	/** Receive urgent pointer */
-	uint32_t rcv_up;
-	/** Initial receive sequence number */
-	uint32_t irs;
-};
-
-/** Data returned by Status user call */
-typedef struct {
-	/** Connection state */
-	tcp_cstate_t cstate;
-} tcp_conn_status_t;
-
-typedef struct {
-	/** SYN, FIN */
-	tcp_control_t ctrl;
-
-	/** Segment sequence number */
-	uint32_t seq;
-	/** Segment acknowledgement number */
-	uint32_t ack;
-	/** Segment length in sequence space */
-	uint32_t len;
-	/** Segment window */
-	uint32_t wnd;
-	/** Segment urgent pointer */
-	uint32_t up;
-
-	/** Segment data, may be moved when trimming segment */
-	void *data;
-	/** Segment data, original pointer used to free data */
-	void *dfptr;
-} tcp_segment_t;
-
-
-typedef struct {
-	link_t link;
-	tcp_sockpair_t sp;
-	tcp_segment_t *seg;
-} tcp_rqueue_entry_t;
-
-/** NCSim queue entry */
-typedef struct {
-	link_t link;
-	suseconds_t delay;
-	tcp_sockpair_t sp;
-	tcp_segment_t *seg;
-} tcp_squeue_entry_t;
-
-typedef struct {
-	link_t link;
-	tcp_segment_t *seg;
-} tcp_iqueue_entry_t;
-
-/** Retransmission queue entry */
-typedef struct {
-	link_t link;
-	tcp_conn_t *conn;
-	tcp_segment_t *seg;
-} tcp_tqueue_entry_t;
-
-typedef enum {
-	cp_continue,
-	cp_done
-} cproc_t;
-
-/** Encoded PDU */
-typedef struct {
-	/** Source address */
-	netaddr_t src_addr;
-	/** Destination address */
-	netaddr_t dest_addr;
-
-	/** Encoded header */
-	void *header;
-	/** Encoded header size */
-	size_t header_size;
-	/** Text */
-	void *text;
-	/** Text size */
-	size_t text_size;
-} tcp_pdu_t;
-
-typedef struct {
-	async_sess_t *sess;
-	socket_cores_t sockets;
-} tcp_client_t;
-
-typedef struct tcp_sockdata {
-	/** Lock */
-	fibril_mutex_t lock;
-	/** Socket core */
-	socket_core_t *sock_core;
-	/** Client */
-	tcp_client_t *client;
-	/** Connection */
-	tcp_conn_t *conn;
-	/** Local address */
-	netaddr_t laddr;
-	/** Backlog size */
-	int backlog;
-	/** Array of listening connections, @c backlog elements */
-	struct tcp_sock_lconn **lconn;
-	/** List of connections (from lconn) that are ready to be accepted */
-	list_t ready;
-} tcp_sockdata_t;
-
-typedef struct tcp_sock_lconn {
-	tcp_conn_t *conn;
-	tcp_sockdata_t *socket;
-	int index;
-	link_t ready_list;
-} tcp_sock_lconn_t;
-
-
-#endif
-
-/** @}
- */
Index: pace/srv/net/tl/tcp/test.c
===================================================================
--- uspace/srv/net/tl/tcp/test.c	(revision bf31e3f1ebd6e88e0c8425f109e42ccd92b6c9b3)
+++ 	(revision )
@@ -1,145 +1,0 @@
-/*
- * Copyright (c) 2011 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup tcp
- * @{
- */
-
-/**
- * @file Internal TCP test
- */
-
-#include <async.h>
-#include <errno.h>
-#include <stdio.h>
-#include <thread.h>
-#include <str.h>
-#include "tcp_type.h"
-#include "ucall.h"
-
-#include "test.h"
-
-#define RCV_BUF_SIZE 64
-
-static void test_srv(void *arg)
-{
-	tcp_conn_t *conn;
-	tcp_sock_t lsock;
-	tcp_sock_t fsock;
-	char rcv_buf[RCV_BUF_SIZE + 1];
-	size_t rcvd;
-	xflags_t xflags;
-
-	printf("test_srv()\n");
-	lsock.port = 80;
-	lsock.addr.ipv4 = 0x7f000001;
-	fsock.port = 1024;
-	fsock.addr.ipv4 = 0x7f000001;
-	printf("S: User open...\n");
-	tcp_uc_open(&lsock, &fsock, ap_passive, 0, &conn);
-	conn->name = (char *) "S";
-
-	while (true) {
-		printf("S: User receive...\n");
-		tcp_uc_receive(conn, rcv_buf, RCV_BUF_SIZE, &rcvd, &xflags);
-		if (rcvd == 0) {
-			printf("S: End of data reached.\n");
-			break;
-		}
-		rcv_buf[rcvd] = '\0';
-		printf("S: User received %zu bytes '%s'.\n", rcvd, rcv_buf);
-
-		async_usleep(1000*1000*2);
-	}
-
-	async_usleep(/*10**/1000*1000);
-
-	printf("S: User close...\n");
-	tcp_uc_close(conn);
-
-	printf("test_srv() terminating\n");
-}
-
-static void test_cli(void *arg)
-{
-	tcp_conn_t *conn;
-	tcp_sock_t lsock;
-	tcp_sock_t fsock;
-	const char *msg = "Hello World!";
-
-	printf("test_cli()\n");
-
-	lsock.port = 1024;
-	lsock.addr.ipv4 = 0x7f000001;
-	fsock.port = 80;
-	fsock.addr.ipv4 = 0x7f000001;
-
-	async_usleep(1000*1000*3);
-	printf("C: User open...\n");
-	tcp_uc_open(&lsock, &fsock, ap_active, 0, &conn);
-	conn->name = (char *) "C";
-
-	async_usleep(1000*1000*10);
-	printf("C: User send...\n");
-	tcp_uc_send(conn, (void *)msg, str_size(msg), 0);
-
-	async_usleep(1000*1000*20/**20*2*/);
-	printf("C: User close...\n");
-	tcp_uc_close(conn);
-}
-
-void tcp_test(void)
-{
-	thread_id_t srv_tid;
-	thread_id_t cli_tid;
-	int rc;
-
-	printf("tcp_test()\n");
-
-	async_usleep(1000*1000);
-
-	if (0) {
-		rc = thread_create(test_srv, NULL, "test_srv", &srv_tid);
-		if (rc != EOK) {
-			printf("Failed to create server thread.\n");
-			return;
-		}
-	}
-
-	if (0) {
-		rc = thread_create(test_cli, NULL, "test_cli", &cli_tid);
-		if (rc != EOK) {
-			printf("Failed to create client thread.\n");
-			return;
-		}
-	}
-}
-
-/**
- * @}
- */
Index: pace/srv/net/tl/tcp/test.h
===================================================================
--- uspace/srv/net/tl/tcp/test.h	(revision bf31e3f1ebd6e88e0c8425f109e42ccd92b6c9b3)
+++ 	(revision )
@@ -1,43 +1,0 @@
-/*
- * Copyright (c) 2011 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup tcp
- * @{
- */
-/** @file Internal TCP test
- */
-
-#ifndef TEST_H
-#define TEST_H
-
-extern void tcp_test(void);
-
-#endif
-
-/** @}
- */
Index: pace/srv/net/tl/tcp/tqueue.c
===================================================================
--- uspace/srv/net/tl/tcp/tqueue.c	(revision bf31e3f1ebd6e88e0c8425f109e42ccd92b6c9b3)
+++ 	(revision )
@@ -1,381 +1,0 @@
-/*
- * Copyright (c) 2011 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup tcp
- * @{
- */
-
-/**
- * @file TCP transmission queue
- */
-
-#include <adt/list.h>
-#include <errno.h>
-#include <fibril_synch.h>
-#include <byteorder.h>
-#include <io/log.h>
-#include <macros.h>
-#include <mem.h>
-#include <stdlib.h>
-#include "conn.h"
-#include "ncsim.h"
-#include "pdu.h"
-#include "rqueue.h"
-#include "segment.h"
-#include "seq_no.h"
-#include "tqueue.h"
-#include "tcp.h"
-#include "tcp_type.h"
-
-#define RETRANSMIT_TIMEOUT	(2*1000*1000)
-
-static void retransmit_timeout_func(void *arg);
-static void tcp_tqueue_timer_set(tcp_conn_t *conn);
-static void tcp_tqueue_timer_clear(tcp_conn_t *conn);
-
-int tcp_tqueue_init(tcp_tqueue_t *tqueue, tcp_conn_t *conn)
-{
-	tqueue->conn = conn;
-	tqueue->timer = fibril_timer_create();
-	if (tqueue->timer == NULL)
-		return ENOMEM;
-
-	list_initialize(&tqueue->list);
-
-	return EOK;
-}
-
-void tcp_tqueue_clear(tcp_tqueue_t *tqueue)
-{
-	tcp_tqueue_timer_clear(tqueue->conn);
-}
-
-void tcp_tqueue_fini(tcp_tqueue_t *tqueue)
-{
-	if (tqueue->timer != NULL) {
-		fibril_timer_destroy(tqueue->timer);
-		tqueue->timer = NULL;
-	}
-}
-
-void tcp_tqueue_ctrl_seg(tcp_conn_t *conn, tcp_control_t ctrl)
-{
-	tcp_segment_t *seg;
-
-	log_msg(LVL_DEBUG, "tcp_tqueue_ctrl_seg(%p, %u)", conn, ctrl);
-
-	seg = tcp_segment_make_ctrl(ctrl);
-	tcp_tqueue_seg(conn, seg);
-}
-
-void tcp_tqueue_seg(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	tcp_segment_t *rt_seg;
-	tcp_tqueue_entry_t *tqe;
-
-	log_msg(LVL_DEBUG, "%s: tcp_tqueue_seg(%p, %p)", conn->name, conn,
-	    seg);
-
-	/*
-	 * Add segment to retransmission queue
-	 */
-
-	if (seg->len > 0) {
-		rt_seg = tcp_segment_dup(seg);
-		if (rt_seg == NULL) {
-			log_msg(LVL_ERROR, "Memory allocation failed.");
-			/* XXX Handle properly */
-			return;
-		}
-
-		tqe = calloc(1, sizeof(tcp_tqueue_entry_t));
-		if (tqe == NULL) {
-			log_msg(LVL_ERROR, "Memory allocation failed.");
-			/* XXX Handle properly */
-			return;
-		}
-
-		tqe->conn = conn;
-		tqe->seg = rt_seg;
-		rt_seg->seq = conn->snd_nxt;
-
-		list_append(&tqe->link, &conn->retransmit.list);
-
-		/* Set retransmission timer */
-		tcp_tqueue_timer_set(conn);
-	}
-
-	tcp_prepare_transmit_segment(conn, seg);
-}
-
-void tcp_prepare_transmit_segment(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	/*
-	 * Always send ACK once we have received SYN, except for RST segments.
-	 * (Spec says we should always send ACK once connection has been
-	 * established.)
-	 */
-	if (tcp_conn_got_syn(conn) && (seg->ctrl & CTL_RST) == 0)
-		seg->ctrl |= CTL_ACK;
-
-	seg->seq = conn->snd_nxt;
-	conn->snd_nxt += seg->len;
-
-	tcp_conn_transmit_segment(conn, seg);
-}
-
-/** Transmit data from the send buffer.
- *
- * @param conn	Connection
- */
-void tcp_tqueue_new_data(tcp_conn_t *conn)
-{
-	size_t avail_wnd;
-	size_t xfer_seqlen;
-	size_t snd_buf_seqlen;
-	size_t data_size;
-	tcp_control_t ctrl;
-	bool send_fin;
-
-	tcp_segment_t *seg;
-
-	log_msg(LVL_DEBUG, "%s: tcp_tqueue_new_data()", conn->name);
-
-	/* Number of free sequence numbers in send window */
-	avail_wnd = (conn->snd_una + conn->snd_wnd) - conn->snd_nxt;
-	snd_buf_seqlen = conn->snd_buf_used + (conn->snd_buf_fin ? 1 : 0);
-
-	xfer_seqlen = min(snd_buf_seqlen, avail_wnd);
-	log_msg(LVL_DEBUG, "%s: snd_buf_seqlen = %zu, SND.WND = %zu, "
-	    "xfer_seqlen = %zu", conn->name, snd_buf_seqlen, conn->snd_wnd,
-	    xfer_seqlen);
-
-	if (xfer_seqlen == 0)
-		return;
-
-	/* XXX Do not always send immediately */
-
-	send_fin = conn->snd_buf_fin && xfer_seqlen == snd_buf_seqlen;
-	data_size = xfer_seqlen - (send_fin ? 1 : 0);
-
-	if (send_fin) {
-		log_msg(LVL_DEBUG, "%s: Sending out FIN.", conn->name);
-		/* We are sending out FIN */
-		ctrl = CTL_FIN;
-	} else {
-		ctrl = 0;
-	}
-
-	seg = tcp_segment_make_data(ctrl, conn->snd_buf, data_size);
-	if (seg == NULL) {
-		log_msg(LVL_ERROR, "Memory allocation failure.");
-		return;
-	}
-
-	/* Remove data from send buffer */
-	memmove(conn->snd_buf, conn->snd_buf + data_size,
-	    conn->snd_buf_used - data_size);
-	conn->snd_buf_used -= data_size;
-
-	if (send_fin)
-		conn->snd_buf_fin = false;
-
-	fibril_condvar_broadcast(&conn->snd_buf_cv);
-
-	if (send_fin)
-		tcp_conn_fin_sent(conn);
-
-	tcp_tqueue_seg(conn, seg);
-}
-
-/** Remove ACKed segments from retransmission queue and possibly transmit
- * more data.
- *
- * This should be called when SND.UNA is updated due to incoming ACK.
- */
-void tcp_tqueue_ack_received(tcp_conn_t *conn)
-{
-	link_t *cur, *next;
-
-	log_msg(LVL_DEBUG, "%s: tcp_tqueue_ack_received(%p)", conn->name,
-	    conn);
-
-	cur = conn->retransmit.list.head.next;
-
-	while (cur != &conn->retransmit.list.head) {
-		next = cur->next;
-
-		tcp_tqueue_entry_t *tqe = list_get_instance(cur,
-		    tcp_tqueue_entry_t, link);
-
-		if (seq_no_segment_acked(conn, tqe->seg, conn->snd_una)) {
-			/* Remove acknowledged segment */
-			list_remove(cur);
-
-			if ((tqe->seg->ctrl & CTL_FIN) != 0) {
-				log_msg(LVL_DEBUG, "Fin has been acked");
-				log_msg(LVL_DEBUG, "SND.UNA=%" PRIu32
-				    " SEG.SEQ=%" PRIu32 " SEG.LEN=%" PRIu32,
-				    conn->snd_una, tqe->seg->seq, tqe->seg->len);
-				/* Our FIN has been acked */
-				conn->fin_is_acked = true;
-			}
-
-			tcp_segment_delete(tqe->seg);
-			free(tqe);
-
-			/* Reset retransmission timer */
-			tcp_tqueue_timer_set(conn);
-		}
-
-		cur = next;
-	}
-
-	/* Clear retransmission timer if the queue is empty. */
-	if (list_empty(&conn->retransmit.list))
-		tcp_tqueue_timer_clear(conn);
-
-	/* Possibly transmit more data */
-	tcp_tqueue_new_data(conn);
-}
-
-void tcp_conn_transmit_segment(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	log_msg(LVL_DEBUG, "%s: tcp_conn_transmit_segment(%p, %p)",
-	    conn->name, conn, seg);
-
-	seg->wnd = conn->rcv_wnd;
-
-	if ((seg->ctrl & CTL_ACK) != 0)
-		seg->ack = conn->rcv_nxt;
-	else
-		seg->ack = 0;
-
-	tcp_transmit_segment(&conn->ident, seg);
-}
-
-void tcp_transmit_segment(tcp_sockpair_t *sp, tcp_segment_t *seg)
-{
-	log_msg(LVL_DEBUG, "tcp_transmit_segment(f:(%x,%u),l:(%x,%u), %p)",
-	    sp->foreign.addr.ipv4, sp->foreign.port,
-	    sp->local.addr.ipv4, sp->local.port, seg);
-
-	log_msg(LVL_DEBUG, "SEG.SEQ=%" PRIu32 ", SEG.WND=%" PRIu32,
-	    seg->seq, seg->wnd);
-
-	tcp_segment_dump(seg);
-/*
-	tcp_pdu_prepare(conn, seg, &data, &len);
-	tcp_pdu_transmit(data, len);
-*/
-//	tcp_rqueue_bounce_seg(sp, seg);
-//	tcp_ncsim_bounce_seg(sp, seg);
-
-	tcp_pdu_t *pdu;
-
-	if (tcp_pdu_encode(sp, seg, &pdu) != EOK) {
-		log_msg(LVL_WARN, "Not enough memory. Segment dropped.");
-		return;
-	}
-
-	tcp_transmit_pdu(pdu);
-	tcp_pdu_delete(pdu);
-}
-
-static void retransmit_timeout_func(void *arg)
-{
-	tcp_conn_t *conn = (tcp_conn_t *) arg;
-	tcp_tqueue_entry_t *tqe;
-	tcp_segment_t *rt_seg;
-	link_t *link;
-
-	log_msg(LVL_DEBUG, "### %s: retransmit_timeout_func(%p)", conn->name, conn);
-
-	fibril_mutex_lock(&conn->lock);
-
-	if (conn->cstate == st_closed) {
-		log_msg(LVL_DEBUG, "Connection already closed.");
-		fibril_mutex_unlock(&conn->lock);
-		tcp_conn_delref(conn);
-		return;
-	}
-
-	link = list_first(&conn->retransmit.list);
-	if (link == NULL) {
-		log_msg(LVL_DEBUG, "Nothing to retransmit");
-		fibril_mutex_unlock(&conn->lock);
-		tcp_conn_delref(conn);
-		return;
-	}
-
-	tqe = list_get_instance(link, tcp_tqueue_entry_t, link);
-
-	rt_seg = tcp_segment_dup(tqe->seg);
-	if (rt_seg == NULL) {
-		log_msg(LVL_ERROR, "Memory allocation failed.");
-		fibril_mutex_unlock(&conn->lock);
-		tcp_conn_delref(conn);
-		/* XXX Handle properly */
-		return;
-	}
-
-	log_msg(LVL_DEBUG, "### %s: retransmitting segment", conn->name);
-	tcp_conn_transmit_segment(tqe->conn, rt_seg);
-
-	/* Reset retransmission timer */
-	tcp_tqueue_timer_set(tqe->conn);
-
-	fibril_mutex_unlock(&conn->lock);
-	tcp_conn_delref(conn);
-}
-
-/** Set or re-set retransmission timer */
-static void tcp_tqueue_timer_set(tcp_conn_t *conn)
-{
-	log_msg(LVL_DEBUG, "### %s: tcp_tqueue_timer_set()", conn->name);
-
-	/* Clear first to make sure we update refcnt correctly */
-	tcp_tqueue_timer_clear(conn);
-
-	tcp_conn_addref(conn);
-	fibril_timer_set(conn->retransmit.timer, RETRANSMIT_TIMEOUT,
-	    retransmit_timeout_func, (void *) conn);
-}
-
-/** Clear retransmission timer */
-static void tcp_tqueue_timer_clear(tcp_conn_t *conn)
-{
-	log_msg(LVL_DEBUG, "### %s: tcp_tqueue_timer_clear()", conn->name);
-
-	if (fibril_timer_clear(conn->retransmit.timer) == fts_active)
-		tcp_conn_delref(conn);
-}
-
-/**
- * @}
- */
Index: pace/srv/net/tl/tcp/tqueue.h
===================================================================
--- uspace/srv/net/tl/tcp/tqueue.h	(revision bf31e3f1ebd6e88e0c8425f109e42ccd92b6c9b3)
+++ 	(revision )
@@ -1,57 +1,0 @@
-/*
- * Copyright (c) 2011 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup tcp
- * @{
- */
-/** @file TCP transmission queue
- */
-
-#ifndef TQUEUE_H
-#define TQUEUE_H
-
-#include "std.h"
-#include "tcp_type.h"
-
-extern int tcp_tqueue_init(tcp_tqueue_t *, tcp_conn_t *);
-extern void tcp_tqueue_clear(tcp_tqueue_t *);
-extern void tcp_tqueue_fini(tcp_tqueue_t *);
-extern void tcp_tqueue_ctrl_seg(tcp_conn_t *, tcp_control_t);
-extern void tcp_tqueue_seg(tcp_conn_t *, tcp_segment_t *);
-extern void tcp_tqueue_new_data(tcp_conn_t *);
-extern void tcp_tqueue_ack_received(tcp_conn_t *);
-extern void tcp_prepare_transmit_segment(tcp_conn_t *, tcp_segment_t *);
-extern void tcp_conn_transmit_segment(tcp_conn_t *, tcp_segment_t *);
-extern void tcp_transmit_segment(tcp_sockpair_t *, tcp_segment_t *);
-extern void tcp_header_setup(tcp_conn_t *, tcp_segment_t *, tcp_header_t *);
-extern void tcp_phdr_setup(tcp_conn_t *, tcp_segment_t *, tcp_phdr_t *);
-
-#endif
-
-/** @}
- */
Index: pace/srv/net/tl/tcp/ucall.c
===================================================================
--- uspace/srv/net/tl/tcp/ucall.c	(revision bf31e3f1ebd6e88e0c8425f109e42ccd92b6c9b3)
+++ 	(revision )
@@ -1,346 +1,0 @@
-/*
- * Copyright (c) 2011 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup tcp
- * @{
- */
-
-/**
- * @file TCP entry points (close to those defined in the RFC)
- */
-
-#include <fibril_synch.h>
-#include <io/log.h>
-#include <macros.h>
-#include <mem.h>
-#include "conn.h"
-#include "tcp_type.h"
-#include "tqueue.h"
-#include "ucall.h"
-
-/*
- * User calls
- */
-
-/** OPEN user call
- *
- * @param lsock		Local socket
- * @param fsock		Foreign socket
- * @param acpass	Active/passive
- * @param oflags	Open flags
- * @param conn		Connection
- *
- * Unlike in the spec we allow specifying the local address. This means
- * the implementation does not need to magically guess it, especially
- * considering there can be more than one local address.
- *
- * XXX We should be able to call active open on an existing listening
- * connection.
- * XXX We should be able to get connection structure immediately, before
- * establishment.
- */
-tcp_error_t tcp_uc_open(tcp_sock_t *lsock, tcp_sock_t *fsock, acpass_t acpass,
-    tcp_open_flags_t oflags, tcp_conn_t **conn)
-{
-	tcp_conn_t *nconn;
-
-	log_msg(LVL_DEBUG, "tcp_uc_open(%p, %p, %s, %s, %p)",
-	    lsock, fsock, acpass == ap_active ? "active" : "passive",
-	    oflags == tcp_open_nonblock ? "nonblock" : "none", conn);
-
-	nconn = tcp_conn_new(lsock, fsock);
-	tcp_conn_add(nconn);
-
-	if (acpass == ap_active) {
-		/* Synchronize (initiate) connection */
-		tcp_conn_sync(nconn);
-	}
-
-	if (oflags == tcp_open_nonblock) {
-		*conn = nconn;
-		return TCP_EOK;
-	}
-
-	/* Wait for connection to be established or reset */
-	log_msg(LVL_DEBUG, "tcp_uc_open: Wait for connection.");
-	fibril_mutex_lock(&nconn->lock);
-	while (nconn->cstate == st_listen ||
-	    nconn->cstate == st_syn_sent ||
-	    nconn->cstate == st_syn_received) {
-		fibril_condvar_wait(&nconn->cstate_cv, &nconn->lock);
-	}
-
-	if (nconn->cstate != st_established) {
-		log_msg(LVL_DEBUG, "tcp_uc_open: Connection was reset.");
-		assert(nconn->cstate == st_closed);
-		fibril_mutex_unlock(&nconn->lock);
-		return TCP_ERESET;
-	}
-
-	fibril_mutex_unlock(&nconn->lock);
-	log_msg(LVL_DEBUG, "tcp_uc_open: Connection was established.");
-
-	*conn = nconn;
-	log_msg(LVL_DEBUG, "tcp_uc_open -> %p", nconn);
-	return TCP_EOK;
-}
-
-/** SEND user call */
-tcp_error_t tcp_uc_send(tcp_conn_t *conn, void *data, size_t size,
-    xflags_t flags)
-{
-	size_t buf_free;
-	size_t xfer_size;
-
-	log_msg(LVL_DEBUG, "%s: tcp_uc_send()", conn->name);
-
-	fibril_mutex_lock(&conn->lock);
-
-	if (conn->cstate == st_closed) {
-		fibril_mutex_unlock(&conn->lock);
-		return TCP_ENOTEXIST;
-	}
-
-	if (conn->cstate == st_listen) {
-		/* Change connection to active */
-		tcp_conn_sync(conn);
-	}
-
-
-	if (conn->snd_buf_fin) {
-		fibril_mutex_unlock(&conn->lock);
-		return TCP_ECLOSING;
-	}
-
-	while (size > 0) {
-		buf_free = conn->snd_buf_size - conn->snd_buf_used;
-		while (buf_free == 0 && !conn->reset) {
-			log_msg(LVL_DEBUG, "%s: buf_free == 0, waiting.",
-			    conn->name);
-			fibril_condvar_wait(&conn->snd_buf_cv, &conn->lock);
-			buf_free = conn->snd_buf_size - conn->snd_buf_used;
-		}
-
-		if (conn->reset) {
-			fibril_mutex_unlock(&conn->lock);
-			return TCP_ERESET;
-		}
-
-		xfer_size = min(size, buf_free);
-
-		/* Copy data to buffer */
-		memcpy(conn->snd_buf + conn->snd_buf_used, data, xfer_size);
-		data += xfer_size;
-		conn->snd_buf_used += xfer_size;
-		size -= xfer_size;
-
-		tcp_tqueue_new_data(conn);
-	}
-
-	tcp_tqueue_new_data(conn);
-	fibril_mutex_unlock(&conn->lock);
-
-	return TCP_EOK;
-}
-
-/** RECEIVE user call */
-tcp_error_t tcp_uc_receive(tcp_conn_t *conn, void *buf, size_t size,
-    size_t *rcvd, xflags_t *xflags)
-{
-	size_t xfer_size;
-
-	log_msg(LVL_DEBUG, "%s: tcp_uc_receive()", conn->name);
-
-	fibril_mutex_lock(&conn->lock);
-
-	if (conn->cstate == st_closed) {
-		fibril_mutex_unlock(&conn->lock);
-		return TCP_ENOTEXIST;
-	}
-
-	/* Wait for data to become available */
-	while (conn->rcv_buf_used == 0 && !conn->rcv_buf_fin && !conn->reset) {
-		log_msg(LVL_DEBUG, "tcp_uc_receive() - wait for data");
-		fibril_condvar_wait(&conn->rcv_buf_cv, &conn->lock);
-	}
-
-	if (conn->rcv_buf_used == 0) {
-		*rcvd = 0;
-		*xflags = 0;
-
-		if (conn->rcv_buf_fin) {
-			/* End of data, peer closed connection */
-			fibril_mutex_unlock(&conn->lock);
-			return TCP_ECLOSING;
-		} else {
-			/* Connection was reset */
-			assert(conn->reset);
-			fibril_mutex_unlock(&conn->lock);
-			return TCP_ERESET;
-		}
-	}
-
-	/* Copy data from receive buffer to user buffer */
-	xfer_size = min(size, conn->rcv_buf_used);
-	memcpy(buf, conn->rcv_buf, xfer_size);
-	*rcvd = xfer_size;
-
-	/* Remove data from receive buffer */
-	memmove(conn->rcv_buf, conn->rcv_buf + xfer_size, conn->rcv_buf_used -
-	    xfer_size);
-	conn->rcv_buf_used -= xfer_size;
-	conn->rcv_wnd += xfer_size;
-
-	/* TODO */
-	*xflags = 0;
-
-	/* Send new size of receive window */
-	tcp_tqueue_ctrl_seg(conn, CTL_ACK);
-
-	log_msg(LVL_DEBUG, "%s: tcp_uc_receive() - returning %zu bytes",
-	    conn->name, xfer_size);
-
-	fibril_mutex_unlock(&conn->lock);
-
-	return TCP_EOK;
-}
-
-/** CLOSE user call */
-tcp_error_t tcp_uc_close(tcp_conn_t *conn)
-{
-	log_msg(LVL_DEBUG, "%s: tcp_uc_close()", conn->name);
-
-	fibril_mutex_lock(&conn->lock);
-
-	if (conn->cstate == st_closed) {
-		fibril_mutex_unlock(&conn->lock);
-		return TCP_ENOTEXIST;
-	}
-
-	if (conn->snd_buf_fin) {
-		fibril_mutex_unlock(&conn->lock);
-		return TCP_ECLOSING;
-	}
-
-	conn->snd_buf_fin = true;
-	tcp_tqueue_new_data(conn);
-
-	fibril_mutex_unlock(&conn->lock);
-	return TCP_EOK;
-}
-
-/** ABORT user call */
-void tcp_uc_abort(tcp_conn_t *conn)
-{
-	log_msg(LVL_DEBUG, "tcp_uc_abort()");
-}
-
-/** STATUS user call */
-void tcp_uc_status(tcp_conn_t *conn, tcp_conn_status_t *cstatus)
-{
-	log_msg(LVL_DEBUG, "tcp_uc_status()");
-	cstatus->cstate = conn->cstate;
-}
-
-/** Delete connection user call.
- *
- * (Not in spec.) Inform TCP that the user is done with this connection
- * and will not make any further calls/references to it. TCP can deallocate
- * the connection from now on.
- */
-void tcp_uc_delete(tcp_conn_t *conn)
-{
-	log_msg(LVL_DEBUG, "tcp_uc_delete()");
-	tcp_conn_delete(conn);
-}
-
-void tcp_uc_set_cstate_cb(tcp_conn_t *conn, tcp_cstate_cb_t cb, void *arg)
-{
-	log_msg(LVL_DEBUG, "tcp_uc_set_ctate_cb(%p, %p, %p)",
-	    conn, cb, arg);
-
-	conn->cstate_cb = cb;
-	conn->cstate_cb_arg = arg;
-}
-
-/*
- * Arriving segments
- */
-
-/** Segment arrived */
-void tcp_as_segment_arrived(tcp_sockpair_t *sp, tcp_segment_t *seg)
-{
-	tcp_conn_t *conn;
-
-	log_msg(LVL_DEBUG, "tcp_as_segment_arrived(f:(%x,%u), l:(%x,%u))",
-	    sp->foreign.addr.ipv4, sp->foreign.port,
-	    sp->local.addr.ipv4, sp->local.port);
-
-	conn = tcp_conn_find_ref(sp);
-	if (conn == NULL) {
-		log_msg(LVL_WARN, "No connection found.");
-		tcp_unexpected_segment(sp, seg);
-		return;
-	}
-
-	fibril_mutex_lock(&conn->lock);
-
-	if (conn->cstate == st_closed) {
-		log_msg(LVL_WARN, "Connection is closed.");
-		tcp_unexpected_segment(sp, seg);
-		fibril_mutex_unlock(&conn->lock);
-		tcp_conn_delref(conn);
-		return;
-	}
-
-	if (conn->ident.foreign.addr.ipv4 == TCP_IPV4_ANY)
-		conn->ident.foreign.addr.ipv4 = sp->foreign.addr.ipv4;
-	if (conn->ident.foreign.port == TCP_PORT_ANY)
-		conn->ident.foreign.port = sp->foreign.port;
-	if (conn->ident.local.addr.ipv4 == TCP_IPV4_ANY)
-		conn->ident.local.addr.ipv4 = sp->local.addr.ipv4;
-
-	tcp_conn_segment_arrived(conn, seg);
-
-	fibril_mutex_unlock(&conn->lock);
-	tcp_conn_delref(conn);
-}
-
-/*
- * Timeouts
- */
-
-/** User timeout */
-void tcp_to_user(void)
-{
-	log_msg(LVL_DEBUG, "tcp_to_user()");
-}
-
-/**
- * @}
- */
Index: pace/srv/net/tl/tcp/ucall.h
===================================================================
--- uspace/srv/net/tl/tcp/ucall.h	(revision bf31e3f1ebd6e88e0c8425f109e42ccd92b6c9b3)
+++ 	(revision )
@@ -1,67 +1,0 @@
-/*
- * Copyright (c) 2011 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup tcp
- * @{
- */
-/** @file TCP user calls (close to those defined in the RFC)
- */
-
-#ifndef UCALL_H
-#define UCALL_H
-
-#include <sys/types.h>
-#include "tcp_type.h"
-
-/*
- * User calls
- */
-extern tcp_error_t tcp_uc_open(tcp_sock_t *, tcp_sock_t *, acpass_t,
-    tcp_open_flags_t, tcp_conn_t **);
-extern tcp_error_t tcp_uc_send(tcp_conn_t *, void *, size_t, xflags_t);
-extern tcp_error_t tcp_uc_receive(tcp_conn_t *, void *, size_t, size_t *, xflags_t *);
-extern tcp_error_t tcp_uc_close(tcp_conn_t *);
-extern void tcp_uc_abort(tcp_conn_t *);
-extern void tcp_uc_status(tcp_conn_t *, tcp_conn_status_t *);
-extern void tcp_uc_delete(tcp_conn_t *);
-extern void tcp_uc_set_cstate_cb(tcp_conn_t *, tcp_cstate_cb_t, void *);
-
-/*
- * Arriving segments
- */
-extern void tcp_as_segment_arrived(tcp_sockpair_t *, tcp_segment_t *);
-
-/*
- * Timeouts
- */
-extern void tcp_to_user(void);
-
-#endif
-
-/** @}
- */
Index: pace/srv/net/tl/udp/Makefile
===================================================================
--- uspace/srv/net/tl/udp/Makefile	(revision bf31e3f1ebd6e88e0c8425f109e42ccd92b6c9b3)
+++ 	(revision )
@@ -1,38 +1,0 @@
-#
-# Copyright (c) 2005 Martin Decky
-# Copyright (c) 2007 Jakub Jermar
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# - Redistributions of source code must retain the above copyright
-#   notice, this list of conditions and the following disclaimer.
-# - Redistributions in binary form must reproduce the above copyright
-#   notice, this list of conditions and the following disclaimer in the
-#   documentation and/or other materials provided with the distribution.
-# - The name of the author may not be used to endorse or promote products
-#   derived from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-
-USPACE_PREFIX = ../../../..
-LIBS = $(LIBNET_PREFIX)/libnet.a
-EXTRA_CFLAGS = -I$(LIBNET_PREFIX)/include
-BINARY = udp
-
-SOURCES = \
-	udp.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: pace/srv/net/tl/udp/udp.c
===================================================================
--- uspace/srv/net/tl/udp/udp.c	(revision bf31e3f1ebd6e88e0c8425f109e42ccd92b6c9b3)
+++ 	(revision )
@@ -1,934 +1,0 @@
-/*
- * Copyright (c) 2008 Lukas Mejdrech
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup udp
- * @{
- */
-
-/** @file
- * UDP module implementation.
- * @see udp.h
- */
-
-#include <async.h>
-#include <fibril_synch.h>
-#include <malloc.h>
-#include <stdio.h>
-#include <ipc/services.h>
-#include <ipc/net.h>
-#include <ipc/tl.h>
-#include <ipc/socket.h>
-#include <adt/dynamic_fifo.h>
-#include <errno.h>
-
-#include <net/socket_codes.h>
-#include <net/ip_protocols.h>
-#include <net/in.h>
-#include <net/in6.h>
-#include <net/inet.h>
-#include <net/modules.h>
-
-#include <packet_client.h>
-#include <packet_remote.h>
-#include <net_checksum.h>
-#include <ip_client.h>
-#include <ip_interface.h>
-#include <icmp_client.h>
-#include <icmp_remote.h>
-#include <net_interface.h>
-#include <socket_core.h>
-#include <tl_common.h>
-#include <tl_remote.h>
-#include <tl_skel.h>
-
-#include "udp.h"
-#include "udp_header.h"
-
-/** UDP module name. */
-#define NAME  "udp"
-
-/** Default UDP checksum computing. */
-#define NET_DEFAULT_UDP_CHECKSUM_COMPUTING	true
-
-/** Default UDP autobind when sending via unbound sockets. */
-#define NET_DEFAULT_UDP_AUTOBINDING	true
-
-/** Maximum UDP fragment size. */
-#define MAX_UDP_FRAGMENT_SIZE		65535
-
-/** Free ports pool start. */
-#define UDP_FREE_PORTS_START		1025
-
-/** Free ports pool end. */
-#define UDP_FREE_PORTS_END		65535
-
-/** UDP global data.  */
-udp_globals_t udp_globals;
-
-/** Releases the packet and returns the result.
- *
- * @param[in] packet	The packet queue to be released.
- * @param[in] result	The result to be returned.
- * @return		The result parameter.
- */
-static int udp_release_and_return(packet_t *packet, int result)
-{
-	pq_release_remote(udp_globals.net_sess, packet_get_id(packet));
-	return result;
-}
-
-/** Processes the received UDP packet queue.
- *
- * Notifies the destination socket application.
- * Releases the packet on error or sends an ICMP error notification.
- *
- * @param[in] device_id	The receiving device identifier.
- * @param[in,out] packet The received packet queue.
- * @param[in] error	The packet error reporting service. Prefixes the
- *			received packet.
- * @return		EOK on success.
- * @return		EINVAL if the packet is not valid.
- * @return		EINVAL if the stored packet address is not the
- *			an_addr_t.
- * @return		EINVAL if the packet does not contain any data.
- * @return 		NO_DATA if the packet content is shorter than the user
- *			datagram header.
- * @return		ENOMEM if there is not enough memory left.
- * @return		EADDRNOTAVAIL if the destination socket does not exist.
- * @return		Other error codes as defined for the
- *			ip_client_process_packet() function.
- */
-static int udp_process_packet(nic_device_id_t device_id, packet_t *packet,
-    services_t error)
-{
-	size_t length;
-	size_t offset;
-	int result;
-	udp_header_t *header;
-	socket_core_t *socket;
-	packet_t *next_packet;
-	size_t total_length;
-	uint32_t checksum;
-	int fragments;
-	packet_t *tmp_packet;
-	icmp_type_t type;
-	icmp_code_t code;
-	void *ip_header;
-	struct sockaddr *src;
-	struct sockaddr *dest;
-	packet_dimension_t *packet_dimension;
-	int rc;
-
-	switch (error) {
-	case SERVICE_NONE:
-		break;
-	case SERVICE_ICMP:
-		/* Ignore error */
-		// length = icmp_client_header_length(packet);
-
-		/* Process error */
-		result = icmp_client_process_packet(packet, &type,
-		    &code, NULL, NULL);
-		if (result < 0)
-			return udp_release_and_return(packet, result);
-		length = (size_t) result;
-		rc = packet_trim(packet, length, 0);
-		if (rc != EOK)
-			return udp_release_and_return(packet, rc);
-		break;
-	default:
-		return udp_release_and_return(packet, ENOTSUP);
-	}
-
-	/* TODO process received ipopts? */
-	result = ip_client_process_packet(packet, NULL, NULL, NULL, NULL, NULL);
-	if (result < 0)
-		return udp_release_and_return(packet, result);
-	offset = (size_t) result;
-
-	length = packet_get_data_length(packet);
-	if (length <= 0)
-		return udp_release_and_return(packet, EINVAL);
-	if (length < UDP_HEADER_SIZE + offset)
-		return udp_release_and_return(packet, NO_DATA);
-
-	/* Trim all but UDP header */
-	rc = packet_trim(packet, offset, 0);
-	if (rc != EOK)
-		return udp_release_and_return(packet, rc);
-
-	/* Get UDP header */
-	header = (udp_header_t *) packet_get_data(packet);
-	if (!header)
-		return udp_release_and_return(packet, NO_DATA);
-
-	/* Find the destination socket */
-	socket = socket_port_find(&udp_globals.sockets,
-	    ntohs(header->destination_port), (uint8_t *) SOCKET_MAP_KEY_LISTENING, 0);
-	if (!socket) {
-		if (tl_prepare_icmp_packet(udp_globals.net_sess,
-		    udp_globals.icmp_sess, packet, error) == EOK) {
-			icmp_destination_unreachable_msg(udp_globals.icmp_sess,
-			    ICMP_PORT_UNREACH, 0, packet);
-		}
-		return EADDRNOTAVAIL;
-	}
-
-	/* Count the received packet fragments */
-	next_packet = packet;
-	fragments = 0;
-	total_length = ntohs(header->total_length);
-
-	/* Compute header checksum if set */
-	if (header->checksum && !error) {
-		result = packet_get_addr(packet, (uint8_t **) &src,
-		    (uint8_t **) &dest);
-		if (result <= 0)
-			return udp_release_and_return(packet, result);
-		
-		rc = ip_client_get_pseudo_header(IPPROTO_UDP, src, result, dest,
-		    result, total_length, &ip_header, &length);
-		if (rc != EOK) {
-			return udp_release_and_return(packet, rc);
-		} else {
-			checksum = compute_checksum(0, ip_header, length);
-			/*
-			 * The udp header checksum will be added with the first
-			 * fragment later.
-			 */
-			free(ip_header);
-		}
-	} else {
-		header->checksum = 0;
-		checksum = 0;
-	}
-
-	do {
-		fragments++;
-		length = packet_get_data_length(next_packet);
-		if (length <= 0)
-			return udp_release_and_return(packet, NO_DATA);
-
-		if (total_length < length) {
-			rc = packet_trim(next_packet, 0, length - total_length);
-			if (rc != EOK)
-				return udp_release_and_return(packet, rc);
-
-			/* Add partial checksum if set */
-			if (header->checksum) {
-				checksum = compute_checksum(checksum,
-				    packet_get_data(packet),
-				    packet_get_data_length(packet));
-			}
-
-			/* Relese the rest of the packet fragments */
-			tmp_packet = pq_next(next_packet);
-			while (tmp_packet) {
-				next_packet = pq_detach(tmp_packet);
-				pq_release_remote(udp_globals.net_sess,
-				    packet_get_id(tmp_packet));
-				tmp_packet = next_packet;
-			}
-
-			/* Exit the loop */
-			break;
-		}
-		total_length -= length;
-
-		/* Add partial checksum if set */
-		if (header->checksum) {
-			checksum = compute_checksum(checksum,
-			    packet_get_data(packet),
-			    packet_get_data_length(packet));
-		}
-
-	} while ((next_packet = pq_next(next_packet)) && (total_length > 0));
-
-	/* Verify checksum */
-	if (header->checksum) {
-		if (flip_checksum(compact_checksum(checksum)) !=
-		    IP_CHECKSUM_ZERO) {
-			if (tl_prepare_icmp_packet(udp_globals.net_sess,
-			    udp_globals.icmp_sess, packet, error) == EOK) {
-				/* Checksum error ICMP */
-				icmp_parameter_problem_msg(
-				    udp_globals.icmp_sess, ICMP_PARAM_POINTER,
-				    ((size_t) ((void *) &header->checksum)) -
-				    ((size_t) ((void *) header)), packet);
-			}
-			return EINVAL;
-		}
-	}
-
-	/* Queue the received packet */
-	rc = dyn_fifo_push(&socket->received, packet_get_id(packet),
-	    SOCKET_MAX_RECEIVED_SIZE);
-	if (rc != EOK)
-		return udp_release_and_return(packet, rc);
-		
-	rc = tl_get_ip_packet_dimension(udp_globals.ip_sess,
-	    &udp_globals.dimensions, device_id, &packet_dimension);
-	if (rc != EOK)
-		return udp_release_and_return(packet, rc);
-
-	/* Notify the destination socket */
-	fibril_rwlock_write_unlock(&udp_globals.lock);
-	
-	async_exch_t *exch = async_exchange_begin(socket->sess);
-	async_msg_5(exch, NET_SOCKET_RECEIVED, (sysarg_t) socket->socket_id,
-	    packet_dimension->content, 0, 0, (sysarg_t) fragments);
-	async_exchange_end(exch);
-
-	return EOK;
-}
-
-/** Processes the received UDP packet queue.
- *
- * Is used as an entry point from the underlying IP module.
- * Locks the global lock and calls udp_process_packet() function.
- *
- * @param[in] device_id	The receiving device identifier.
- * @param[in,out] packet The received packet queue.
- * @param receiver	The target service. Ignored parameter.
- * @param[in] error	The packet error reporting service. Prefixes the
- *			received packet.
- * @return		EOK on success.
- * @return		Other error codes as defined for the
- *			udp_process_packet() function.
- */
-static int udp_received_msg(nic_device_id_t device_id, packet_t *packet,
-    services_t receiver, services_t error)
-{
-	int result;
-
-	fibril_rwlock_write_lock(&udp_globals.lock);
-	result = udp_process_packet(device_id, packet, error);
-	if (result != EOK)
-		fibril_rwlock_write_unlock(&udp_globals.lock);
-
-	return result;
-}
-
-/** Process IPC messages from the IP module
- *
- * @param[in]     iid   Message identifier.
- * @param[in,out] icall Message parameters.
- * @param[in]     arg   Local argument.
- *
- */
-static void udp_receiver(ipc_callid_t iid, ipc_call_t *icall, void *arg)
-{
-	packet_t *packet;
-	int rc;
-	
-	while (true) {
-		switch (IPC_GET_IMETHOD(*icall)) {
-		case NET_TL_RECEIVED:
-			rc = packet_translate_remote(udp_globals.net_sess, &packet,
-			    IPC_GET_PACKET(*icall));
-			if (rc == EOK)
-				rc = udp_received_msg(IPC_GET_DEVICE(*icall), packet,
-				    SERVICE_UDP, IPC_GET_ERROR(*icall));
-			
-			async_answer_0(iid, (sysarg_t) rc);
-			break;
-		default:
-			async_answer_0(iid, (sysarg_t) ENOTSUP);
-		}
-		
-		iid = async_get_call(icall);
-	}
-}
-
-/** Initialize the UDP module.
- *
- * @param[in] sess Network module session.
- *
- * @return EOK on success.
- * @return ENOMEM if there is not enough memory left.
- *
- */
-int tl_initialize(async_sess_t *sess)
-{
-	measured_string_t names[] = {
-		{
-			(uint8_t *) "UDP_CHECKSUM_COMPUTING",
-			22
-		},
-		{
-			(uint8_t *) "UDP_AUTOBINDING",
-			15
-		}
-	};
-	measured_string_t *configuration;
-	size_t count = sizeof(names) / sizeof(measured_string_t);
-	uint8_t *data;
-	
-	fibril_rwlock_initialize(&udp_globals.lock);
-	fibril_rwlock_write_lock(&udp_globals.lock);
-	
-	udp_globals.net_sess = sess;
-	udp_globals.icmp_sess = icmp_connect_module();
-	
-	udp_globals.ip_sess = ip_bind_service(SERVICE_IP, IPPROTO_UDP,
-	     SERVICE_UDP, udp_receiver);
-	if (udp_globals.ip_sess == NULL) {
-	    fibril_rwlock_write_unlock(&udp_globals.lock);
-	    return ENOENT;
-	}
-	
-	/* Read default packet dimensions */
-	int rc = ip_packet_size_req(udp_globals.ip_sess, -1,
-	    &udp_globals.packet_dimension);
-	if (rc != EOK) {
-		fibril_rwlock_write_unlock(&udp_globals.lock);
-		return rc;
-	}
-	
-	rc = socket_ports_initialize(&udp_globals.sockets);
-	if (rc != EOK) {
-		fibril_rwlock_write_unlock(&udp_globals.lock);
-		return rc;
-	}
-	
-	rc = packet_dimensions_initialize(&udp_globals.dimensions);
-	if (rc != EOK) {
-		socket_ports_destroy(&udp_globals.sockets, free);
-		fibril_rwlock_write_unlock(&udp_globals.lock);
-		return rc;
-	}
-	
-	udp_globals.packet_dimension.prefix += sizeof(udp_header_t);
-	udp_globals.packet_dimension.content -= sizeof(udp_header_t);
-	udp_globals.last_used_port = UDP_FREE_PORTS_START - 1;
-
-	udp_globals.checksum_computing = NET_DEFAULT_UDP_CHECKSUM_COMPUTING;
-	udp_globals.autobinding = NET_DEFAULT_UDP_AUTOBINDING;
-
-	/* Get configuration */
-	configuration = &names[0];
-	rc = net_get_conf_req(udp_globals.net_sess, &configuration, count,
-	    &data);
-	if (rc != EOK) {
-		socket_ports_destroy(&udp_globals.sockets, free);
-		fibril_rwlock_write_unlock(&udp_globals.lock);
-		return rc;
-	}
-	
-	if (configuration) {
-		if (configuration[0].value)
-			udp_globals.checksum_computing =
-			    (configuration[0].value[0] == 'y');
-		
-		if (configuration[1].value)
-			udp_globals.autobinding =
-			    (configuration[1].value[0] == 'y');
-
-		net_free_settings(configuration, data);
-	}
-
-	fibril_rwlock_write_unlock(&udp_globals.lock);
-	return EOK;
-}
-
-/** Sends data from the socket to the remote address.
- *
- * Binds the socket to a free port if not already connected/bound.
- * Handles the NET_SOCKET_SENDTO message.
- * Supports AF_INET and AF_INET6 address families.
- *
- * @param[in,out] local_sockets The application local sockets.
- * @param[in] socket_id	Socket identifier.
- * @param[in] addr	The destination address.
- * @param[in] addrlen	The address length.
- * @param[in] fragments	The number of data fragments.
- * @param[out] data_fragment_size The data fragment size in bytes.
- * @param[in] flags	Various send flags.
- * @return		EOK on success.
- * @return		EAFNOTSUPPORT if the address family is not supported.
- * @return		ENOTSOCK if the socket is not found.
- * @return		EINVAL if the address is invalid.
- * @return		ENOTCONN if the sending socket is not and cannot be
- *			bound.
- * @return		ENOMEM if there is not enough memory left.
- * @return		Other error codes as defined for the
- *			socket_read_packet_data() function.
- * @return		Other error codes as defined for the
- *			ip_client_prepare_packet() function.
- * @return		Other error codes as defined for the ip_send_msg()
- *			function.
- */
-static int udp_sendto_message(socket_cores_t *local_sockets, int socket_id,
-    const struct sockaddr *addr, socklen_t addrlen, int fragments,
-    size_t *data_fragment_size, int flags)
-{
-	socket_core_t *socket;
-	packet_t *packet;
-	packet_t *next_packet;
-	udp_header_t *header;
-	int index;
-	size_t total_length;
-	int result;
-	uint16_t dest_port;
-	uint32_t checksum;
-	void *ip_header;
-	size_t headerlen;
-	nic_device_id_t device_id;
-	packet_dimension_t *packet_dimension;
-	size_t size;
-	int rc;
-
-	/* In case of error, do not update the data fragment size. */
-	*data_fragment_size = 0;
-	
-	rc = tl_get_address_port(addr, addrlen, &dest_port);
-	if (rc != EOK)
-		return rc;
-
-	socket = socket_cores_find(local_sockets, socket_id);
-	if (!socket)
-		return ENOTSOCK;
-
-	if ((socket->port <= 0) && udp_globals.autobinding) {
-		/* Bind the socket to a random free port if not bound */
-		rc = socket_bind_free_port(&udp_globals.sockets, socket,
-		    UDP_FREE_PORTS_START, UDP_FREE_PORTS_END,
-		    udp_globals.last_used_port);
-		if (rc != EOK)
-			return rc;
-		/* Set the next port as the search starting port number */
-		udp_globals.last_used_port = socket->port;
-	}
-
-	if (udp_globals.checksum_computing) {
-		rc = ip_get_route_req(udp_globals.ip_sess, IPPROTO_UDP, addr,
-		    addrlen, &device_id, &ip_header, &headerlen);
-		if (rc != EOK)
-			return rc;
-		/* Get the device packet dimension */
-//		rc = tl_get_ip_packet_dimension(udp_globals.ip_sess,
-//		    &udp_globals.dimensions, device_id, &packet_dimension);
-//		if (rc != EOK)
-//			return rc;
-	}
-//	} else {
-		/* Do not ask all the time */
-		rc = ip_packet_size_req(udp_globals.ip_sess, -1,
-		    &udp_globals.packet_dimension);
-		if (rc != EOK)
-			return rc;
-		packet_dimension = &udp_globals.packet_dimension;
-//	}
-
-	/*
-	 * Update the data fragment size based on what the lower layers can
-	 * handle without fragmentation, but not more than the maximum allowed
-	 * for UDP.
-	 */
-	size = MAX_UDP_FRAGMENT_SIZE;
-	if (packet_dimension->content < size)
-	    size = packet_dimension->content;
-	*data_fragment_size = size;
-
-	/* Read the first packet fragment */
-	result = tl_socket_read_packet_data(udp_globals.net_sess, &packet,
-	    UDP_HEADER_SIZE, packet_dimension, addr, addrlen);
-	if (result < 0)
-		return result;
-
-	total_length = (size_t) result;
-	if (udp_globals.checksum_computing)
-		checksum = compute_checksum(0, packet_get_data(packet),
-		    packet_get_data_length(packet));
-	else
-		checksum = 0;
-
-	/* Prefix the UDP header */
-	header = PACKET_PREFIX(packet, udp_header_t);
-	if (!header)
-		return udp_release_and_return(packet, ENOMEM);
-
-	bzero(header, sizeof(*header));
-
-	/* Read the rest of the packet fragments */
-	for (index = 1; index < fragments; index++) {
-		result = tl_socket_read_packet_data(udp_globals.net_sess,
-		    &next_packet, 0, packet_dimension, addr, addrlen);
-		if (result < 0)
-			return udp_release_and_return(packet, result);
-
-		rc = pq_add(&packet, next_packet, index, 0);
-		if (rc != EOK)
-			return udp_release_and_return(packet, rc);
-
-		total_length += (size_t) result;
-		if (udp_globals.checksum_computing) {
-			checksum = compute_checksum(checksum,
-			    packet_get_data(next_packet),
-			    packet_get_data_length(next_packet));
-		}
-	}
-
-	/* Set the UDP header */
-	header->source_port = htons((socket->port > 0) ? socket->port : 0);
-	header->destination_port = htons(dest_port);
-	header->total_length = htons(total_length + sizeof(*header));
-	header->checksum = 0;
-
-	if (udp_globals.checksum_computing) {
-		/* Update the pseudo header */
-		rc = ip_client_set_pseudo_header_data_length(ip_header,
-		    headerlen, total_length + UDP_HEADER_SIZE);
-		if (rc != EOK) {
-			free(ip_header);
-			return udp_release_and_return(packet, rc);
-		}
-
-		/* Finish the checksum computation */
-		checksum = compute_checksum(checksum, ip_header, headerlen);
-		checksum = compute_checksum(checksum, (uint8_t *) header,
-		    sizeof(*header));
-		header->checksum =
-		    htons(flip_checksum(compact_checksum(checksum)));
-		free(ip_header);
-	} else
-		device_id = NIC_DEVICE_INVALID_ID;
-
-	/* Prepare the first packet fragment */
-	rc = ip_client_prepare_packet(packet, IPPROTO_UDP, 0, 0, 0, 0);
-	if (rc != EOK)
-		return udp_release_and_return(packet, rc);
-
-	/* Release the UDP global lock on success. */
-	fibril_rwlock_write_unlock(&udp_globals.lock);
-
-	/* Send the packet */
-	ip_send_msg(udp_globals.ip_sess, device_id, packet, SERVICE_UDP, 0);
-
-	return EOK;
-}
-
-/** Receives data to the socket.
- *
- * Handles the NET_SOCKET_RECVFROM message.
- * Replies the source address as well.
- *
- * @param[in] local_sockets The application local sockets.
- * @param[in] socket_id	Socket identifier.
- * @param[in] flags	Various receive flags.
- * @param[out] addrlen	The source address length.
- * @return		The number of bytes received.
- * @return		ENOTSOCK if the socket is not found.
- * @return		NO_DATA if there are no received packets or data.
- * @return		ENOMEM if there is not enough memory left.
- * @return		EINVAL if the received address is not an IP address.
- * @return		Other error codes as defined for the packet_translate()
- *			function.
- * @return		Other error codes as defined for the data_reply()
- *			function.
- */
-static int udp_recvfrom_message(socket_cores_t *local_sockets, int socket_id,
-    int flags, size_t *addrlen)
-{
-	socket_core_t *socket;
-	int packet_id;
-	packet_t *packet;
-	udp_header_t *header;
-	struct sockaddr *addr;
-	size_t length;
-	uint8_t *data;
-	int result;
-	int rc;
-
-	/* Find the socket */
-	socket = socket_cores_find(local_sockets, socket_id);
-	if (!socket)
-		return ENOTSOCK;
-
-	/* Get the next received packet */
-	packet_id = dyn_fifo_value(&socket->received);
-	if (packet_id < 0)
-		return NO_DATA;
-	
-	rc = packet_translate_remote(udp_globals.net_sess, &packet, packet_id);
-	if (rc != EOK) {
-		(void) dyn_fifo_pop(&socket->received);
-		return rc;
-	}
-
-	/* Get UDP header */
-	data = packet_get_data(packet);
-	if (!data) {
-		(void) dyn_fifo_pop(&socket->received);
-		return udp_release_and_return(packet, NO_DATA);
-	}
-	header = (udp_header_t *) data;
-
-	/* Set the source address port */
-	result = packet_get_addr(packet, (uint8_t **) &addr, NULL);
-	rc = tl_set_address_port(addr, result, ntohs(header->source_port));
-	if (rc != EOK) {
-		(void) dyn_fifo_pop(&socket->received);
-		return udp_release_and_return(packet, rc);
-	}
-	*addrlen = (size_t) result;
-
-	/* Send the source address */
-	rc = data_reply(addr, *addrlen);
-	switch (rc) {
-	case EOK:
-		break;
-	case EOVERFLOW:
-		return rc;
-	default:
-		(void) dyn_fifo_pop(&socket->received);
-		return udp_release_and_return(packet, rc);
-	}
-
-	/* Trim the header */
-	rc = packet_trim(packet, UDP_HEADER_SIZE, 0);
-	if (rc != EOK) {
-		(void) dyn_fifo_pop(&socket->received);
-		return udp_release_and_return(packet, rc);
-	}
-
-	/* Reply the packets */
-	rc = socket_reply_packets(packet, &length);
-	switch (rc) {
-	case EOK:
-		break;
-	case EOVERFLOW:
-		return rc;
-	default:
-		(void) dyn_fifo_pop(&socket->received);
-		return udp_release_and_return(packet, rc);
-	}
-
-	(void) dyn_fifo_pop(&socket->received);
-
-	/* Release the packet and return the total length */
-	return udp_release_and_return(packet, (int) length);
-}
-
-/** Process the socket client messages.
- *
- * Run until the client module disconnects.
- *
- * @see socket.h
- *
- * @param[in] sess   Callback session.
- * @param[in] callid Message identifier.
- * @param[in] call   Message parameters.
- *
- * @return EOK on success.
- *
- */
-static int udp_process_client_messages(async_sess_t *sess, ipc_callid_t callid,
-    ipc_call_t call)
-{
-	int res;
-	socket_cores_t local_sockets;
-	struct sockaddr *addr;
-	int socket_id;
-	size_t addrlen;
-	size_t size;
-	ipc_call_t answer;
-	size_t answer_count;
-	packet_dimension_t *packet_dimension;
-
-	/*
-	 * Accept the connection
-	 *  - Answer the first IPC_M_CONNECT_TO_ME call.
-	 */
-	res = EOK;
-	answer_count = 0;
-
-	/*
-	 * The client connection is only in one fibril and therefore no
-	 * additional locks are needed.
-	 */
-
-	socket_cores_initialize(&local_sockets);
-
-	while (true) {
-
-		/* Answer the call */
-		answer_call(callid, res, &answer, answer_count);
-
-		/* Refresh data */
-		refresh_answer(&answer, &answer_count);
-
-		/* Get the next call */
-		callid = async_get_call(&call);
-
-		/* Process the call */
-		if (!IPC_GET_IMETHOD(call)) {
-			res = EHANGUP;
-			break;
-		}
-		
-		switch (IPC_GET_IMETHOD(call)) {
-		case NET_SOCKET:
-			socket_id = SOCKET_GET_SOCKET_ID(call);
-			res = socket_create(&local_sockets, sess, NULL,
-			    &socket_id);
-			SOCKET_SET_SOCKET_ID(answer, socket_id);
-
-			if (res != EOK)
-				break;
-			
-			size = MAX_UDP_FRAGMENT_SIZE;
-			if (tl_get_ip_packet_dimension(udp_globals.ip_sess,
-			    &udp_globals.dimensions, NIC_DEVICE_INVALID_ID,
-			    &packet_dimension) == EOK) {
-				if (packet_dimension->content < size)
-					size = packet_dimension->content;
-			}
-			SOCKET_SET_DATA_FRAGMENT_SIZE(answer, size);
-			SOCKET_SET_HEADER_SIZE(answer, UDP_HEADER_SIZE);
-			answer_count = 3;
-			break;
-
-		case NET_SOCKET_BIND:
-			res = async_data_write_accept((void **) &addr, false,
-			    0, 0, 0, &addrlen);
-			if (res != EOK)
-				break;
-			fibril_rwlock_write_lock(&udp_globals.lock);
-			res = socket_bind(&local_sockets, &udp_globals.sockets,
-			    SOCKET_GET_SOCKET_ID(call), addr, addrlen,
-			    UDP_FREE_PORTS_START, UDP_FREE_PORTS_END,
-			    udp_globals.last_used_port);
-			fibril_rwlock_write_unlock(&udp_globals.lock);
-			free(addr);
-			break;
-
-		case NET_SOCKET_SENDTO:
-			res = async_data_write_accept((void **) &addr, false,
-			    0, 0, 0, &addrlen);
-			if (res != EOK)
-				break;
-
-			fibril_rwlock_write_lock(&udp_globals.lock);
-			res = udp_sendto_message(&local_sockets,
-			    SOCKET_GET_SOCKET_ID(call), addr, addrlen,
-			    SOCKET_GET_DATA_FRAGMENTS(call), &size,
-			    SOCKET_GET_FLAGS(call));
-			SOCKET_SET_DATA_FRAGMENT_SIZE(answer, size);
-
-			if (res != EOK)
-				fibril_rwlock_write_unlock(&udp_globals.lock);
-			else
-				answer_count = 2;
-			
-			free(addr);
-			break;
-
-		case NET_SOCKET_RECVFROM:
-			fibril_rwlock_write_lock(&udp_globals.lock);
-			res = udp_recvfrom_message(&local_sockets,
-			     SOCKET_GET_SOCKET_ID(call), SOCKET_GET_FLAGS(call),
-			     &addrlen);
-			fibril_rwlock_write_unlock(&udp_globals.lock);
-
-			if (res <= 0)
-				break;
-
-			SOCKET_SET_READ_DATA_LENGTH(answer, res);
-			SOCKET_SET_ADDRESS_LENGTH(answer, addrlen);
-			answer_count = 3;
-			res = EOK;
-			break;
-			
-		case NET_SOCKET_CLOSE:
-			fibril_rwlock_write_lock(&udp_globals.lock);
-			res = socket_destroy(udp_globals.net_sess,
-			    SOCKET_GET_SOCKET_ID(call), &local_sockets,
-			    &udp_globals.sockets, NULL);
-			fibril_rwlock_write_unlock(&udp_globals.lock);
-			break;
-
-		case NET_SOCKET_GETSOCKOPT:
-		case NET_SOCKET_SETSOCKOPT:
-		default:
-			res = ENOTSUP;
-			break;
-		}
-	}
-
-	/* Release the application session */
-	async_hangup(sess);
-
-	/* Release all local sockets */
-	socket_cores_release(udp_globals.net_sess, &local_sockets,
-	    &udp_globals.sockets, NULL);
-
-	return res;
-}
-
-/** Per-connection initialization
- *
- */
-void tl_connection(void)
-{
-}
-
-/** Processes the UDP message.
- *
- * @param[in] callid	The message identifier.
- * @param[in] call	The message parameters.
- * @param[out] answer	The message answer parameters.
- * @param[out] answer_count The last parameter for the actual answer in the
- *			answer parameter.
- * @return		EOK on success.
- * @return		ENOTSUP if the message is not known.
- *
- * @see udp_interface.h
- * @see IS_NET_UDP_MESSAGE()
- */
-int tl_message(ipc_callid_t callid, ipc_call_t *call,
-    ipc_call_t *answer, size_t *answer_count)
-{
-	*answer_count = 0;
-	
-	async_sess_t *callback =
-	    async_callback_receive_start(EXCHANGE_SERIALIZE, call);
-	if (callback)
-		return udp_process_client_messages(callback, callid, *call);
-	
-	return ENOTSUP;
-}
-
-int main(int argc, char *argv[])
-{
-	/* Start the module */
-	return tl_module_start(SERVICE_UDP);
-}
-
-/** @}
- */
Index: pace/srv/net/tl/udp/udp.h
===================================================================
--- uspace/srv/net/tl/udp/udp.h	(revision bf31e3f1ebd6e88e0c8425f109e42ccd92b6c9b3)
+++ 	(revision )
@@ -1,77 +1,0 @@
-/*
- * Copyright (c) 2008 Lukas Mejdrech
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup udp
- * @{
- */
-
-/** @file
- * UDP module.
- */
-
-#ifndef NET_UDP_H_
-#define NET_UDP_H_
-
-#include <async.h>
-#include <fibril_synch.h>
-#include <socket_core.h>
-#include <tl_common.h>
-
-/** Type definition of the UDP global data.
- * @see udp_globals
- */
-typedef struct udp_globals udp_globals_t;
-
-/** UDP global data. */
-struct udp_globals {
-	/** Networking module session. */
-	async_sess_t *net_sess;
-	/** IP module session. */
-	async_sess_t *ip_sess;
-	/** ICMP module session. */
-	async_sess_t *icmp_sess;
-	/** Packet dimension. */
-	packet_dimension_t packet_dimension;
-	/** Indicates whether UDP checksum computing is enabled. */
-	int checksum_computing;
-	/** Indicates whether UDP autobnding on send is enabled. */
-	int autobinding;
-	/** Last used free port. */
-	int last_used_port;
-	/** Active sockets. */
-	socket_ports_t sockets;
-	/** Device packet dimensions. */
-	packet_dimensions_t dimensions;
-	/** Safety lock. */
-	fibril_rwlock_t lock;
-};
-
-#endif
-
-/** @}
- */
Index: pace/srv/net/tl/udp/udp_header.h
===================================================================
--- uspace/srv/net/tl/udp/udp_header.h	(revision bf31e3f1ebd6e88e0c8425f109e42ccd92b6c9b3)
+++ 	(revision )
@@ -1,62 +1,0 @@
-/*
- * Copyright (c) 2009 Lukas Mejdrech
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup udp
- * @{
- */
-
-/** @file
- * UDP header definition.
- * Based on the RFC 768.
- */
-
-#ifndef NET_UDP_HEADER_H_
-#define NET_UDP_HEADER_H_
-
-#include <sys/types.h>
-
-/** UDP header size in bytes. */
-#define UDP_HEADER_SIZE		sizeof(udp_header_t)
-
-/** Type definition of the user datagram header.
- * @see udp_header
- */
-typedef struct udp_header udp_header_t;
-
-/** User datagram header. */
-struct udp_header {
-	uint16_t source_port;
-	uint16_t destination_port;
-	uint16_t total_length;
-	uint16_t checksum;
-} __attribute__ ((packed));
-
-#endif
-
-/** @}
- */
Index: uspace/srv/tcp/Makefile
===================================================================
--- uspace/srv/tcp/Makefile	(revision 4d9fe7b307128cbbbd04d982fef935c842053872)
+++ uspace/srv/tcp/Makefile	(revision 4d9fe7b307128cbbbd04d982fef935c842053872)
@@ -0,0 +1,48 @@
+#
+# Copyright (c) 2011 Jiri Svoboda
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# - Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+# - Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in the
+#   documentation and/or other materials provided with the distribution.
+# - The name of the author may not be used to endorse or promote products
+#   derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+USPACE_PREFIX = ../../../..
+LIBS = $(LIBNET_PREFIX)/libnet.a
+EXTRA_CFLAGS = -I$(LIBNET_PREFIX)/include
+BINARY = tcp
+
+SOURCES = \
+	conn.c \
+	iqueue.c \
+	ncsim.c \
+	pdu.c \
+	rqueue.c \
+	segment.c \
+	seq_no.c \
+	sock.c \
+	tcp.c \
+	test.c \
+	tqueue.c \
+	ucall.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/tcp/conn.c
===================================================================
--- uspace/srv/tcp/conn.c	(revision 4d9fe7b307128cbbbd04d982fef935c842053872)
+++ uspace/srv/tcp/conn.c	(revision 4d9fe7b307128cbbbd04d982fef935c842053872)
@@ -0,0 +1,1282 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup tcp
+ * @{
+ */
+
+/**
+ * @file TCP connection processing and state machine
+ */
+
+#include <adt/list.h>
+#include <bool.h>
+#include <errno.h>
+#include <io/log.h>
+#include <macros.h>
+#include <stdlib.h>
+#include "conn.h"
+#include "iqueue.h"
+#include "segment.h"
+#include "seq_no.h"
+#include "tcp_type.h"
+#include "tqueue.h"
+#include "ucall.h"
+
+#define RCV_BUF_SIZE 4096/*2*/
+#define SND_BUF_SIZE 4096
+
+#define MAX_SEGMENT_LIFETIME	(15*1000*1000) //(2*60*1000*1000)
+#define TIME_WAIT_TIMEOUT	(2*MAX_SEGMENT_LIFETIME)
+
+LIST_INITIALIZE(conn_list);
+FIBRIL_MUTEX_INITIALIZE(conn_list_lock);
+
+static void tcp_conn_seg_process(tcp_conn_t *conn, tcp_segment_t *seg);
+static void tcp_conn_tw_timer_set(tcp_conn_t *conn);
+static void tcp_conn_tw_timer_clear(tcp_conn_t *conn);
+
+/** Create new connection structure.
+ *
+ * @param lsock		Local socket (will be deeply copied)
+ * @param fsock		Foreign socket (will be deeply copied)
+ * @return		New connection or NULL
+ */
+tcp_conn_t *tcp_conn_new(tcp_sock_t *lsock, tcp_sock_t *fsock)
+{
+	tcp_conn_t *conn = NULL;
+	bool tqueue_inited = false;
+
+	/* Allocate connection structure */
+	conn = calloc(1, sizeof(tcp_conn_t));
+	if (conn == NULL)
+		goto error;
+
+	conn->tw_timer = fibril_timer_create();
+	if (conn->tw_timer == NULL)
+		goto error;
+
+	fibril_mutex_initialize(&conn->lock);
+
+	/* One for the user, one for not being in closed state */
+	atomic_set(&conn->refcnt, 2);
+
+	/* Allocate receive buffer */
+	fibril_condvar_initialize(&conn->rcv_buf_cv);
+	conn->rcv_buf_size = RCV_BUF_SIZE;
+	conn->rcv_buf_used = 0;
+	conn->rcv_buf_fin = false;
+
+	conn->rcv_buf = calloc(1, conn->rcv_buf_size);
+	if (conn->rcv_buf == NULL)
+		goto error;
+
+	/** Allocate send buffer */
+	fibril_condvar_initialize(&conn->snd_buf_cv);
+	conn->snd_buf_size = SND_BUF_SIZE;
+	conn->snd_buf_used = 0;
+	conn->snd_buf_fin = false;
+	conn->snd_buf = calloc(1, conn->snd_buf_size);
+	if (conn->snd_buf == NULL)
+		goto error;
+
+	/* Set up receive window. */
+	conn->rcv_wnd = conn->rcv_buf_size;
+
+	/* Initialize incoming segment queue */
+	tcp_iqueue_init(&conn->incoming, conn);
+
+	/* Initialize retransmission queue */
+	if (tcp_tqueue_init(&conn->retransmit, conn) != EOK)
+		goto error;
+
+	tqueue_inited = true;
+
+	/* Connection state change signalling */
+	fibril_condvar_initialize(&conn->cstate_cv);
+
+	conn->cstate_cb = NULL;
+
+	conn->cstate = st_listen;
+	conn->reset = false;
+	conn->deleted = false;
+	conn->ap = ap_passive;
+	conn->fin_is_acked = false;
+	conn->ident.local = *lsock;
+	if (fsock != NULL)
+		conn->ident.foreign = *fsock;
+
+	return conn;
+
+error:
+	if (tqueue_inited)
+		tcp_tqueue_fini(&conn->retransmit);
+	if (conn != NULL && conn->rcv_buf != NULL)
+		free(conn->rcv_buf);
+	if (conn != NULL && conn->snd_buf != NULL)
+		free(conn->snd_buf);
+	if (conn != NULL && conn->tw_timer != NULL)
+		fibril_timer_destroy(conn->tw_timer);
+	if (conn != NULL)
+		free(conn);
+
+	return NULL;
+}
+
+/** Destroy connection structure.
+ *
+ * Connection structure should be destroyed when the folowing condtitions
+ * are met:
+ * (1) user has deleted the connection
+ * (2) the connection has entered closed state
+ * (3) nobody is holding references to the connection
+ *
+ * This happens when @a conn->refcnt is zero as we count (1) and (2)
+ * as special references.
+ *
+ * @param conn		Connection
+ */
+static void tcp_conn_free(tcp_conn_t *conn)
+{
+	log_msg(LVL_DEBUG, "%s: tcp_conn_free(%p)", conn->name, conn);
+	tcp_tqueue_fini(&conn->retransmit);
+
+	if (conn->rcv_buf != NULL)
+		free(conn->rcv_buf);
+	if (conn->snd_buf != NULL)
+		free(conn->snd_buf);
+	if (conn->tw_timer != NULL)
+		fibril_timer_destroy(conn->tw_timer);
+	free(conn);
+}
+
+/** Add reference to connection.
+ *
+ * Increase connection reference count by one.
+ *
+ * @param conn		Connection
+ */
+void tcp_conn_addref(tcp_conn_t *conn)
+{
+	log_msg(LVL_DEBUG, "%s: tcp_conn_addref(%p)", conn->name, conn);
+	atomic_inc(&conn->refcnt);
+}
+
+/** Remove reference from connection.
+ *
+ * Decrease connection reference count by one.
+ *
+ * @param conn		Connection
+ */
+void tcp_conn_delref(tcp_conn_t *conn)
+{
+	log_msg(LVL_DEBUG, "%s: tcp_conn_delref(%p)", conn->name, conn);
+
+	if (atomic_predec(&conn->refcnt) == 0)
+		tcp_conn_free(conn);
+}
+
+/** Delete connection.
+ *
+ * The caller promises not make no further references to @a conn.
+ * TCP will free @a conn eventually.
+ *
+ * @param conn		Connection
+ */
+void tcp_conn_delete(tcp_conn_t *conn)
+{
+	log_msg(LVL_DEBUG, "%s: tcp_conn_delete(%p)", conn->name, conn);
+
+	assert(conn->deleted == false);
+	tcp_conn_delref(conn);
+}
+
+/** Enlist connection.
+ *
+ * Add connection to the connection map.
+ */
+void tcp_conn_add(tcp_conn_t *conn)
+{
+	tcp_conn_addref(conn);
+	fibril_mutex_lock(&conn_list_lock);
+	list_append(&conn->link, &conn_list);
+	fibril_mutex_unlock(&conn_list_lock);
+}
+
+/** Delist connection.
+ *
+ * Remove connection from the connection map.
+ */
+void tcp_conn_remove(tcp_conn_t *conn)
+{
+	fibril_mutex_lock(&conn_list_lock);
+	list_remove(&conn->link);
+	fibril_mutex_unlock(&conn_list_lock);
+	tcp_conn_delref(conn);
+}
+
+static void tcp_conn_state_set(tcp_conn_t *conn, tcp_cstate_t nstate)
+{
+	tcp_cstate_t old_state;
+
+	log_msg(LVL_DEBUG, "tcp_conn_state_set(%p)", conn);
+
+	old_state = conn->cstate;
+	conn->cstate = nstate;
+	fibril_condvar_broadcast(&conn->cstate_cv);
+
+	/* Run user callback function */
+	if (conn->cstate_cb != NULL) {
+		log_msg(LVL_DEBUG, "tcp_conn_state_set() - run user CB");
+		conn->cstate_cb(conn, conn->cstate_cb_arg);
+	} else {
+		log_msg(LVL_DEBUG, "tcp_conn_state_set() - no user CB");
+	}
+
+	assert(old_state != st_closed);
+	if (nstate == st_closed) {
+		/* Drop one reference for now being in closed state */
+		tcp_conn_delref(conn);
+	}
+}
+
+/** Synchronize connection.
+ *
+ * This is the first step of an active connection attempt,
+ * sends out SYN and sets up ISS and SND.xxx.
+ */
+void tcp_conn_sync(tcp_conn_t *conn)
+{
+	/* XXX select ISS */
+	conn->iss = 1;
+	conn->snd_nxt = conn->iss;
+	conn->snd_una = conn->iss;
+	conn->ap = ap_active;
+
+	tcp_tqueue_ctrl_seg(conn, CTL_SYN);
+	tcp_conn_state_set(conn, st_syn_sent);
+}
+
+/** FIN has been sent.
+ *
+ * This function should be called when FIN is sent over the connection,
+ * as a result the connection state is changed appropriately.
+ */
+void tcp_conn_fin_sent(tcp_conn_t *conn)
+{
+	switch (conn->cstate) {
+	case st_syn_received:
+	case st_established:
+		log_msg(LVL_DEBUG, "%s: FIN sent -> Fin-Wait-1", conn->name);
+		tcp_conn_state_set(conn, st_fin_wait_1);
+		break;
+	case st_close_wait:
+		log_msg(LVL_DEBUG, "%s: FIN sent -> Last-Ack", conn->name);
+		tcp_conn_state_set(conn, st_last_ack);
+		break;
+	default:
+		log_msg(LVL_ERROR, "%s: Connection state %d", conn->name,
+		    conn->cstate);
+		assert(false);
+	}
+
+	conn->fin_is_acked = false;
+}
+
+/** Compare two sockets.
+ *
+ * Two sockets are equal if the address is equal and the port number
+ * is equal.
+ */
+static bool tcp_socket_match(tcp_sock_t *sock, tcp_sock_t *patt)
+{
+	log_msg(LVL_DEBUG, "tcp_socket_match(sock=(%x,%u), pat=(%x,%u))",
+	    sock->addr.ipv4, sock->port, patt->addr.ipv4, patt->port);
+
+	if (patt->addr.ipv4 != TCP_IPV4_ANY &&
+	    patt->addr.ipv4 != sock->addr.ipv4)
+		return false;
+
+	if (patt->port != TCP_PORT_ANY &&
+	    patt->port != sock->port)
+		return false;
+
+	log_msg(LVL_DEBUG, " -> match");
+
+	return true;
+}
+
+/** Match socket with pattern. */
+static bool tcp_sockpair_match(tcp_sockpair_t *sp, tcp_sockpair_t *pattern)
+{
+	log_msg(LVL_DEBUG, "tcp_sockpair_match(%p, %p)", sp, pattern);
+
+	if (!tcp_socket_match(&sp->local, &pattern->local))
+		return false;
+
+	if (!tcp_socket_match(&sp->foreign, &pattern->foreign))
+		return false;
+
+	return true;
+}
+
+/** Find connection structure for specified socket pair.
+ *
+ * A connection is uniquely identified by a socket pair. Look up our
+ * connection map and return connection structure based on socket pair.
+ * The connection reference count is bumped by one.
+ *
+ * @param sp	Socket pair
+ * @return	Connection structure or NULL if not found.
+ */
+tcp_conn_t *tcp_conn_find_ref(tcp_sockpair_t *sp)
+{
+	log_msg(LVL_DEBUG, "tcp_conn_find(%p)", sp);
+
+	fibril_mutex_lock(&conn_list_lock);
+
+	list_foreach(conn_list, link) {
+		tcp_conn_t *conn = list_get_instance(link, tcp_conn_t, link);
+		tcp_sockpair_t *csp = &conn->ident;
+		log_msg(LVL_DEBUG, "compare with conn (f:(%x,%u), l:(%x,%u))",
+		    csp->foreign.addr.ipv4, csp->foreign.port,
+		    csp->local.addr.ipv4, csp->local.port);
+		if (tcp_sockpair_match(sp, csp)) {
+			tcp_conn_addref(conn);
+			fibril_mutex_unlock(&conn_list_lock);
+			return conn;
+		}
+	}
+
+	fibril_mutex_unlock(&conn_list_lock);
+	return NULL;
+}
+
+/** Reset connection.
+ *
+ * @param conn	Connection
+ */
+static void tcp_conn_reset(tcp_conn_t *conn)
+{
+	log_msg(LVL_DEBUG, "%s: tcp_conn_reset()", conn->name);
+	tcp_conn_state_set(conn, st_closed);
+	conn->reset = true;
+
+	tcp_conn_tw_timer_clear(conn);
+	tcp_tqueue_clear(&conn->retransmit);
+
+	fibril_condvar_broadcast(&conn->rcv_buf_cv);
+	fibril_condvar_broadcast(&conn->snd_buf_cv);
+}
+
+/** Signal to the user that connection has been reset.
+ *
+ * Send an out-of-band signal to the user.
+ */
+static void tcp_reset_signal(tcp_conn_t *conn)
+{
+	/* TODO */
+	log_msg(LVL_DEBUG, "%s: tcp_reset_signal()", conn->name);
+}
+
+/** Determine if SYN has been received.
+ *
+ * @param conn	Connection
+ * @return	@c true if SYN has been received, @c false otherwise.
+ */
+bool tcp_conn_got_syn(tcp_conn_t *conn)
+{
+	switch (conn->cstate) {
+	case st_listen:
+	case st_syn_sent:
+		return false;
+	case st_syn_received:
+	case st_established:
+	case st_fin_wait_1:
+	case st_fin_wait_2:
+	case st_close_wait:
+	case st_closing:
+	case st_last_ack:
+	case st_time_wait:
+		return true;
+	case st_closed:
+		log_msg(LVL_WARN, "state=%d", (int) conn->cstate);
+		assert(false);
+	}
+
+	assert(false);
+}
+
+/** Segment arrived in Listen state.
+ *
+ * @param conn		Connection
+ * @param seg		Segment
+ */
+static void tcp_conn_sa_listen(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	log_msg(LVL_DEBUG, "tcp_conn_sa_listen(%p, %p)", conn, seg);
+
+	if ((seg->ctrl & CTL_RST) != 0) {
+		log_msg(LVL_DEBUG, "Ignoring incoming RST.");
+		return;
+	}
+
+	if ((seg->ctrl & CTL_ACK) != 0) {
+		log_msg(LVL_DEBUG, "Incoming ACK, send acceptable RST.");
+		tcp_reply_rst(&conn->ident, seg);
+		return;
+	}
+
+	if ((seg->ctrl & CTL_SYN) == 0) {
+		log_msg(LVL_DEBUG, "SYN not present. Ignoring segment.");
+		return;
+	}
+
+	log_msg(LVL_DEBUG, "Got SYN, sending SYN, ACK.");
+
+	conn->rcv_nxt = seg->seq + 1;
+	conn->irs = seg->seq;
+
+
+	log_msg(LVL_DEBUG, "rcv_nxt=%u", conn->rcv_nxt);
+
+	if (seg->len > 1)
+		log_msg(LVL_WARN, "SYN combined with data, ignoring data.");
+
+	/* XXX select ISS */
+	conn->iss = 1;
+	conn->snd_nxt = conn->iss;
+	conn->snd_una = conn->iss;
+
+	/*
+	 * Surprisingly the spec does not deal with initial window setting.
+	 * Set SND.WND = SEG.WND and set SND.WL1 so that next segment
+	 * will always be accepted as new window setting.
+	 */
+	conn->snd_wnd = seg->wnd;
+	conn->snd_wl1 = seg->seq;
+	conn->snd_wl2 = seg->seq;
+
+	tcp_conn_state_set(conn, st_syn_received);
+
+	tcp_tqueue_ctrl_seg(conn, CTL_SYN | CTL_ACK /* XXX */);
+
+	tcp_segment_delete(seg);
+}
+
+/** Segment arrived in Syn-Sent state.
+ *
+ * @param conn		Connection
+ * @param seg		Segment
+ */
+static void tcp_conn_sa_syn_sent(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	log_msg(LVL_DEBUG, "tcp_conn_sa_syn_sent(%p, %p)", conn, seg);
+
+	if ((seg->ctrl & CTL_ACK) != 0) {
+		log_msg(LVL_DEBUG, "snd_una=%u, seg.ack=%u, snd_nxt=%u",
+		    conn->snd_una, seg->ack, conn->snd_nxt);
+		if (!seq_no_ack_acceptable(conn, seg->ack)) {
+			if ((seg->ctrl & CTL_RST) == 0) {
+				log_msg(LVL_WARN, "ACK not acceptable, send RST");
+				tcp_reply_rst(&conn->ident, seg);
+			} else {
+				log_msg(LVL_WARN, "RST,ACK not acceptable, drop");
+			}
+			return;
+		}
+	}
+
+	if ((seg->ctrl & CTL_RST) != 0) {
+		/* If we get here, we have either an acceptable ACK or no ACK */
+		if ((seg->ctrl & CTL_ACK) != 0) {
+			log_msg(LVL_DEBUG, "%s: Connection reset. -> Closed",
+			    conn->name);
+			/* Reset connection */
+			tcp_conn_reset(conn);
+			return;
+		} else {
+			log_msg(LVL_DEBUG, "%s: RST without ACK, drop",
+			    conn->name);
+			return;
+		}
+	}
+
+	/* XXX precedence */
+
+	if ((seg->ctrl & CTL_SYN) == 0) {
+		log_msg(LVL_DEBUG, "No SYN bit, ignoring segment.");
+		return;
+	}
+
+	conn->rcv_nxt = seg->seq + 1;
+	conn->irs = seg->seq;
+
+	if ((seg->ctrl & CTL_ACK) != 0) {
+		conn->snd_una = seg->ack;
+
+		/*
+		 * Prune acked segments from retransmission queue and
+		 * possibly transmit more data.
+		 */
+		tcp_tqueue_ack_received(conn);
+	}
+
+	log_msg(LVL_DEBUG, "Sent SYN, got SYN.");
+
+	/*
+	 * Surprisingly the spec does not deal with initial window setting.
+	 * Set SND.WND = SEG.WND and set SND.WL1 so that next segment
+	 * will always be accepted as new window setting.
+	 */
+	log_msg(LVL_DEBUG, "SND.WND := %" PRIu32 ", SND.WL1 := %" PRIu32 ", "
+	    "SND.WL2 = %" PRIu32, seg->wnd, seg->seq, seg->seq);
+	conn->snd_wnd = seg->wnd;
+	conn->snd_wl1 = seg->seq;
+	conn->snd_wl2 = seg->seq;
+
+	if (seq_no_syn_acked(conn)) {
+		log_msg(LVL_DEBUG, "%s: syn acked -> Established", conn->name);
+		tcp_conn_state_set(conn, st_established);
+		tcp_tqueue_ctrl_seg(conn, CTL_ACK /* XXX */);
+	} else {
+		log_msg(LVL_DEBUG, "%s: syn not acked -> Syn-Received",
+		    conn->name);
+		tcp_conn_state_set(conn, st_syn_received);
+		tcp_tqueue_ctrl_seg(conn, CTL_SYN | CTL_ACK /* XXX */);
+	}
+
+	tcp_segment_delete(seg);
+}
+
+/** Segment arrived in state where segments are processed in sequence order.
+ *
+ * Queue segment in incoming segments queue for processing.
+ *
+ * @param conn		Connection
+ * @param seg		Segment
+ */
+static void tcp_conn_sa_queue(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	tcp_segment_t *pseg;
+
+	log_msg(LVL_DEBUG, "tcp_conn_sa_seq(%p, %p)", conn, seg);
+
+	/* Discard unacceptable segments ("old duplicates") */
+	if (!seq_no_segment_acceptable(conn, seg)) {
+		log_msg(LVL_DEBUG, "Replying ACK to unacceptable segment.");
+		tcp_tqueue_ctrl_seg(conn, CTL_ACK);
+		tcp_segment_delete(seg);
+		return;
+	}
+
+	/* Queue for processing */
+	tcp_iqueue_insert_seg(&conn->incoming, seg);
+
+	/*
+	 * Process all segments from incoming queue that are ready.
+	 * Unacceptable segments are discarded by tcp_iqueue_get_ready_seg().
+	 *
+	 * XXX Need to return ACK for unacceptable segments
+	 */
+	while (tcp_iqueue_get_ready_seg(&conn->incoming, &pseg) == EOK)
+		tcp_conn_seg_process(conn, pseg);
+}
+
+/** Process segment RST field.
+ *
+ * @param conn		Connection
+ * @param seg		Segment
+ * @return		cp_done if we are done with this segment, cp_continue
+ *			if not
+ */
+static cproc_t tcp_conn_seg_proc_rst(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	if ((seg->ctrl & CTL_RST) == 0)
+		return cp_continue;
+
+	switch (conn->cstate) {
+	case st_syn_received:
+		/* XXX In case of passive open, revert to Listen state */
+		if (conn->ap == ap_passive) {
+			tcp_conn_state_set(conn, st_listen);
+			/* XXX Revert conn->ident */
+			tcp_conn_tw_timer_clear(conn);
+			tcp_tqueue_clear(&conn->retransmit);
+		} else {
+			tcp_conn_reset(conn);
+		}
+		break;
+	case st_established:
+	case st_fin_wait_1:
+	case st_fin_wait_2:
+	case st_close_wait:
+		/* General "connection reset" signal */
+		tcp_reset_signal(conn);
+		tcp_conn_reset(conn);
+		break;
+	case st_closing:
+	case st_last_ack:
+	case st_time_wait:
+		tcp_conn_reset(conn);
+		break;
+	case st_listen:
+	case st_syn_sent:
+	case st_closed:
+		assert(false);
+	}
+
+	return cp_done;
+}
+
+/** Process segment security and precedence fields.
+ *
+ * @param conn		Connection
+ * @param seg		Segment
+ * @return		cp_done if we are done with this segment, cp_continue
+ *			if not
+ */
+static cproc_t tcp_conn_seg_proc_sp(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	/* TODO */
+	return cp_continue;
+}
+
+/** Process segment SYN field.
+ *
+ * @param conn		Connection
+ * @param seg		Segment
+ * @return		cp_done if we are done with this segment, cp_continue
+ *			if not
+ */
+static cproc_t tcp_conn_seg_proc_syn(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	if ((seg->ctrl & CTL_SYN) == 0)
+		return cp_continue;
+
+	/*
+	 * Assert SYN is in receive window, otherwise this step should not
+	 * be reached.
+	 */
+	assert(seq_no_in_rcv_wnd(conn, seg->seq));
+
+	log_msg(LVL_WARN, "SYN is in receive window, should send reset. XXX");
+
+	/*
+	 * TODO
+	 *
+	 * Send a reset, resond "reset" to all outstanding RECEIVEs and SEND,
+	 * flush segment queues. Send unsolicited "connection reset" signal
+	 * to user, connection -> closed state, delete TCB, return.
+	 */
+	return cp_done;
+}
+
+/** Process segment ACK field in Syn-Received state.
+ *
+ * @param conn		Connection
+ * @param seg		Segment
+ * @return		cp_done if we are done with this segment, cp_continue
+ *			if not
+ */
+static cproc_t tcp_conn_seg_proc_ack_sr(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	if (!seq_no_ack_acceptable(conn, seg->ack)) {
+		/* ACK is not acceptable, send RST. */
+		log_msg(LVL_WARN, "Segment ACK not acceptable, sending RST.");
+		tcp_reply_rst(&conn->ident, seg);
+		tcp_segment_delete(seg);
+		return cp_done;
+	}
+
+	log_msg(LVL_DEBUG, "%s: SYN ACKed -> Established", conn->name);
+
+	tcp_conn_state_set(conn, st_established);
+
+	/* XXX Not mentioned in spec?! */
+	conn->snd_una = seg->ack;
+
+	return cp_continue;
+}
+
+/** Process segment ACK field in Established state.
+ *
+ * @param conn		Connection
+ * @param seg		Segment
+ * @return		cp_done if we are done with this segment, cp_continue
+ *			if not
+ */
+static cproc_t tcp_conn_seg_proc_ack_est(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	log_msg(LVL_DEBUG, "tcp_conn_seg_proc_ack_est(%p, %p)", conn, seg);
+
+	log_msg(LVL_DEBUG, "SEG.ACK=%u, SND.UNA=%u, SND.NXT=%u",
+	    (unsigned)seg->ack, (unsigned)conn->snd_una,
+	    (unsigned)conn->snd_nxt);
+
+	if (!seq_no_ack_acceptable(conn, seg->ack)) {
+		log_msg(LVL_DEBUG, "ACK not acceptable.");
+		if (!seq_no_ack_duplicate(conn, seg->ack)) {
+			log_msg(LVL_WARN, "Not acceptable, not duplicate. "
+			    "Send ACK and drop.");
+			/* Not acceptable, not duplicate. Send ACK and drop. */
+			tcp_tqueue_ctrl_seg(conn, CTL_ACK);
+			tcp_segment_delete(seg);
+			return cp_done;
+		} else {
+			log_msg(LVL_DEBUG, "Ignoring duplicate ACK.");
+		}
+	} else {
+		/* Update SND.UNA */
+		conn->snd_una = seg->ack;
+	}
+
+	if (seq_no_new_wnd_update(conn, seg)) {
+		conn->snd_wnd = seg->wnd;
+		conn->snd_wl1 = seg->seq;
+		conn->snd_wl2 = seg->ack;
+
+		log_msg(LVL_DEBUG, "Updating send window, SND.WND=%" PRIu32
+		    ", SND.WL1=%" PRIu32 ", SND.WL2=%" PRIu32,
+		    conn->snd_wnd, conn->snd_wl1, conn->snd_wl2);
+	}
+
+	/*
+	 * Prune acked segments from retransmission queue and
+	 * possibly transmit more data.
+	 */
+	tcp_tqueue_ack_received(conn);
+
+	return cp_continue;
+}
+
+/** Process segment ACK field in Fin-Wait-1 state.
+ *
+ * @param conn		Connection
+ * @param seg		Segment
+ * @return		cp_done if we are done with this segment, cp_continue
+ *			if not
+ */
+static cproc_t tcp_conn_seg_proc_ack_fw1(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	if (tcp_conn_seg_proc_ack_est(conn, seg) == cp_done)
+		return cp_done;
+
+	if (conn->fin_is_acked) {
+		log_msg(LVL_DEBUG, "%s: FIN acked -> Fin-Wait-2", conn->name);
+		tcp_conn_state_set(conn, st_fin_wait_2);
+	}
+
+	return cp_continue;
+}
+
+/** Process segment ACK field in Fin-Wait-2 state.
+ *
+ * @param conn		Connection
+ * @param seg		Segment
+ * @return		cp_done if we are done with this segment, cp_continue
+ *			if not
+ */
+static cproc_t tcp_conn_seg_proc_ack_fw2(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	if (tcp_conn_seg_proc_ack_est(conn, seg) == cp_done)
+		return cp_done;
+
+	/* TODO */
+	return cp_continue;
+}
+
+/** Process segment ACK field in Close-Wait state.
+ *
+ * @param conn		Connection
+ * @param seg		Segment
+ * @return		cp_done if we are done with this segment, cp_continue
+ *			if not
+ */
+static cproc_t tcp_conn_seg_proc_ack_cw(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	/* The same processing as in Established state */
+	return tcp_conn_seg_proc_ack_est(conn, seg);
+}
+
+/** Process segment ACK field in Closing state.
+ *
+ * @param conn		Connection
+ * @param seg		Segment
+ * @return		cp_done if we are done with this segment, cp_continue
+ *			if not
+ */
+static cproc_t tcp_conn_seg_proc_ack_cls(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	if (tcp_conn_seg_proc_ack_est(conn, seg) == cp_done)
+		return cp_done;
+
+	/* TODO */
+	return cp_continue;
+}
+
+/** Process segment ACK field in Last-Ack state.
+ *
+ * @param conn		Connection
+ * @param seg		Segment
+ * @return		cp_done if we are done with this segment, cp_continue
+ *			if not
+ */
+static cproc_t tcp_conn_seg_proc_ack_la(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	if (tcp_conn_seg_proc_ack_est(conn, seg) == cp_done)
+		return cp_done;
+
+	if (conn->fin_is_acked) {
+		log_msg(LVL_DEBUG, "%s: FIN acked -> Closed", conn->name);
+		tcp_conn_remove(conn);
+		tcp_conn_state_set(conn, st_closed);
+		return cp_done;
+	}
+
+	return cp_continue;
+}
+
+/** Process segment ACK field in Time-Wait state.
+ *
+ * @param conn		Connection
+ * @param seg		Segment
+ * @return		cp_done if we are done with this segment, cp_continue
+ *			if not
+ */
+static cproc_t tcp_conn_seg_proc_ack_tw(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	/* Nothing to do */
+	return cp_continue;
+}
+
+/** Process segment ACK field.
+ *
+ * @param conn		Connection
+ * @param seg		Segment
+ * @return		cp_done if we are done with this segment, cp_continue
+ *			if not
+ */
+static cproc_t tcp_conn_seg_proc_ack(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	log_msg(LVL_DEBUG, "%s: tcp_conn_seg_proc_ack(%p, %p)",
+	    conn->name, conn, seg);
+
+	if ((seg->ctrl & CTL_ACK) == 0) {
+		log_msg(LVL_WARN, "Segment has no ACK. Dropping.");
+		tcp_segment_delete(seg);
+		return cp_done;
+	}
+
+	switch (conn->cstate) {
+	case st_syn_received:
+		return tcp_conn_seg_proc_ack_sr(conn, seg);
+	case st_established:
+		return tcp_conn_seg_proc_ack_est(conn, seg);
+	case st_fin_wait_1:
+		return tcp_conn_seg_proc_ack_fw1(conn, seg);
+	case st_fin_wait_2:
+		return tcp_conn_seg_proc_ack_fw2(conn, seg);
+	case st_close_wait:
+		return tcp_conn_seg_proc_ack_cw(conn, seg);
+	case st_closing:
+		return tcp_conn_seg_proc_ack_cls(conn, seg);
+	case st_last_ack:
+		return tcp_conn_seg_proc_ack_la(conn, seg);
+	case st_time_wait:
+		return tcp_conn_seg_proc_ack_tw(conn, seg);
+	case st_listen:
+	case st_syn_sent:
+	case st_closed:
+		assert(false);
+	}
+
+	assert(false);
+}
+
+/** Process segment URG field.
+ *
+ * @param conn		Connection
+ * @param seg		Segment
+ * @return		cp_done if we are done with this segment, cp_continue
+ *			if not
+ */
+static cproc_t tcp_conn_seg_proc_urg(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	return cp_continue;
+}
+
+/** Process segment text.
+ *
+ * @param conn		Connection
+ * @param seg		Segment
+ * @return		cp_done if we are done with this segment, cp_continue
+ *			if not
+ */
+static cproc_t tcp_conn_seg_proc_text(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	size_t text_size;
+	size_t xfer_size;
+
+	log_msg(LVL_DEBUG, "%s: tcp_conn_seg_proc_text(%p, %p)",
+	    conn->name, conn, seg);
+
+	switch (conn->cstate) {
+	case st_established:
+	case st_fin_wait_1:
+	case st_fin_wait_2:
+		/* OK */
+		break;
+	case st_close_wait:
+	case st_closing:
+	case st_last_ack:
+	case st_time_wait:
+		/* Invalid since FIN has been received. Ignore text. */
+		return cp_continue;
+	case st_listen:
+	case st_syn_sent:
+	case st_syn_received:
+	case st_closed:
+		assert(false);
+	}
+
+	/*
+	 * Process segment text
+	 */
+	assert(seq_no_segment_ready(conn, seg));
+
+	/* Trim anything outside our receive window */
+	tcp_conn_trim_seg_to_wnd(conn, seg);
+
+	/* Determine how many bytes to copy */
+	text_size = tcp_segment_text_size(seg);
+	xfer_size = min(text_size, conn->rcv_buf_size - conn->rcv_buf_used);
+
+	/* Copy data to receive buffer */
+	tcp_segment_text_copy(seg, conn->rcv_buf + conn->rcv_buf_used,
+	    xfer_size);
+	conn->rcv_buf_used += xfer_size;
+
+	/* Signal to the receive function that new data has arrived */
+	fibril_condvar_broadcast(&conn->rcv_buf_cv);
+
+	log_msg(LVL_DEBUG, "Received %zu bytes of data.", xfer_size);
+
+	/* Advance RCV.NXT */
+	conn->rcv_nxt += xfer_size;
+
+	/* Update receive window. XXX Not an efficient strategy. */
+	conn->rcv_wnd -= xfer_size;
+
+	/* Send ACK */
+	if (xfer_size > 0)
+		tcp_tqueue_ctrl_seg(conn, CTL_ACK);
+
+	if (xfer_size < seg->len) {
+		/* Trim part of segment which we just received */
+		tcp_conn_trim_seg_to_wnd(conn, seg);
+	} else {
+		log_msg(LVL_DEBUG, "%s: Nothing left in segment, dropping "
+		    "(xfer_size=%zu, SEG.LEN=%zu, seg->ctrl=%u)",
+		    conn->name, xfer_size, seg->len, (unsigned)seg->ctrl);
+		/* Nothing left in segment */
+		tcp_segment_delete(seg);
+		return cp_done;
+	}
+
+	return cp_continue;
+}
+
+/** Process segment FIN field.
+ *
+ * @param conn		Connection
+ * @param seg		Segment
+ * @return		cp_done if we are done with this segment, cp_continue
+ *			if not
+ */
+static cproc_t tcp_conn_seg_proc_fin(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	log_msg(LVL_DEBUG, "%s: tcp_conn_seg_proc_fin(%p, %p)",
+	    conn->name, conn, seg);
+	log_msg(LVL_DEBUG, " seg->len=%zu, seg->ctl=%u", (size_t) seg->len,
+	    (unsigned) seg->ctrl);
+
+	/* Only process FIN if no text is left in segment. */
+	if (tcp_segment_text_size(seg) == 0 && (seg->ctrl & CTL_FIN) != 0) {
+		log_msg(LVL_DEBUG, " - FIN found in segment.");
+
+		/* Send ACK */
+		tcp_tqueue_ctrl_seg(conn, CTL_ACK);
+
+		conn->rcv_nxt++;
+		conn->rcv_wnd--;
+
+		/* Change connection state */
+		switch (conn->cstate) {
+		case st_listen:
+		case st_syn_sent:
+		case st_closed:
+			/* Connection not synchronized */
+			assert(false);
+		case st_syn_received:
+		case st_established:
+			log_msg(LVL_DEBUG, "%s: FIN received -> Close-Wait",
+			    conn->name);
+			tcp_conn_state_set(conn, st_close_wait);
+			break;
+		case st_fin_wait_1:
+			log_msg(LVL_DEBUG, "%s: FIN received -> Closing",
+			    conn->name);
+			tcp_conn_state_set(conn, st_closing);
+			break;
+		case st_fin_wait_2:
+			log_msg(LVL_DEBUG, "%s: FIN received -> Time-Wait",
+			    conn->name);
+			tcp_conn_state_set(conn, st_time_wait);
+			/* Start the Time-Wait timer */
+			tcp_conn_tw_timer_set(conn);
+			break;
+		case st_close_wait:
+		case st_closing:
+		case st_last_ack:
+			/* Do nothing */
+			break;
+		case st_time_wait:
+			/* Restart the Time-Wait timer */
+			tcp_conn_tw_timer_set(conn);
+			break;
+		}
+
+		/* Add FIN to the receive buffer */
+		conn->rcv_buf_fin = true;
+		fibril_condvar_broadcast(&conn->rcv_buf_cv);
+
+		tcp_segment_delete(seg);
+		return cp_done;
+	}
+
+	return cp_continue;
+}
+
+/** Process incoming segment.
+ *
+ * We are in connection state where segments are processed in order
+ * of sequence number. This processes one segment taken from the
+ * connection incoming segments queue.
+ *
+ * @param conn		Connection
+ * @param seg		Segment
+ */
+static void tcp_conn_seg_process(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	log_msg(LVL_DEBUG, "tcp_conn_seg_process(%p, %p)", conn, seg);
+	tcp_segment_dump(seg);
+
+	/* Check whether segment is acceptable */
+	/* XXX Permit valid ACKs, URGs and RSTs */
+/*	if (!seq_no_segment_acceptable(conn, seg)) {
+		log_msg(LVL_WARN, "Segment not acceptable, dropping.");
+		if ((seg->ctrl & CTL_RST) == 0) {
+			tcp_tqueue_ctrl_seg(conn, CTL_ACK);
+		}
+		return;
+	}
+*/
+
+	if (tcp_conn_seg_proc_rst(conn, seg) == cp_done)
+		return;
+
+	if (tcp_conn_seg_proc_sp(conn, seg) == cp_done)
+		return;
+
+	if (tcp_conn_seg_proc_syn(conn, seg) == cp_done)
+		return;
+
+	if (tcp_conn_seg_proc_ack(conn, seg) == cp_done)
+		return;
+
+	if (tcp_conn_seg_proc_urg(conn, seg) == cp_done)
+		return;
+
+	if (tcp_conn_seg_proc_text(conn, seg) == cp_done)
+		return;
+
+	if (tcp_conn_seg_proc_fin(conn, seg) == cp_done)
+		return;
+
+	/*
+	 * If anything is left from the segment, insert it back into the
+	 * incoming segments queue.
+	 */
+	if (seg->len > 0) {
+		log_msg(LVL_DEBUG, "Re-insert segment %p. seg->len=%zu",
+		    seg, (size_t) seg->len);
+		tcp_iqueue_insert_seg(&conn->incoming, seg);
+	} else {
+		tcp_segment_delete(seg);
+	}
+}
+
+/** Segment arrived on a connection.
+ *
+ * @param conn		Connection
+ * @param seg		Segment
+ */
+void tcp_conn_segment_arrived(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	log_msg(LVL_DEBUG, "%c: tcp_conn_segment_arrived(%p)",
+	    conn->name, seg);
+
+	switch (conn->cstate) {
+	case st_listen:
+		tcp_conn_sa_listen(conn, seg); break;
+	case st_syn_sent:
+		tcp_conn_sa_syn_sent(conn, seg); break;
+	case st_syn_received:
+	case st_established:
+	case st_fin_wait_1:
+	case st_fin_wait_2:
+	case st_close_wait:
+	case st_closing:
+	case st_last_ack:
+	case st_time_wait:
+		/* Process segments in order of sequence number */
+		tcp_conn_sa_queue(conn, seg); break;
+	case st_closed:
+		log_msg(LVL_DEBUG, "state=%d", (int) conn->cstate);
+		assert(false);
+	}
+}
+
+/** Time-Wait timeout handler.
+ *
+ * @param arg	Connection
+ */
+static void tw_timeout_func(void *arg)
+{
+	tcp_conn_t *conn = (tcp_conn_t *) arg;
+
+	log_msg(LVL_DEBUG, "tw_timeout_func(%p)", conn);
+
+	fibril_mutex_lock(&conn->lock);
+
+	if (conn->cstate == st_closed) {
+		log_msg(LVL_DEBUG, "Connection already closed.");
+		fibril_mutex_unlock(&conn->lock);
+		tcp_conn_delref(conn);
+		return;
+	}
+
+	log_msg(LVL_DEBUG, "%s: TW Timeout -> Closed", conn->name);
+	tcp_conn_remove(conn);
+	tcp_conn_state_set(conn, st_closed);
+
+	fibril_mutex_unlock(&conn->lock);
+	tcp_conn_delref(conn);
+}
+
+/** Start or restart the Time-Wait timeout.
+ *
+ * @param conn		Connection
+ */
+void tcp_conn_tw_timer_set(tcp_conn_t *conn)
+{
+	tcp_conn_addref(conn);
+	fibril_timer_set(conn->tw_timer, TIME_WAIT_TIMEOUT, tw_timeout_func,
+	    (void *)conn);
+}
+
+/** Clear the Time-Wait timeout.
+ *
+ * @param conn		Connection
+ */
+void tcp_conn_tw_timer_clear(tcp_conn_t *conn)
+{
+	if (fibril_timer_clear(conn->tw_timer) == fts_active)
+		tcp_conn_delref(conn);
+}
+
+/** Trim segment to the receive window.
+ *
+ * @param conn		Connection
+ * @param seg		Segment
+ */
+void tcp_conn_trim_seg_to_wnd(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	uint32_t left, right;
+
+	seq_no_seg_trim_calc(conn, seg, &left, &right);
+	tcp_segment_trim(seg, left, right);
+}
+
+/** Handle unexpected segment received on a socket pair.
+ *
+ * We reply with an RST unless the received segment has RST.
+ *
+ * @param sp		Socket pair which received the segment
+ * @param seg		Unexpected segment
+ */
+void tcp_unexpected_segment(tcp_sockpair_t *sp, tcp_segment_t *seg)
+{
+	log_msg(LVL_DEBUG, "tcp_unexpected_segment(%p, %p)", sp, seg);
+
+	if ((seg->ctrl & CTL_RST) == 0)
+		tcp_reply_rst(sp, seg);
+}
+
+/** Compute flipped socket pair for response.
+ *
+ * Flipped socket pair has local and foreign sockets exchanged.
+ *
+ * @param sp		Socket pair
+ * @param fsp		Place to store flipped socket pair
+ */
+void tcp_sockpair_flipped(tcp_sockpair_t *sp, tcp_sockpair_t *fsp)
+{
+	fsp->local = sp->foreign;
+	fsp->foreign = sp->local;
+}
+
+/** Send RST in response to an incoming segment.
+ *
+ * @param sp		Socket pair which received the segment
+ * @param seg		Incoming segment
+ */
+void tcp_reply_rst(tcp_sockpair_t *sp, tcp_segment_t *seg)
+{
+	tcp_segment_t *rseg;
+
+	log_msg(LVL_DEBUG, "tcp_reply_rst(%p, %p)", sp, seg);
+
+	rseg = tcp_segment_make_rst(seg);
+	tcp_transmit_segment(sp, rseg);
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/tcp/conn.h
===================================================================
--- uspace/srv/tcp/conn.h	(revision 4d9fe7b307128cbbbd04d982fef935c842053872)
+++ uspace/srv/tcp/conn.h	(revision 4d9fe7b307128cbbbd04d982fef935c842053872)
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup tcp
+ * @{
+ */
+/** @file TCP connection processing and state machine
+ */
+
+#ifndef CONN_H
+#define CONN_H
+
+#include <bool.h>
+#include "tcp_type.h"
+
+extern tcp_conn_t *tcp_conn_new(tcp_sock_t *, tcp_sock_t *);
+extern void tcp_conn_delete(tcp_conn_t *);
+extern void tcp_conn_add(tcp_conn_t *);
+extern void tcp_conn_remove(tcp_conn_t *);
+extern void tcp_conn_sync(tcp_conn_t *);
+extern void tcp_conn_fin_sent(tcp_conn_t *);
+extern void tcp_conn_ack_of_fin_rcvd(tcp_conn_t *);
+extern tcp_conn_t *tcp_conn_find_ref(tcp_sockpair_t *);
+extern void tcp_conn_addref(tcp_conn_t *);
+extern void tcp_conn_delref(tcp_conn_t *);
+extern bool tcp_conn_got_syn(tcp_conn_t *);
+extern void tcp_conn_segment_arrived(tcp_conn_t *, tcp_segment_t *);
+extern void tcp_conn_trim_seg_to_wnd(tcp_conn_t *, tcp_segment_t *);
+extern void tcp_unexpected_segment(tcp_sockpair_t *, tcp_segment_t *);
+extern void tcp_sockpair_flipped(tcp_sockpair_t *, tcp_sockpair_t *);
+extern void tcp_reply_rst(tcp_sockpair_t *, tcp_segment_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/tcp/iqueue.c
===================================================================
--- uspace/srv/tcp/iqueue.c	(revision 4d9fe7b307128cbbbd04d982fef935c842053872)
+++ uspace/srv/tcp/iqueue.c	(revision 4d9fe7b307128cbbbd04d982fef935c842053872)
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup tcp
+ * @{
+ */
+
+/**
+ * @file Connection incoming segments queue
+ *
+ * Segments are sorted in order of their sequence number.
+ */
+
+#include <adt/list.h>
+#include <errno.h>
+#include <io/log.h>
+#include <stdlib.h>
+#include "iqueue.h"
+#include "segment.h"
+#include "seq_no.h"
+#include "tcp_type.h"
+
+/** Initialize incoming segments queue.
+ *
+ * @param iqueue	Incoming queue
+ * @param conn		Connection the queue is associated with
+ */
+void tcp_iqueue_init(tcp_iqueue_t *iqueue, tcp_conn_t *conn)
+{
+	list_initialize(&iqueue->list);
+	iqueue->conn = conn;
+}
+
+/** Insert segment into incoming queue.
+ *
+ * @param iqueue	Incoming queue
+ * @param seg		Segment
+ */
+void tcp_iqueue_insert_seg(tcp_iqueue_t *iqueue, tcp_segment_t *seg)
+{
+	tcp_iqueue_entry_t *iqe;
+	tcp_iqueue_entry_t *qe;
+	link_t *link;
+	log_msg(LVL_DEBUG, "tcp_iqueue_insert_seg()");
+
+	iqe = calloc(1, sizeof(tcp_iqueue_entry_t));
+	if (iqe == NULL) {
+		log_msg(LVL_ERROR, "Failed allocating IQE.");
+		return;
+	}
+
+	iqe->seg = seg;
+
+	/* Sort by sequence number */
+
+	link = list_first(&iqueue->list);
+	while (link != NULL) {
+		qe = list_get_instance(link,
+		    tcp_iqueue_entry_t, link);
+
+		if (seq_no_seg_cmp(iqueue->conn, iqe->seg, qe->seg) >= 0)
+			break;
+	}
+
+	if (link != NULL)
+		list_insert_before(&iqe->link, &qe->link);
+	else
+		list_append(&iqe->link, &iqueue->list);
+}
+
+/** Get next ready segment from incoming queue.
+ *
+ * Return the segment with the earliest sequence number if it is ready.
+ * A segment is ready if its SEG.SEQ is earlier or equal to RCV.NXT.
+ *
+ * @param iqueue	Incoming queue
+ * @param seg		Place to store pointer to segment
+ * @return		EOK on success, ENOENT if no segment is ready
+ */
+int tcp_iqueue_get_ready_seg(tcp_iqueue_t *iqueue, tcp_segment_t **seg)
+{
+	tcp_iqueue_entry_t *iqe;
+	link_t *link;
+
+	log_msg(LVL_DEBUG, "tcp_get_ready_seg()");
+
+	link = list_first(&iqueue->list);
+	if (link == NULL) {
+		log_msg(LVL_DEBUG, "iqueue is empty");
+		return ENOENT;
+	}
+
+	iqe = list_get_instance(link, tcp_iqueue_entry_t, link);
+
+	while (!seq_no_segment_acceptable(iqueue->conn, iqe->seg)) {
+		log_msg(LVL_DEBUG, "Skipping unacceptable segment (RCV.NXT=%"
+		    PRIu32 ", RCV.NXT+RCV.WND=%" PRIu32 ", SEG.SEQ=%" PRIu32
+		    ", SEG.LEN=%" PRIu32 ")", iqueue->conn->rcv_nxt,
+		    iqueue->conn->rcv_nxt + iqueue->conn->rcv_wnd,
+		    iqe->seg->seq, iqe->seg->len);
+
+		list_remove(&iqe->link);
+		tcp_segment_delete(iqe->seg);
+
+         	link = list_first(&iqueue->list);
+		if (link == NULL) {
+			log_msg(LVL_DEBUG, "iqueue is empty");
+			return ENOENT;
+		}
+
+		iqe = list_get_instance(link, tcp_iqueue_entry_t, link);
+	}
+
+	/* Do not return segments that are not ready for processing */
+	if (!seq_no_segment_ready(iqueue->conn, iqe->seg)) {
+		log_msg(LVL_DEBUG, "Next segment not ready: SEG.SEQ=%u, "
+		    "RCV.NXT=%u, SEG.LEN=%u", iqe->seg->seq,
+		    iqueue->conn->rcv_nxt, iqe->seg->len);
+		return ENOENT;
+	}
+
+	log_msg(LVL_DEBUG, "Returning ready segment %p", iqe->seg);
+	list_remove(&iqe->link);
+	*seg = iqe->seg;
+
+	return EOK;
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/tcp/iqueue.h
===================================================================
--- uspace/srv/tcp/iqueue.h	(revision 4d9fe7b307128cbbbd04d982fef935c842053872)
+++ uspace/srv/tcp/iqueue.h	(revision 4d9fe7b307128cbbbd04d982fef935c842053872)
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup tcp
+ * @{
+ */
+/** @file Connection incoming segments queue
+ */
+
+#ifndef IQUEUE_H
+#define IQUEUE_H
+
+#include "tcp_type.h"
+
+extern void tcp_iqueue_init(tcp_iqueue_t *, tcp_conn_t *);
+extern void tcp_iqueue_insert_seg(tcp_iqueue_t *, tcp_segment_t *);
+extern int tcp_iqueue_get_ready_seg(tcp_iqueue_t *, tcp_segment_t **);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/tcp/ncsim.c
===================================================================
--- uspace/srv/tcp/ncsim.c	(revision 4d9fe7b307128cbbbd04d982fef935c842053872)
+++ uspace/srv/tcp/ncsim.c	(revision 4d9fe7b307128cbbbd04d982fef935c842053872)
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup tcp
+ * @{
+ */
+
+/**
+ * @file Network condition simulator
+ *
+ * Simulate network conditions for testing the reliability implementation:
+ *    - variable latency
+ *    - frame drop
+ */
+
+#include <adt/list.h>
+#include <async.h>
+#include <errno.h>
+#include <io/log.h>
+#include <stdlib.h>
+#include <thread.h>
+#include "conn.h"
+#include "ncsim.h"
+#include "rqueue.h"
+#include "segment.h"
+#include "tcp_type.h"
+
+static list_t sim_queue;
+static fibril_mutex_t sim_queue_lock;
+static fibril_condvar_t sim_queue_cv;
+
+/** Initialize segment receive queue. */
+void tcp_ncsim_init(void)
+{
+	list_initialize(&sim_queue);
+	fibril_mutex_initialize(&sim_queue_lock);
+	fibril_condvar_initialize(&sim_queue_cv);
+}
+
+/** Bounce segment through simulator into receive queue.
+ *
+ * @param sp	Socket pair, oriented for transmission
+ * @param seg	Segment
+ */
+void tcp_ncsim_bounce_seg(tcp_sockpair_t *sp, tcp_segment_t *seg)
+{
+	tcp_squeue_entry_t *sqe;
+	tcp_squeue_entry_t *old_qe;
+	link_t *link;
+
+	log_msg(LVL_DEBUG, "tcp_ncsim_bounce_seg()");
+	tcp_rqueue_bounce_seg(sp, seg);
+	return;
+
+	if (0 /*random() % 4 == 3*/) {
+		/* Drop segment */
+		log_msg(LVL_ERROR, "NCSim dropping segment");
+		tcp_segment_delete(seg);
+		return;
+	}
+
+	sqe = calloc(1, sizeof(tcp_squeue_entry_t));
+	if (sqe == NULL) {
+		log_msg(LVL_ERROR, "Failed allocating SQE.");
+		return;
+	}
+
+	sqe->delay = random() % (1000 * 1000);
+	sqe->sp = *sp;
+	sqe->seg = seg;
+
+	fibril_mutex_lock(&sim_queue_lock);
+
+	link = list_first(&sim_queue);
+	while (link != NULL && sqe->delay > 0) {
+		old_qe = list_get_instance(link, tcp_squeue_entry_t, link);
+		if (sqe->delay < old_qe->delay)
+			break;
+
+		sqe->delay -= old_qe->delay;
+
+		link = link->next;
+		if (link == &sim_queue.head)
+			link = NULL;
+	}
+
+	if (link != NULL)
+		list_insert_after(&sqe->link, link);
+	else
+		list_append(&sqe->link, &sim_queue);
+
+	fibril_condvar_broadcast(&sim_queue_cv);
+	fibril_mutex_unlock(&sim_queue_lock);
+}
+
+/** Network condition simulator handler thread. */
+static void tcp_ncsim_thread(void *arg)
+{
+	link_t *link;
+	tcp_squeue_entry_t *sqe;
+	int rc;
+
+	log_msg(LVL_DEBUG, "tcp_ncsim_thread()");
+
+
+	while (true) {
+		fibril_mutex_lock(&sim_queue_lock);
+
+		while (list_empty(&sim_queue))
+			fibril_condvar_wait(&sim_queue_cv, &sim_queue_lock);
+
+		do {
+			link = list_first(&sim_queue);
+			sqe = list_get_instance(link, tcp_squeue_entry_t, link);
+
+			log_msg(LVL_DEBUG, "NCSim - Sleep");
+			rc = fibril_condvar_wait_timeout(&sim_queue_cv,
+			    &sim_queue_lock, sqe->delay);
+		} while (rc != ETIMEOUT);
+
+		list_remove(link);
+		fibril_mutex_unlock(&sim_queue_lock);
+
+		log_msg(LVL_DEBUG, "NCSim - End Sleep");
+		tcp_rqueue_bounce_seg(&sqe->sp, sqe->seg);
+		free(sqe);
+	}
+}
+
+/** Start simulator handler thread. */
+void tcp_ncsim_thread_start(void)
+{
+	thread_id_t tid;
+        int rc;
+
+	log_msg(LVL_DEBUG, "tcp_ncsim_thread_start()");
+
+	rc = thread_create(tcp_ncsim_thread, NULL, "ncsim", &tid);
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Failed creating ncsim thread.");
+		return;
+	}
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/tcp/ncsim.h
===================================================================
--- uspace/srv/tcp/ncsim.h	(revision 4d9fe7b307128cbbbd04d982fef935c842053872)
+++ uspace/srv/tcp/ncsim.h	(revision 4d9fe7b307128cbbbd04d982fef935c842053872)
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup tcp
+ * @{
+ */
+/** @file Network condition simulator
+ */
+
+#ifndef NCSIM_H
+#define NCSIM_H
+
+#include "tcp_type.h"
+
+extern void tcp_ncsim_init(void);
+extern void tcp_ncsim_bounce_seg(tcp_sockpair_t *, tcp_segment_t *);
+extern void tcp_ncsim_thread_start(void);
+
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/tcp/pdu.c
===================================================================
--- uspace/srv/tcp/pdu.c	(revision 4d9fe7b307128cbbbd04d982fef935c842053872)
+++ uspace/srv/tcp/pdu.c	(revision 4d9fe7b307128cbbbd04d982fef935c842053872)
@@ -0,0 +1,314 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup tcp
+ * @{
+ */
+
+/**
+ * @file TCP header encoding and decoding
+ */
+
+#include <bitops.h>
+#include <byteorder.h>
+#include <errno.h>
+#include <mem.h>
+#include <stdlib.h>
+#include "pdu.h"
+#include "segment.h"
+#include "seq_no.h"
+#include "std.h"
+#include "tcp_type.h"
+
+#define TCP_CHECKSUM_INIT 0xffff
+
+/** One's complement addition.
+ *
+ * Result is a + b + carry.
+ */
+static uint16_t tcp_ocadd16(uint16_t a, uint16_t b)
+{
+	uint32_t s;
+
+	s = (uint32_t)a + (uint32_t)b;
+	return (s & 0xffff) + (s >> 16);
+}
+
+static uint16_t tcp_checksum_calc(uint16_t ivalue, void *data, size_t size)
+{
+	uint16_t sum;
+	uint16_t w;
+	size_t words, i;
+	uint8_t *bdata;
+
+	sum = ~ivalue;
+	words = size / 2;
+	bdata = (uint8_t *)data;
+
+	for (i = 0; i < words; i++) {
+		w = ((uint16_t)bdata[2*i] << 8) | bdata[2*i + 1];
+		sum = tcp_ocadd16(sum, w);
+	}
+
+	if (size % 2 != 0) {
+		w = ((uint16_t)bdata[2*words] << 8);
+		sum = tcp_ocadd16(sum, w);
+	}
+
+	return ~sum;
+}
+
+static void tcp_header_decode_flags(uint16_t doff_flags, tcp_control_t *rctl)
+{
+	tcp_control_t ctl;
+
+	ctl = 0;
+
+	if ((doff_flags & BIT_V(uint16_t, DF_URG)) != 0)
+		ctl |= 0 /* XXX */;
+	if ((doff_flags & BIT_V(uint16_t, DF_ACK)) != 0)
+		ctl |= CTL_ACK;
+	if ((doff_flags & BIT_V(uint16_t, DF_PSH)) != 0)
+		ctl |= 0 /* XXX */;
+	if ((doff_flags & BIT_V(uint16_t, DF_RST)) != 0)
+		ctl |= CTL_RST;
+	if ((doff_flags & BIT_V(uint16_t, DF_SYN)) != 0)
+		ctl |= CTL_SYN;
+	if ((doff_flags & BIT_V(uint16_t, DF_FIN)) != 0)
+		ctl |= CTL_FIN;
+
+	*rctl = ctl;
+}
+
+static void tcp_header_encode_flags(tcp_control_t ctl, uint16_t doff_flags0,
+    uint16_t *rdoff_flags)
+{
+	uint16_t doff_flags;
+
+	doff_flags = doff_flags0;
+
+	if ((ctl & CTL_ACK) != 0)
+		doff_flags |= BIT_V(uint16_t, DF_ACK);
+	if ((ctl & CTL_RST) != 0)
+		doff_flags |= BIT_V(uint16_t, DF_RST);
+	if ((ctl & CTL_SYN) != 0)
+		doff_flags |= BIT_V(uint16_t, DF_SYN);
+	if ((ctl & CTL_FIN) != 0)
+		doff_flags |= BIT_V(uint16_t, DF_FIN);
+
+	*rdoff_flags = doff_flags;
+}
+
+static void tcp_header_setup(tcp_sockpair_t *sp, tcp_segment_t *seg, tcp_header_t *hdr)
+{
+	uint16_t doff_flags;
+	uint16_t doff;
+
+	hdr->src_port = host2uint16_t_be(sp->local.port);
+	hdr->dest_port = host2uint16_t_be(sp->foreign.port);
+	hdr->seq = host2uint32_t_be(seg->seq);
+	hdr->ack = host2uint32_t_be(seg->ack);
+
+	doff = (sizeof(tcp_header_t) / sizeof(uint32_t)) << DF_DATA_OFFSET_l;
+	tcp_header_encode_flags(seg->ctrl, doff, &doff_flags);
+
+	hdr->doff_flags = host2uint16_t_be(doff_flags);
+	hdr->window = host2uint16_t_be(seg->wnd);
+	hdr->checksum = 0;
+	hdr->urg_ptr = host2uint16_t_be(seg->up);
+}
+
+static void tcp_phdr_setup(tcp_pdu_t *pdu, tcp_phdr_t *phdr)
+{
+	phdr->src_addr = host2uint32_t_be(pdu->src_addr.ipv4);
+	phdr->dest_addr = host2uint32_t_be(pdu->dest_addr.ipv4);
+	phdr->zero = 0;
+	phdr->protocol = 6; /* XXX Magic number */
+	phdr->tcp_length = host2uint16_t_be(pdu->header_size + pdu->text_size);
+}
+
+static void tcp_header_decode(tcp_header_t *hdr, tcp_segment_t *seg)
+{
+	tcp_header_decode_flags(uint16_t_be2host(hdr->doff_flags), &seg->ctrl);
+	seg->seq = uint32_t_be2host(hdr->seq);
+	seg->ack = uint32_t_be2host(hdr->ack);
+	seg->wnd = uint16_t_be2host(hdr->window);
+	seg->up = uint16_t_be2host(hdr->urg_ptr);
+}
+
+static int tcp_header_encode(tcp_sockpair_t *sp, tcp_segment_t *seg,
+    void **header, size_t *size)
+{
+	tcp_header_t *hdr;
+
+	hdr = calloc(1, sizeof(tcp_header_t));
+	if (hdr == NULL)
+		return ENOMEM;
+
+	tcp_header_setup(sp, seg, hdr);
+	*header = hdr;
+	*size = sizeof(tcp_header_t);
+
+	return EOK;
+}
+
+static tcp_pdu_t *tcp_pdu_new(void)
+{
+	return calloc(1, sizeof(tcp_pdu_t));
+}
+
+/** Create PDU with the specified header and text data.
+ *
+ * Note that you still need to set addresses in the returned PDU.
+ *
+ * @param hdr		Header data
+ * @param hdr_size      Header size in bytes
+ * @param text		Text data
+ * @param text_size	Text size in bytes
+ * @return		New PDU
+ */
+tcp_pdu_t *tcp_pdu_create(void *hdr, size_t hdr_size, void *text,
+    size_t text_size)
+{
+	tcp_pdu_t *pdu;
+
+	pdu = tcp_pdu_new();
+	if (pdu == NULL)
+		return NULL;
+
+	pdu->header = malloc(hdr_size);
+	pdu->text = malloc(text_size);
+	if (pdu->header == NULL || pdu->text == NULL)
+		goto error;
+
+	memcpy(pdu->header, hdr, hdr_size);
+	memcpy(pdu->text, text, text_size);
+
+	pdu->header_size = hdr_size;
+	pdu->text_size = text_size;
+
+	return pdu;
+
+error:
+	if (pdu->header != NULL)
+		free(pdu->header);
+	if (pdu->text != NULL)
+		free(pdu->text);
+
+	return NULL;
+}
+
+void tcp_pdu_delete(tcp_pdu_t *pdu)
+{
+	free(pdu->header);
+	free(pdu->text);
+	free(pdu);
+}
+
+static uint16_t tcp_pdu_checksum_calc(tcp_pdu_t *pdu)
+{
+	uint16_t cs_phdr;
+	uint16_t cs_headers;
+	uint16_t cs_all;
+	tcp_phdr_t phdr;
+
+	tcp_phdr_setup(pdu, &phdr);
+	cs_phdr = tcp_checksum_calc(TCP_CHECKSUM_INIT, (void *)&phdr,
+	    sizeof(tcp_phdr_t));
+	cs_headers = tcp_checksum_calc(cs_phdr, pdu->header, pdu->header_size);
+	cs_all = tcp_checksum_calc(cs_headers, pdu->text, pdu->text_size);
+
+	return cs_all;
+}
+
+static void tcp_pdu_set_checksum(tcp_pdu_t *pdu, uint16_t checksum)
+{
+	tcp_header_t *hdr;
+
+	hdr = (tcp_header_t *)pdu->header;
+	hdr->checksum = host2uint16_t_be(checksum);
+}
+
+/** Encode outgoing PDU */
+int tcp_pdu_decode(tcp_pdu_t *pdu, tcp_sockpair_t *sp, tcp_segment_t **seg)
+{
+	tcp_segment_t *nseg;
+	tcp_header_t *hdr;
+
+	nseg = tcp_segment_make_data(0, pdu->text, pdu->text_size);
+	if (nseg == NULL)
+		return ENOMEM;
+
+	tcp_header_decode(pdu->header, nseg);
+	nseg->len += seq_no_control_len(nseg->ctrl);
+
+	hdr = (tcp_header_t *)pdu->header;
+
+	sp->local.port = uint16_t_be2host(hdr->dest_port);
+	sp->local.addr = pdu->dest_addr;
+	sp->foreign.port = uint16_t_be2host(hdr->src_port);
+	sp->foreign.addr = pdu->src_addr;
+
+	*seg = nseg;
+	return EOK;
+}
+
+/** Decode incoming PDU */
+int tcp_pdu_encode(tcp_sockpair_t *sp, tcp_segment_t *seg, tcp_pdu_t **pdu)
+{
+	tcp_pdu_t *npdu;
+	size_t text_size;
+	uint16_t checksum;
+
+	npdu = tcp_pdu_new();
+	if (npdu == NULL)
+		return ENOMEM;
+
+	npdu->src_addr = sp->local.addr;
+	npdu->dest_addr = sp->foreign.addr;
+	tcp_header_encode(sp, seg, &npdu->header, &npdu->header_size);
+
+	text_size = tcp_segment_text_size(seg);
+	npdu->text = calloc(1, text_size);
+	if (npdu->text == NULL)
+		return ENOMEM;
+
+	npdu->text_size = text_size;
+	memcpy(npdu->text, seg->data, text_size);
+
+	/* Checksum calculation */
+	checksum = tcp_pdu_checksum_calc(npdu);
+	tcp_pdu_set_checksum(npdu, checksum);
+
+	*pdu = npdu;
+	return EOK;
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/tcp/pdu.h
===================================================================
--- uspace/srv/tcp/pdu.h	(revision 4d9fe7b307128cbbbd04d982fef935c842053872)
+++ uspace/srv/tcp/pdu.h	(revision 4d9fe7b307128cbbbd04d982fef935c842053872)
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup tcp
+ * @{
+ */
+/** @file TCP PDU (encoded Protocol Data Unit) handling
+ */
+
+#ifndef PDU_H
+#define PDU_H
+
+#include <sys/types.h>
+#include "std.h"
+#include "tcp_type.h"
+
+extern tcp_pdu_t *tcp_pdu_create(void *, size_t, void *, size_t);
+extern void tcp_pdu_delete(tcp_pdu_t *);
+extern int tcp_pdu_decode(tcp_pdu_t *, tcp_sockpair_t *, tcp_segment_t **);
+extern int tcp_pdu_encode(tcp_sockpair_t *, tcp_segment_t *, tcp_pdu_t **);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/tcp/rqueue.c
===================================================================
--- uspace/srv/tcp/rqueue.c	(revision 4d9fe7b307128cbbbd04d982fef935c842053872)
+++ uspace/srv/tcp/rqueue.c	(revision 4d9fe7b307128cbbbd04d982fef935c842053872)
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup tcp
+ * @{
+ */
+
+/**
+ * @file Global segment receive queue
+ */
+
+#include <adt/prodcons.h>
+#include <errno.h>
+#include <io/log.h>
+#include <stdlib.h>
+#include <thread.h>
+#include "conn.h"
+#include "pdu.h"
+#include "rqueue.h"
+#include "segment.h"
+#include "tcp_type.h"
+#include "ucall.h"
+
+/** Transcode bounced segments.
+ *
+ * If defined, segments bounced via the internal debugging loopback will
+ * be encoded to a PDU and the decoded. Otherwise they will be bounced back
+ * directly without passing the encoder-decoder.
+ */
+#define BOUNCE_TRANSCODE
+
+static prodcons_t rqueue;
+
+/** Initialize segment receive queue. */
+void tcp_rqueue_init(void)
+{
+	prodcons_initialize(&rqueue);
+}
+
+/** Bounce segment directy into receive queue without constructing the PDU.
+ *
+ * This is for testing purposes only.
+ *
+ * @param sp	Socket pair, oriented for transmission
+ * @param seg	Segment
+ */
+void tcp_rqueue_bounce_seg(tcp_sockpair_t *sp, tcp_segment_t *seg)
+{
+	tcp_sockpair_t rident;
+
+	log_msg(LVL_DEBUG, "tcp_rqueue_bounce_seg()");
+
+#ifdef BOUNCE_TRANSCODE
+	tcp_pdu_t *pdu;
+	tcp_segment_t *dseg;
+
+	if (tcp_pdu_encode(sp, seg, &pdu) != EOK) {
+		log_msg(LVL_WARN, "Not enough memory. Segment dropped.");
+		return;
+	}
+
+	if (tcp_pdu_decode(pdu, &rident, &dseg) != EOK) {
+		log_msg(LVL_WARN, "Not enough memory. Segment dropped.");
+		return;
+	}
+
+	tcp_pdu_delete(pdu);
+
+	/** Insert decoded segment into rqueue */
+	tcp_rqueue_insert_seg(&rident, dseg);
+	tcp_segment_delete(seg);
+#else
+	/* Reverse the identification */
+	tcp_sockpair_flipped(sp, &rident);
+
+	/* Insert segment back into rqueue */
+	tcp_rqueue_insert_seg(&rident, seg);
+#endif
+}
+
+/** Insert segment into receive queue.
+ *
+ * @param sp	Socket pair, oriented for reception
+ * @param seg	Segment
+ */
+void tcp_rqueue_insert_seg(tcp_sockpair_t *sp, tcp_segment_t *seg)
+{
+	tcp_rqueue_entry_t *rqe;
+	log_msg(LVL_DEBUG, "tcp_rqueue_insert_seg()");
+
+	tcp_segment_dump(seg);
+
+	rqe = calloc(1, sizeof(tcp_rqueue_entry_t));
+	if (rqe == NULL) {
+		log_msg(LVL_ERROR, "Failed allocating RQE.");
+		return;
+	}
+
+	rqe->sp = *sp;
+	rqe->seg = seg;
+
+	prodcons_produce(&rqueue, &rqe->link);
+}
+
+/** Receive queue handler thread. */
+static void tcp_rqueue_thread(void *arg)
+{
+	link_t *link;
+	tcp_rqueue_entry_t *rqe;
+
+	log_msg(LVL_DEBUG, "tcp_rqueue_thread()");
+
+	while (true) {
+		link = prodcons_consume(&rqueue);
+		rqe = list_get_instance(link, tcp_rqueue_entry_t, link);
+
+		tcp_as_segment_arrived(&rqe->sp, rqe->seg);
+	}
+}
+
+/** Start receive queue handler thread. */
+void tcp_rqueue_thread_start(void)
+{
+	thread_id_t tid;
+        int rc;
+
+	log_msg(LVL_DEBUG, "tcp_rqueue_thread_start()");
+
+	rc = thread_create(tcp_rqueue_thread, NULL, "rqueue", &tid);
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Failed creating rqueue thread.");
+		return;
+	}
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/tcp/rqueue.h
===================================================================
--- uspace/srv/tcp/rqueue.h	(revision 4d9fe7b307128cbbbd04d982fef935c842053872)
+++ uspace/srv/tcp/rqueue.h	(revision 4d9fe7b307128cbbbd04d982fef935c842053872)
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup tcp
+ * @{
+ */
+/** @file Global segment receive queue
+ */
+
+#ifndef RQUEUE_H
+#define RQUEUE_H
+
+#include "tcp_type.h"
+
+extern void tcp_rqueue_init(void);
+extern void tcp_rqueue_bounce_seg(tcp_sockpair_t *, tcp_segment_t *);
+extern void tcp_rqueue_insert_seg(tcp_sockpair_t *, tcp_segment_t *);
+extern void tcp_rqueue_handler(void *);
+extern void tcp_rqueue_thread_start(void);
+
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/tcp/segment.c
===================================================================
--- uspace/srv/tcp/segment.c	(revision 4d9fe7b307128cbbbd04d982fef935c842053872)
+++ uspace/srv/tcp/segment.c	(revision 4d9fe7b307128cbbbd04d982fef935c842053872)
@@ -0,0 +1,261 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup tcp
+ * @{
+ */
+
+/**
+ * @file Segment processing
+ */
+
+#include <io/log.h>
+#include <mem.h>
+#include <stdlib.h>
+#include "segment.h"
+#include "seq_no.h"
+#include "tcp_type.h"
+
+/** Alocate new segment structure. */
+tcp_segment_t *tcp_segment_new(void)
+{
+	return calloc(1, sizeof(tcp_segment_t));
+}
+
+/** Delete segment. */
+void tcp_segment_delete(tcp_segment_t *seg)
+{
+	free(seg);
+}
+
+/** Create duplicate of segment.
+ *
+ * @param seg	Segment
+ * @return 	Duplicate segment
+ */
+tcp_segment_t *tcp_segment_dup(tcp_segment_t *seg)
+{
+	tcp_segment_t *scopy;
+	size_t tsize;
+
+	scopy = tcp_segment_new();
+	if (scopy == NULL)
+		return NULL;
+
+	scopy->ctrl = seg->ctrl;
+	scopy->seq = seg->seq;
+	scopy->ack = seg->ack;
+	scopy->len = seg->len;
+	scopy->wnd = seg->wnd;
+	scopy->up = seg->up;
+
+	tsize = tcp_segment_text_size(seg);
+	scopy->data = calloc(tsize, 1);
+	if (scopy->data == NULL) {
+		free(scopy);
+		return NULL;
+	}
+
+	memcpy(scopy->data, seg->data, tsize);
+	scopy->dfptr = scopy->data;
+
+	return scopy;
+}
+
+/** Create a control-only segment.
+ *
+  * @return	Segment
+ */
+tcp_segment_t *tcp_segment_make_ctrl(tcp_control_t ctrl)
+{
+	tcp_segment_t *seg;
+
+	seg = tcp_segment_new();
+	if (seg == NULL)
+		return NULL;
+
+	seg->ctrl = ctrl;
+	seg->len = seq_no_control_len(ctrl);
+
+	return seg;
+}
+
+/** Create an RST segment.
+ *
+ * @param seg	Segment we are replying to
+ * @return	RST segment
+ */
+tcp_segment_t *tcp_segment_make_rst(tcp_segment_t *seg)
+{
+	tcp_segment_t *rseg;
+
+	rseg = tcp_segment_new();
+	if (rseg == NULL)
+		return NULL;
+
+	if ((seg->ctrl & CTL_ACK) == 0) {
+		rseg->ctrl = CTL_RST | CTL_ACK;
+		rseg->seq = 0;
+		rseg->ack = seg->seq + seg->len;
+	} else {
+		rseg->ctrl = CTL_RST;
+		rseg->seq = seg->ack;
+	}
+
+	return rseg;
+}
+
+/** Create a control segment.
+ *
+  * @return	Segment
+ */
+tcp_segment_t *tcp_segment_make_data(tcp_control_t ctrl, void *data,
+    size_t size)
+{
+	tcp_segment_t *seg;
+
+	seg = tcp_segment_new();
+	if (seg == NULL)
+		return NULL;
+
+	seg->ctrl = ctrl;
+	seg->len = seq_no_control_len(ctrl) + size;
+
+	seg->dfptr = seg->data = malloc(size);
+	if (seg->dfptr == NULL) {
+		free(seg);
+		return NULL;
+	}
+
+	memcpy(seg->data, data, size);
+
+	return seg;
+}
+
+
+/** Trim segment from left and right by the specified amount.
+ *
+ * Trim any text or control to remove the specified amount of sequence
+ * numbers from the left (lower sequence numbers) and right side
+ * (higher sequence numbers) of the segment.
+ *
+ * @param seg		Segment, will be modified in place
+ * @param left		Amount of sequence numbers to trim from the left
+ * @param right		Amount of sequence numbers to trim from the right
+ */
+void tcp_segment_trim(tcp_segment_t *seg, uint32_t left, uint32_t right)
+{
+	uint32_t t_size;
+
+	assert(left + right <= seg->len);
+
+	/* Special case, entire segment trimmed from left */
+	if (left == seg->len) {
+		seg->seq = seg->seq + seg->len;
+		seg->len = 0;
+		return;
+	}
+
+	/* Special case, entire segment trimmed from right */
+	if (right == seg->len) {
+		seg->len = 0;
+		return;
+	}
+
+	/* General case */
+
+	t_size = tcp_segment_text_size(seg);
+
+	if (left > 0 && (seg->ctrl & CTL_SYN) != 0) {
+		/* Trim SYN */
+		seg->ctrl &= ~CTL_SYN;
+		seg->seq++;
+		seg->len--;
+		left--;
+	}
+
+	if (right > 0 && (seg->ctrl & CTL_FIN) != 0) {
+		/* Trim FIN */
+		seg->ctrl &= ~CTL_FIN;
+		seg->len--;
+		right--;
+	}
+
+	if (left > 0 || right > 0) {
+		/* Trim segment text */
+		assert(left + right <= t_size);
+
+		seg->data += left;
+		seg->len -= left + right;
+	}
+}
+
+/** Copy out text data from segment.
+ *
+ * Data is copied from the beginning of the segment text up to @a size bytes.
+ * @a size must not be greater than the size of the segment text, but
+ * it can be less.
+ *
+ * @param seg	Segment
+ * @param buf	Destination buffer
+ * @param size	Size of destination buffer
+ */
+void tcp_segment_text_copy(tcp_segment_t *seg, void *buf, size_t size)
+{
+	assert(size <= tcp_segment_text_size(seg));
+	memcpy(buf, seg->data, size);
+}
+
+/** Return number of bytes in segment text.
+ *
+ * @param seg	Segment
+ * @return	Number of bytes in segment text
+ */
+size_t tcp_segment_text_size(tcp_segment_t *seg)
+{
+	return seg->len - seq_no_control_len(seg->ctrl);
+}
+
+/** Dump segment contents to log.
+ *
+ * @param seg	Segment
+ */
+void tcp_segment_dump(tcp_segment_t *seg)
+{
+	log_msg(LVL_DEBUG, "Segment dump:");
+	log_msg(LVL_DEBUG, " - ctrl = %u", (unsigned)seg->ctrl);
+	log_msg(LVL_DEBUG, " - seq = % " PRIu32, seg->seq);
+	log_msg(LVL_DEBUG, " - ack = % " PRIu32, seg->ack);
+	log_msg(LVL_DEBUG, " - len = % " PRIu32, seg->len);
+	log_msg(LVL_DEBUG, " - wnd = % " PRIu32, seg->wnd);
+	log_msg(LVL_DEBUG, " - up = % " PRIu32, seg->up);
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/tcp/segment.h
===================================================================
--- uspace/srv/tcp/segment.h	(revision 4d9fe7b307128cbbbd04d982fef935c842053872)
+++ uspace/srv/tcp/segment.h	(revision 4d9fe7b307128cbbbd04d982fef935c842053872)
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup tcp
+ * @{
+ */
+/** @file Segment processing
+ */
+
+#ifndef SEGMENT_H
+#define SEGMENT_H
+
+#include <sys/types.h>
+#include "tcp_type.h"
+
+extern tcp_segment_t *tcp_segment_new(void);
+extern void tcp_segment_delete(tcp_segment_t *);
+extern tcp_segment_t *tcp_segment_dup(tcp_segment_t *);
+extern tcp_segment_t *tcp_segment_make_ctrl(tcp_control_t);
+extern tcp_segment_t *tcp_segment_make_rst(tcp_segment_t *);
+extern tcp_segment_t *tcp_segment_make_data(tcp_control_t, void *, size_t);
+extern void tcp_segment_trim(tcp_segment_t *, uint32_t, uint32_t);
+extern void tcp_segment_text_copy(tcp_segment_t *, void *, size_t);
+extern size_t tcp_segment_text_size(tcp_segment_t *);
+extern void tcp_segment_dump(tcp_segment_t *);
+
+
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/tcp/seq_no.c
===================================================================
--- uspace/srv/tcp/seq_no.c	(revision 4d9fe7b307128cbbbd04d982fef935c842053872)
+++ uspace/srv/tcp/seq_no.c	(revision 4d9fe7b307128cbbbd04d982fef935c842053872)
@@ -0,0 +1,243 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup tcp
+ * @{
+ */
+
+/**
+ * @file Sequence number computations
+ */
+
+#include <assert.h>
+#include <bool.h>
+#include <sys/types.h>
+#include "seq_no.h"
+#include "tcp_type.h"
+
+/** a <= b < c modulo sequence space */
+static bool seq_no_le_lt(uint32_t a, uint32_t b, uint32_t c)
+{
+	if (a <= c) {
+		return (a <= b) && (b < c);
+	} else {
+		return (b < c) || (a <= b);
+	}
+}
+
+/** a < b <= c modulo sequence space */
+static bool seq_no_lt_le(uint32_t a, uint32_t b, uint32_t c)
+{
+	if (a <= c) {
+		return (a < b) && (b <= c);
+	} else {
+		return (b <= c) || (a < b);
+	}
+}
+
+/** Determine wheter ack is acceptable (new acknowledgement) */
+bool seq_no_ack_acceptable(tcp_conn_t *conn, uint32_t seg_ack)
+{
+	/* SND.UNA < SEG.ACK <= SND.NXT */
+	return seq_no_lt_le(conn->snd_una, seg_ack, conn->snd_nxt);
+}
+
+/** Determine wheter ack is duplicate.
+ *
+ * ACK is duplicate if it refers to a sequence number that has
+ * aleady been acked (SEG.ACK <= SND.UNA).
+ */
+bool seq_no_ack_duplicate(tcp_conn_t *conn, uint32_t seg_ack)
+{
+	uint32_t diff;
+
+	/*
+	 * There does not seem to be a three-point comparison
+	 * equivalent of SEG.ACK < SND.UNA. Thus we do it
+	 * on a best-effort basis, based on the difference.
+	 * [-2^31, 0) means less-than, 0 means equal, [0, 2^31)
+	 * means greater-than. Less-than or equal means duplicate.
+	 */
+	diff = seg_ack - conn->snd_una;
+	return diff == 0 || (diff & (0x1 << 31)) != 0;
+}
+
+/** Determine if sequence number is in receive window. */
+bool seq_no_in_rcv_wnd(tcp_conn_t *conn, uint32_t sn)
+{
+	return seq_no_le_lt(conn->rcv_nxt, sn, conn->rcv_nxt + conn->rcv_wnd);
+}
+
+/** Determine segment has new window update.
+ *
+ * Window update is new if either SND.WL1 < SEG.SEQ or
+ * (SND.WL1 = SEG.SEQ and SND.WL2 <= SEG.ACK).
+ */
+bool seq_no_new_wnd_update(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	bool n_seq, n_ack;
+
+	assert(seq_no_segment_acceptable(conn, seg));
+
+	/*
+	 * We make use of the fact that the peer should not ACK anything
+	 * beyond our send window (we surely haven't sent that yet)
+	 * as we should have filtered those acks out.
+	 * We use SND.UNA+SND.WND as the third point of comparison.
+	 */
+
+	n_seq = seq_no_lt_le(conn->snd_wl1, seg->seq,
+	    conn->snd_una + conn->snd_wnd);
+
+	n_ack = conn->snd_wl1 == seg->seq &&
+	    seq_no_le_lt(conn->snd_wl2, seg->ack,
+	    conn->snd_una + conn->snd_wnd + 1);
+
+	return n_seq || n_ack;
+}
+
+/** Determine if segment is ready for processing.
+ *
+ * Assuming segment is acceptable, a segment is ready if it intersects
+ * RCV.NXT, that is we can process it immediately.
+ */
+bool seq_no_segment_ready(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	assert(seq_no_segment_acceptable(conn, seg));
+
+	return seq_no_le_lt(seg->seq, conn->rcv_nxt, seg->seq + seg->len + 1);
+}
+
+/** Determine whether segment is fully acked */
+bool seq_no_segment_acked(tcp_conn_t *conn, tcp_segment_t *seg, uint32_t ack)
+{
+	assert(seg->len > 0);
+	return seq_no_lt_le(seg->seq, seg->seq + seg->len, ack);
+}
+
+/** Determine whether initial SYN is acked */
+bool seq_no_syn_acked(tcp_conn_t *conn)
+{
+	return seq_no_lt_le(conn->iss, conn->snd_una, conn->snd_nxt);
+}
+
+/** Determine whether segment overlaps the receive window */
+bool seq_no_segment_acceptable(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	bool b_in, e_in;
+
+	b_in = seq_no_le_lt(conn->rcv_nxt, seg->seq, conn->rcv_nxt
+	    + conn->rcv_wnd);
+
+	e_in = seq_no_le_lt(conn->rcv_nxt, seg->seq + seg->len - 1,
+	    conn->rcv_nxt + conn->rcv_wnd);
+
+	if (seg->len == 0 && conn->rcv_wnd == 0) {
+		return seg->seq == conn->rcv_nxt;
+	} else if (seg->len == 0 && conn->rcv_wnd != 0) {
+		return b_in;
+	} else if (seg->len > 0 && conn->rcv_wnd == 0) {
+		return false;
+	} else {
+		return b_in || e_in;
+	}
+}
+
+/** Determine size that control bits occupy in sequence space. */
+uint32_t seq_no_control_len(tcp_control_t ctrl)
+{
+	uint32_t len = 0;
+
+	if ((ctrl & CTL_SYN) != 0)
+		++len;
+
+	if ((ctrl & CTL_FIN) != 0)
+		++len;
+
+	return len;
+}
+
+/** Calculate the amount of trim needed to fit segment in receive window. */
+void seq_no_seg_trim_calc(tcp_conn_t *conn, tcp_segment_t *seg,
+    uint32_t *left, uint32_t *right)
+{
+	assert(seq_no_segment_acceptable(conn, seg));
+
+	/*
+	 * If RCV.NXT is between SEG.SEQ and RCV.NXT+RCV.WND, then
+	 * left trim amount is positive
+	 */
+	if (seq_no_lt_le(seg->seq, conn->rcv_nxt,
+	    conn->rcv_nxt + conn->rcv_wnd)) {
+		*left = conn->rcv_nxt - seg->seq;
+	} else {
+		*left = 0;
+	}
+
+	/*
+	 * If SEG.SEQ+SEG.LEN is between SEG.SEQ and RCV.NXT+RCV.WND,
+	 * then right trim is zero.
+	 */
+	if (seq_no_lt_le(seg->seq - 1, seg->seq + seg->len,
+	    conn->rcv_nxt + conn->rcv_wnd)) {
+		*right = 0;
+	} else {
+		*right = (seg->seq + seg->len) -
+		    (conn->rcv_nxt + conn->rcv_wnd);
+	}
+}
+
+/** Segment order comparison.
+ *
+ * Compare sequence order of two acceptable segments.
+ *
+ * @param conn		Connection
+ * @param sa		Segment A
+ * @param sb		Segment B
+ *
+ * @return		-1, 0, 1, resp. if A < B, A == B, A > B in terms
+ *			of sequence order of the beginning of the segment.
+ */
+int seq_no_seg_cmp(tcp_conn_t *conn, tcp_segment_t *sa, tcp_segment_t *sb)
+{
+	assert(seq_no_segment_acceptable(conn, sa));
+	assert(seq_no_segment_acceptable(conn, sb));
+
+	if (seq_no_lt_le(sa->seq, sb->seq, conn->rcv_nxt + conn->rcv_wnd))
+		return -1;
+
+	if (seq_no_lt_le(sb->seq, sa->seq, conn->rcv_nxt + conn->rcv_wnd))
+		return +1;
+
+	assert(sa->seq == sb->seq);
+	return 0;
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/tcp/seq_no.h
===================================================================
--- uspace/srv/tcp/seq_no.h	(revision 4d9fe7b307128cbbbd04d982fef935c842053872)
+++ uspace/srv/tcp/seq_no.h	(revision 4d9fe7b307128cbbbd04d982fef935c842053872)
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup tcp
+ * @{
+ */
+/** @file Sequence number computations
+ */
+
+#ifndef SEQ_NO_H
+#define SEQ_NO_H
+
+#include <sys/types.h>
+#include "tcp_type.h"
+
+extern bool seq_no_ack_acceptable(tcp_conn_t *, uint32_t);
+extern bool seq_no_ack_duplicate(tcp_conn_t *, uint32_t);
+extern bool seq_no_in_rcv_wnd(tcp_conn_t *, uint32_t);
+extern bool seq_no_new_wnd_update(tcp_conn_t *, tcp_segment_t *);
+extern bool seq_no_segment_acked(tcp_conn_t *, tcp_segment_t *, uint32_t);
+extern bool seq_no_syn_acked(tcp_conn_t *);
+extern bool seq_no_segment_ready(tcp_conn_t *, tcp_segment_t *);
+extern bool seq_no_segment_acceptable(tcp_conn_t *, tcp_segment_t *);
+extern void seq_no_seg_trim_calc(tcp_conn_t *, tcp_segment_t *, uint32_t *,
+    uint32_t *);
+extern int seq_no_seg_cmp(tcp_conn_t *, tcp_segment_t *, tcp_segment_t *);
+
+extern uint32_t seq_no_control_len(tcp_control_t);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/tcp/sock.c
===================================================================
--- uspace/srv/tcp/sock.c	(revision 4d9fe7b307128cbbbd04d982fef935c842053872)
+++ uspace/srv/tcp/sock.c	(revision 4d9fe7b307128cbbbd04d982fef935c842053872)
@@ -0,0 +1,832 @@
+/*
+ * Copyright (c) 2008 Lukas Mejdrech
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup tcp
+ * @{
+ */
+
+/**
+ * @file Socket provider
+ */
+
+#include <async.h>
+#include <errno.h>
+#include <io/log.h>
+#include <ip_client.h>
+#include <ipc/socket.h>
+#include <net/modules.h>
+#include <net/socket.h>
+
+#include "sock.h"
+#include "std.h"
+#include "tcp.h"
+#include "tcp_type.h"
+#include "ucall.h"
+
+#define FRAGMENT_SIZE 1024
+
+#define MAX_BACKLOG 128
+
+/** Free ports pool start. */
+#define TCP_FREE_PORTS_START		1025
+
+/** Free ports pool end. */
+#define TCP_FREE_PORTS_END		65535
+
+static int last_used_port = TCP_FREE_PORTS_START - 1;
+static socket_ports_t gsock;
+
+static void tcp_sock_cstate_cb(tcp_conn_t *conn, void *arg);
+
+void tcp_sock_init(void)
+{
+	socket_ports_initialize(&gsock);
+}
+
+static void tcp_free_sock_data(socket_core_t *sock_core)
+{
+	tcp_sockdata_t *socket;
+
+	socket = (tcp_sockdata_t *)sock_core->specific_data;
+	(void)socket;
+}
+
+static void tcp_sock_notify_data(socket_core_t *sock_core)
+{
+	log_msg(LVL_DEBUG, "tcp_sock_notify_data(%d)", sock_core->socket_id);
+	async_exch_t *exch = async_exchange_begin(sock_core->sess);
+	async_msg_5(exch, NET_SOCKET_RECEIVED, (sysarg_t)sock_core->socket_id,
+	    FRAGMENT_SIZE, 0, 0, 1);
+	async_exchange_end(exch);
+}
+
+static void tcp_sock_notify_aconn(socket_core_t *lsock_core)
+{
+	log_msg(LVL_DEBUG, "tcp_sock_notify_aconn(%d)", lsock_core->socket_id);
+	async_exch_t *exch = async_exchange_begin(lsock_core->sess);
+	async_msg_5(exch, NET_SOCKET_ACCEPTED, (sysarg_t)lsock_core->socket_id,
+	    FRAGMENT_SIZE, 0, 0, 0);
+	async_exchange_end(exch);
+}
+
+static void tcp_sock_socket(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
+{
+	tcp_sockdata_t *sock;
+	socket_core_t *sock_core;
+	int sock_id;
+	int rc;
+	ipc_call_t answer;
+
+	log_msg(LVL_DEBUG, "tcp_sock_socket()");
+	sock = calloc(sizeof(tcp_sockdata_t), 1);
+	if (sock == NULL) {
+		async_answer_0(callid, ENOMEM);
+		return;
+	}
+
+	fibril_mutex_initialize(&sock->lock);
+	sock->client = client;
+	sock->laddr.ipv4 = TCP_IPV4_ANY;
+	sock->lconn = NULL;
+	sock->backlog = 0;
+	list_initialize(&sock->ready);
+
+	sock_id = SOCKET_GET_SOCKET_ID(call);
+	rc = socket_create(&client->sockets, client->sess, sock, &sock_id);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	sock_core = socket_cores_find(&client->sockets, sock_id);
+	assert(sock_core != NULL);
+	sock->sock_core = sock_core;
+
+	refresh_answer(&answer, NULL);
+	SOCKET_SET_SOCKET_ID(answer, sock_id);
+
+	SOCKET_SET_DATA_FRAGMENT_SIZE(answer, FRAGMENT_SIZE);
+	SOCKET_SET_HEADER_SIZE(answer, sizeof(tcp_header_t));
+	answer_call(callid, EOK, &answer, 3);
+}
+
+static void tcp_sock_bind(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
+{
+	int rc;
+	struct sockaddr *addr;
+	size_t addr_len;
+	socket_core_t *sock_core;
+	tcp_sockdata_t *socket;
+
+	log_msg(LVL_DEBUG, "tcp_sock_bind()");
+	log_msg(LVL_DEBUG, " - async_data_write_accept");
+	rc = async_data_write_accept((void **) &addr, false, 0, 0, 0, &addr_len);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	log_msg(LVL_DEBUG, " - call socket_bind");
+	rc = socket_bind(&client->sockets, &gsock, SOCKET_GET_SOCKET_ID(call),
+	    addr, addr_len, TCP_FREE_PORTS_START, TCP_FREE_PORTS_END,
+	    last_used_port);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	log_msg(LVL_DEBUG, " - call socket_cores_find");
+	sock_core = socket_cores_find(&client->sockets, SOCKET_GET_SOCKET_ID(call));
+	if (sock_core != NULL) {
+		socket = (tcp_sockdata_t *)sock_core->specific_data;
+		/* XXX Anything to do? */
+		(void) socket;
+	}
+
+	log_msg(LVL_DEBUG, " - success");
+	async_answer_0(callid, EOK);
+}
+
+static void tcp_sock_listen(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
+{
+	int socket_id;
+	int backlog;
+	socket_core_t *sock_core;
+	tcp_sockdata_t *socket;
+	tcp_error_t trc;
+	tcp_sock_t lsocket;
+	tcp_sock_t fsocket;
+	tcp_conn_t *conn;
+	tcp_sock_lconn_t *lconn;
+	int i;
+
+	log_msg(LVL_DEBUG, "tcp_sock_listen()");
+
+	socket_id = SOCKET_GET_SOCKET_ID(call);
+	backlog = SOCKET_GET_BACKLOG(call);
+
+	if (backlog < 0) {
+		async_answer_0(callid, EINVAL);
+		return;
+	}
+
+	if (backlog > MAX_BACKLOG)
+		backlog = MAX_BACKLOG;
+
+	sock_core = socket_cores_find(&client->sockets, socket_id);
+	if (sock_core == NULL) {
+		async_answer_0(callid, ENOTSOCK);
+		return;
+	}
+
+	socket = (tcp_sockdata_t *)sock_core->specific_data;
+
+	/*
+	 * Prepare @c backlog listening connections.
+	 */
+	fibril_mutex_lock(&socket->lock);
+
+	socket->backlog = backlog;
+	socket->lconn = calloc(sizeof(tcp_conn_t *), backlog);
+	if (socket->lconn == NULL) {
+		fibril_mutex_unlock(&socket->lock);
+		async_answer_0(callid, ENOMEM);
+		return;
+	}
+
+	log_msg(LVL_DEBUG, " - open connections");
+
+	lsocket.addr.ipv4 = TCP_IPV4_ANY;
+	lsocket.port = sock_core->port;
+	fsocket.addr.ipv4 = TCP_IPV4_ANY;
+	fsocket.port = TCP_PORT_ANY;
+
+	for (i = 0; i < backlog; i++) {
+
+		lconn = calloc(sizeof(tcp_sock_lconn_t), 1);
+		if (lconn == NULL) {
+			/* XXX Clean up */
+			fibril_mutex_unlock(&socket->lock);
+			async_answer_0(callid, ENOMEM);
+			return;
+		}
+
+		trc = tcp_uc_open(&lsocket, &fsocket, ap_passive,
+		    tcp_open_nonblock, &conn);
+		if (conn == NULL) {
+			/* XXX Clean up */
+			fibril_mutex_unlock(&socket->lock);
+			async_answer_0(callid, ENOMEM);
+			return;
+		}
+
+		tcp_uc_set_cstate_cb(conn, tcp_sock_cstate_cb, lconn);
+
+		assert(trc == TCP_EOK);
+		conn->name = (char *)"S";
+
+		lconn->conn = conn;
+		lconn->socket = socket;
+		link_initialize(&lconn->ready_list);
+		socket->lconn[i] = lconn;
+	}
+
+	fibril_mutex_unlock(&socket->lock);
+	async_answer_0(callid, EOK);
+}
+
+static void tcp_sock_connect(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
+{
+	int rc;
+	struct sockaddr_in *addr;
+	int socket_id;
+	size_t addr_len;
+	socket_core_t *sock_core;
+	tcp_sockdata_t *socket;
+	tcp_error_t trc;
+	tcp_sock_t lsocket;
+	tcp_sock_t fsocket;
+	nic_device_id_t dev_id;
+	tcp_phdr_t *phdr;
+	size_t phdr_len;
+
+	log_msg(LVL_DEBUG, "tcp_sock_connect()");
+
+	rc = async_data_write_accept((void **) &addr, false, 0, 0, 0, &addr_len);
+	if (rc != EOK || addr_len != sizeof(struct sockaddr_in)) {
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	socket_id = SOCKET_GET_SOCKET_ID(call);
+
+	sock_core = socket_cores_find(&client->sockets, socket_id);
+	if (sock_core == NULL) {
+		async_answer_0(callid, ENOTSOCK);
+		return;
+	}
+
+	socket = (tcp_sockdata_t *)sock_core->specific_data;
+	if (sock_core->port <= 0) {
+		rc = socket_bind_free_port(&gsock, sock_core,
+		    TCP_FREE_PORTS_START, TCP_FREE_PORTS_END,
+		    last_used_port);
+		if (rc != EOK) {
+			async_answer_0(callid, rc);
+			return;
+		}
+
+		last_used_port = sock_core->port;
+	}
+
+	fibril_mutex_lock(&socket->lock);
+
+	if (socket->laddr.ipv4 == TCP_IPV4_ANY) {
+		/* Find route to determine local IP address. */
+		rc = ip_get_route_req(ip_sess, IPPROTO_TCP,
+		    (struct sockaddr *)addr, sizeof(*addr), &dev_id,
+		    (void **)&phdr, &phdr_len);
+		if (rc != EOK) {
+			fibril_mutex_unlock(&socket->lock);
+			async_answer_0(callid, rc);
+			log_msg(LVL_DEBUG, "tcp_transmit_connect: Failed to find route.");
+			return;
+		}
+
+		socket->laddr.ipv4 = uint32_t_be2host(phdr->src_addr);
+		log_msg(LVL_DEBUG, "Local IP address is %x", socket->laddr.ipv4);
+		free(phdr);
+	}
+
+	lsocket.addr.ipv4 = socket->laddr.ipv4;
+	lsocket.port = sock_core->port;
+	fsocket.addr.ipv4 = uint32_t_be2host(addr->sin_addr.s_addr);
+	fsocket.port = uint16_t_be2host(addr->sin_port);
+
+	trc = tcp_uc_open(&lsocket, &fsocket, ap_active, 0, &socket->conn);
+
+	if (socket->conn != NULL)
+		socket->conn->name = (char *)"C";
+
+	fibril_mutex_unlock(&socket->lock);
+
+	switch (trc) {
+	case TCP_EOK:
+		rc = EOK;
+		break;
+	case TCP_ERESET:
+		rc = ECONNREFUSED;
+		break;
+	default:
+		assert(false);
+	}
+
+	async_answer_0(callid, rc);
+
+	/* Push one fragment notification to client's queue */
+	tcp_sock_notify_data(sock_core);
+	log_msg(LVL_DEBUG, "tcp_sock_connect(): notify conn\n");
+}
+
+static void tcp_sock_accept(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
+{
+	ipc_call_t answer;
+	int socket_id;
+	int asock_id;
+	socket_core_t *sock_core;
+	socket_core_t *asock_core;
+	tcp_sockdata_t *socket;
+	tcp_sockdata_t *asocket;
+	tcp_error_t trc;
+	tcp_sock_t lsocket;
+	tcp_sock_t fsocket;
+	tcp_conn_t *conn;
+	tcp_conn_t *rconn;
+	tcp_sock_lconn_t *lconn;
+	int rc;
+
+	log_msg(LVL_DEBUG, "tcp_sock_accept()");
+
+	socket_id = SOCKET_GET_SOCKET_ID(call);
+	asock_id = SOCKET_GET_NEW_SOCKET_ID(call);
+
+	sock_core = socket_cores_find(&client->sockets, socket_id);
+	if (sock_core == NULL) {
+		async_answer_0(callid, ENOTSOCK);
+		return;
+	}
+
+	socket = (tcp_sockdata_t *)sock_core->specific_data;
+	fibril_mutex_lock(&socket->lock);
+
+	log_msg(LVL_DEBUG, " - verify socket->conn");
+	if (socket->conn != NULL) {
+		fibril_mutex_unlock(&socket->lock);
+		async_answer_0(callid, EINVAL);
+		return;
+	}
+
+	if (list_empty(&socket->ready)) {
+		fibril_mutex_unlock(&socket->lock);
+		async_answer_0(callid, ENOENT);
+		return;
+	}
+
+	lconn = list_get_instance(list_first(&socket->ready),
+	    tcp_sock_lconn_t, ready_list);
+	list_remove(&lconn->ready_list);
+
+	conn = lconn->conn;
+	tcp_uc_set_cstate_cb(conn, NULL, NULL);
+
+	/* Replenish listening connection */
+
+	lsocket.addr.ipv4 = TCP_IPV4_ANY;
+	lsocket.port = sock_core->port;
+	fsocket.addr.ipv4 = TCP_IPV4_ANY;
+	fsocket.port = TCP_PORT_ANY;
+
+	trc = tcp_uc_open(&lsocket, &fsocket, ap_passive, tcp_open_nonblock,
+	    &rconn);
+	if (rconn == NULL) {
+		/* XXX Clean up */
+		fibril_mutex_unlock(&socket->lock);
+		async_answer_0(callid, ENOMEM);
+		return;
+	}
+
+	tcp_uc_set_cstate_cb(rconn, tcp_sock_cstate_cb, lconn);
+
+	assert(trc == TCP_EOK);
+	rconn->name = (char *)"S";
+
+	lconn->conn = rconn;
+
+	/* Allocate socket for accepted connection */
+
+	log_msg(LVL_DEBUG, "tcp_sock_accept(): allocate asocket\n");
+	asocket = calloc(sizeof(tcp_sockdata_t), 1);
+	if (asocket == NULL) {
+		fibril_mutex_unlock(&socket->lock);
+		async_answer_0(callid, ENOMEM);
+		return;
+	}
+
+	fibril_mutex_initialize(&asocket->lock);
+	asocket->client = client;
+	asocket->conn = conn;
+	log_msg(LVL_DEBUG, "tcp_sock_accept():create asocket\n");
+
+	rc = socket_create(&client->sockets, client->sess, asocket, &asock_id);
+	if (rc != EOK) {
+		fibril_mutex_unlock(&socket->lock);
+		async_answer_0(callid, rc);
+		return;
+	}
+	log_msg(LVL_DEBUG, "tcp_sock_accept(): find acore\n");
+
+	asock_core = socket_cores_find(&client->sockets, asock_id);
+	assert(asock_core != NULL);
+
+	refresh_answer(&answer, NULL);
+
+	SOCKET_SET_DATA_FRAGMENT_SIZE(answer, FRAGMENT_SIZE);
+	SOCKET_SET_SOCKET_ID(answer, asock_id);
+	SOCKET_SET_ADDRESS_LENGTH(answer, sizeof(struct sockaddr_in));
+
+	answer_call(callid, asock_core->socket_id, &answer, 3);
+
+	/* Push one fragment notification to client's queue */
+	log_msg(LVL_DEBUG, "tcp_sock_accept(): notify data\n");
+	tcp_sock_notify_data(asock_core);
+	fibril_mutex_unlock(&socket->lock);
+}
+
+static void tcp_sock_send(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
+{
+	int socket_id;
+	int fragments;
+	int index;
+	socket_core_t *sock_core;
+	tcp_sockdata_t *socket;
+	ipc_call_t answer;
+	ipc_callid_t wcallid;
+	size_t length;
+	uint8_t buffer[FRAGMENT_SIZE];
+	tcp_error_t trc;
+	int rc;
+
+	log_msg(LVL_DEBUG, "tcp_sock_send()");
+	socket_id = SOCKET_GET_SOCKET_ID(call);
+	fragments = SOCKET_GET_DATA_FRAGMENTS(call);
+	SOCKET_GET_FLAGS(call);
+
+	sock_core = socket_cores_find(&client->sockets, socket_id);
+	if (sock_core == NULL) {
+		async_answer_0(callid, ENOTSOCK);
+		return;
+	}
+
+	socket = (tcp_sockdata_t *)sock_core->specific_data;
+	fibril_mutex_lock(&socket->lock);
+
+	if (socket->conn == NULL) {
+		fibril_mutex_unlock(&socket->lock);
+		async_answer_0(callid, ENOTCONN);
+		return;
+	}
+
+	for (index = 0; index < fragments; index++) {
+		if (!async_data_write_receive(&wcallid, &length)) {
+			fibril_mutex_unlock(&socket->lock);
+			async_answer_0(callid, EINVAL);
+			return;
+		}
+
+		if (length > FRAGMENT_SIZE)
+			length = FRAGMENT_SIZE;
+
+		rc = async_data_write_finalize(wcallid, buffer, length);
+		if (rc != EOK) {
+			fibril_mutex_unlock(&socket->lock);
+			async_answer_0(callid, rc);
+			return;
+		}
+
+		trc = tcp_uc_send(socket->conn, buffer, length, 0);
+
+		switch (trc) {
+		case TCP_EOK:
+			rc = EOK;
+			break;
+		case TCP_ENOTEXIST:
+			rc = ENOTCONN;
+			break;
+		case TCP_ECLOSING:
+			rc = ENOTCONN;
+			break;
+		case TCP_ERESET:
+			rc = ECONNABORTED;
+			break;
+		default:
+			assert(false);
+		}
+
+		if (rc != EOK) {
+			fibril_mutex_unlock(&socket->lock);
+			async_answer_0(callid, rc);
+			return;
+		}
+	}
+
+	refresh_answer(&answer, NULL);
+	SOCKET_SET_DATA_FRAGMENT_SIZE(answer, FRAGMENT_SIZE);
+	answer_call(callid, EOK, &answer, 2);
+	fibril_mutex_unlock(&socket->lock);
+}
+
+static void tcp_sock_sendto(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
+{
+	log_msg(LVL_DEBUG, "tcp_sock_sendto()");
+	async_answer_0(callid, ENOTSUP);
+}
+
+static void tcp_sock_recvfrom(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
+{
+	int socket_id;
+	int flags;
+	size_t addr_length, length;
+	socket_core_t *sock_core;
+	tcp_sockdata_t *socket;
+	ipc_call_t answer;
+	ipc_callid_t rcallid;
+	uint8_t buffer[FRAGMENT_SIZE];
+	size_t data_len;
+	xflags_t xflags;
+	tcp_error_t trc;
+	struct sockaddr_in addr;
+	tcp_sock_t *rsock;
+	int rc;
+
+	log_msg(LVL_DEBUG, "%p: tcp_sock_recv[from]()", client);
+
+	socket_id = SOCKET_GET_SOCKET_ID(call);
+	flags = SOCKET_GET_FLAGS(call);
+
+	sock_core = socket_cores_find(&client->sockets, socket_id);
+	if (sock_core == NULL) {
+		async_answer_0(callid, ENOTSOCK);
+		return;
+	}
+
+	socket = (tcp_sockdata_t *)sock_core->specific_data;
+	fibril_mutex_lock(&socket->lock);
+
+	if (socket->conn == NULL) {
+		fibril_mutex_unlock(&socket->lock);
+		async_answer_0(callid, ENOTCONN);
+		return;
+	}
+
+	(void)flags;
+
+	trc = tcp_uc_receive(socket->conn, buffer, FRAGMENT_SIZE, &data_len,
+	    &xflags);
+	log_msg(LVL_DEBUG, "**** tcp_uc_receive done");
+
+	switch (trc) {
+	case TCP_EOK:
+		rc = EOK;
+		break;
+	case TCP_ENOTEXIST:
+	case TCP_ECLOSING:
+		rc = ENOTCONN;
+		break;
+	case TCP_ERESET:
+		rc = ECONNABORTED;
+		break;
+	default:
+		assert(false);
+	}
+
+	log_msg(LVL_DEBUG, "**** tcp_uc_receive -> %d", rc);
+	if (rc != EOK) {
+		fibril_mutex_unlock(&socket->lock);
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	if (IPC_GET_IMETHOD(call) == NET_SOCKET_RECVFROM) {
+		/* Fill addr */
+		rsock = &socket->conn->ident.foreign;
+		addr.sin_family = AF_INET;
+		addr.sin_addr.s_addr = host2uint32_t_be(rsock->addr.ipv4);
+		addr.sin_port = host2uint16_t_be(rsock->port);
+
+		log_msg(LVL_DEBUG, "addr read receive");
+		if (!async_data_read_receive(&rcallid, &addr_length)) {
+			fibril_mutex_unlock(&socket->lock);
+			async_answer_0(callid, EINVAL);
+			return;
+		}
+
+		if (addr_length > sizeof(addr))
+			addr_length = sizeof(addr);
+
+		log_msg(LVL_DEBUG, "addr read finalize");
+		rc = async_data_read_finalize(rcallid, &addr, addr_length);
+		if (rc != EOK) {
+			fibril_mutex_unlock(&socket->lock);
+			async_answer_0(callid, EINVAL);
+			return;
+		}
+	}
+
+	log_msg(LVL_DEBUG, "data read receive");
+	if (!async_data_read_receive(&rcallid, &length)) {
+		fibril_mutex_unlock(&socket->lock);
+		async_answer_0(callid, EINVAL);
+		return;
+	}
+
+	if (length > data_len)
+		length = data_len;
+
+	log_msg(LVL_DEBUG, "data read finalize");
+	rc = async_data_read_finalize(rcallid, buffer, length);
+
+	if (length < data_len && rc == EOK)
+		rc = EOVERFLOW;
+
+	SOCKET_SET_READ_DATA_LENGTH(answer, length);
+	answer_call(callid, EOK, &answer, 1);
+
+	/* Push one fragment notification to client's queue */
+	tcp_sock_notify_data(sock_core);
+	fibril_mutex_unlock(&socket->lock);
+}
+
+static void tcp_sock_close(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
+{
+	int socket_id;
+	socket_core_t *sock_core;
+	tcp_sockdata_t *socket;
+	tcp_error_t trc;
+	int rc;
+	uint8_t buffer[FRAGMENT_SIZE];
+	size_t data_len;
+	xflags_t xflags;
+
+	log_msg(LVL_DEBUG, "tcp_sock_close()");
+	socket_id = SOCKET_GET_SOCKET_ID(call);
+
+	sock_core = socket_cores_find(&client->sockets, socket_id);
+	if (sock_core == NULL) {
+		async_answer_0(callid, ENOTSOCK);
+		return;
+	}
+
+	socket = (tcp_sockdata_t *)sock_core->specific_data;
+	fibril_mutex_lock(&socket->lock);
+
+	if (socket->conn != NULL) {
+		trc = tcp_uc_close(socket->conn);
+		if (trc != TCP_EOK && trc != TCP_ENOTEXIST) {
+			fibril_mutex_unlock(&socket->lock);
+			async_answer_0(callid, EBADF);
+			return;
+		}
+
+		/* Drain incoming data. This should really be done in the background. */
+		do {
+			trc = tcp_uc_receive(socket->conn, buffer,
+			    FRAGMENT_SIZE, &data_len, &xflags);
+		} while (trc == TCP_EOK);
+
+		tcp_uc_delete(socket->conn);
+	}
+
+	rc = socket_destroy(net_sess, socket_id, &client->sockets, &gsock,
+	    tcp_free_sock_data);
+	if (rc != EOK) {
+		fibril_mutex_unlock(&socket->lock);
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	fibril_mutex_unlock(&socket->lock);
+	async_answer_0(callid, EOK);
+}
+
+static void tcp_sock_getsockopt(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
+{
+	log_msg(LVL_DEBUG, "tcp_sock_getsockopt()");
+	async_answer_0(callid, ENOTSUP);
+}
+
+static void tcp_sock_setsockopt(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
+{
+	log_msg(LVL_DEBUG, "tcp_sock_setsockopt()");
+	async_answer_0(callid, ENOTSUP);
+}
+
+/** Called when connection state changes. */
+static void tcp_sock_cstate_cb(tcp_conn_t *conn, void *arg)
+{
+	tcp_conn_status_t cstatus;
+	tcp_sock_lconn_t *lconn = (tcp_sock_lconn_t *)arg;
+	tcp_sockdata_t *socket = lconn->socket;
+
+	log_msg(LVL_DEBUG, "tcp_sock_cstate_cb()");
+	fibril_mutex_lock(&socket->lock);
+	assert(conn == lconn->conn);
+
+	tcp_uc_status(conn, &cstatus);
+	if (cstatus.cstate != st_established) {
+		fibril_mutex_unlock(&socket->lock);
+		return;
+	}
+
+	assert_link_not_used(&lconn->ready_list);
+	list_append(&lconn->ready_list, &socket->ready);
+
+	log_msg(LVL_DEBUG, "tcp_sock_cstate_cb(): notify accept");
+
+	/* Push one accept notification to client's queue */
+	tcp_sock_notify_aconn(socket->sock_core);
+	fibril_mutex_unlock(&socket->lock);
+}
+
+int tcp_sock_connection(async_sess_t *sess, ipc_callid_t iid, ipc_call_t icall)
+{
+	ipc_callid_t callid;
+	ipc_call_t call;
+	tcp_client_t client;
+
+	/* Accept the connection */
+	async_answer_0(iid, EOK);
+
+	client.sess = sess;
+	socket_cores_initialize(&client.sockets);
+
+	while (true) {
+		callid = async_get_call(&call);
+		if (!IPC_GET_IMETHOD(call))
+			break;
+
+		log_msg(LVL_DEBUG, "tcp_sock_connection: METHOD=%d\n",
+		    (int)IPC_GET_IMETHOD(call));
+
+		switch (IPC_GET_IMETHOD(call)) {
+		case NET_SOCKET:
+			tcp_sock_socket(&client, callid, call);
+			break;
+		case NET_SOCKET_BIND:
+			tcp_sock_bind(&client, callid, call);
+			break;
+		case NET_SOCKET_LISTEN:
+			tcp_sock_listen(&client, callid, call);
+			break;
+		case NET_SOCKET_CONNECT:
+			tcp_sock_connect(&client, callid, call);
+			break;
+		case NET_SOCKET_ACCEPT:
+			tcp_sock_accept(&client, callid, call);
+			break;
+		case NET_SOCKET_SEND:
+			tcp_sock_send(&client, callid, call);
+			break;
+		case NET_SOCKET_SENDTO:
+			tcp_sock_sendto(&client, callid, call);
+			break;
+		case NET_SOCKET_RECV:
+		case NET_SOCKET_RECVFROM:
+			tcp_sock_recvfrom(&client, callid, call);
+			break;
+		case NET_SOCKET_CLOSE:
+			tcp_sock_close(&client, callid, call);
+			break;
+		case NET_SOCKET_GETSOCKOPT:
+			tcp_sock_getsockopt(&client, callid, call);
+			break;
+		case NET_SOCKET_SETSOCKOPT:
+			tcp_sock_setsockopt(&client, callid, call);
+			break;
+		default:
+			async_answer_0(callid, ENOTSUP);
+			break;
+		}
+	}
+
+	return EOK;
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/tcp/sock.h
===================================================================
--- uspace/srv/tcp/sock.h	(revision 4d9fe7b307128cbbbd04d982fef935c842053872)
+++ uspace/srv/tcp/sock.h	(revision 4d9fe7b307128cbbbd04d982fef935c842053872)
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup tcp
+ * @{
+ */
+/** @file Socket provider
+ */
+
+#ifndef SOCK_H
+#define SOCK_H
+
+#include <async.h>
+
+extern void tcp_sock_init(void);
+extern int tcp_sock_connection(async_sess_t *, ipc_callid_t, ipc_call_t);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/tcp/std.h
===================================================================
--- uspace/srv/tcp/std.h	(revision 4d9fe7b307128cbbbd04d982fef935c842053872)
+++ uspace/srv/tcp/std.h	(revision 4d9fe7b307128cbbbd04d982fef935c842053872)
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup tcp
+ * @{
+ */
+/** @file TCP header definitions
+ *
+ * Based on IETF RFC 793
+ */
+
+#ifndef STD_H
+#define STD_H
+
+#include <sys/types.h>
+
+/** TCP Header (fixed part) */
+typedef struct {
+	/** Source port */
+	uint16_t src_port;
+	/** Destination port */
+	uint16_t dest_port;
+	/** Sequence number */
+	uint32_t seq;
+	/** Acknowledgement number */
+	uint32_t ack;
+	/** Data Offset, Reserved, Flags */
+	uint16_t doff_flags;
+	/** Window */
+	uint16_t window;
+	/* Checksum */
+	uint16_t checksum;
+	/** Urgent pointer */
+	uint16_t urg_ptr;
+} tcp_header_t;
+
+/** Bits in tcp_header_t.doff_flags */
+enum doff_flags_bits {
+	DF_DATA_OFFSET_h	= 15,
+	DF_DATA_OFFSET_l	= 12,
+	DF_URG			= 5,
+	DF_ACK			= 4,
+	DF_PSH			= 3,
+	DF_RST			= 2,
+	DF_SYN			= 1,
+	DF_FIN			= 0
+};
+
+/** TCP pseudo header */
+typedef struct {
+	/** Source address */
+	uint32_t src_addr;
+	/** Destination address */
+	uint32_t dest_addr;
+	/** Zero */
+	uint8_t zero;
+	/** Protocol */
+	uint8_t protocol;
+	/** TCP length */
+	uint16_t tcp_length;
+} tcp_phdr_t;
+
+/** Option kind */
+enum opt_kind {
+	/** End of option list */
+	OPT_END_LIST		= 0,
+	/** No-operation */
+	OPT_NOP			= 1,
+	/** Maximum segment size */
+	OPT_MAX_SEG_SIZE	= 2
+};
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/tcp/tcp.c
===================================================================
--- uspace/srv/tcp/tcp.c	(revision 4d9fe7b307128cbbbd04d982fef935c842053872)
+++ uspace/srv/tcp/tcp.c	(revision 4d9fe7b307128cbbbd04d982fef935c842053872)
@@ -0,0 +1,446 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup tcp
+ * @{
+ */
+
+/**
+ * @file TCP (Transmission Control Protocol) network module
+ */
+
+#include <async.h>
+#include <bitops.h>
+#include <byteorder.h>
+#include <errno.h>
+#include <io/log.h>
+#include <stdio.h>
+#include <task.h>
+
+#include <icmp_remote.h>
+#include <ip_client.h>
+#include <ip_interface.h>
+#include <ipc/services.h>
+#include <ipc/tl.h>
+#include <tl_common.h>
+#include <tl_skel.h>
+#include <packet_client.h>
+#include <packet_remote.h>
+
+#include "ncsim.h"
+#include "pdu.h"
+#include "rqueue.h"
+#include "sock.h"
+#include "std.h"
+#include "tcp.h"
+#include "test.h"
+
+#define NAME       "tcp"
+
+async_sess_t *net_sess;
+static async_sess_t *icmp_sess;
+async_sess_t *ip_sess;
+packet_dimensions_t pkt_dims;
+
+static void tcp_received_pdu(tcp_pdu_t *pdu);
+
+/* Pull up packets into a single memory block. */
+static int pq_pullup(packet_t *packet, void **data, size_t *dsize)
+{
+	packet_t *npacket;
+	size_t tot_len;
+	int length;
+
+	npacket = packet;
+	tot_len = 0;
+	do {
+		length = packet_get_data_length(packet);
+		if (length <= 0)
+			return EINVAL;
+
+		tot_len += length;
+	} while ((npacket = pq_next(npacket)) != NULL);
+
+	uint8_t *buf;
+	uint8_t *dp;
+
+	buf = calloc(tot_len, 1);
+	if (buf == NULL) {
+		free(buf);
+		return ENOMEM;
+	}
+
+	npacket = packet;
+	dp = buf;
+	do {
+		length = packet_get_data_length(packet);
+		if (length <= 0) {
+			free(buf);
+			return EINVAL;
+		}
+
+		memcpy(dp, packet_get_data(packet), length);
+		dp += length;
+	} while ((npacket = pq_next(npacket)) != NULL);
+
+	*data = buf;
+	*dsize = tot_len;
+	return EOK;
+}
+
+/** Process packet received from network layer. */
+static int tcp_received_msg(nic_device_id_t device_id, packet_t *packet,
+    services_t error)
+{
+	int rc;
+	size_t offset;
+	int length;
+	struct sockaddr_in *src_addr;
+	struct sockaddr_in *dest_addr;
+	size_t addr_len;
+
+	log_msg(LVL_DEBUG, "tcp_received_msg()");
+
+	switch (error) {
+	case SERVICE_NONE:
+		break;
+	case SERVICE_ICMP:
+	default:
+		log_msg(LVL_WARN, "Unsupported service number %u",
+		    (unsigned)error);
+		pq_release_remote(net_sess, packet_get_id(packet));
+		return ENOTSUP;
+	}
+
+	/* Process and trim off IP header */
+	log_msg(LVL_DEBUG, "tcp_received_msg() - IP header");
+
+	rc = ip_client_process_packet(packet, NULL, NULL, NULL, NULL, NULL);
+	if (rc < 0) {
+		log_msg(LVL_WARN, "ip_client_process_packet() failed");
+		pq_release_remote(net_sess, packet_get_id(packet));
+		return rc;
+	}
+
+	offset = (size_t)rc;
+	length = packet_get_data_length(packet);
+
+	if (length < 0 || (size_t)length < offset) {
+		log_msg(LVL_WARN, "length=%d, dropping.", length);
+		pq_release_remote(net_sess, packet_get_id(packet));
+		return EINVAL;
+	}
+
+	addr_len = packet_get_addr(packet, (uint8_t **)&src_addr,
+	    (uint8_t **)&dest_addr);
+	if (addr_len <= 0) {
+		log_msg(LVL_WARN, "Failed to get packet address.");
+		pq_release_remote(net_sess, packet_get_id(packet));
+		return EINVAL;
+	}
+
+	if (addr_len != sizeof(struct sockaddr_in)) {
+		log_msg(LVL_WARN, "Unsupported address size %zu (!= %zu)",
+		    addr_len, sizeof(struct sockaddr_in));
+		pq_release_remote(net_sess, packet_get_id(packet));
+		return EINVAL;
+	}
+
+	rc = packet_trim(packet, offset, 0);
+	if (rc != EOK) {
+		log_msg(LVL_WARN, "Failed to trim packet.");
+		pq_release_remote(net_sess, packet_get_id(packet));
+		return rc;
+	}
+
+	/* Pull up packets into a single memory block, pdu_raw. */
+	log_msg(LVL_DEBUG, "tcp_received_msg() - pull up");
+	uint8_t *pdu_raw;
+	size_t pdu_raw_size = 0;
+
+	pq_pullup(packet, (void **)&pdu_raw, &pdu_raw_size);
+
+	/* Split into header and payload. */
+
+	log_msg(LVL_DEBUG, "tcp_received_msg() - split header/payload");
+
+	tcp_pdu_t *pdu;
+	size_t hdr_size;
+	tcp_header_t *hdr;
+	uint32_t data_offset;
+
+	if (pdu_raw_size < sizeof(tcp_header_t)) {
+		log_msg(LVL_WARN, "pdu_raw_size = %zu < sizeof(tcp_header_t) = %zu",
+		    pdu_raw_size, sizeof(tcp_header_t));
+		pq_release_remote(net_sess, packet_get_id(packet));
+		return EINVAL;
+	}
+
+	hdr = (tcp_header_t *)pdu_raw;
+	data_offset = BIT_RANGE_EXTRACT(uint32_t, DF_DATA_OFFSET_h, DF_DATA_OFFSET_l,
+	    uint16_t_be2host(hdr->doff_flags));
+
+	hdr_size = sizeof(uint32_t) * data_offset;
+
+	if (pdu_raw_size < hdr_size) {
+		log_msg(LVL_WARN, "pdu_raw_size = %zu < hdr_size = %zu",
+		    pdu_raw_size, hdr_size);
+		pq_release_remote(net_sess, packet_get_id(packet));
+		return EINVAL;
+	}
+
+	if (hdr_size < sizeof(tcp_header_t)) {
+		log_msg(LVL_WARN, "hdr_size = %zu < sizeof(tcp_header_t) = %zu",
+		    hdr_size, sizeof(tcp_header_t));
+		pq_release_remote(net_sess, packet_get_id(packet));
+		return EINVAL;
+	}
+
+	log_msg(LVL_DEBUG, "pdu_raw_size=%zu, hdr_size=%zu",
+	    pdu_raw_size, hdr_size);
+	pdu = tcp_pdu_create(pdu_raw, hdr_size, pdu_raw + hdr_size,
+	    pdu_raw_size - hdr_size);
+	if (pdu == NULL) {
+		log_msg(LVL_WARN, "Failed creating PDU. Dropped.");
+		return ENOMEM;
+	}
+
+	free(pdu_raw);
+
+	pdu->src_addr.ipv4 = uint32_t_be2host(src_addr->sin_addr.s_addr);
+	pdu->dest_addr.ipv4 = uint32_t_be2host(dest_addr->sin_addr.s_addr);
+	log_msg(LVL_DEBUG, "src: 0x%08x, dest: 0x%08x",
+	    pdu->src_addr.ipv4, pdu->dest_addr.ipv4);
+
+	tcp_received_pdu(pdu);
+	tcp_pdu_delete(pdu);
+
+	return EOK;
+}
+
+/** Receive packets from network layer. */
+static void tcp_receiver(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	packet_t *packet;
+	int rc;
+
+	log_msg(LVL_DEBUG, "tcp_receiver()");
+
+	while (true) {
+		switch (IPC_GET_IMETHOD(*icall)) {
+		case NET_TL_RECEIVED:
+			log_msg(LVL_DEBUG, "method = NET_TL_RECEIVED");
+			rc = packet_translate_remote(net_sess, &packet,
+			    IPC_GET_PACKET(*icall));
+			if (rc != EOK) {
+				log_msg(LVL_DEBUG, "Error %d translating packet.", rc);
+				async_answer_0(iid, (sysarg_t)rc);
+				break;
+			}
+			rc = tcp_received_msg(IPC_GET_DEVICE(*icall), packet,
+			    IPC_GET_ERROR(*icall));
+			async_answer_0(iid, (sysarg_t)rc);
+			break;
+		default:
+			log_msg(LVL_DEBUG, "method = %u",
+			    (unsigned)IPC_GET_IMETHOD(*icall));
+			async_answer_0(iid, ENOTSUP);
+			break;
+		}
+
+		iid = async_get_call(icall);
+	}
+}
+
+/** Transmit PDU over network layer. */
+void tcp_transmit_pdu(tcp_pdu_t *pdu)
+{
+	struct sockaddr_in dest;
+	nic_device_id_t dev_id;
+	void *phdr;
+	size_t phdr_len;
+	packet_dimension_t *pkt_dim;
+	int rc;
+	packet_t *packet;
+	void *pkt_data;
+	size_t pdu_size;
+
+	dest.sin_family = AF_INET;
+	dest.sin_port = 0; /* not needed */
+	dest.sin_addr.s_addr = host2uint32_t_be(pdu->dest_addr.ipv4);
+
+	/* Find route. Obtained pseudo-header is not used. */
+	rc = ip_get_route_req(ip_sess, IPPROTO_TCP, (struct sockaddr *)&dest,
+	    sizeof(dest), &dev_id, &phdr, &phdr_len);
+	if (rc != EOK) {
+		log_msg(LVL_DEBUG, "tcp_transmit_pdu: Failed to find route.");
+		return;
+	}
+
+	rc = tl_get_ip_packet_dimension(ip_sess, &pkt_dims, dev_id, &pkt_dim);
+	if (rc != EOK) {
+		log_msg(LVL_DEBUG, "tcp_transmit_pdu: Failed to get dimension.");
+		return;
+	}
+
+	pdu_size = pdu->header_size + pdu->text_size;
+
+	packet = packet_get_4_remote(net_sess, pdu_size, pkt_dim->addr_len,
+	    pkt_dim->prefix, pkt_dim->suffix);
+	if (!packet) {
+		log_msg(LVL_DEBUG, "tcp_transmit_pdu: Failed to get packet.");
+		return;
+	}
+
+	pkt_data = packet_suffix(packet, pdu_size);
+	if (!pkt_data) {
+		log_msg(LVL_DEBUG, "tcp_transmit_pdu: Failed to get pkt_data ptr.");
+		pq_release_remote(net_sess, packet_get_id(packet));
+		return;
+	}
+
+	rc = ip_client_prepare_packet(packet, IPPROTO_TCP, 0, 0, 0, 0);
+	if (rc != EOK) {
+		log_msg(LVL_DEBUG, "tcp_transmit_pdu: Failed to prepare IP packet part.");
+		pq_release_remote(net_sess, packet_get_id(packet));
+		return;
+	}
+
+	rc = packet_set_addr(packet, NULL, (uint8_t *)&dest, sizeof(dest));
+	if (rc != EOK) {
+		log_msg(LVL_DEBUG, "tcp_transmit_pdu: Failed to set packet address.");
+		pq_release_remote(net_sess, packet_get_id(packet));
+		return;
+	}
+
+	/* Copy PDU data to packet */
+	memcpy(pkt_data, pdu->header, pdu->header_size);
+	memcpy((uint8_t *)pkt_data + pdu->header_size, pdu->text,
+	    pdu->text_size);
+
+	/* Transmit packet. XXX Transfers packet ownership to IP? */
+	ip_send_msg(ip_sess, dev_id, packet, SERVICE_TCP, 0);
+}
+
+/** Process received PDU. */
+static void tcp_received_pdu(tcp_pdu_t *pdu)
+{
+	tcp_segment_t *dseg;
+	tcp_sockpair_t rident;
+
+	log_msg(LVL_DEBUG, "tcp_received_pdu()");
+
+	if (tcp_pdu_decode(pdu, &rident, &dseg) != EOK) {
+		log_msg(LVL_WARN, "Not enough memory. PDU dropped.");
+		return;
+	}
+
+	/* Insert decoded segment into rqueue */
+	tcp_rqueue_insert_seg(&rident, dseg);
+}
+
+/* Called from libnet */
+void tl_connection(void)
+{
+	log_msg(LVL_DEBUG, "tl_connection()");
+}
+
+/* Called from libnet */
+int tl_message(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer,
+    size_t *answer_count)
+{
+	async_sess_t *callback;
+
+	log_msg(LVL_DEBUG, "tl_message()");
+
+	*answer_count = 0;
+	callback = async_callback_receive_start(EXCHANGE_SERIALIZE, call);
+	if (callback)
+		return tcp_sock_connection(callback, callid, *call);
+
+	return ENOTSUP;
+}
+
+/* Called from libnet */
+int tl_initialize(async_sess_t *sess)
+{
+	int rc;
+
+	net_sess = sess;
+	icmp_sess = icmp_connect_module();
+
+	log_msg(LVL_DEBUG, "tl_initialize()");
+
+	tcp_sock_init();
+
+	ip_sess = ip_bind_service(SERVICE_IP, IPPROTO_TCP, SERVICE_TCP,
+	    tcp_receiver);
+	if (ip_sess == NULL)
+		return ENOENT;
+
+	rc = packet_dimensions_initialize(&pkt_dims);
+	if (rc != EOK)
+		return rc;
+
+	return EOK;
+}
+
+int main(int argc, char **argv)
+{
+	int rc;
+
+	printf(NAME ": TCP (Transmission Control Protocol) network module\n");
+
+	rc = log_init(NAME, LVL_ERROR);
+	if (rc != EOK) {
+		printf(NAME ": Failed to initialize log.\n");
+		return 1;
+	}
+
+//	printf(NAME ": Accepting connections\n");
+//	task_retval(0);
+
+	tcp_rqueue_init();
+	tcp_rqueue_thread_start();
+
+	tcp_ncsim_init();
+	tcp_ncsim_thread_start();
+
+	if (0) tcp_test();
+/*
+	async_manager();
+*/
+	tl_module_start(SERVICE_TCP);
+
+	/* Not reached */
+	return 0;
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/tcp/tcp.h
===================================================================
--- uspace/srv/tcp/tcp.h	(revision 4d9fe7b307128cbbbd04d982fef935c842053872)
+++ uspace/srv/tcp/tcp.h	(revision 4d9fe7b307128cbbbd04d982fef935c842053872)
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup tcp
+ * @{
+ */
+/** @file TCP (Transmission Control Protocol) network module
+ */
+
+#ifndef TCP_H
+#define TCP_H
+
+#include <async.h>
+#include <packet_remote.h>
+#include "tcp_type.h"
+
+extern async_sess_t *net_sess;
+extern async_sess_t *ip_sess;
+extern void tcp_transmit_pdu(tcp_pdu_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/tcp/tcp_type.h
===================================================================
--- uspace/srv/tcp/tcp_type.h	(revision 4d9fe7b307128cbbbd04d982fef935c842053872)
+++ uspace/srv/tcp/tcp_type.h	(revision 4d9fe7b307128cbbbd04d982fef935c842053872)
@@ -0,0 +1,363 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup tcp
+ * @{
+ */
+/** @file TCP type definitions
+ */
+
+#ifndef TCP_TYPE_H
+#define TCP_TYPE_H
+
+#include <adt/list.h>
+#include <async.h>
+#include <bool.h>
+#include <fibril_synch.h>
+#include <socket_core.h>
+#include <sys/types.h>
+
+struct tcp_conn;
+
+typedef enum {
+	/** Listen */
+	st_listen,
+	/** Syn-sent */
+	st_syn_sent,
+	/** Syn-received */
+	st_syn_received,
+	/** Established */
+	st_established,
+	/** Fin-wait-1 */
+	st_fin_wait_1,
+	/** Fin-wait-2 */
+	st_fin_wait_2,
+	/** Close-wait */
+	st_close_wait,
+	/** Closing */
+	st_closing,
+	/** Last-ack */
+	st_last_ack,
+	/** Time-wait */
+	st_time_wait,
+	/** Closed */
+	st_closed
+} tcp_cstate_t;
+
+/** Error codes returned by TCP user calls (per the spec). */
+typedef enum {
+	/* OK */
+	TCP_EOK,
+	/* Connection aborted due to user timeout */
+	TCP_EABORTED,
+	/* Connection already exists */
+	TCP_EEXISTS,
+	/* Connection closing */
+	TCP_ECLOSING,
+	/* Connection does not exist */
+	TCP_ENOTEXIST,
+	/* Connection illegal for this process */
+	TCP_EILLEGAL,
+	/* Connection not open */
+	TCP_ENOTOPEN,
+	/* Connection reset */
+	TCP_ERESET,
+	/* Foreign socket unspecified */
+	TCP_EUNSPEC,
+	/* Insufficient resources */
+	TCP_ENORES,
+	/* Precedence not allowed */
+	TCP_EINVPREC,
+	/* Security/compartment not allowed */
+	TCP_EINVCOMP
+} tcp_error_t;
+
+typedef enum {
+	XF_PUSH		= 0x1,
+	XF_URGENT	= 0x2
+} xflags_t;
+
+typedef enum {
+	CTL_SYN		= 0x1,
+	CTL_FIN		= 0x2,
+	CTL_RST		= 0x4,
+	CTL_ACK		= 0x8
+} tcp_control_t;
+
+typedef struct {
+	uint32_t ipv4;
+} netaddr_t;
+
+typedef struct {
+	netaddr_t addr;
+	uint16_t port;
+} tcp_sock_t;
+
+enum netaddr {
+	TCP_IPV4_ANY = 0
+};
+
+enum tcp_port {
+	TCP_PORT_ANY = 0
+};
+
+typedef struct {
+	tcp_sock_t local;
+	tcp_sock_t foreign;
+} tcp_sockpair_t;
+
+/** Connection incoming segments queue */
+typedef struct {
+	struct tcp_conn *conn;
+	list_t list;
+} tcp_iqueue_t;
+
+/** Retransmission queue */
+typedef struct {
+	struct tcp_conn *conn;
+	list_t list;
+
+	/** Retransmission timer */
+	fibril_timer_t *timer;
+} tcp_tqueue_t;
+
+typedef enum {
+	ap_active,
+	ap_passive
+} acpass_t;
+
+typedef enum {
+	tcp_open_nonblock = 1
+} tcp_open_flags_t;
+
+typedef struct tcp_conn tcp_conn_t;
+
+/** Connection state change callback function */
+typedef void (*tcp_cstate_cb_t)(tcp_conn_t *, void *);
+
+/** Connection */
+struct tcp_conn {
+	char *name;
+	link_t link;
+
+	/** Connection state change callback function */
+	tcp_cstate_cb_t cstate_cb;
+	/** Argument to @c cstate_cb */
+	void *cstate_cb_arg;
+
+	/** Connection identification (local and foreign socket) */
+	tcp_sockpair_t ident;
+
+	/** Active or passive connection */
+	acpass_t ap;
+
+	/** Protects access to connection structure */
+	fibril_mutex_t lock;
+	/** Reference count */
+	atomic_t refcnt;
+
+	/** Connection state */
+	tcp_cstate_t cstate;
+	/** True if connection was reset */
+	bool reset;
+	/** True if connection was deleted by user */
+	bool deleted;
+	/** Signalled when @c cstate changes */
+	fibril_condvar_t cstate_cv;
+
+	/** Set when FIN is removed from the retransmission queue */
+	bool fin_is_acked;
+
+	/** Queue of incoming segments */
+	tcp_iqueue_t incoming;
+
+	/** Retransmission queue */
+	tcp_tqueue_t retransmit;
+
+	/** Time-Wait timeout timer */
+	fibril_timer_t *tw_timer;
+
+	/** Receive buffer */
+	uint8_t *rcv_buf;
+	/** Receive buffer size */
+	size_t rcv_buf_size;
+	/** Receive buffer number of bytes used */
+	size_t rcv_buf_used;
+	/** Receive buffer contains FIN */
+	bool rcv_buf_fin;
+	/** Receive buffer CV. Broadcast when new data is inserted */
+	fibril_condvar_t rcv_buf_cv;
+
+	/** Send buffer */
+	uint8_t *snd_buf;
+	/** Send buffer size */
+	size_t snd_buf_size;
+	/** Send buffer number of bytes used */
+	size_t snd_buf_used;
+	/** Send buffer contains FIN */
+	bool snd_buf_fin;
+	/** Send buffer CV. Broadcast when space is made available in buffer */
+	fibril_condvar_t snd_buf_cv;
+
+	/** Send unacknowledged */
+	uint32_t snd_una;
+	/** Send next */
+	uint32_t snd_nxt;
+	/** Send window */
+	uint32_t snd_wnd;
+	/** Send urgent pointer */
+	uint32_t snd_up;
+	/** Segment sequence number used for last window update */
+	uint32_t snd_wl1;
+	/** Segment acknowledgement number used for last window update */
+	uint32_t snd_wl2;
+	/** Initial send sequence number */
+	uint32_t iss;
+
+	/** Receive next */
+	uint32_t rcv_nxt;
+	/** Receive window */
+	uint32_t rcv_wnd;
+	/** Receive urgent pointer */
+	uint32_t rcv_up;
+	/** Initial receive sequence number */
+	uint32_t irs;
+};
+
+/** Data returned by Status user call */
+typedef struct {
+	/** Connection state */
+	tcp_cstate_t cstate;
+} tcp_conn_status_t;
+
+typedef struct {
+	/** SYN, FIN */
+	tcp_control_t ctrl;
+
+	/** Segment sequence number */
+	uint32_t seq;
+	/** Segment acknowledgement number */
+	uint32_t ack;
+	/** Segment length in sequence space */
+	uint32_t len;
+	/** Segment window */
+	uint32_t wnd;
+	/** Segment urgent pointer */
+	uint32_t up;
+
+	/** Segment data, may be moved when trimming segment */
+	void *data;
+	/** Segment data, original pointer used to free data */
+	void *dfptr;
+} tcp_segment_t;
+
+
+typedef struct {
+	link_t link;
+	tcp_sockpair_t sp;
+	tcp_segment_t *seg;
+} tcp_rqueue_entry_t;
+
+/** NCSim queue entry */
+typedef struct {
+	link_t link;
+	suseconds_t delay;
+	tcp_sockpair_t sp;
+	tcp_segment_t *seg;
+} tcp_squeue_entry_t;
+
+typedef struct {
+	link_t link;
+	tcp_segment_t *seg;
+} tcp_iqueue_entry_t;
+
+/** Retransmission queue entry */
+typedef struct {
+	link_t link;
+	tcp_conn_t *conn;
+	tcp_segment_t *seg;
+} tcp_tqueue_entry_t;
+
+typedef enum {
+	cp_continue,
+	cp_done
+} cproc_t;
+
+/** Encoded PDU */
+typedef struct {
+	/** Source address */
+	netaddr_t src_addr;
+	/** Destination address */
+	netaddr_t dest_addr;
+
+	/** Encoded header */
+	void *header;
+	/** Encoded header size */
+	size_t header_size;
+	/** Text */
+	void *text;
+	/** Text size */
+	size_t text_size;
+} tcp_pdu_t;
+
+typedef struct {
+	async_sess_t *sess;
+	socket_cores_t sockets;
+} tcp_client_t;
+
+typedef struct tcp_sockdata {
+	/** Lock */
+	fibril_mutex_t lock;
+	/** Socket core */
+	socket_core_t *sock_core;
+	/** Client */
+	tcp_client_t *client;
+	/** Connection */
+	tcp_conn_t *conn;
+	/** Local address */
+	netaddr_t laddr;
+	/** Backlog size */
+	int backlog;
+	/** Array of listening connections, @c backlog elements */
+	struct tcp_sock_lconn **lconn;
+	/** List of connections (from lconn) that are ready to be accepted */
+	list_t ready;
+} tcp_sockdata_t;
+
+typedef struct tcp_sock_lconn {
+	tcp_conn_t *conn;
+	tcp_sockdata_t *socket;
+	int index;
+	link_t ready_list;
+} tcp_sock_lconn_t;
+
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/tcp/test.c
===================================================================
--- uspace/srv/tcp/test.c	(revision 4d9fe7b307128cbbbd04d982fef935c842053872)
+++ uspace/srv/tcp/test.c	(revision 4d9fe7b307128cbbbd04d982fef935c842053872)
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup tcp
+ * @{
+ */
+
+/**
+ * @file Internal TCP test
+ */
+
+#include <async.h>
+#include <errno.h>
+#include <stdio.h>
+#include <thread.h>
+#include <str.h>
+#include "tcp_type.h"
+#include "ucall.h"
+
+#include "test.h"
+
+#define RCV_BUF_SIZE 64
+
+static void test_srv(void *arg)
+{
+	tcp_conn_t *conn;
+	tcp_sock_t lsock;
+	tcp_sock_t fsock;
+	char rcv_buf[RCV_BUF_SIZE + 1];
+	size_t rcvd;
+	xflags_t xflags;
+
+	printf("test_srv()\n");
+	lsock.port = 80;
+	lsock.addr.ipv4 = 0x7f000001;
+	fsock.port = 1024;
+	fsock.addr.ipv4 = 0x7f000001;
+	printf("S: User open...\n");
+	tcp_uc_open(&lsock, &fsock, ap_passive, 0, &conn);
+	conn->name = (char *) "S";
+
+	while (true) {
+		printf("S: User receive...\n");
+		tcp_uc_receive(conn, rcv_buf, RCV_BUF_SIZE, &rcvd, &xflags);
+		if (rcvd == 0) {
+			printf("S: End of data reached.\n");
+			break;
+		}
+		rcv_buf[rcvd] = '\0';
+		printf("S: User received %zu bytes '%s'.\n", rcvd, rcv_buf);
+
+		async_usleep(1000*1000*2);
+	}
+
+	async_usleep(/*10**/1000*1000);
+
+	printf("S: User close...\n");
+	tcp_uc_close(conn);
+
+	printf("test_srv() terminating\n");
+}
+
+static void test_cli(void *arg)
+{
+	tcp_conn_t *conn;
+	tcp_sock_t lsock;
+	tcp_sock_t fsock;
+	const char *msg = "Hello World!";
+
+	printf("test_cli()\n");
+
+	lsock.port = 1024;
+	lsock.addr.ipv4 = 0x7f000001;
+	fsock.port = 80;
+	fsock.addr.ipv4 = 0x7f000001;
+
+	async_usleep(1000*1000*3);
+	printf("C: User open...\n");
+	tcp_uc_open(&lsock, &fsock, ap_active, 0, &conn);
+	conn->name = (char *) "C";
+
+	async_usleep(1000*1000*10);
+	printf("C: User send...\n");
+	tcp_uc_send(conn, (void *)msg, str_size(msg), 0);
+
+	async_usleep(1000*1000*20/**20*2*/);
+	printf("C: User close...\n");
+	tcp_uc_close(conn);
+}
+
+void tcp_test(void)
+{
+	thread_id_t srv_tid;
+	thread_id_t cli_tid;
+	int rc;
+
+	printf("tcp_test()\n");
+
+	async_usleep(1000*1000);
+
+	if (0) {
+		rc = thread_create(test_srv, NULL, "test_srv", &srv_tid);
+		if (rc != EOK) {
+			printf("Failed to create server thread.\n");
+			return;
+		}
+	}
+
+	if (0) {
+		rc = thread_create(test_cli, NULL, "test_cli", &cli_tid);
+		if (rc != EOK) {
+			printf("Failed to create client thread.\n");
+			return;
+		}
+	}
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/tcp/test.h
===================================================================
--- uspace/srv/tcp/test.h	(revision 4d9fe7b307128cbbbd04d982fef935c842053872)
+++ uspace/srv/tcp/test.h	(revision 4d9fe7b307128cbbbd04d982fef935c842053872)
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup tcp
+ * @{
+ */
+/** @file Internal TCP test
+ */
+
+#ifndef TEST_H
+#define TEST_H
+
+extern void tcp_test(void);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/tcp/tqueue.c
===================================================================
--- uspace/srv/tcp/tqueue.c	(revision 4d9fe7b307128cbbbd04d982fef935c842053872)
+++ uspace/srv/tcp/tqueue.c	(revision 4d9fe7b307128cbbbd04d982fef935c842053872)
@@ -0,0 +1,381 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup tcp
+ * @{
+ */
+
+/**
+ * @file TCP transmission queue
+ */
+
+#include <adt/list.h>
+#include <errno.h>
+#include <fibril_synch.h>
+#include <byteorder.h>
+#include <io/log.h>
+#include <macros.h>
+#include <mem.h>
+#include <stdlib.h>
+#include "conn.h"
+#include "ncsim.h"
+#include "pdu.h"
+#include "rqueue.h"
+#include "segment.h"
+#include "seq_no.h"
+#include "tqueue.h"
+#include "tcp.h"
+#include "tcp_type.h"
+
+#define RETRANSMIT_TIMEOUT	(2*1000*1000)
+
+static void retransmit_timeout_func(void *arg);
+static void tcp_tqueue_timer_set(tcp_conn_t *conn);
+static void tcp_tqueue_timer_clear(tcp_conn_t *conn);
+
+int tcp_tqueue_init(tcp_tqueue_t *tqueue, tcp_conn_t *conn)
+{
+	tqueue->conn = conn;
+	tqueue->timer = fibril_timer_create();
+	if (tqueue->timer == NULL)
+		return ENOMEM;
+
+	list_initialize(&tqueue->list);
+
+	return EOK;
+}
+
+void tcp_tqueue_clear(tcp_tqueue_t *tqueue)
+{
+	tcp_tqueue_timer_clear(tqueue->conn);
+}
+
+void tcp_tqueue_fini(tcp_tqueue_t *tqueue)
+{
+	if (tqueue->timer != NULL) {
+		fibril_timer_destroy(tqueue->timer);
+		tqueue->timer = NULL;
+	}
+}
+
+void tcp_tqueue_ctrl_seg(tcp_conn_t *conn, tcp_control_t ctrl)
+{
+	tcp_segment_t *seg;
+
+	log_msg(LVL_DEBUG, "tcp_tqueue_ctrl_seg(%p, %u)", conn, ctrl);
+
+	seg = tcp_segment_make_ctrl(ctrl);
+	tcp_tqueue_seg(conn, seg);
+}
+
+void tcp_tqueue_seg(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	tcp_segment_t *rt_seg;
+	tcp_tqueue_entry_t *tqe;
+
+	log_msg(LVL_DEBUG, "%s: tcp_tqueue_seg(%p, %p)", conn->name, conn,
+	    seg);
+
+	/*
+	 * Add segment to retransmission queue
+	 */
+
+	if (seg->len > 0) {
+		rt_seg = tcp_segment_dup(seg);
+		if (rt_seg == NULL) {
+			log_msg(LVL_ERROR, "Memory allocation failed.");
+			/* XXX Handle properly */
+			return;
+		}
+
+		tqe = calloc(1, sizeof(tcp_tqueue_entry_t));
+		if (tqe == NULL) {
+			log_msg(LVL_ERROR, "Memory allocation failed.");
+			/* XXX Handle properly */
+			return;
+		}
+
+		tqe->conn = conn;
+		tqe->seg = rt_seg;
+		rt_seg->seq = conn->snd_nxt;
+
+		list_append(&tqe->link, &conn->retransmit.list);
+
+		/* Set retransmission timer */
+		tcp_tqueue_timer_set(conn);
+	}
+
+	tcp_prepare_transmit_segment(conn, seg);
+}
+
+void tcp_prepare_transmit_segment(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	/*
+	 * Always send ACK once we have received SYN, except for RST segments.
+	 * (Spec says we should always send ACK once connection has been
+	 * established.)
+	 */
+	if (tcp_conn_got_syn(conn) && (seg->ctrl & CTL_RST) == 0)
+		seg->ctrl |= CTL_ACK;
+
+	seg->seq = conn->snd_nxt;
+	conn->snd_nxt += seg->len;
+
+	tcp_conn_transmit_segment(conn, seg);
+}
+
+/** Transmit data from the send buffer.
+ *
+ * @param conn	Connection
+ */
+void tcp_tqueue_new_data(tcp_conn_t *conn)
+{
+	size_t avail_wnd;
+	size_t xfer_seqlen;
+	size_t snd_buf_seqlen;
+	size_t data_size;
+	tcp_control_t ctrl;
+	bool send_fin;
+
+	tcp_segment_t *seg;
+
+	log_msg(LVL_DEBUG, "%s: tcp_tqueue_new_data()", conn->name);
+
+	/* Number of free sequence numbers in send window */
+	avail_wnd = (conn->snd_una + conn->snd_wnd) - conn->snd_nxt;
+	snd_buf_seqlen = conn->snd_buf_used + (conn->snd_buf_fin ? 1 : 0);
+
+	xfer_seqlen = min(snd_buf_seqlen, avail_wnd);
+	log_msg(LVL_DEBUG, "%s: snd_buf_seqlen = %zu, SND.WND = %zu, "
+	    "xfer_seqlen = %zu", conn->name, snd_buf_seqlen, conn->snd_wnd,
+	    xfer_seqlen);
+
+	if (xfer_seqlen == 0)
+		return;
+
+	/* XXX Do not always send immediately */
+
+	send_fin = conn->snd_buf_fin && xfer_seqlen == snd_buf_seqlen;
+	data_size = xfer_seqlen - (send_fin ? 1 : 0);
+
+	if (send_fin) {
+		log_msg(LVL_DEBUG, "%s: Sending out FIN.", conn->name);
+		/* We are sending out FIN */
+		ctrl = CTL_FIN;
+	} else {
+		ctrl = 0;
+	}
+
+	seg = tcp_segment_make_data(ctrl, conn->snd_buf, data_size);
+	if (seg == NULL) {
+		log_msg(LVL_ERROR, "Memory allocation failure.");
+		return;
+	}
+
+	/* Remove data from send buffer */
+	memmove(conn->snd_buf, conn->snd_buf + data_size,
+	    conn->snd_buf_used - data_size);
+	conn->snd_buf_used -= data_size;
+
+	if (send_fin)
+		conn->snd_buf_fin = false;
+
+	fibril_condvar_broadcast(&conn->snd_buf_cv);
+
+	if (send_fin)
+		tcp_conn_fin_sent(conn);
+
+	tcp_tqueue_seg(conn, seg);
+}
+
+/** Remove ACKed segments from retransmission queue and possibly transmit
+ * more data.
+ *
+ * This should be called when SND.UNA is updated due to incoming ACK.
+ */
+void tcp_tqueue_ack_received(tcp_conn_t *conn)
+{
+	link_t *cur, *next;
+
+	log_msg(LVL_DEBUG, "%s: tcp_tqueue_ack_received(%p)", conn->name,
+	    conn);
+
+	cur = conn->retransmit.list.head.next;
+
+	while (cur != &conn->retransmit.list.head) {
+		next = cur->next;
+
+		tcp_tqueue_entry_t *tqe = list_get_instance(cur,
+		    tcp_tqueue_entry_t, link);
+
+		if (seq_no_segment_acked(conn, tqe->seg, conn->snd_una)) {
+			/* Remove acknowledged segment */
+			list_remove(cur);
+
+			if ((tqe->seg->ctrl & CTL_FIN) != 0) {
+				log_msg(LVL_DEBUG, "Fin has been acked");
+				log_msg(LVL_DEBUG, "SND.UNA=%" PRIu32
+				    " SEG.SEQ=%" PRIu32 " SEG.LEN=%" PRIu32,
+				    conn->snd_una, tqe->seg->seq, tqe->seg->len);
+				/* Our FIN has been acked */
+				conn->fin_is_acked = true;
+			}
+
+			tcp_segment_delete(tqe->seg);
+			free(tqe);
+
+			/* Reset retransmission timer */
+			tcp_tqueue_timer_set(conn);
+		}
+
+		cur = next;
+	}
+
+	/* Clear retransmission timer if the queue is empty. */
+	if (list_empty(&conn->retransmit.list))
+		tcp_tqueue_timer_clear(conn);
+
+	/* Possibly transmit more data */
+	tcp_tqueue_new_data(conn);
+}
+
+void tcp_conn_transmit_segment(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	log_msg(LVL_DEBUG, "%s: tcp_conn_transmit_segment(%p, %p)",
+	    conn->name, conn, seg);
+
+	seg->wnd = conn->rcv_wnd;
+
+	if ((seg->ctrl & CTL_ACK) != 0)
+		seg->ack = conn->rcv_nxt;
+	else
+		seg->ack = 0;
+
+	tcp_transmit_segment(&conn->ident, seg);
+}
+
+void tcp_transmit_segment(tcp_sockpair_t *sp, tcp_segment_t *seg)
+{
+	log_msg(LVL_DEBUG, "tcp_transmit_segment(f:(%x,%u),l:(%x,%u), %p)",
+	    sp->foreign.addr.ipv4, sp->foreign.port,
+	    sp->local.addr.ipv4, sp->local.port, seg);
+
+	log_msg(LVL_DEBUG, "SEG.SEQ=%" PRIu32 ", SEG.WND=%" PRIu32,
+	    seg->seq, seg->wnd);
+
+	tcp_segment_dump(seg);
+/*
+	tcp_pdu_prepare(conn, seg, &data, &len);
+	tcp_pdu_transmit(data, len);
+*/
+//	tcp_rqueue_bounce_seg(sp, seg);
+//	tcp_ncsim_bounce_seg(sp, seg);
+
+	tcp_pdu_t *pdu;
+
+	if (tcp_pdu_encode(sp, seg, &pdu) != EOK) {
+		log_msg(LVL_WARN, "Not enough memory. Segment dropped.");
+		return;
+	}
+
+	tcp_transmit_pdu(pdu);
+	tcp_pdu_delete(pdu);
+}
+
+static void retransmit_timeout_func(void *arg)
+{
+	tcp_conn_t *conn = (tcp_conn_t *) arg;
+	tcp_tqueue_entry_t *tqe;
+	tcp_segment_t *rt_seg;
+	link_t *link;
+
+	log_msg(LVL_DEBUG, "### %s: retransmit_timeout_func(%p)", conn->name, conn);
+
+	fibril_mutex_lock(&conn->lock);
+
+	if (conn->cstate == st_closed) {
+		log_msg(LVL_DEBUG, "Connection already closed.");
+		fibril_mutex_unlock(&conn->lock);
+		tcp_conn_delref(conn);
+		return;
+	}
+
+	link = list_first(&conn->retransmit.list);
+	if (link == NULL) {
+		log_msg(LVL_DEBUG, "Nothing to retransmit");
+		fibril_mutex_unlock(&conn->lock);
+		tcp_conn_delref(conn);
+		return;
+	}
+
+	tqe = list_get_instance(link, tcp_tqueue_entry_t, link);
+
+	rt_seg = tcp_segment_dup(tqe->seg);
+	if (rt_seg == NULL) {
+		log_msg(LVL_ERROR, "Memory allocation failed.");
+		fibril_mutex_unlock(&conn->lock);
+		tcp_conn_delref(conn);
+		/* XXX Handle properly */
+		return;
+	}
+
+	log_msg(LVL_DEBUG, "### %s: retransmitting segment", conn->name);
+	tcp_conn_transmit_segment(tqe->conn, rt_seg);
+
+	/* Reset retransmission timer */
+	tcp_tqueue_timer_set(tqe->conn);
+
+	fibril_mutex_unlock(&conn->lock);
+	tcp_conn_delref(conn);
+}
+
+/** Set or re-set retransmission timer */
+static void tcp_tqueue_timer_set(tcp_conn_t *conn)
+{
+	log_msg(LVL_DEBUG, "### %s: tcp_tqueue_timer_set()", conn->name);
+
+	/* Clear first to make sure we update refcnt correctly */
+	tcp_tqueue_timer_clear(conn);
+
+	tcp_conn_addref(conn);
+	fibril_timer_set(conn->retransmit.timer, RETRANSMIT_TIMEOUT,
+	    retransmit_timeout_func, (void *) conn);
+}
+
+/** Clear retransmission timer */
+static void tcp_tqueue_timer_clear(tcp_conn_t *conn)
+{
+	log_msg(LVL_DEBUG, "### %s: tcp_tqueue_timer_clear()", conn->name);
+
+	if (fibril_timer_clear(conn->retransmit.timer) == fts_active)
+		tcp_conn_delref(conn);
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/tcp/tqueue.h
===================================================================
--- uspace/srv/tcp/tqueue.h	(revision 4d9fe7b307128cbbbd04d982fef935c842053872)
+++ uspace/srv/tcp/tqueue.h	(revision 4d9fe7b307128cbbbd04d982fef935c842053872)
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup tcp
+ * @{
+ */
+/** @file TCP transmission queue
+ */
+
+#ifndef TQUEUE_H
+#define TQUEUE_H
+
+#include "std.h"
+#include "tcp_type.h"
+
+extern int tcp_tqueue_init(tcp_tqueue_t *, tcp_conn_t *);
+extern void tcp_tqueue_clear(tcp_tqueue_t *);
+extern void tcp_tqueue_fini(tcp_tqueue_t *);
+extern void tcp_tqueue_ctrl_seg(tcp_conn_t *, tcp_control_t);
+extern void tcp_tqueue_seg(tcp_conn_t *, tcp_segment_t *);
+extern void tcp_tqueue_new_data(tcp_conn_t *);
+extern void tcp_tqueue_ack_received(tcp_conn_t *);
+extern void tcp_prepare_transmit_segment(tcp_conn_t *, tcp_segment_t *);
+extern void tcp_conn_transmit_segment(tcp_conn_t *, tcp_segment_t *);
+extern void tcp_transmit_segment(tcp_sockpair_t *, tcp_segment_t *);
+extern void tcp_header_setup(tcp_conn_t *, tcp_segment_t *, tcp_header_t *);
+extern void tcp_phdr_setup(tcp_conn_t *, tcp_segment_t *, tcp_phdr_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/tcp/ucall.c
===================================================================
--- uspace/srv/tcp/ucall.c	(revision 4d9fe7b307128cbbbd04d982fef935c842053872)
+++ uspace/srv/tcp/ucall.c	(revision 4d9fe7b307128cbbbd04d982fef935c842053872)
@@ -0,0 +1,346 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup tcp
+ * @{
+ */
+
+/**
+ * @file TCP entry points (close to those defined in the RFC)
+ */
+
+#include <fibril_synch.h>
+#include <io/log.h>
+#include <macros.h>
+#include <mem.h>
+#include "conn.h"
+#include "tcp_type.h"
+#include "tqueue.h"
+#include "ucall.h"
+
+/*
+ * User calls
+ */
+
+/** OPEN user call
+ *
+ * @param lsock		Local socket
+ * @param fsock		Foreign socket
+ * @param acpass	Active/passive
+ * @param oflags	Open flags
+ * @param conn		Connection
+ *
+ * Unlike in the spec we allow specifying the local address. This means
+ * the implementation does not need to magically guess it, especially
+ * considering there can be more than one local address.
+ *
+ * XXX We should be able to call active open on an existing listening
+ * connection.
+ * XXX We should be able to get connection structure immediately, before
+ * establishment.
+ */
+tcp_error_t tcp_uc_open(tcp_sock_t *lsock, tcp_sock_t *fsock, acpass_t acpass,
+    tcp_open_flags_t oflags, tcp_conn_t **conn)
+{
+	tcp_conn_t *nconn;
+
+	log_msg(LVL_DEBUG, "tcp_uc_open(%p, %p, %s, %s, %p)",
+	    lsock, fsock, acpass == ap_active ? "active" : "passive",
+	    oflags == tcp_open_nonblock ? "nonblock" : "none", conn);
+
+	nconn = tcp_conn_new(lsock, fsock);
+	tcp_conn_add(nconn);
+
+	if (acpass == ap_active) {
+		/* Synchronize (initiate) connection */
+		tcp_conn_sync(nconn);
+	}
+
+	if (oflags == tcp_open_nonblock) {
+		*conn = nconn;
+		return TCP_EOK;
+	}
+
+	/* Wait for connection to be established or reset */
+	log_msg(LVL_DEBUG, "tcp_uc_open: Wait for connection.");
+	fibril_mutex_lock(&nconn->lock);
+	while (nconn->cstate == st_listen ||
+	    nconn->cstate == st_syn_sent ||
+	    nconn->cstate == st_syn_received) {
+		fibril_condvar_wait(&nconn->cstate_cv, &nconn->lock);
+	}
+
+	if (nconn->cstate != st_established) {
+		log_msg(LVL_DEBUG, "tcp_uc_open: Connection was reset.");
+		assert(nconn->cstate == st_closed);
+		fibril_mutex_unlock(&nconn->lock);
+		return TCP_ERESET;
+	}
+
+	fibril_mutex_unlock(&nconn->lock);
+	log_msg(LVL_DEBUG, "tcp_uc_open: Connection was established.");
+
+	*conn = nconn;
+	log_msg(LVL_DEBUG, "tcp_uc_open -> %p", nconn);
+	return TCP_EOK;
+}
+
+/** SEND user call */
+tcp_error_t tcp_uc_send(tcp_conn_t *conn, void *data, size_t size,
+    xflags_t flags)
+{
+	size_t buf_free;
+	size_t xfer_size;
+
+	log_msg(LVL_DEBUG, "%s: tcp_uc_send()", conn->name);
+
+	fibril_mutex_lock(&conn->lock);
+
+	if (conn->cstate == st_closed) {
+		fibril_mutex_unlock(&conn->lock);
+		return TCP_ENOTEXIST;
+	}
+
+	if (conn->cstate == st_listen) {
+		/* Change connection to active */
+		tcp_conn_sync(conn);
+	}
+
+
+	if (conn->snd_buf_fin) {
+		fibril_mutex_unlock(&conn->lock);
+		return TCP_ECLOSING;
+	}
+
+	while (size > 0) {
+		buf_free = conn->snd_buf_size - conn->snd_buf_used;
+		while (buf_free == 0 && !conn->reset) {
+			log_msg(LVL_DEBUG, "%s: buf_free == 0, waiting.",
+			    conn->name);
+			fibril_condvar_wait(&conn->snd_buf_cv, &conn->lock);
+			buf_free = conn->snd_buf_size - conn->snd_buf_used;
+		}
+
+		if (conn->reset) {
+			fibril_mutex_unlock(&conn->lock);
+			return TCP_ERESET;
+		}
+
+		xfer_size = min(size, buf_free);
+
+		/* Copy data to buffer */
+		memcpy(conn->snd_buf + conn->snd_buf_used, data, xfer_size);
+		data += xfer_size;
+		conn->snd_buf_used += xfer_size;
+		size -= xfer_size;
+
+		tcp_tqueue_new_data(conn);
+	}
+
+	tcp_tqueue_new_data(conn);
+	fibril_mutex_unlock(&conn->lock);
+
+	return TCP_EOK;
+}
+
+/** RECEIVE user call */
+tcp_error_t tcp_uc_receive(tcp_conn_t *conn, void *buf, size_t size,
+    size_t *rcvd, xflags_t *xflags)
+{
+	size_t xfer_size;
+
+	log_msg(LVL_DEBUG, "%s: tcp_uc_receive()", conn->name);
+
+	fibril_mutex_lock(&conn->lock);
+
+	if (conn->cstate == st_closed) {
+		fibril_mutex_unlock(&conn->lock);
+		return TCP_ENOTEXIST;
+	}
+
+	/* Wait for data to become available */
+	while (conn->rcv_buf_used == 0 && !conn->rcv_buf_fin && !conn->reset) {
+		log_msg(LVL_DEBUG, "tcp_uc_receive() - wait for data");
+		fibril_condvar_wait(&conn->rcv_buf_cv, &conn->lock);
+	}
+
+	if (conn->rcv_buf_used == 0) {
+		*rcvd = 0;
+		*xflags = 0;
+
+		if (conn->rcv_buf_fin) {
+			/* End of data, peer closed connection */
+			fibril_mutex_unlock(&conn->lock);
+			return TCP_ECLOSING;
+		} else {
+			/* Connection was reset */
+			assert(conn->reset);
+			fibril_mutex_unlock(&conn->lock);
+			return TCP_ERESET;
+		}
+	}
+
+	/* Copy data from receive buffer to user buffer */
+	xfer_size = min(size, conn->rcv_buf_used);
+	memcpy(buf, conn->rcv_buf, xfer_size);
+	*rcvd = xfer_size;
+
+	/* Remove data from receive buffer */
+	memmove(conn->rcv_buf, conn->rcv_buf + xfer_size, conn->rcv_buf_used -
+	    xfer_size);
+	conn->rcv_buf_used -= xfer_size;
+	conn->rcv_wnd += xfer_size;
+
+	/* TODO */
+	*xflags = 0;
+
+	/* Send new size of receive window */
+	tcp_tqueue_ctrl_seg(conn, CTL_ACK);
+
+	log_msg(LVL_DEBUG, "%s: tcp_uc_receive() - returning %zu bytes",
+	    conn->name, xfer_size);
+
+	fibril_mutex_unlock(&conn->lock);
+
+	return TCP_EOK;
+}
+
+/** CLOSE user call */
+tcp_error_t tcp_uc_close(tcp_conn_t *conn)
+{
+	log_msg(LVL_DEBUG, "%s: tcp_uc_close()", conn->name);
+
+	fibril_mutex_lock(&conn->lock);
+
+	if (conn->cstate == st_closed) {
+		fibril_mutex_unlock(&conn->lock);
+		return TCP_ENOTEXIST;
+	}
+
+	if (conn->snd_buf_fin) {
+		fibril_mutex_unlock(&conn->lock);
+		return TCP_ECLOSING;
+	}
+
+	conn->snd_buf_fin = true;
+	tcp_tqueue_new_data(conn);
+
+	fibril_mutex_unlock(&conn->lock);
+	return TCP_EOK;
+}
+
+/** ABORT user call */
+void tcp_uc_abort(tcp_conn_t *conn)
+{
+	log_msg(LVL_DEBUG, "tcp_uc_abort()");
+}
+
+/** STATUS user call */
+void tcp_uc_status(tcp_conn_t *conn, tcp_conn_status_t *cstatus)
+{
+	log_msg(LVL_DEBUG, "tcp_uc_status()");
+	cstatus->cstate = conn->cstate;
+}
+
+/** Delete connection user call.
+ *
+ * (Not in spec.) Inform TCP that the user is done with this connection
+ * and will not make any further calls/references to it. TCP can deallocate
+ * the connection from now on.
+ */
+void tcp_uc_delete(tcp_conn_t *conn)
+{
+	log_msg(LVL_DEBUG, "tcp_uc_delete()");
+	tcp_conn_delete(conn);
+}
+
+void tcp_uc_set_cstate_cb(tcp_conn_t *conn, tcp_cstate_cb_t cb, void *arg)
+{
+	log_msg(LVL_DEBUG, "tcp_uc_set_ctate_cb(%p, %p, %p)",
+	    conn, cb, arg);
+
+	conn->cstate_cb = cb;
+	conn->cstate_cb_arg = arg;
+}
+
+/*
+ * Arriving segments
+ */
+
+/** Segment arrived */
+void tcp_as_segment_arrived(tcp_sockpair_t *sp, tcp_segment_t *seg)
+{
+	tcp_conn_t *conn;
+
+	log_msg(LVL_DEBUG, "tcp_as_segment_arrived(f:(%x,%u), l:(%x,%u))",
+	    sp->foreign.addr.ipv4, sp->foreign.port,
+	    sp->local.addr.ipv4, sp->local.port);
+
+	conn = tcp_conn_find_ref(sp);
+	if (conn == NULL) {
+		log_msg(LVL_WARN, "No connection found.");
+		tcp_unexpected_segment(sp, seg);
+		return;
+	}
+
+	fibril_mutex_lock(&conn->lock);
+
+	if (conn->cstate == st_closed) {
+		log_msg(LVL_WARN, "Connection is closed.");
+		tcp_unexpected_segment(sp, seg);
+		fibril_mutex_unlock(&conn->lock);
+		tcp_conn_delref(conn);
+		return;
+	}
+
+	if (conn->ident.foreign.addr.ipv4 == TCP_IPV4_ANY)
+		conn->ident.foreign.addr.ipv4 = sp->foreign.addr.ipv4;
+	if (conn->ident.foreign.port == TCP_PORT_ANY)
+		conn->ident.foreign.port = sp->foreign.port;
+	if (conn->ident.local.addr.ipv4 == TCP_IPV4_ANY)
+		conn->ident.local.addr.ipv4 = sp->local.addr.ipv4;
+
+	tcp_conn_segment_arrived(conn, seg);
+
+	fibril_mutex_unlock(&conn->lock);
+	tcp_conn_delref(conn);
+}
+
+/*
+ * Timeouts
+ */
+
+/** User timeout */
+void tcp_to_user(void)
+{
+	log_msg(LVL_DEBUG, "tcp_to_user()");
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/tcp/ucall.h
===================================================================
--- uspace/srv/tcp/ucall.h	(revision 4d9fe7b307128cbbbd04d982fef935c842053872)
+++ uspace/srv/tcp/ucall.h	(revision 4d9fe7b307128cbbbd04d982fef935c842053872)
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup tcp
+ * @{
+ */
+/** @file TCP user calls (close to those defined in the RFC)
+ */
+
+#ifndef UCALL_H
+#define UCALL_H
+
+#include <sys/types.h>
+#include "tcp_type.h"
+
+/*
+ * User calls
+ */
+extern tcp_error_t tcp_uc_open(tcp_sock_t *, tcp_sock_t *, acpass_t,
+    tcp_open_flags_t, tcp_conn_t **);
+extern tcp_error_t tcp_uc_send(tcp_conn_t *, void *, size_t, xflags_t);
+extern tcp_error_t tcp_uc_receive(tcp_conn_t *, void *, size_t, size_t *, xflags_t *);
+extern tcp_error_t tcp_uc_close(tcp_conn_t *);
+extern void tcp_uc_abort(tcp_conn_t *);
+extern void tcp_uc_status(tcp_conn_t *, tcp_conn_status_t *);
+extern void tcp_uc_delete(tcp_conn_t *);
+extern void tcp_uc_set_cstate_cb(tcp_conn_t *, tcp_cstate_cb_t, void *);
+
+/*
+ * Arriving segments
+ */
+extern void tcp_as_segment_arrived(tcp_sockpair_t *, tcp_segment_t *);
+
+/*
+ * Timeouts
+ */
+extern void tcp_to_user(void);
+
+#endif
+
+/** @}
+ */
