Index: uspace/Makefile
===================================================================
--- uspace/Makefile	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ uspace/Makefile	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -73,11 +73,11 @@
 	srv/loc \
 	srv/devman \
-	srv/ethip \
-	srv/inet \
 	srv/loader \
+	srv/net/ethip \
+	srv/net/inet \
+	srv/net/tcp \
+	srv/net/udp \
 	srv/ns \
 	srv/taskmon \
-	srv/tcp \
-	srv/udp \
 	srv/vfs \
 	srv/bd/ata_bd \
Index: uspace/srv/ethip/Makefile
===================================================================
--- uspace/srv/ethip/Makefile	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(revision )
@@ -1,39 +1,0 @@
-#
-# Copyright (c) 2012 Jiri Svoboda
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# - Redistributions of source code must retain the above copyright
-#   notice, this list of conditions and the following disclaimer.
-# - Redistributions in binary form must reproduce the above copyright
-#   notice, this list of conditions and the following disclaimer in the
-#   documentation and/or other materials provided with the distribution.
-# - The name of the author may not be used to endorse or promote products
-#   derived from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-
-USPACE_PREFIX = ../..
-BINARY = ethip
-
-SOURCES = \
-	arp.c \
-	atrans.c \
-	ethip.c \
-	ethip_nic.c \
-	pdu.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/ethip/arp.c
===================================================================
--- uspace/srv/ethip/arp.c	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(revision )
@@ -1,151 +1,0 @@
-/*
- * Copyright (c) 2012 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup inet
- * @{
- */
-/**
- * @file
- * @brief
- */
-
-#include <errno.h>
-#include <io/log.h>
-#include <inet/iplink_srv.h>
-#include <stdlib.h>
-
-#include "arp.h"
-#include "atrans.h"
-#include "ethip.h"
-#include "ethip_nic.h"
-#include "pdu.h"
-#include "std.h"
-
-/** Time to wait for ARP reply in microseconds */
-#define ARP_REQUEST_TIMEOUT (3 * 1000 * 1000)
-
-static int arp_send_packet(ethip_nic_t *nic, arp_eth_packet_t *packet);
-
-void arp_received(ethip_nic_t *nic, eth_frame_t *frame)
-{
-	int rc;
-	arp_eth_packet_t packet;
-	arp_eth_packet_t reply;
-	ethip_link_addr_t *laddr;
-
-	log_msg(LVL_DEBUG, "arp_received()");
-
-	rc = arp_pdu_decode(frame->data, frame->size, &packet);
-	if (rc != EOK)
-		return;
-
-	log_msg(LVL_DEBUG, "ARP PDU decoded, opcode=%d, tpa=%x",
-	    packet.opcode, packet.target_proto_addr.ipv4);
-
-	laddr = ethip_nic_addr_find(nic, &packet.target_proto_addr);
-	if (laddr != NULL) {
-		log_msg(LVL_DEBUG, "Request/reply to my address");
-
-		(void) atrans_add(&packet.sender_proto_addr,
-		    &packet.sender_hw_addr);
-
-		if (packet.opcode == aop_request) {
-        		reply.opcode = aop_reply;
-        		reply.sender_hw_addr = nic->mac_addr;
-			reply.sender_proto_addr = laddr->addr;
-			reply.target_hw_addr = packet.sender_hw_addr;
-			reply.target_proto_addr = packet.sender_proto_addr;
-
-			arp_send_packet(nic, &reply);
-		}
-	}
-}
-
-int arp_translate(ethip_nic_t *nic, iplink_srv_addr_t *src_addr,
-    iplink_srv_addr_t *ip_addr, mac48_addr_t *mac_addr)
-{
-	int rc;
-	arp_eth_packet_t packet;
-
-	rc = atrans_lookup(ip_addr, mac_addr);
-	if (rc == EOK)
-		return EOK;
-
-	packet.opcode = aop_request;
-	packet.sender_hw_addr = nic->mac_addr;
-	packet.sender_proto_addr = *src_addr;
-	packet.target_hw_addr.addr = MAC48_BROADCAST;
-	packet.target_proto_addr = *ip_addr;
-
-	rc = arp_send_packet(nic, &packet);
-	if (rc != EOK)
-		return rc;
-
-	(void) atrans_wait_timeout(ARP_REQUEST_TIMEOUT);
-
-	return atrans_lookup(ip_addr, mac_addr);
-}
-
-static int arp_send_packet(ethip_nic_t *nic, arp_eth_packet_t *packet)
-{
-	int rc;
-	void *pdata;
-	size_t psize;
-
-	eth_frame_t frame;
-	void *fdata;
-	size_t fsize;
-
-	log_msg(LVL_DEBUG, "arp_send_packet()");
-
-	rc = arp_pdu_encode(packet, &pdata, &psize);
-	if (rc != EOK)
-		return rc;
-
-	frame.dest.addr = packet->target_hw_addr.addr;
-	frame.src.addr =  packet->sender_hw_addr.addr;
-	frame.etype_len = ETYPE_ARP;
-	frame.data = pdata;
-	frame.size = psize;
-
-	rc = eth_pdu_encode(&frame, &fdata, &fsize);
-	if (rc != EOK) {
-		free(pdata);
-		return rc;
-	}
-
-	rc = ethip_nic_send(nic, fdata, fsize);
-	free(fdata);
-	free(pdata);
-
-	return rc;
-
-}
-
-/** @}
- */
Index: uspace/srv/ethip/arp.h
===================================================================
--- uspace/srv/ethip/arp.h	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(revision )
@@ -1,50 +1,0 @@
-/*
- * Copyright (c) 2012 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup inet
- * @{
- */
-/**
- * @file
- * @brief
- */
-
-#ifndef ARP_H_
-#define ARP_H_
-
-#include <inet/iplink_srv.h>
-#include "ethip.h"
-
-extern void arp_received(ethip_nic_t *, eth_frame_t *);
-extern int arp_translate(ethip_nic_t *, iplink_srv_addr_t *,
-    iplink_srv_addr_t *, mac48_addr_t *);
-
-#endif
-
-/** @}
- */
Index: uspace/srv/ethip/atrans.c
===================================================================
--- uspace/srv/ethip/atrans.c	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(revision )
@@ -1,137 +1,0 @@
-/*
- * Copyright (c) 2012 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup inet
- * @{
- */
-/**
- * @file
- * @brief
- */
-
-#include <adt/list.h>
-#include <errno.h>
-#include <fibril_synch.h>
-#include <inet/iplink_srv.h>
-#include <stdlib.h>
-
-#include "atrans.h"
-#include "ethip.h"
-
-/** Address translation list (of ethip_atrans_t) */
-static FIBRIL_MUTEX_INITIALIZE(atrans_list_lock);
-static LIST_INITIALIZE(atrans_list);
-static FIBRIL_CONDVAR_INITIALIZE(atrans_cv);
-
-static ethip_atrans_t *atrans_find(iplink_srv_addr_t *ip_addr)
-{
-	list_foreach(atrans_list, link) {
-		ethip_atrans_t *atrans = list_get_instance(link,
-		    ethip_atrans_t, atrans_list);
-
-		if (atrans->ip_addr.ipv4 == ip_addr->ipv4)
-			return atrans;
-	}
-
-	return NULL;
-}
-
-int atrans_add(iplink_srv_addr_t *ip_addr, mac48_addr_t *mac_addr)
-{
-	ethip_atrans_t *atrans;
-	ethip_atrans_t *prev;
-
-	atrans = calloc(1, sizeof(ethip_atrans_t));
-	if (atrans == NULL)
-		return ENOMEM;
-
-	atrans->ip_addr = *ip_addr;
-	atrans->mac_addr = *mac_addr;
-
-	fibril_mutex_lock(&atrans_list_lock);
-	prev = atrans_find(ip_addr);
-	if (prev != NULL) {
-		list_remove(&prev->atrans_list);
-		free(prev);
-	}
-
-	list_append(&atrans->atrans_list, &atrans_list);
-	fibril_mutex_unlock(&atrans_list_lock);
-	fibril_condvar_broadcast(&atrans_cv);
-
-	return EOK;
-}
-
-int atrans_remove(iplink_srv_addr_t *ip_addr)
-{
-	ethip_atrans_t *atrans;
-
-	fibril_mutex_lock(&atrans_list_lock);
-	atrans = atrans_find(ip_addr);
-	if (atrans == NULL) {
-		fibril_mutex_unlock(&atrans_list_lock);
-		return ENOENT;
-	}
-
-	list_remove(&atrans->atrans_list);
-	fibril_mutex_unlock(&atrans_list_lock);
-	free(atrans);
-
-	return EOK;
-}
-
-int atrans_lookup(iplink_srv_addr_t *ip_addr, mac48_addr_t *mac_addr)
-{
-	ethip_atrans_t *atrans;
-
-	fibril_mutex_lock(&atrans_list_lock);
-	atrans = atrans_find(ip_addr);
-	if (atrans == NULL) {
-		fibril_mutex_unlock(&atrans_list_lock);
-		return ENOENT;
-	}
-
-	fibril_mutex_unlock(&atrans_list_lock);
-	*mac_addr = atrans->mac_addr;
-	return EOK;
-}
-
-int atrans_wait_timeout(suseconds_t timeout)
-{
-	int rc;
-
-	fibril_mutex_lock(&atrans_list_lock);
-	rc = fibril_condvar_wait_timeout(&atrans_cv, &atrans_list_lock,
-	    timeout);
-	fibril_mutex_unlock(&atrans_list_lock);
-
-	return rc;
-}
-
-/** @}
- */
Index: uspace/srv/ethip/atrans.h
===================================================================
--- uspace/srv/ethip/atrans.h	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(revision )
@@ -1,51 +1,0 @@
-/*
- * Copyright (c) 2012 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup inet
- * @{
- */
-/**
- * @file
- * @brief
- */
-
-#ifndef ATRANS_H_
-#define ATRANS_H_
-
-#include <inet/iplink_srv.h>
-#include "ethip.h"
-
-extern int atrans_add(iplink_srv_addr_t *, mac48_addr_t *);
-extern int atrans_remove(iplink_srv_addr_t *);
-extern int atrans_lookup(iplink_srv_addr_t *, mac48_addr_t *);
-extern int atrans_wait_timeout(suseconds_t);
-
-#endif
-
-/** @}
- */
Index: uspace/srv/ethip/ethip.c
===================================================================
--- uspace/srv/ethip/ethip.c	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(revision )
@@ -1,288 +1,0 @@
-/*
- * Copyright (c) 2012 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup ethip
- * @{
- */
-/**
- * @file
- * @brief IP link provider for Ethernet
- *
- * Based on the IETF RFC 894 standard.
- */
-
-#include <async.h>
-#include <errno.h>
-#include <inet/iplink_srv.h>
-#include <io/log.h>
-#include <loc.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "arp.h"
-#include "ethip.h"
-#include "ethip_nic.h"
-#include "pdu.h"
-#include "std.h"
-
-#define NAME "eth"
-
-static int ethip_open(iplink_srv_t *srv);
-static int ethip_close(iplink_srv_t *srv);
-static int ethip_send(iplink_srv_t *srv, iplink_srv_sdu_t *sdu);
-static int ethip_get_mtu(iplink_srv_t *srv, size_t *mtu);
-static int ethip_addr_add(iplink_srv_t *srv, iplink_srv_addr_t *addr);
-static int ethip_addr_remove(iplink_srv_t *srv, iplink_srv_addr_t *addr);
-
-static void ethip_client_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg);
-
-static iplink_ops_t ethip_iplink_ops = {
-	.open = ethip_open,
-	.close = ethip_close,
-	.send = ethip_send,
-	.get_mtu = ethip_get_mtu,
-	.addr_add = ethip_addr_add,
-	.addr_remove = ethip_addr_remove
-};
-
-static int ethip_init(void)
-{
-	int rc;
-
-	async_set_client_connection(ethip_client_conn);
-
-	rc = loc_server_register(NAME);
-	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed registering server.");
-		return rc;
-	}
-
-	rc = ethip_nic_discovery_start();
-	if (rc != EOK)
-		return rc;
-
-	return EOK;
-}
-
-int ethip_iplink_init(ethip_nic_t *nic)
-{
-	int rc;
-	service_id_t sid;
-	category_id_t iplink_cat;
-	static unsigned link_num = 0;
-	char *svc_name = NULL;
-
-	log_msg(LVL_DEBUG, "ethip_iplink_init()");
-
-	iplink_srv_init(&nic->iplink);
-	nic->iplink.ops = &ethip_iplink_ops;
-	nic->iplink.arg = nic;
-
-	rc = asprintf(&svc_name, "net/eth%u", ++link_num);
-	if (rc < 0) {
-		log_msg(LVL_ERROR, "Out of memory.");
-		goto error;
-	}
-
-	rc = loc_service_register(svc_name, &sid);
-	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed registering service %s.", svc_name);
-		goto error;
-	}
-
-	nic->iplink_sid = sid;
-
-	rc = loc_category_get_id("iplink", &iplink_cat, IPC_FLAG_BLOCKING);
-	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed resolving category 'iplink'.");
-		goto error;
-	}
-
-	rc = loc_service_add_to_cat(sid, iplink_cat);
-	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed adding %s to category.", svc_name);
-		goto error;
-	}
-
-	return EOK;
-
-error:
-	if (svc_name != NULL)
-		free(svc_name);
-	return rc;
-}
-
-static void ethip_client_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
-{
-	ethip_nic_t *nic;
-	service_id_t sid;
-
-	sid = (service_id_t)IPC_GET_ARG1(*icall);
-	log_msg(LVL_DEBUG, "ethip_client_conn(%u)", (unsigned)sid);
-	nic = ethip_nic_find_by_iplink_sid(sid);
-	if (nic == NULL) {
-		log_msg(LVL_WARN, "Uknown service ID.");
-		return;
-	}
-
-	iplink_conn(iid, icall, &nic->iplink);
-}
-
-static int ethip_open(iplink_srv_t *srv)
-{
-	log_msg(LVL_DEBUG, "ethip_open()");
-	return EOK;
-}
-
-static int ethip_close(iplink_srv_t *srv)
-{
-	log_msg(LVL_DEBUG, "ethip_close()");
-	return EOK;
-}
-
-static int ethip_send(iplink_srv_t *srv, iplink_srv_sdu_t *sdu)
-{
-	ethip_nic_t *nic = (ethip_nic_t *)srv->arg;
-	eth_frame_t frame;
-	void *data;
-	size_t size;
-	mac48_addr_t dest_mac_addr;
-	int rc;
-
-	log_msg(LVL_DEBUG, "ethip_send()");
-
-	rc = arp_translate(nic, &sdu->lsrc, &sdu->ldest, &dest_mac_addr);
-	if (rc != EOK) {
-		log_msg(LVL_WARN, "Failed to look up IP address 0x%" PRIx32,
-		    sdu->ldest.ipv4);
-		return rc;
-	}
-
-	frame.dest      = dest_mac_addr;
-	frame.src       = nic->mac_addr;
-	frame.etype_len = ETYPE_IP;
-	frame.data = sdu->data;
-	frame.size = sdu->size;
-
-	rc = eth_pdu_encode(&frame, &data, &size);
-	if (rc != EOK)
-		return rc;
-
-	rc = ethip_nic_send(nic, data, size);
-	free(data);
-
-	return rc;
-}
-
-int ethip_received(iplink_srv_t *srv, void *data, size_t size)
-{
-	log_msg(LVL_DEBUG, "ethip_received(): srv=%p", srv);
-	ethip_nic_t *nic = (ethip_nic_t *)srv->arg;
-	eth_frame_t frame;
-	iplink_srv_sdu_t sdu;
-	int rc;
-
-	log_msg(LVL_DEBUG, "ethip_received()");
-
-	log_msg(LVL_DEBUG, " - eth_pdu_decode");
-	rc = eth_pdu_decode(data, size, &frame);
-	if (rc != EOK) {
-		log_msg(LVL_DEBUG, " - eth_pdu_decode failed");
-		return rc;
-	}
-
-	switch (frame.etype_len) {
-	case ETYPE_ARP:
-		arp_received(nic, &frame);
-		break;
-	case ETYPE_IP:
-		log_msg(LVL_DEBUG, " - construct SDU");
-		sdu.lsrc.ipv4 = (192 << 24) | (168 << 16) | (0 << 8) | 1;
-		sdu.ldest.ipv4 = (192 << 24) | (168 << 16) | (0 << 8) | 4;
-		sdu.data = frame.data;
-		sdu.size = frame.size;
-		log_msg(LVL_DEBUG, " - call iplink_ev_recv");
-		rc = iplink_ev_recv(&nic->iplink, &sdu);
-		break;
-	default:
-		log_msg(LVL_DEBUG, "Unknown ethertype 0x%" PRIx16,
-		    frame.etype_len);
-	}
-
-	free(frame.data);
-	return rc;
-}
-
-static int ethip_get_mtu(iplink_srv_t *srv, size_t *mtu)
-{
-	log_msg(LVL_DEBUG, "ethip_get_mtu()");
-	*mtu = 1500;
-	return EOK;
-}
-
-static int ethip_addr_add(iplink_srv_t *srv, iplink_srv_addr_t *addr)
-{
-	ethip_nic_t *nic = (ethip_nic_t *)srv->arg;
-
-	log_msg(LVL_DEBUG, "ethip_addr_add(0x%" PRIx32 ")", addr->ipv4);
-	return ethip_nic_addr_add(nic, addr);
-}
-
-static int ethip_addr_remove(iplink_srv_t *srv, iplink_srv_addr_t *addr)
-{
-	ethip_nic_t *nic = (ethip_nic_t *)srv->arg;
-
-	log_msg(LVL_DEBUG, "ethip_addr_remove(0x%" PRIx32 ")", addr->ipv4);
-	return ethip_nic_addr_add(nic, addr);
-}
-
-int main(int argc, char *argv[])
-{
-	int rc;
-
-	printf(NAME ": HelenOS IP over Ethernet service\n");
-
-	if (log_init(NAME, LVL_DEBUG) != EOK) {
-		printf(NAME ": Failed to initialize logging.\n");
-		return 1;
-	}
-
-	rc = ethip_init();
-	if (rc != EOK)
-		return 1;
-
-	printf(NAME ": Accepting connections.\n");
-	task_retval(0);
-	async_manager();
-
-	/* Not reached */
-	return 0;
-}
-
-/** @}
- */
Index: uspace/srv/ethip/ethip.h
===================================================================
--- uspace/srv/ethip/ethip.h	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(revision )
@@ -1,126 +1,0 @@
-/*
- * Copyright (c) 2012 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup ethip
- * @{
- */
-/**
- * @file
- * @brief
- */
-
-#ifndef ETHIP_H_
-#define ETHIP_H_
-
-#include <adt/list.h>
-#include <async.h>
-#include <inet/iplink_srv.h>
-#include <loc.h>
-#include <sys/types.h>
-
-#define MAC48_BROADCAST 0xffffffffffff
-
-typedef struct {
-	link_t addr_list;
-	iplink_srv_addr_t addr;
-} ethip_link_addr_t;
-
-/** IEEE MAC-48 identifier */
-typedef struct {
-	/** MAC Address (in lowest 48 bits) */
-	uint64_t addr;
-} mac48_addr_t;
-
-typedef struct ethip_nic {
-	link_t nic_list;
-	service_id_t svc_id;
-	char *svc_name;
-	async_sess_t *sess;
-
-	iplink_srv_t iplink;
-	service_id_t iplink_sid;
-
-	/** MAC address */
-	mac48_addr_t mac_addr;
-	/** List of IP addresses configured on this link */
-	list_t addr_list; /* of ethip_link_addr_t */
-} ethip_nic_t;
-
-/** Ethernet frame */
-typedef struct {
-	/** Destination Address */
-	mac48_addr_t dest;
-	/** Source Address */
-	mac48_addr_t src;
-	/** Ethertype or Length */
-	uint16_t etype_len;
-	/** Payload */
-	void *data;
-	/** Payload size */
-	size_t size;
-} eth_frame_t;
-
-/** ARP opcode */
-typedef enum {
-	/** Request */
-	aop_request,
-	/** Reply */
-	aop_reply
-} arp_opcode_t;
-
-/** ARP packet (for 48-bit MAC addresses and IPv4)
- *
- * Internal representation
- */
-typedef struct {
-	/** Opcode */
-	arp_opcode_t opcode;
-	/** Sender hardware address */
-	mac48_addr_t sender_hw_addr;
-	/** Sender protocol address */
-	iplink_srv_addr_t sender_proto_addr;
-	/** Target hardware address */
-	mac48_addr_t target_hw_addr;
-	/** Target protocol address */
-	iplink_srv_addr_t target_proto_addr;
-} arp_eth_packet_t;
-
-/** Address translation table element */
-typedef struct {
-	link_t atrans_list;
-	iplink_srv_addr_t ip_addr;
-	mac48_addr_t mac_addr;
-} ethip_atrans_t;
-
-extern int ethip_iplink_init(ethip_nic_t *);
-extern int ethip_received(iplink_srv_t *, void *, size_t);
-
-#endif
-
-/** @}
- */
Index: uspace/srv/ethip/ethip_nic.c
===================================================================
--- uspace/srv/ethip/ethip_nic.c	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(revision )
@@ -1,391 +1,0 @@
-/*
- * Copyright (c) 2012 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup ethip
- * @{
- */
-/**
- * @file
- * @brief
- */
-
-#include <adt/list.h>
-#include <async.h>
-#include <bool.h>
-#include <errno.h>
-#include <fibril_synch.h>
-#include <inet/iplink_srv.h>
-#include <io/log.h>
-#include <loc.h>
-#include <device/nic.h>
-#include <stdlib.h>
-
-#include "ethip.h"
-#include "ethip_nic.h"
-#include "pdu.h"
-
-static int ethip_nic_open(service_id_t sid);
-static void ethip_nic_cb_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg);
-
-static LIST_INITIALIZE(ethip_nic_list);
-static FIBRIL_MUTEX_INITIALIZE(ethip_discovery_lock);
-
-static int ethip_nic_check_new(void)
-{
-	bool already_known;
-	category_id_t iplink_cat;
-	service_id_t *svcs;
-	size_t count, i;
-	int rc;
-
-	fibril_mutex_lock(&ethip_discovery_lock);
-
-	rc = loc_category_get_id("nic", &iplink_cat, IPC_FLAG_BLOCKING);
-	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed resolving category 'nic'.");
-		fibril_mutex_unlock(&ethip_discovery_lock);
-		return ENOENT;
-	}
-
-	rc = loc_category_get_svcs(iplink_cat, &svcs, &count);
-	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed getting list of IP links.");
-		fibril_mutex_unlock(&ethip_discovery_lock);
-		return EIO;
-	}
-
-	for (i = 0; i < count; i++) {
-		already_known = false;
-
-		list_foreach(ethip_nic_list, nic_link) {
-			ethip_nic_t *nic = list_get_instance(nic_link,
-			    ethip_nic_t, nic_list);
-			if (nic->svc_id == svcs[i]) {
-				already_known = true;
-				break;
-			}
-		}
-
-		if (!already_known) {
-			log_msg(LVL_DEBUG, "Found NIC '%lu'",
-			    (unsigned long) svcs[i]);
-			rc = ethip_nic_open(svcs[i]);
-			if (rc != EOK)
-				log_msg(LVL_ERROR, "Could not open NIC.");
-		}
-	}
-
-	fibril_mutex_unlock(&ethip_discovery_lock);
-	return EOK;
-}
-
-static ethip_nic_t *ethip_nic_new(void)
-{
-	ethip_nic_t *nic = calloc(1, sizeof(ethip_nic_t));
-
-	if (nic == NULL) {
-		log_msg(LVL_ERROR, "Failed allocating NIC structure. "
-		    "Out of memory.");
-		return NULL;
-	}
-
-	link_initialize(&nic->nic_list);
-	list_initialize(&nic->addr_list);
-
-	return nic;
-}
-
-static ethip_link_addr_t *ethip_nic_addr_new(iplink_srv_addr_t *addr)
-{
-	ethip_link_addr_t *laddr = calloc(1, sizeof(ethip_link_addr_t));
-
-	if (laddr == NULL) {
-		log_msg(LVL_ERROR, "Failed allocating NIC address structure. "
-		    "Out of memory.");
-		return NULL;
-	}
-
-	link_initialize(&laddr->addr_list);
-	laddr->addr.ipv4 = addr->ipv4;
-	return laddr;
-}
-
-static void ethip_nic_delete(ethip_nic_t *nic)
-{
-	if (nic->svc_name != NULL)
-		free(nic->svc_name);
-	free(nic);
-}
-
-static void ethip_link_addr_delete(ethip_link_addr_t *laddr)
-{
-	free(laddr);
-}
-
-static int ethip_nic_open(service_id_t sid)
-{
-	ethip_nic_t *nic;
-	int rc;
-	bool in_list = false;
-	nic_address_t nic_address;
-
-	log_msg(LVL_DEBUG, "ethip_nic_open()");
-	nic = ethip_nic_new();
-	if (nic == NULL)
-		return ENOMEM;
-
-	rc = loc_service_get_name(sid, &nic->svc_name);
-	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed getting service name.");
-		goto error;
-	}
-
-	nic->sess = loc_service_connect(EXCHANGE_SERIALIZE, sid, 0);
-	if (nic->sess == NULL) {
-		log_msg(LVL_ERROR, "Failed connecting '%s'", nic->svc_name);
-		goto error;
-	}
-
-	nic->svc_id = sid;
-
-	rc = nic_callback_create(nic->sess, ethip_nic_cb_conn, nic);
-	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed creating callback connection "
-		    "from '%s'", nic->svc_name);
-		goto error;
-	}
-
-	log_msg(LVL_DEBUG, "Opened NIC '%s'", nic->svc_name);
-	list_append(&nic->nic_list, &ethip_nic_list);
-	in_list = true;
-
-	rc = ethip_iplink_init(nic);
-	if (rc != EOK)
-		goto error;
-
-	rc = nic_get_address(nic->sess, &nic_address);
-	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Error getting MAC address of NIC '%s'.",
-		    nic->svc_name);
-		goto error;
-	}
-
-	mac48_decode(nic_address.address, &nic->mac_addr);
-
-	rc = nic_set_state(nic->sess, NIC_STATE_ACTIVE);
-	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Error activating NIC '%s'.",
-		    nic->svc_name);
-		goto error;
-	}
-
-	log_msg(LVL_DEBUG, "Initialized IP link service, MAC = 0x%" PRIx64,
-	    nic->mac_addr.addr);
-
-	return EOK;
-
-error:
-	if (in_list)
-		list_remove(&nic->nic_list);
-	if (nic->sess != NULL)
-		async_hangup(nic->sess);
-	ethip_nic_delete(nic);
-	return rc;
-}
-
-static void ethip_nic_cat_change_cb(void)
-{
-	(void) ethip_nic_check_new();
-}
-
-static void ethip_nic_addr_changed(ethip_nic_t *nic, ipc_callid_t callid,
-    ipc_call_t *call)
-{
-	log_msg(LVL_DEBUG, "ethip_nic_addr_changed()");
-	async_answer_0(callid, ENOTSUP);
-}
-
-#include <stdio.h>
-static void ethip_nic_received(ethip_nic_t *nic, ipc_callid_t callid,
-    ipc_call_t *call)
-{
-	int rc;
-	void *data;
-	size_t size;
-
-	log_msg(LVL_DEBUG, "ethip_nic_received() nic=%p", nic);
-
-	rc = async_data_write_accept(&data, false, 0, 0, 0, &size);
-	if (rc != EOK) {
-		log_msg(LVL_DEBUG, "data_write_accept() failed");
-		return;
-	}
-
-	log_msg(LVL_DEBUG, "Ethernet PDU contents (%zu bytes)",
-	    size);
-	size_t i;
-	for (i = 0; i < size; i++)
-		printf("%02x ", ((uint8_t *)data)[i]);
-	printf("\n");
-
-	log_msg(LVL_DEBUG, "call ethip_received");
-	rc = ethip_received(&nic->iplink, data, size);
-	log_msg(LVL_DEBUG, "free data");
-	free(data);
-
-	log_msg(LVL_DEBUG, "ethip_nic_received() done, rc=%d", rc);
-	async_answer_0(callid, rc);
-}
-
-static void ethip_nic_device_state(ethip_nic_t *nic, ipc_callid_t callid,
-    ipc_call_t *call)
-{
-	log_msg(LVL_DEBUG, "ethip_nic_device_state()");
-	async_answer_0(callid, ENOTSUP);
-}
-
-static void ethip_nic_cb_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
-{
-	ethip_nic_t *nic = (ethip_nic_t *)arg;
-
-	log_msg(LVL_DEBUG, "ethnip_nic_cb_conn()");
-
-	while (true) {
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-
-		if (!IPC_GET_IMETHOD(call)) {
-			/* TODO: Handle hangup */
-			return;
-		}
-
-		switch (IPC_GET_IMETHOD(call)) {
-		case NIC_EV_ADDR_CHANGED:
-			ethip_nic_addr_changed(nic, callid, &call);
-			break;
-		case NIC_EV_RECEIVED:
-			ethip_nic_received(nic, callid, &call);
-			break;
-		case NIC_EV_DEVICE_STATE:
-			ethip_nic_device_state(nic, callid, &call);
-			break;
-		default:
-			async_answer_0(callid, ENOTSUP);
-		}
-	}
-}
-
-int ethip_nic_discovery_start(void)
-{
-	int rc;
-
-	rc = loc_register_cat_change_cb(ethip_nic_cat_change_cb);
-	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed registering callback for NIC "
-		    "discovery (%d).", rc);
-		return rc;
-	}
-
-	return ethip_nic_check_new();
-}
-
-ethip_nic_t *ethip_nic_find_by_iplink_sid(service_id_t iplink_sid)
-{
-	log_msg(LVL_DEBUG, "ethip_nic_find_by_iplink_sid(%u)",
-	    (unsigned) iplink_sid);
-
-	list_foreach(ethip_nic_list, link) {
-		log_msg(LVL_DEBUG, "ethip_nic_find_by_iplink_sid - element");
-		ethip_nic_t *nic = list_get_instance(link, ethip_nic_t,
-		    nic_list);
-
-		if (nic->iplink_sid == iplink_sid) {
-			log_msg(LVL_DEBUG, "ethip_nic_find_by_iplink_sid - found %p", nic);
-			return nic;
-		}
-	}
-
-	log_msg(LVL_DEBUG, "ethip_nic_find_by_iplink_sid - not found");
-	return NULL;
-}
-
-int ethip_nic_send(ethip_nic_t *nic, void *data, size_t size)
-{
-	int rc;
-	log_msg(LVL_DEBUG, "ethip_nic_send(size=%zu)", size);
-	rc = nic_send_frame(nic->sess, data, size);
-	log_msg(LVL_DEBUG, "nic_send_frame -> %d", rc);
-	return rc;
-}
-
-int ethip_nic_addr_add(ethip_nic_t *nic, iplink_srv_addr_t *addr)
-{
-	ethip_link_addr_t *laddr;
-
-	log_msg(LVL_DEBUG, "ethip_nic_addr_add()");
-	laddr = ethip_nic_addr_new(addr);
-	if (laddr == NULL)
-		return ENOMEM;
-
-	list_append(&laddr->addr_list, &nic->addr_list);
-	return EOK;
-}
-
-int ethip_nic_addr_remove(ethip_nic_t *nic, iplink_srv_addr_t *addr)
-{
-	ethip_link_addr_t *laddr;
-
-	log_msg(LVL_DEBUG, "ethip_nic_addr_remove()");
-
-	laddr = ethip_nic_addr_find(nic, addr);
-	if (laddr == NULL)
-		return ENOENT;
-
-	list_remove(&laddr->addr_list);
-	ethip_link_addr_delete(laddr);
-	return EOK;
-}
-
-ethip_link_addr_t *ethip_nic_addr_find(ethip_nic_t *nic,
-    iplink_srv_addr_t *addr)
-{
-	log_msg(LVL_DEBUG, "ethip_nic_addr_find()");
-
-	list_foreach(nic->addr_list, link) {
-		ethip_link_addr_t *laddr = list_get_instance(link,
-		    ethip_link_addr_t, addr_list);
-
-		if (addr->ipv4 == laddr->addr.ipv4)
-			return laddr;
-	}
-
-	return NULL;
-}
-
-/** @}
- */
Index: uspace/srv/ethip/ethip_nic.h
===================================================================
--- uspace/srv/ethip/ethip_nic.h	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(revision )
@@ -1,54 +1,0 @@
-/*
- * Copyright (c) 2012 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup ethip
- * @{
- */
-/**
- * @file
- * @brief
- */
-
-#ifndef ETHIP_NIC_H_
-#define ETHIP_NIC_H_
-
-#include <ipc/loc.h>
-#include "ethip.h"
-
-extern int ethip_nic_discovery_start(void);
-extern ethip_nic_t *ethip_nic_find_by_iplink_sid(service_id_t);
-extern int ethip_nic_send(ethip_nic_t *, void *, size_t);
-extern int ethip_nic_addr_add(ethip_nic_t *, iplink_srv_addr_t *);
-extern int ethip_nic_addr_remove(ethip_nic_t *, iplink_srv_addr_t *);
-extern ethip_link_addr_t *ethip_nic_addr_find(ethip_nic_t *,
-    iplink_srv_addr_t *);
-
-#endif
-
-/** @}
- */
Index: uspace/srv/ethip/pdu.c
===================================================================
--- uspace/srv/ethip/pdu.c	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(revision )
@@ -1,253 +1,0 @@
-/*
- * Copyright (c) 2012 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup inet
- * @{
- */
-/**
- * @file
- * @brief
- */
-
-#include <byteorder.h>
-#include <errno.h>
-#include <io/log.h>
-#include <macros.h>
-#include <mem.h>
-#include <stdlib.h>
-
-#include "ethip.h"
-#include "std.h"
-#include "pdu.h"
-
-#define MAC48_BYTES 6
-
-/** Encode Ethernet PDU. */
-#include <stdio.h>
-int eth_pdu_encode(eth_frame_t *frame, void **rdata, size_t *rsize)
-{
-	void *data;
-	size_t size;
-	eth_header_t *hdr;
-
-	size = max(sizeof(eth_header_t) + frame->size, ETH_FRAME_MIN_SIZE);
-
-	data = calloc(size, 1);
-	if (data == NULL)
-		return ENOMEM;
-
-	hdr = (eth_header_t *)data;
-	mac48_encode(&frame->src, hdr->src);
-	mac48_encode(&frame->dest, hdr->dest);
-	hdr->etype_len = host2uint16_t_be(frame->etype_len);
-
-	memcpy((uint8_t *)data + sizeof(eth_header_t), frame->data,
-	    frame->size);
-
-	log_msg(LVL_DEBUG, "Encoding Ethernet frame src=%llx dest=%llx etype=%x",
-	    frame->src, frame->dest, frame->etype_len);
-	log_msg(LVL_DEBUG, "Encoded Ethernet frame (%zu bytes)", size);
-	size_t i;
-	for (i = 0; i < size; i++) {
-		printf("%02x ", ((uint8_t *)(data))[sizeof(eth_header_t) + i]);
-	}
-	printf("\n");
-
-
-	*rdata = data;
-	*rsize = size;
-	return EOK;
-}
-
-#include <stdio.h>
-/** Decode Ethernet PDU. */
-int eth_pdu_decode(void *data, size_t size, eth_frame_t *frame)
-{
-	eth_header_t *hdr;
-
-	log_msg(LVL_DEBUG, "eth_pdu_decode()");
-
-	if (size < sizeof(eth_header_t)) {
-		log_msg(LVL_DEBUG, "PDU too short (%zu)", size);
-		return EINVAL;
-	}
-
-	hdr = (eth_header_t *)data;
-
-	frame->size = size - sizeof(eth_header_t);
-	frame->data = calloc(frame->size, 1);
-	if (frame->data == NULL)
-		return ENOMEM;
-
-	mac48_decode(hdr->src, &frame->src);
-	mac48_decode(hdr->dest, &frame->dest);
-	frame->etype_len = uint16_t_be2host(hdr->etype_len);
-
-	memcpy(frame->data, (uint8_t *)data + sizeof(eth_header_t),
-	    frame->size);
-
-	log_msg(LVL_DEBUG, "Decoding Ethernet frame src=%llx dest=%llx etype=%x",
-	    frame->src, frame->dest, frame->etype_len);
-	log_msg(LVL_DEBUG, "Decoded Ethernet frame payload (%zu bytes)", frame->size);
-	size_t i;
-	for (i = 0; i < frame->size; i++) {
-		printf("%02x ", ((uint8_t *)(frame->data))[i]);
-	}
-	printf("\n");
-
-	return EOK;
-}
-
-void mac48_encode(mac48_addr_t *addr, void *buf)
-{
-	uint64_t val;
-	uint8_t *bbuf = (uint8_t *)buf;
-	int i;
-
-	val = addr->addr;
-	for (i = 0; i < MAC48_BYTES; i++)
-		bbuf[i] = (val >> (8 * (MAC48_BYTES - i - 1))) & 0xff;
-}
-
-void mac48_decode(void *data, mac48_addr_t *addr)
-{
-	uint64_t val;
-	uint8_t *bdata = (uint8_t *)data;
-	int i;
-
-	val = 0;
-	for (i = 0; i < MAC48_BYTES; i++)
-		val |= (uint64_t)bdata[i] << (8 * (MAC48_BYTES - i - 1));
-
-	addr->addr = val;
-}
-
-/** Encode ARP PDU. */
-int arp_pdu_encode(arp_eth_packet_t *packet, void **rdata, size_t *rsize)
-{
-	void *data;
-	size_t size;
-	arp_eth_packet_fmt_t *pfmt;
-	uint16_t fopcode;
-
-	log_msg(LVL_DEBUG, "arp_pdu_encode()");
-
-	size = sizeof(arp_eth_packet_fmt_t);
-
-	data = calloc(size, 1);
-	if (data == NULL)
-		return ENOMEM;
-
-	pfmt = (arp_eth_packet_fmt_t *)data;
-
-	switch (packet->opcode) {
-	case aop_request: fopcode = AOP_REQUEST; break;
-	case aop_reply: fopcode = AOP_REPLY; break;
-	default:
-		assert(false);
-		fopcode = 0;
-	}
-
-	pfmt->hw_addr_space = host2uint16_t_be(AHRD_ETHERNET);
-	pfmt->proto_addr_space = host2uint16_t_be(ETYPE_IP);
-	pfmt->hw_addr_size = ETH_ADDR_SIZE;
-	pfmt->proto_addr_size = IPV4_ADDR_SIZE;
-	pfmt->opcode = host2uint16_t_be(fopcode);
-	mac48_encode(&packet->sender_hw_addr, pfmt->sender_hw_addr);
-	pfmt->sender_proto_addr =
-	    host2uint32_t_be(packet->sender_proto_addr.ipv4);
-	mac48_encode(&packet->target_hw_addr, pfmt->target_hw_addr);
-	pfmt->target_proto_addr =
-	    host2uint32_t_be(packet->target_proto_addr.ipv4);
-
-	*rdata = data;
-	*rsize = size;
-	return EOK;
-}
-
-/** Decode ARP PDU. */
-int arp_pdu_decode(void *data, size_t size, arp_eth_packet_t *packet)
-{
-	arp_eth_packet_fmt_t *pfmt;
-
-	log_msg(LVL_DEBUG, "arp_pdu_decode()");
-
-	if (size < sizeof(arp_eth_packet_fmt_t)) {
-		log_msg(LVL_DEBUG, "ARP PDU too short (%zu)", size);
-		return EINVAL;
-	}
-
-	pfmt = (arp_eth_packet_fmt_t *)data;
-
-	if (uint16_t_be2host(pfmt->hw_addr_space) != AHRD_ETHERNET) {
-		log_msg(LVL_DEBUG, "HW address space != %u (%" PRIu16 ")",
-		    AHRD_ETHERNET, uint16_t_be2host(pfmt->hw_addr_space));
-		return EINVAL;
-	}
-
-	if (uint16_t_be2host(pfmt->proto_addr_space) != 0x0800) {
-		log_msg(LVL_DEBUG, "Proto address space != %u (%" PRIu16 ")",
-		    ETYPE_IP, uint16_t_be2host(pfmt->proto_addr_space));
-		return EINVAL;
-	}
-
-	if (pfmt->hw_addr_size != ETH_ADDR_SIZE) {
-		log_msg(LVL_DEBUG, "HW address size != %zu (%zu)",
-		    (size_t)ETH_ADDR_SIZE, (size_t)pfmt->hw_addr_size);
-		return EINVAL;
-	}
-
-	if (pfmt->proto_addr_size != IPV4_ADDR_SIZE) {
-		log_msg(LVL_DEBUG, "Proto address size != %zu (%zu)",
-		    (size_t)IPV4_ADDR_SIZE, (size_t)pfmt->proto_addr_size);
-		return EINVAL;
-	}
-
-	switch (uint16_t_be2host(pfmt->opcode)) {
-	case AOP_REQUEST: packet->opcode = aop_request; break;
-	case AOP_REPLY: packet->opcode = aop_reply; break;
-	default:
-		log_msg(LVL_DEBUG, "Invalid ARP opcode (%" PRIu16 ")",
-		    uint16_t_be2host(pfmt->opcode));
-		return EINVAL;
-	}
-
-	mac48_decode(pfmt->sender_hw_addr, &packet->sender_hw_addr);
-	packet->sender_proto_addr.ipv4 =
-	    uint32_t_be2host(pfmt->sender_proto_addr);
-	mac48_decode(pfmt->target_hw_addr, &packet->target_hw_addr);
-	packet->target_proto_addr.ipv4 =
-	    uint32_t_be2host(pfmt->target_proto_addr);
-	log_msg(LVL_DEBUG, "packet->tpa = %x\n", pfmt->target_proto_addr);
-
-	return EOK;
-}
-
-
-/** @}
- */
Index: uspace/srv/ethip/pdu.h
===================================================================
--- uspace/srv/ethip/pdu.h	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(revision )
@@ -1,53 +1,0 @@
-/*
- * Copyright (c) 2012 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup inet
- * @{
- */
-/**
- * @file
- * @brief
- */
-
-#ifndef ETH_PDU_H_
-#define ETH_PDU_H_
-
-#include "ethip.h"
-
-extern int eth_pdu_encode(eth_frame_t *, void **, size_t *);
-extern int eth_pdu_decode(void *, size_t, eth_frame_t *);
-extern void mac48_encode(mac48_addr_t *, void *);
-extern void mac48_decode(void *, mac48_addr_t *);
-extern int arp_pdu_encode(arp_eth_packet_t *, void **, size_t *);
-extern int arp_pdu_decode(void *, size_t, arp_eth_packet_t *);
-
-
-#endif
-
-/** @}
- */
Index: uspace/srv/ethip/std.h
===================================================================
--- uspace/srv/ethip/std.h	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(revision )
@@ -1,97 +1,0 @@
-/*
- * Copyright (c) 2012 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup ethip
- * @{
- */
-/**
- * @file Ethernet, IP/Ethernet standard definitions
- *
- */
-
-#ifndef ETHIP_STD_H_
-#define ETHIP_STD_H_
-
-#include <sys/types.h>
-
-#define ETH_ADDR_SIZE 6
-#define IPV4_ADDR_SIZE 4
-#define ETH_FRAME_MIN_SIZE 60
-
-/** Ethernet frame header */
-typedef struct {
-	/** Destination Address */
-	uint8_t dest[ETH_ADDR_SIZE];
-	/** Source Address */
-	uint8_t src[ETH_ADDR_SIZE];
-	/** Ethertype or Length */
-	uint16_t etype_len;
-} eth_header_t;
-
-/** ARP packet format (for 48-bit MAC addresses and IPv4) */
-typedef struct {
-	/** Hardware address space */
-	uint16_t hw_addr_space;
-	/** Protocol address space */
-	uint16_t proto_addr_space;
-	/** Hardware address size */
-	uint8_t hw_addr_size;
-	/** Protocol address size */
-	uint8_t proto_addr_size;
-	/** Opcode */
-	uint16_t opcode;
-	/** Sender hardware address */
-	uint8_t sender_hw_addr[ETH_ADDR_SIZE];
-	/** Sender protocol address */
-	uint32_t sender_proto_addr;
-	/** Target hardware address */
-	uint8_t target_hw_addr[ETH_ADDR_SIZE];
-	/** Target protocol address */
-	uint32_t target_proto_addr;
-} __attribute__((packed)) arp_eth_packet_fmt_t;
-
-enum arp_opcode_fmt {
-	AOP_REQUEST = 1,
-	AOP_REPLY   = 2
-};
-
-enum arp_hw_addr_space {
-	AHRD_ETHERNET = 1
-};
-
-/** IP Ethertype */
-enum ether_type {
-	ETYPE_ARP = 0x0806,
-	ETYPE_IP  = 0x0800
-};
-
-
-#endif
-
-/** @}
- */
Index: uspace/srv/inet/Makefile
===================================================================
--- uspace/srv/inet/Makefile	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(revision )
@@ -1,44 +1,0 @@
-#
-# Copyright (c) 2012 Jiri Svoboda
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# - Redistributions of source code must retain the above copyright
-#   notice, this list of conditions and the following disclaimer.
-# - Redistributions in binary form must reproduce the above copyright
-#   notice, this list of conditions and the following disclaimer in the
-#   documentation and/or other materials provided with the distribution.
-# - The name of the author may not be used to endorse or promote products
-#   derived from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-
-USPACE_PREFIX = ../..
-BINARY = inet
-
-SOURCES = \
-	addrobj.c \
-	icmp.c \
-	inet.c \
-	inet_link.c \
-	inet_util.c \
-	inetcfg.c \
-	inetping.c \
-	pdu.c \
-	reass.c \
-	sroute.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/inet/addrobj.c
===================================================================
--- uspace/srv/inet/addrobj.c	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(revision )
@@ -1,229 +1,0 @@
-/*
- * Copyright (c) 2012 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup inet
- * @{
- */
-/**
- * @file
- * @brief
- */
-
-#include <bitops.h>
-#include <errno.h>
-#include <fibril_synch.h>
-#include <io/log.h>
-#include <ipc/loc.h>
-#include <stdlib.h>
-#include <str.h>
-
-#include "addrobj.h"
-#include "inet.h"
-#include "inet_link.h"
-#include "inet_util.h"
-
-static FIBRIL_MUTEX_INITIALIZE(addr_list_lock);
-static LIST_INITIALIZE(addr_list);
-static sysarg_t addr_id = 0;
-
-inet_addrobj_t *inet_addrobj_new(void)
-{
-	inet_addrobj_t *addr = calloc(1, sizeof(inet_addrobj_t));
-
-	if (addr == NULL) {
-		log_msg(LVL_ERROR, "Failed allocating address object. "
-		    "Out of memory.");
-		return NULL;
-	}
-
-	link_initialize(&addr->addr_list);
-	fibril_mutex_lock(&addr_list_lock);
-	addr->id = ++addr_id;
-	fibril_mutex_unlock(&addr_list_lock);
-
-	return addr;
-}
-
-void inet_addrobj_delete(inet_addrobj_t *addr)
-{
-	if (addr->name != NULL)
-		free(addr->name);
-	free(addr);
-}
-
-void inet_addrobj_add(inet_addrobj_t *addr)
-{
-	fibril_mutex_lock(&addr_list_lock);
-	list_append(&addr->addr_list, &addr_list);
-	fibril_mutex_unlock(&addr_list_lock);
-}
-
-void inet_addrobj_remove(inet_addrobj_t *addr)
-{
-	fibril_mutex_lock(&addr_list_lock);
-	list_remove(&addr->addr_list);
-	fibril_mutex_unlock(&addr_list_lock);
-}
-
-/** Find address object matching address @a addr.
- *
- * @param addr	Address
- * @oaram find	iaf_net to find network (using mask),
- *		iaf_addr to find local address (exact match)
- */
-inet_addrobj_t *inet_addrobj_find(inet_addr_t *addr, inet_addrobj_find_t find)
-{
-	uint32_t mask;
-
-	log_msg(LVL_DEBUG, "inet_addrobj_find(%x)", (unsigned)addr->ipv4);
-
-	fibril_mutex_lock(&addr_list_lock);
-
-	list_foreach(addr_list, link) {
-		inet_addrobj_t *naddr = list_get_instance(link,
-		    inet_addrobj_t, addr_list);
-
-		mask = inet_netmask(naddr->naddr.bits);
-		if ((naddr->naddr.ipv4 & mask) == (addr->ipv4 & mask)) {
-			fibril_mutex_unlock(&addr_list_lock);
-			log_msg(LVL_DEBUG, "inet_addrobj_find: found %p",
-			    naddr);
-			return naddr;
-		}
-	}
-
-	log_msg(LVL_DEBUG, "inet_addrobj_find: Not found");
-	fibril_mutex_unlock(&addr_list_lock);
-
-	return NULL;
-}
-
-/** Find address object on a link, with a specific name.
- *
- * @param name	Address object name
- * @param ilink	Inet link
- * @return	Address object
- */
-inet_addrobj_t *inet_addrobj_find_by_name(const char *name, inet_link_t *ilink)
-{
-	log_msg(LVL_DEBUG, "inet_addrobj_find_by_name('%s', '%s')",
-	    name, ilink->svc_name);
-
-	fibril_mutex_lock(&addr_list_lock);
-
-	list_foreach(addr_list, link) {
-		inet_addrobj_t *naddr = list_get_instance(link,
-		    inet_addrobj_t, addr_list);
-
-		if (naddr->ilink == ilink && str_cmp(naddr->name, name) == 0) {
-			fibril_mutex_unlock(&addr_list_lock);
-			log_msg(LVL_DEBUG, "inet_addrobj_find_by_name: found %p",
-			    naddr);
-			return naddr;
-		}
-	}
-
-	log_msg(LVL_DEBUG, "inet_addrobj_find_by_name: Not found");
-	fibril_mutex_unlock(&addr_list_lock);
-
-	return NULL;
-}
-
-/** Find address object with the given ID.
- *
- * @param id	Address object ID
- * @return	Address object
- */
-inet_addrobj_t *inet_addrobj_get_by_id(sysarg_t id)
-{
-	log_msg(LVL_DEBUG, "inet_addrobj_get_by_id(%zu)", (size_t)id);
-
-	fibril_mutex_lock(&addr_list_lock);
-
-	list_foreach(addr_list, link) {
-		inet_addrobj_t *naddr = list_get_instance(link,
-		    inet_addrobj_t, addr_list);
-
-		if (naddr->id == id) {
-			fibril_mutex_unlock(&addr_list_lock);
-			return naddr;
-		}
-	}
-
-	fibril_mutex_unlock(&addr_list_lock);
-
-	return NULL;
-}
-
-/** Send datagram from address object */
-int inet_addrobj_send_dgram(inet_addrobj_t *addr, inet_addr_t *ldest,
-    inet_dgram_t *dgram, uint8_t proto, uint8_t ttl, int df)
-{
-	inet_addr_t lsrc_addr;
-	inet_addr_t *ldest_addr;
-
-	lsrc_addr.ipv4 = addr->naddr.ipv4;
-	ldest_addr = &dgram->dest;
-
-	return inet_link_send_dgram(addr->ilink, &lsrc_addr, ldest_addr, dgram,
-	    proto, ttl, df);
-}
-
-/** Get IDs of all address objects. */
-int inet_addrobj_get_id_list(sysarg_t **rid_list, size_t *rcount)
-{
-	sysarg_t *id_list;
-	size_t count, i;
-
-	fibril_mutex_lock(&addr_list_lock);
-	count = list_count(&addr_list);
-
-	id_list = calloc(count, sizeof(sysarg_t));
-	if (id_list == NULL) {
-		fibril_mutex_unlock(&addr_list_lock);
-		return ENOMEM;
-	}
-
-	i = 0;
-	list_foreach(addr_list, link) {
-		inet_addrobj_t *addr = list_get_instance(link,
-		    inet_addrobj_t, addr_list);
-
-		id_list[i++] = addr->id;
-	}
-
-	fibril_mutex_unlock(&addr_list_lock);
-
-	*rid_list = id_list;
-	*rcount = count;
-
-	return EOK;
-}
-
-/** @}
- */
Index: uspace/srv/inet/addrobj.h
===================================================================
--- uspace/srv/inet/addrobj.h	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(revision )
@@ -1,65 +1,0 @@
-/*
- * Copyright (c) 2012 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup inet
- * @{
- */
-/**
- * @file
- * @brief
- */
-
-#ifndef INET_ADDROBJ_H_
-#define INET_ADDROBJ_H_
-
-#include <sys/types.h>
-#include "inet.h"
-
-typedef enum {
-	/* Find matching network address (using mask) */
-	iaf_net,
-	/* Find exact local address (not using mask) */
-	iaf_addr
-} inet_addrobj_find_t;
-
-extern inet_addrobj_t *inet_addrobj_new(void);
-extern void inet_addrobj_delete(inet_addrobj_t *);
-extern void inet_addrobj_add(inet_addrobj_t *);
-extern void inet_addrobj_remove(inet_addrobj_t *);
-extern inet_addrobj_t *inet_addrobj_find(inet_addr_t *, inet_addrobj_find_t);
-extern inet_addrobj_t *inet_addrobj_find_by_name(const char *, inet_link_t *);
-extern inet_addrobj_t *inet_addrobj_get_by_id(sysarg_t);
-extern int inet_addrobj_send_dgram(inet_addrobj_t *, inet_addr_t *,
-    inet_dgram_t *, uint8_t, uint8_t, int);
-extern int inet_addrobj_get_id_list(sysarg_t **, size_t *);
-
-
-#endif
-
-/** @}
- */
Index: uspace/srv/inet/icmp.c
===================================================================
--- uspace/srv/inet/icmp.c	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(revision )
@@ -1,183 +1,0 @@
-/*
- * Copyright (c) 2012 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup inet
- * @{
- */
-/**
- * @file
- * @brief
- */
-
-#include <byteorder.h>
-#include <errno.h>
-#include <io/log.h>
-#include <mem.h>
-#include <stdlib.h>
-
-#include "icmp.h"
-#include "icmp_std.h"
-#include "inet.h"
-#include "inetping.h"
-#include "pdu.h"
-
-/* XXX */
-#define INET_TTL_MAX 255
-
-static int icmp_recv_echo_request(inet_dgram_t *);
-static int icmp_recv_echo_reply(inet_dgram_t *);
-
-int icmp_recv(inet_dgram_t *dgram)
-{
-	uint8_t type;
-
-	log_msg(LVL_DEBUG, "icmp_recv()");
-
-	if (dgram->size < 1)
-		return EINVAL;
-
-	type = *(uint8_t *)dgram->data;
-
-	switch (type) {
-	case ICMP_ECHO_REQUEST:
-		return icmp_recv_echo_request(dgram);
-	case ICMP_ECHO_REPLY:
-		return icmp_recv_echo_reply(dgram);
-	default:
-		break;
-	}
-
-	return EINVAL;
-}
-
-static int icmp_recv_echo_request(inet_dgram_t *dgram)
-{
-	icmp_echo_t *request, *reply;
-	uint16_t checksum;
-	size_t size;
-	inet_dgram_t rdgram;
-	int rc;
-
-	log_msg(LVL_DEBUG, "icmp_recv_echo_request()");
-
-	if (dgram->size < sizeof(icmp_echo_t))
-		return EINVAL;
-
-	request = (icmp_echo_t *)dgram->data;
-	size = dgram->size;
-
-	reply = calloc(size, 1);
-	if (reply == NULL)
-		return ENOMEM;
-
-	memcpy(reply, request, size);
-
-	reply->type = ICMP_ECHO_REPLY;
-	reply->code = 0;
-	reply->checksum = 0;
-
-	checksum = inet_checksum_calc(INET_CHECKSUM_INIT, reply, size);
-	reply->checksum = host2uint16_t_be(checksum);
-
-	rdgram.src = dgram->dest;
-	rdgram.dest = dgram->src;
-	rdgram.tos = ICMP_TOS;
-	rdgram.data = reply;
-	rdgram.size = size;
-
-	rc = inet_route_packet(&rdgram, IP_PROTO_ICMP, INET_TTL_MAX, 0);
-
-	free(reply);
-
-	return rc;
-}
-
-static int icmp_recv_echo_reply(inet_dgram_t *dgram)
-{
-	icmp_echo_t *reply;
-	inetping_sdu_t sdu;
-	uint16_t ident;
-
-	log_msg(LVL_DEBUG, "icmp_recv_echo_reply()");
-
-	if (dgram->size < sizeof(icmp_echo_t))
-		return EINVAL;
-
-	reply = (icmp_echo_t *)dgram->data;
-
-	sdu.src = dgram->src;
-	sdu.dest = dgram->dest;
-	sdu.seq_no = uint16_t_be2host(reply->seq_no);
-	sdu.data = reply + sizeof(icmp_echo_t);
-	sdu.size = dgram->size - sizeof(icmp_echo_t);
-	ident = uint16_t_be2host(reply->ident);
-
-	return inetping_recv(ident, &sdu);
-}
-
-int icmp_ping_send(uint16_t ident, inetping_sdu_t *sdu)
-{
-	inet_dgram_t dgram;
-	icmp_echo_t *request;
-	void *rdata;
-	size_t rsize;
-	uint16_t checksum;
-	int rc;
-
-	rsize = sizeof(icmp_echo_t) + sdu->size;
-	rdata = calloc(rsize, 1);
-	if (rdata == NULL)
-		return ENOMEM;
-
-	request = (icmp_echo_t *)rdata;
-
-	request->type = ICMP_ECHO_REQUEST;
-	request->code = 0;
-	request->checksum = 0;
-	request->ident = host2uint16_t_be(ident);
-	request->seq_no = host2uint16_t_be(sdu->seq_no);
-
-	memcpy(rdata + sizeof(icmp_echo_t), sdu->data, sdu->size);
-
-	checksum = inet_checksum_calc(INET_CHECKSUM_INIT, rdata, rsize);
-	request->checksum = host2uint16_t_be(checksum);
-
-	dgram.src = sdu->src;
-	dgram.dest = sdu->dest;
-	dgram.tos = ICMP_TOS;
-	dgram.data = rdata;
-	dgram.size = rsize;
-
-	rc = inet_route_packet(&dgram, IP_PROTO_ICMP, INET_TTL_MAX, 0);
-
-	free(rdata);
-	return rc;
-}
-
-/** @}
- */
Index: uspace/srv/inet/icmp.h
===================================================================
--- uspace/srv/inet/icmp.h	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(revision )
@@ -1,48 +1,0 @@
-/*
- * Copyright (c) 2012 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup inet
- * @{
- */
-/**
- * @file
- * @brief
- */
-
-#ifndef ICMP_H_
-#define ICMP_H_
-
-#include "inet.h"
-
-extern int icmp_recv(inet_dgram_t *);
-extern int icmp_ping_send(uint16_t, inetping_sdu_t *);
-
-#endif
-
-/** @}
- */
Index: uspace/srv/inet/icmp_std.h
===================================================================
--- uspace/srv/inet/icmp_std.h	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(revision )
@@ -1,70 +1,0 @@
-/*
- * Copyright (c) 2012 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup inet
- * @{
- */
-/**
- * @file ICMP standard definitions
- *
- */
-
-#ifndef ICMP_STD_H_
-#define ICMP_STD_H_
-
-#include <sys/types.h>
-
-#define IP_PROTO_ICMP 1
-
-/** Type of service used for ICMP */
-#define ICMP_TOS	0
-
-/** ICMP message type */
-enum icmp_type {
-	ICMP_ECHO_REPLY   = 0,
-	ICMP_ECHO_REQUEST = 8
-};
-
-/** ICMP Echo Request or Reply message header */
-typedef struct {
-	/** ICMP message type */
-	uint8_t type;
-	/** Code (0) */
-	uint8_t code;
-	/** Internet checksum of the ICMP message */
-	uint16_t checksum;
-	/** Indentifier */
-	uint16_t ident;
-	/** Sequence number */
-	uint16_t seq_no;
-} icmp_echo_t;
-
-#endif
-
-/** @}
- */
Index: uspace/srv/inet/inet.c
===================================================================
--- uspace/srv/inet/inet.c	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(revision )
@@ -1,450 +1,0 @@
-/*
- * Copyright (c) 2012 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup inet
- * @{
- */
-/**
- * @file
- * @brief Internet Protocol service
- */
-
-#include <adt/list.h>
-#include <async.h>
-#include <errno.h>
-#include <fibril_synch.h>
-#include <io/log.h>
-#include <ipc/inet.h>
-#include <ipc/services.h>
-#include <loc.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/types.h>
-
-#include "addrobj.h"
-#include "icmp.h"
-#include "icmp_std.h"
-#include "inet.h"
-#include "inetcfg.h"
-#include "inetping.h"
-#include "inet_link.h"
-#include "reass.h"
-#include "sroute.h"
-
-#define NAME "inet"
-
-static void inet_client_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg);
-
-static FIBRIL_MUTEX_INITIALIZE(client_list_lock);
-static LIST_INITIALIZE(client_list);
-
-static int inet_init(void)
-{
-	service_id_t sid;
-	int rc;
-
-	log_msg(LVL_DEBUG, "inet_init()");
-
-	async_set_client_connection(inet_client_conn);
-
-	rc = loc_server_register(NAME);
-	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed registering server (%d).", rc);
-		return EEXIST;
-	}
-
-	rc = loc_service_register_with_iface(SERVICE_NAME_INET, &sid,
-	    INET_PORT_DEFAULT);
-	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed registering service (%d).", rc);
-		return EEXIST;
-	}
-
-	rc = loc_service_register_with_iface(SERVICE_NAME_INETCFG, &sid,
-	    INET_PORT_CFG);
-	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed registering service (%d).", rc);
-		return EEXIST;
-	}
-
-	rc = loc_service_register_with_iface(SERVICE_NAME_INETPING, &sid,
-	    INET_PORT_PING);
-	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed registering service (%d).", rc);
-		return EEXIST;
-	}
-
-	rc = inet_link_discovery_start();
-	if (rc != EOK)
-		return EEXIST;
-
-	return EOK;
-}
-
-static void inet_callback_create_srv(inet_client_t *client, ipc_callid_t callid,
-    ipc_call_t *call)
-{
-	log_msg(LVL_DEBUG, "inet_callback_create_srv()");
-
-	async_sess_t *sess = async_callback_receive(EXCHANGE_SERIALIZE);
-	if (sess == NULL) {
-		async_answer_0(callid, ENOMEM);
-		return;
-	}
-
-	client->sess = sess;
-	async_answer_0(callid, EOK);
-}
-
-static int inet_find_dir(inet_addr_t *src, inet_addr_t *dest, uint8_t tos,
-    inet_dir_t *dir)
-{
-	inet_sroute_t *sr;
-
-	/* XXX Handle case where source address is specified */
-	(void) src;
-
-	dir->aobj = inet_addrobj_find(dest, iaf_net);
-	if (dir->aobj != NULL) {
-		dir->ldest = *dest;
-		dir->dtype = dt_direct;
-	} else {
-		/* No direct path, try using a static route */
-		sr = inet_sroute_find(dest);
-		if (sr != NULL) {
-			dir->aobj = inet_addrobj_find(&sr->router, iaf_net);
-			dir->ldest = sr->router;
-			dir->dtype = dt_router;
-		}
-	}
-
-	if (dir->aobj == NULL) {
-		log_msg(LVL_DEBUG, "inet_send: No route to destination.");
-		return ENOENT;
-	}
-
-	return EOK;
-}
-
-int inet_route_packet(inet_dgram_t *dgram, uint8_t proto, uint8_t ttl,
-    int df)
-{
-	inet_dir_t dir;
-	int rc;
-
-	rc = inet_find_dir(&dgram->src, &dgram->dest, dgram->tos, &dir);
-	if (rc != EOK)
-		return rc;
-
-	return inet_addrobj_send_dgram(dir.aobj, &dir.ldest, dgram,
-	    proto, ttl, df);
-}
-
-static int inet_send(inet_client_t *client, inet_dgram_t *dgram,
-    uint8_t proto, uint8_t ttl, int df)
-{
-	return inet_route_packet(dgram, proto, ttl, df);
-}
-
-int inet_get_srcaddr(inet_addr_t *remote, uint8_t tos, inet_addr_t *local)
-{
-	inet_dir_t dir;
-	int rc;
-
-	rc = inet_find_dir(NULL, remote, tos, &dir);
-	if (rc != EOK)
-		return rc;
-
-	/* XXX dt_local? */
-
-	/* Take source address from the address object */
-	local->ipv4 = dir.aobj->naddr.ipv4;
-	return EOK;
-}
-
-static void inet_get_srcaddr_srv(inet_client_t *client, ipc_callid_t callid,
-    ipc_call_t *call)
-{
-	inet_addr_t remote;
-	uint8_t tos;
-	inet_addr_t local;
-	int rc;
-
-	log_msg(LVL_DEBUG, "inet_get_srcaddr_srv()");
-
-	remote.ipv4 = IPC_GET_ARG1(*call);
-	tos = IPC_GET_ARG2(*call);
-	local.ipv4 = 0;
-
-	rc = inet_get_srcaddr(&remote, tos, &local);
-	async_answer_1(callid, rc, local.ipv4);
-}
-
-static void inet_send_srv(inet_client_t *client, ipc_callid_t callid,
-    ipc_call_t *call)
-{
-	inet_dgram_t dgram;
-	uint8_t ttl;
-	int df;
-	int rc;
-
-	log_msg(LVL_DEBUG, "inet_send_srv()");
-
-	dgram.src.ipv4 = IPC_GET_ARG1(*call);
-	dgram.dest.ipv4 = IPC_GET_ARG2(*call);
-	dgram.tos = IPC_GET_ARG3(*call);
-	ttl = IPC_GET_ARG4(*call);
-	df = IPC_GET_ARG5(*call);
-
-	rc = async_data_write_accept(&dgram.data, false, 0, 0, 0, &dgram.size);
-	if (rc != EOK) {
-		async_answer_0(callid, rc);
-		return;
-	}
-
-	rc = inet_send(client, &dgram, client->protocol, ttl, df);
-
-	free(dgram.data);
-	async_answer_0(callid, rc);
-}
-
-static void inet_set_proto_srv(inet_client_t *client, ipc_callid_t callid,
-    ipc_call_t *call)
-{
-	sysarg_t proto;
-
-	proto = IPC_GET_ARG1(*call);
-	log_msg(LVL_DEBUG, "inet_set_proto_srv(%lu)", (unsigned long) proto);
-
-	if (proto > UINT8_MAX) {
-		async_answer_0(callid, EINVAL);
-		return;
-	}
-
-	client->protocol = proto;
-	async_answer_0(callid, EOK);
-}
-
-static void inet_client_init(inet_client_t *client)
-{
-	client->sess = NULL;
-
-	fibril_mutex_lock(&client_list_lock);
-	list_append(&client->client_list, &client_list);
-	fibril_mutex_unlock(&client_list_lock);
-}
-
-static void inet_client_fini(inet_client_t *client)
-{
-	async_hangup(client->sess);
-	client->sess = NULL;
-
-	fibril_mutex_lock(&client_list_lock);
-	list_remove(&client->client_list);
-	fibril_mutex_unlock(&client_list_lock);
-}
-
-static void inet_default_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
-{
-	inet_client_t client;
-
-	log_msg(LVL_DEBUG, "inet_default_conn()");
-
-	/* Accept the connection */
-	async_answer_0(iid, EOK);
-
-	inet_client_init(&client);
-
-	while (true) {
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-		sysarg_t method = IPC_GET_IMETHOD(call);
-
-		if (!method) {
-			/* The other side has hung up */
-			async_answer_0(callid, EOK);
-			return;
-		}
-
-		switch (method) {
-		case INET_CALLBACK_CREATE:
-			inet_callback_create_srv(&client, callid, &call);
-			break;
-		case INET_GET_SRCADDR:
-			inet_get_srcaddr_srv(&client, callid, &call);
-			break;
-		case INET_SEND:
-			inet_send_srv(&client, callid, &call);
-			break;
-		case INET_SET_PROTO:
-			inet_set_proto_srv(&client, callid, &call);
-			break;
-		default:
-			async_answer_0(callid, EINVAL);
-		}
-	}
-
-	inet_client_fini(&client);
-}
-
-static void inet_client_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
-{
-	sysarg_t port;
-
-	port = IPC_GET_ARG1(*icall);
-
-	switch (port) {
-	case INET_PORT_DEFAULT:
-		inet_default_conn(iid, icall, arg);
-		break;
-	case INET_PORT_CFG:
-		inet_cfg_conn(iid, icall, arg);
-		break;
-	case INET_PORT_PING:
-		inetping_conn(iid, icall, arg);
-		break;
-	default:
-		async_answer_0(iid, ENOTSUP);
-		break;
-	}
-}
-
-static inet_client_t *inet_client_find(uint8_t proto)
-{
-	fibril_mutex_lock(&client_list_lock);
-
-	list_foreach(client_list, link) {
-		inet_client_t *client = list_get_instance(link, inet_client_t,
-		    client_list);
-
-		if (client->protocol == proto) {
-			fibril_mutex_unlock(&client_list_lock);
-			return client;
-		}
-	}
-
-	fibril_mutex_unlock(&client_list_lock);
-	return NULL;
-}
-
-int inet_ev_recv(inet_client_t *client, inet_dgram_t *dgram)
-{
-	async_exch_t *exch = async_exchange_begin(client->sess);
-
-	ipc_call_t answer;
-	aid_t req = async_send_3(exch, INET_EV_RECV, dgram->src.ipv4,
-	    dgram->dest.ipv4, dgram->tos, &answer);
-	int rc = async_data_write_start(exch, dgram->data, dgram->size);
-	async_exchange_end(exch);
-
-	if (rc != EOK) {
-		async_wait_for(req, NULL);
-		return rc;
-	}
-
-	sysarg_t retval;
-	async_wait_for(req, &retval);
-	if (retval != EOK)
-		return retval;
-
-	return EOK;
-}
-
-int inet_recv_dgram_local(inet_dgram_t *dgram, uint8_t proto)
-{
-	inet_client_t *client;
-
-	log_msg(LVL_DEBUG, "inet_recv_dgram_local()");
-
-	/* ICMP messages are handled internally */
-	if (proto == IP_PROTO_ICMP)
-		return icmp_recv(dgram);
-
-	client = inet_client_find(proto);
-	if (client == NULL) {
-		log_msg(LVL_DEBUG, "No client found for protocol 0x%" PRIx8,
-		    proto);
-		return ENOENT;
-	}
-
-	return inet_ev_recv(client, dgram);
-}
-
-int inet_recv_packet(inet_packet_t *packet)
-{
-	inet_addrobj_t *addr;
-	inet_dgram_t dgram;
-
-	addr = inet_addrobj_find(&packet->dest, iaf_addr);
-	if (addr != NULL) {
-		/* Destined for one of the local addresses */
-
-		/* Check if packet is a complete datagram */
-		if (packet->offs == 0 && !packet->mf) {
-			/* It is complete deliver it immediately */
-			dgram.src = packet->src;
-			dgram.dest = packet->dest;
-			dgram.tos = packet->tos;
-			dgram.data = packet->data;
-			dgram.size = packet->size;
-
-			return inet_recv_dgram_local(&dgram, packet->proto);
-		} else {
-			/* It is a fragment, queue it for reassembly */
-			inet_reass_queue_packet(packet);
-		}
-	}
-
-	return ENOENT;
-}
-
-int main(int argc, char *argv[])
-{
-	int rc;
-
-	printf(NAME ": HelenOS Internet Protocol service\n");
-
-	if (log_init(NAME, LVL_DEBUG) != EOK) {
-		printf(NAME ": Failed to initialize logging.\n");
-		return 1;
-	}
-
-	rc = inet_init();
-	if (rc != EOK)
-		return 1;
-
-	printf(NAME ": Accepting connections.\n");
-	task_retval(0);
-	async_manager();
-
-	/* Not reached */
-	return 0;
-}
-
-/** @}
- */
Index: uspace/srv/inet/inet.h
===================================================================
--- uspace/srv/inet/inet.h	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(revision )
@@ -1,202 +1,0 @@
-/*
- * Copyright (c) 2012 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup inet
- * @{
- */
-/**
- * @file
- * @brief
- */
-
-#ifndef INET_H_
-#define INET_H_
-
-#include <adt/list.h>
-#include <bool.h>
-#include <inet/iplink.h>
-#include <ipc/loc.h>
-#include <sys/types.h>
-#include <async.h>
-
-/** Inet Client */
-typedef struct {
-	async_sess_t *sess;
-	uint8_t protocol;
-	link_t client_list;
-} inet_client_t;
-
-/** Inetping Client */
-typedef struct {
-	/** Callback session */
-	async_sess_t *sess;
-	/** Session identifier */
-	uint16_t ident;
-	/** Link to client list */
-	link_t client_list;
-} inetping_client_t;
-
-/** Host address */
-typedef struct {
-	uint32_t ipv4;
-} inet_addr_t;
-
-/** Network address */
-typedef struct {
-	/** Address */
-	uint32_t ipv4;
-	/** Number of valid bits in @c ipv4 */
-	int bits;
-} inet_naddr_t;
-
-/** Address object info */
-typedef struct {
-	/** Network address */
-	inet_naddr_t naddr;
-	/** Link service ID */
-	sysarg_t ilink;
-	/** Address object name */
-	char *name;
-} inet_addr_info_t;
-
-/** IP link info */
-typedef struct {
-	/** Link service name */
-	char *name;
-	/** Default MTU */
-	size_t def_mtu;
-} inet_link_info_t;
-
-/** Static route info */
-typedef struct {
-	/** Destination network address */
-	inet_naddr_t dest;
-	/** Router address */
-	inet_addr_t router;
-	/** Static route name */
-	char *name;
-} inet_sroute_info_t;
-
-typedef struct {
-	/** Source address */
-	inet_addr_t src;
-	/** Destination address */
-	inet_addr_t dest;
-	/** Type of service */
-	uint8_t tos;
-	/** Protocol */
-	uint8_t proto;
-	/** Time to live */
-	uint8_t ttl;
-	/** Identifier */
-	uint16_t ident;
-	/** Do not fragment */
-	bool df;
-	/** More fragments */
-	bool mf;
-	/** Offset of fragment into datagram, in bytes */
-	size_t offs;
-	/** Packet data */
-	void *data;
-	/** Packet data size in bytes */
-	size_t size;
-} inet_packet_t;
-
-typedef struct {
-	inet_addr_t src;
-	inet_addr_t dest;
-	uint8_t tos;
-	void *data;
-	size_t size;
-} inet_dgram_t;
-
-typedef struct {
-	link_t link_list;
-	service_id_t svc_id;
-	char *svc_name;
-	async_sess_t *sess;
-	iplink_t *iplink;
-	size_t def_mtu;
-} inet_link_t;
-
-typedef struct {
-	link_t addr_list;
-	sysarg_t id;
-	inet_naddr_t naddr;
-	inet_link_t *ilink;
-	char *name;
-} inet_addrobj_t;
-
-/** Static route configuration */
-typedef struct {
-	link_t sroute_list;
-	sysarg_t id;
-	/** Destination network */
-	inet_naddr_t dest;
-	/** Router via which to route packets */
-	inet_addr_t router;
-	char *name;
-} inet_sroute_t;
-
-typedef enum {
-	/** Destination is on this network node */
-	dt_local,
-	/** Destination is directly reachable */
-	dt_direct,
-	/** Destination is behind a router */
-	dt_router
-} inet_dir_type_t;
-
-/** Direction (next hop) to a destination */
-typedef struct {
-	/** Route type */
-	inet_dir_type_t dtype;
-	/** Address object (direction) */
-	inet_addrobj_t *aobj;
-	/** Local destination address */
-	inet_addr_t ldest;
-} inet_dir_t;
-
-typedef struct {
-	inet_addr_t src;
-	inet_addr_t dest;
-	uint16_t seq_no;
-	void *data;
-	size_t size;
-} inetping_sdu_t;
-
-extern int inet_ev_recv(inet_client_t *, inet_dgram_t *);
-extern int inet_recv_packet(inet_packet_t *);
-extern int inet_route_packet(inet_dgram_t *, uint8_t, uint8_t, int);
-extern int inet_get_srcaddr(inet_addr_t *, uint8_t, inet_addr_t *);
-extern int inet_recv_dgram_local(inet_dgram_t *, uint8_t);
-
-#endif
-
-/** @}
- */
Index: uspace/srv/inet/inet_link.c
===================================================================
--- uspace/srv/inet/inet_link.c	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(revision )
@@ -1,309 +1,0 @@
-/*
- * Copyright (c) 2012 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup inet
- * @{
- */
-/**
- * @file
- * @brief
- */
-
-#include <bool.h>
-#include <errno.h>
-#include <fibril_synch.h>
-#include <inet/iplink.h>
-#include <io/log.h>
-#include <loc.h>
-#include <stdlib.h>
-#include <str.h>
-
-#include "addrobj.h"
-#include "inet.h"
-#include "inet_link.h"
-#include "pdu.h"
-
-static int inet_link_open(service_id_t sid);
-static int inet_iplink_recv(iplink_t *ilink, iplink_sdu_t *sdu);
-
-static iplink_ev_ops_t inet_iplink_ev_ops = {
-	.recv = inet_iplink_recv
-};
-
-static LIST_INITIALIZE(inet_link_list);
-static FIBRIL_MUTEX_INITIALIZE(inet_discovery_lock);
-
-static int inet_iplink_recv(iplink_t *iplink, iplink_sdu_t *sdu)
-{
-	inet_packet_t packet;
-	int rc;
-
-	log_msg(LVL_DEBUG, "inet_iplink_recv()");
-	rc = inet_pdu_decode(sdu->data, sdu->size, &packet);
-	if (rc != EOK) {
-		log_msg(LVL_DEBUG, "failed decoding PDU");
-		return rc;
-	}
-
-	log_msg(LVL_DEBUG, "call inet_recv_packet()");
-	rc = inet_recv_packet(&packet);
-	log_msg(LVL_DEBUG, "call inet_recv_packet -> %d", rc);
-	free(packet.data);
-
-	return rc;
-}
-
-static int inet_link_check_new(void)
-{
-	bool already_known;
-	category_id_t iplink_cat;
-	service_id_t *svcs;
-	size_t count, i;
-	int rc;
-
-	fibril_mutex_lock(&inet_discovery_lock);
-
-	rc = loc_category_get_id("iplink", &iplink_cat, IPC_FLAG_BLOCKING);
-	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed resolving category 'iplink'.");
-		fibril_mutex_unlock(&inet_discovery_lock);
-		return ENOENT;
-	}
-
-	rc = loc_category_get_svcs(iplink_cat, &svcs, &count);
-	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed getting list of IP links.");
-		fibril_mutex_unlock(&inet_discovery_lock);
-		return EIO;
-	}
-
-	for (i = 0; i < count; i++) {
-		already_known = false;
-
-		list_foreach(inet_link_list, ilink_link) {
-			inet_link_t *ilink = list_get_instance(ilink_link,
-			    inet_link_t, link_list);
-			if (ilink->svc_id == svcs[i]) {
-				already_known = true;
-				break;
-			}
-		}
-
-		if (!already_known) {
-			log_msg(LVL_DEBUG, "Found IP link '%lu'",
-			    (unsigned long) svcs[i]);
-			rc = inet_link_open(svcs[i]);
-			if (rc != EOK)
-				log_msg(LVL_ERROR, "Could not open IP link.");
-		}
-	}
-
-	fibril_mutex_unlock(&inet_discovery_lock);
-	return EOK;
-}
-
-static inet_link_t *inet_link_new(void)
-{
-	inet_link_t *ilink = calloc(1, sizeof(inet_link_t));
-
-	if (ilink == NULL) {
-		log_msg(LVL_ERROR, "Failed allocating link structure. "
-		    "Out of memory.");
-		return NULL;
-	}
-
-	link_initialize(&ilink->link_list);
-
-	return ilink;
-}
-
-static void inet_link_delete(inet_link_t *ilink)
-{
-	if (ilink->svc_name != NULL)
-		free(ilink->svc_name);
-	free(ilink);
-}
-
-static int inet_link_open(service_id_t sid)
-{
-	inet_link_t *ilink;
-	iplink_addr_t iaddr;
-	int rc;
-
-	log_msg(LVL_DEBUG, "inet_link_open()");
-	ilink = inet_link_new();
-	if (ilink == NULL)
-		return ENOMEM;
-
-	ilink->svc_id = sid;
-	ilink->iplink = NULL;
-
-	rc = loc_service_get_name(sid, &ilink->svc_name);
-	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed getting service name.");
-		goto error;
-	}
-
-	ilink->sess = loc_service_connect(EXCHANGE_SERIALIZE, sid, 0);
-	if (ilink->sess == NULL) {
-		log_msg(LVL_ERROR, "Failed connecting '%s'", ilink->svc_name);
-		goto error;
-	}
-
-	rc = iplink_open(ilink->sess, &inet_iplink_ev_ops, &ilink->iplink);
-	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed opening IP link '%s'",
-		    ilink->svc_name);
-		goto error;
-	}
-
-	rc = iplink_get_mtu(ilink->iplink, &ilink->def_mtu);
-	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed determinning MTU of link '%s'",
-		    ilink->svc_name);
-		goto error;
-	}
-
-	log_msg(LVL_DEBUG, "Opened IP link '%s'", ilink->svc_name);
-	list_append(&ilink->link_list, &inet_link_list);
-
-	inet_addrobj_t *addr;
-
-	static int first = 1;
-	/* XXX For testing: set static IP address 192.168.0.4/24 */
-	addr = inet_addrobj_new();
-	if (first) {
-		addr->naddr.ipv4 = (127 << 24) + (0 << 16) + (0 << 8) + 1;
-		first = 0;
-	} else {
-		addr->naddr.ipv4 = (192 << 24) + (168 << 16) + (0 << 8) + 4;
-	}
-	addr->naddr.bits = 24;
-	addr->ilink = ilink;
-	addr->name = str_dup("v4a");
-	inet_addrobj_add(addr);
-
-	iaddr.ipv4 = addr->naddr.ipv4;
-	rc = iplink_addr_add(ilink->iplink, &iaddr);
-	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed setting IP address on internet link.");
-		/* XXX Roll back */
-		return rc;
-	}
-
-	return EOK;
-
-error:
-	if (ilink->iplink != NULL)
-		iplink_close(ilink->iplink);
-	inet_link_delete(ilink);
-	return rc;
-}
-
-static void inet_link_cat_change_cb(void)
-{
-	(void) inet_link_check_new();
-}
-
-int inet_link_discovery_start(void)
-{
-	int rc;
-
-	rc = loc_register_cat_change_cb(inet_link_cat_change_cb);
-	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed registering callback for IP link "
-		    "discovery (%d).", rc);
-		return rc;
-	}
-
-	return inet_link_check_new();
-}
-
-/** Send datagram over Internet link */
-int inet_link_send_dgram(inet_link_t *ilink, inet_addr_t *lsrc,
-    inet_addr_t *ldest, inet_dgram_t *dgram, uint8_t proto, uint8_t ttl, int df)
-{
-	iplink_sdu_t sdu;
-	inet_packet_t packet;
-	int rc;
-	size_t offs, roffs;
-
-	/*
-	 * Fill packet structure. Fragmentation is performed by
-	 * inet_pdu_encode().
-	 */
-	packet.src = dgram->src;
-	packet.dest = dgram->dest;
-	packet.tos = dgram->tos;
-	packet.proto = proto;
-	packet.ttl = ttl;
-	packet.df = df;
-	packet.data = dgram->data;
-	packet.size = dgram->size;
-
-	sdu.lsrc.ipv4 = lsrc->ipv4;
-	sdu.ldest.ipv4 = ldest->ipv4;
-
-	offs = 0;
-	do {
-		/* Encode one fragment */
-		rc = inet_pdu_encode(&packet, offs, ilink->def_mtu, &sdu.data,
-		    &sdu.size, &roffs);
-		if (rc != EOK)
-			return rc;
-
-		/* Send the PDU */
-		rc = iplink_send(ilink->iplink, &sdu);
-		free(sdu.data);
-
-		offs = roffs;
-	} while (offs < packet.size);
-
-	return rc;
-}
-
-inet_link_t *inet_link_get_by_id(sysarg_t link_id)
-{
-	fibril_mutex_lock(&inet_discovery_lock);
-
-	list_foreach(inet_link_list, elem) {
-		inet_link_t *ilink = list_get_instance(elem, inet_link_t,
-		    link_list);
-
-		if (ilink->svc_id == link_id) {
-			fibril_mutex_unlock(&inet_discovery_lock);
-			return ilink;
-		}
-	}
-
-	fibril_mutex_unlock(&inet_discovery_lock);
-	return NULL;
-}
-
-/** @}
- */
Index: uspace/srv/inet/inet_link.h
===================================================================
--- uspace/srv/inet/inet_link.h	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(revision )
@@ -1,51 +1,0 @@
-/*
- * Copyright (c) 2012 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup inet
- * @{
- */
-/**
- * @file
- * @brief
- */
-
-#ifndef INET_LINK_H_
-#define INET_LINK_H_
-
-#include <sys/types.h>
-#include "inet.h"
-
-extern int inet_link_discovery_start(void);
-extern int inet_link_send_dgram(inet_link_t *, inet_addr_t *,
-    inet_addr_t *, inet_dgram_t *, uint8_t, uint8_t, int);
-extern inet_link_t *inet_link_get_by_id(sysarg_t);
-
-#endif
-
-/** @}
- */
Index: uspace/srv/inet/inet_std.h
===================================================================
--- uspace/srv/inet/inet_std.h	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(revision )
@@ -1,98 +1,0 @@
-/*
- * Copyright (c) 2012 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup inet
- * @{
- */
-/**
- * @file IP header definitions
- *
- */
-
-#ifndef INET_STD_H_
-#define INET_STD_H_
-
-#include <sys/types.h>
-
-/** Internet Datagram header (fixed part) */
-typedef struct {
-	/** Version, Internet Header Length */
-	uint8_t ver_ihl;
-	/* Type of Service */
-	uint8_t tos;
-	/** Total Length */
-	uint16_t tot_len;
-	/** Identification */
-	uint16_t id;
-	/** Flags, Fragment Offset */
-	uint16_t flags_foff;
-	/** Time to Live */
-	uint8_t ttl;
-	/** Protocol */
-	uint8_t proto;
-	/** Header Checksum */
-	uint16_t chksum;
-	/** Source Address */
-	uint32_t src_addr;
-	/** Destination Address */
-	uint32_t dest_addr;
-} ip_header_t;
-
-/** Bits in ip_header_t.ver_ihl */
-enum ver_ihl_bits {
-	/** Version, highest bit */
-	VI_VERSION_h = 7,
-	/** Version, lowest bit */
-	VI_VERSION_l = 4,
-	/** Internet Header Length, highest bit */
-	VI_IHL_h     = 3,
-	/** Internet Header Length, lowest bit */
-	VI_IHL_l     = 0
-};
-
-/** Bits in ip_header_t.flags_foff */
-enum flags_foff_bits {
-	/** Reserved, must be zero */
-	FF_FLAG_RSVD = 15,
-	/** Don't Fragment */
-	FF_FLAG_DF = 14,
-	/** More Fragments */
-	FF_FLAG_MF = 13,
-	/** Fragment Offset, highest bit */
-	FF_FRAGOFF_h = 12,
-	/** Fragment Offset, lowest bit */
-	FF_FRAGOFF_l = 0
-};
-
-/** Fragment offset is expressed in units of 8 bytes */
-#define FRAG_OFFS_UNIT 8
-
-#endif
-
-/** @}
- */
Index: uspace/srv/inet/inet_util.c
===================================================================
--- uspace/srv/inet/inet_util.c	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(revision )
@@ -1,54 +1,0 @@
-/*
- * Copyright (c) 2012 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup inet
- * @{
- */
-/**
- * @file
- * @brief
- */
-
-#include <assert.h>
-#include <bitops.h>
-#include <sys/types.h>
-#include "inet_util.h"
-
-uint32_t inet_netmask(int bits)
-{
-	assert(bits >= 0);
-	assert(bits < 32);
-
-	if (bits == 0)
-		return 0;
-	else
-		return BIT_RANGE(uint32_t, 31, 31 - (bits - 1));
-}
-
-/** @}
- */
Index: uspace/srv/inet/inet_util.h
===================================================================
--- uspace/srv/inet/inet_util.h	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(revision )
@@ -1,47 +1,0 @@
-/*
- * Copyright (c) 2012 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup inet
- * @{
- */
-/**
- * @file
- * @brief
- */
-
-#ifndef INET_UTIL_H_
-#define INET_UTIL_H_
-
-#include <sys/types.h>
-
-uint32_t inet_netmask(int bits);
-
-#endif
-
-/** @}
- */
Index: uspace/srv/inet/inetcfg.c
===================================================================
--- uspace/srv/inet/inetcfg.c	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(revision )
@@ -1,631 +1,0 @@
-/*
- * Copyright (c) 2012 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup inet
- * @{
- */
-/**
- * @file
- * @brief
- */
-
-#include <async.h>
-#include <errno.h>
-#include <macros.h>
-#include <io/log.h>
-#include <ipc/inet.h>
-#include <loc.h>
-#include <stdlib.h>
-#include <str.h>
-#include <sys/types.h>
-
-#include "addrobj.h"
-#include "inet.h"
-#include "inet_link.h"
-#include "inetcfg.h"
-#include "sroute.h"
-
-static int inetcfg_addr_create_static(char *name, inet_naddr_t *naddr,
-    sysarg_t link_id, sysarg_t *addr_id)
-{
-	inet_link_t *ilink;
-	inet_addrobj_t *addr;
-	iplink_addr_t iaddr;
-	int rc;
-
-	ilink = inet_link_get_by_id(link_id);
-	if (ilink == NULL) {
-		log_msg(LVL_DEBUG, "Link %lu not found.",
-		    (unsigned long) link_id);
-		return ENOENT;
-	}
-
-	addr = inet_addrobj_new();
-	if (addr == NULL) {
-		*addr_id = 0;
-		return ENOMEM;
-	}
-
-	addr->naddr = *naddr;
-	addr->ilink = ilink;
-	addr->name = str_dup(name);
-	inet_addrobj_add(addr);
-
-	iaddr.ipv4 = addr->naddr.ipv4;
-	rc = iplink_addr_add(ilink->iplink, &iaddr);
-	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed setting IP address on internet link.");
-		inet_addrobj_remove(addr);
-		inet_addrobj_delete(addr);
-		return rc;
-	}
-
-	return EOK;
-}
-
-static int inetcfg_addr_delete(sysarg_t addr_id)
-{
-	inet_addrobj_t *addr;
-
-	addr = inet_addrobj_get_by_id(addr_id);
-	if (addr == NULL)
-		return ENOENT;
-
-	inet_addrobj_remove(addr);
-	inet_addrobj_delete(addr);
-
-	return EOK;
-}
-
-static int inetcfg_addr_get(sysarg_t addr_id, inet_addr_info_t *ainfo)
-{
-	inet_addrobj_t *addr;
-
-	addr = inet_addrobj_get_by_id(addr_id);
-	if (addr == NULL)
-		return ENOENT;
-
-	ainfo->naddr = addr->naddr;
-	ainfo->ilink = addr->ilink->svc_id;
-	ainfo->name = str_dup(addr->name);
-
-	return EOK;
-}
-
-static int inetcfg_addr_get_id(char *name, sysarg_t link_id, sysarg_t *addr_id)
-{
-	inet_link_t *ilink;
-	inet_addrobj_t *addr;
-
-	ilink = inet_link_get_by_id(link_id);
-	if (ilink == NULL) {
-		log_msg(LVL_DEBUG, "Link %zu not found.", (size_t) link_id);
-		return ENOENT;
-	}
-
-	addr = inet_addrobj_find_by_name(name, ilink);
-	if (addr == NULL) {
-		log_msg(LVL_DEBUG, "Address '%s' not found.", name);
-		return ENOENT;
-	}
-
-	*addr_id = addr->id;
-	return EOK;
-}
-
-static int inetcfg_get_addr_list(sysarg_t **addrs, size_t *count)
-{
-	return inet_addrobj_get_id_list(addrs, count);
-}
-
-static int inetcfg_get_link_list(sysarg_t **addrs, size_t *count)
-{
-	return ENOTSUP;
-}
-
-static int inetcfg_get_sroute_list(sysarg_t **sroutes, size_t *count)
-{
-	return inet_sroute_get_id_list(sroutes, count);
-}
-
-static int inetcfg_link_get(sysarg_t link_id, inet_link_info_t *linfo)
-{
-	inet_link_t *ilink;
-
-	ilink = inet_link_get_by_id(link_id);
-	if (ilink == NULL) {
-		return ENOENT;
-	}
-
-	linfo->name = str_dup(ilink->svc_name);
-	linfo->def_mtu = ilink->def_mtu;
-	return EOK;
-}
-
-static int inetcfg_sroute_create(char *name, inet_naddr_t *dest,
-    inet_addr_t *router, sysarg_t *sroute_id)
-{
-	inet_sroute_t *sroute;
-
-	sroute = inet_sroute_new();
-	if (sroute == NULL) {
-		*sroute_id = 0;
-		return ENOMEM;
-	}
-
-	sroute->dest = *dest;
-	sroute->router = *router;
-	sroute->name = str_dup(name);
-	inet_sroute_add(sroute);
-
-	*sroute_id = sroute->id;
-	return EOK;
-}
-
-static int inetcfg_sroute_delete(sysarg_t sroute_id)
-{
-	inet_sroute_t *sroute;
-
-	sroute = inet_sroute_get_by_id(sroute_id);
-	if (sroute == NULL)
-		return ENOENT;
-
-	inet_sroute_remove(sroute);
-	inet_sroute_delete(sroute);
-
-	return EOK;
-}
-
-static int inetcfg_sroute_get(sysarg_t sroute_id, inet_sroute_info_t *srinfo)
-{
-	inet_sroute_t *sroute;
-
-	sroute = inet_sroute_get_by_id(sroute_id);
-	if (sroute == NULL)
-		return ENOENT;
-
-	srinfo->dest = sroute->dest;
-	srinfo->router = sroute->router;
-	srinfo->name = str_dup(sroute->name);
-
-	return EOK;
-}
-
-static int inetcfg_sroute_get_id(char *name, sysarg_t *sroute_id)
-{
-	inet_sroute_t *sroute;
-
-	sroute = inet_sroute_find_by_name(name);
-	if (sroute == NULL) {
-		log_msg(LVL_DEBUG, "Static route '%s' not found.", name);
-		return ENOENT;
-	}
-
-	*sroute_id = sroute->id;
-	return EOK;
-}
-
-static void inetcfg_addr_create_static_srv(ipc_callid_t callid,
-    ipc_call_t *call)
-{
-	char *name;
-	inet_naddr_t naddr;
-	sysarg_t link_id;
-	sysarg_t addr_id;
-	int rc;
-
-	log_msg(LVL_DEBUG, "inetcfg_addr_create_static_srv()");
-
-	rc = async_data_write_accept((void **) &name, true, 0, LOC_NAME_MAXLEN,
-	    0, NULL);
-	if (rc != EOK) {
-		async_answer_0(callid, rc);
-		return;
-	}
-
-	naddr.ipv4 = IPC_GET_ARG1(*call);
-	naddr.bits = IPC_GET_ARG2(*call);
-	link_id    = IPC_GET_ARG3(*call);
-
-	addr_id = 0;
-	rc = inetcfg_addr_create_static(name, &naddr, link_id, &addr_id);
-	free(name);
-	async_answer_1(callid, rc, addr_id);
-}
-
-static void inetcfg_addr_delete_srv(ipc_callid_t callid, ipc_call_t *call)
-{
-	sysarg_t addr_id;
-	int rc;
-
-	log_msg(LVL_DEBUG, "inetcfg_addr_delete_srv()");
-
-	addr_id = IPC_GET_ARG1(*call);
-
-	rc = inetcfg_addr_delete(addr_id);
-	async_answer_0(callid, rc);
-}
-
-static void inetcfg_addr_get_srv(ipc_callid_t callid, ipc_call_t *call)
-{
-	ipc_callid_t rcallid;
-	size_t max_size;
-
-	sysarg_t addr_id;
-	inet_addr_info_t ainfo;
-	int rc;
-
-	addr_id = IPC_GET_ARG1(*call);
-	log_msg(LVL_DEBUG, "inetcfg_addr_get_srv()");
-
-	ainfo.naddr.ipv4 = 0;
-	ainfo.naddr.bits = 0;
-	ainfo.ilink = 0;
-	ainfo.name = NULL;
-
-	if (!async_data_read_receive(&rcallid, &max_size)) {
-		async_answer_0(rcallid, EREFUSED);
-		async_answer_0(callid, EREFUSED);
-		return;
-	}
-
-	rc = inetcfg_addr_get(addr_id, &ainfo);
-	if (rc != EOK) {
-		async_answer_0(callid, rc);
-		return;
-	}
-
-	sysarg_t retval = async_data_read_finalize(rcallid, ainfo.name,
-	    min(max_size, str_size(ainfo.name)));
-	free(ainfo.name);
-
-	async_answer_3(callid, retval, ainfo.naddr.ipv4, ainfo.naddr.bits,
-	    ainfo.ilink);
-}
-
-static void inetcfg_addr_get_id_srv(ipc_callid_t callid, ipc_call_t *call)
-{
-	char *name;
-	sysarg_t link_id;
-	sysarg_t addr_id;
-	int rc;
-
-	log_msg(LVL_DEBUG, "inetcfg_addr_get_id_srv()");
-
-	link_id = IPC_GET_ARG1(*call);
-
-	rc = async_data_write_accept((void **) &name, true, 0, LOC_NAME_MAXLEN,
-	    0, NULL);
-	if (rc != EOK) {
-		async_answer_0(callid, rc);
-		return;
-	}
-
-	addr_id = 0;
-	rc = inetcfg_addr_get_id(name, link_id, &addr_id);
-	free(name);
-	async_answer_1(callid, rc, addr_id);
-}
-
-static void inetcfg_get_addr_list_srv(ipc_callid_t callid, ipc_call_t *call)
-{
-	ipc_callid_t rcallid;
-	size_t count;
-	size_t max_size;
-	size_t act_size;
-	size_t size;
-	sysarg_t *id_buf;
-	int rc;
-
-	log_msg(LVL_DEBUG, "inetcfg_get_addr_list_srv()");
-
-	if (!async_data_read_receive(&rcallid, &max_size)) {
-		async_answer_0(rcallid, EREFUSED);
-		async_answer_0(callid, EREFUSED);
-		return;
-	}
-
-	rc = inetcfg_get_addr_list(&id_buf, &count);
-	if (rc != EOK) {
-		async_answer_0(rcallid, rc);
-		async_answer_0(callid, rc);
-		return;
-	}
-
-	act_size = count * sizeof(sysarg_t);
-	size = min(act_size, max_size);
-
-	sysarg_t retval = async_data_read_finalize(rcallid, id_buf, size);
-	free(id_buf);
-
-	async_answer_1(callid, retval, act_size);
-}
-
-
-static void inetcfg_get_link_list_srv(ipc_callid_t callid, ipc_call_t *call)
-{
-	ipc_callid_t rcallid;
-	size_t max_size;
-	size_t act_size;
-	size_t size;
-	sysarg_t *id_buf;
-	int rc;
-
-	log_msg(LVL_DEBUG, "inetcfg_get_link_list_srv()");
-
-	if (!async_data_read_receive(&rcallid, &max_size)) {
-		async_answer_0(rcallid, EREFUSED);
-		async_answer_0(callid, EREFUSED);
-		return;
-	}
-
-	rc = inetcfg_get_link_list(&id_buf, &act_size);
-	if (rc != EOK) {
-		async_answer_0(rcallid, rc);
-		async_answer_0(callid, rc);
-		return;
-	}
-
-	size = min(act_size, max_size);
-
-	sysarg_t retval = async_data_read_finalize(rcallid, id_buf, size);
-	free(id_buf);
-
-	async_answer_1(callid, retval, act_size);
-}
-
-static void inetcfg_get_sroute_list_srv(ipc_callid_t callid, ipc_call_t *call)
-{
-	ipc_callid_t rcallid;
-	size_t count;
-	size_t max_size;
-	size_t act_size;
-	size_t size;
-	sysarg_t *id_buf;
-	int rc;
-
-	log_msg(LVL_DEBUG, "inetcfg_get_sroute_list_srv()");
-
-	if (!async_data_read_receive(&rcallid, &max_size)) {
-		async_answer_0(rcallid, EREFUSED);
-		async_answer_0(callid, EREFUSED);
-		return;
-	}
-
-	rc = inetcfg_get_sroute_list(&id_buf, &count);
-	if (rc != EOK) {
-		async_answer_0(rcallid, rc);
-		async_answer_0(callid, rc);
-		return;
-	}
-
-	act_size = count * sizeof(sysarg_t);
-	size = min(act_size, max_size);
-
-	sysarg_t retval = async_data_read_finalize(rcallid, id_buf, size);
-	free(id_buf);
-
-	async_answer_1(callid, retval, act_size);
-}
-
-static void inetcfg_link_get_srv(ipc_callid_t callid, ipc_call_t *call)
-{
-	ipc_callid_t rcallid;
-	size_t max_size;
-
-	sysarg_t link_id;
-	inet_link_info_t linfo;
-	int rc;
-
-	link_id = IPC_GET_ARG1(*call);
-	log_msg(LVL_DEBUG, "inetcfg_link_get_srv()");
-
-	linfo.name = NULL;
-
-	if (!async_data_read_receive(&rcallid, &max_size)) {
-		async_answer_0(rcallid, EREFUSED);
-		async_answer_0(callid, EREFUSED);
-		return;
-	}
-
-	rc = inetcfg_link_get(link_id, &linfo);
-	if (rc != EOK) {
-		async_answer_0(rcallid, rc);
-		async_answer_0(callid, rc);
-		return;
-	}
-
-	sysarg_t retval = async_data_read_finalize(rcallid, linfo.name,
-	    min(max_size, str_size(linfo.name)));
-	free(linfo.name);
-
-	async_answer_1(callid, retval, linfo.def_mtu);
-}
-
-static void inetcfg_sroute_create_srv(ipc_callid_t callid,
-    ipc_call_t *call)
-{
-	char *name;
-	inet_naddr_t dest;
-	inet_addr_t router;
-	sysarg_t sroute_id;
-	int rc;
-
-	log_msg(LVL_DEBUG, "inetcfg_sroute_create_srv()");
-
-	rc = async_data_write_accept((void **) &name, true, 0, LOC_NAME_MAXLEN,
-	    0, NULL);
-	if (rc != EOK) {
-		async_answer_0(callid, rc);
-		return;
-	}
-
-	dest.ipv4   = IPC_GET_ARG1(*call);
-	dest.bits   = IPC_GET_ARG2(*call);
-	router.ipv4 = IPC_GET_ARG3(*call);
-
-	sroute_id = 0;
-	rc = inetcfg_sroute_create(name, &dest, &router, &sroute_id);
-	free(name);
-	async_answer_1(callid, rc, sroute_id);
-}
-
-static void inetcfg_sroute_delete_srv(ipc_callid_t callid, ipc_call_t *call)
-{
-	sysarg_t sroute_id;
-	int rc;
-
-	log_msg(LVL_DEBUG, "inetcfg_sroute_delete_srv()");
-
-	sroute_id = IPC_GET_ARG1(*call);
-
-	rc = inetcfg_sroute_delete(sroute_id);
-	async_answer_0(callid, rc);
-}
-
-static void inetcfg_sroute_get_srv(ipc_callid_t callid, ipc_call_t *call)
-{
-	ipc_callid_t rcallid;
-	size_t max_size;
-
-	sysarg_t sroute_id;
-	inet_sroute_info_t srinfo;
-	int rc;
-
-	sroute_id = IPC_GET_ARG1(*call);
-	log_msg(LVL_DEBUG, "inetcfg_sroute_get_srv()");
-
-	srinfo.dest.ipv4 = 0;
-	srinfo.dest.bits = 0;
-	srinfo.router.ipv4 = 0;
-	srinfo.name = NULL;
-
-	if (!async_data_read_receive(&rcallid, &max_size)) {
-		async_answer_0(rcallid, EREFUSED);
-		async_answer_0(callid, EREFUSED);
-		return;
-	}
-
-	rc = inetcfg_sroute_get(sroute_id, &srinfo);
-	if (rc != EOK) {
-		async_answer_0(callid, rc);
-		return;
-	}
-
-	sysarg_t retval = async_data_read_finalize(rcallid, srinfo.name,
-	    min(max_size, str_size(srinfo.name)));
-	free(srinfo.name);
-
-	async_answer_3(callid, retval, srinfo.dest.ipv4, srinfo.dest.bits,
-	    srinfo.router.ipv4);
-}
-
-static void inetcfg_sroute_get_id_srv(ipc_callid_t callid, ipc_call_t *call)
-{
-	char *name;
-	sysarg_t sroute_id;
-	int rc;
-
-	log_msg(LVL_DEBUG, "inetcfg_sroute_get_id_srv()");
-
-	rc = async_data_write_accept((void **) &name, true, 0, LOC_NAME_MAXLEN,
-	    0, NULL);
-	if (rc != EOK) {
-		async_answer_0(callid, rc);
-		return;
-	}
-
-	sroute_id = 0;
-	rc = inetcfg_sroute_get_id(name, &sroute_id);
-	free(name);
-	async_answer_1(callid, rc, sroute_id);
-}
-
-void inet_cfg_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
-{
-	log_msg(LVL_DEBUG, "inet_cfg_conn()");
-
-	/* Accept the connection */
-	async_answer_0(iid, EOK);
-
-	while (true) {
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-		sysarg_t method = IPC_GET_IMETHOD(call);
-
-		if (!method) {
-			/* The other side has hung up */
-			async_answer_0(callid, EOK);
-			return;
-		}
-
-		switch (method) {
-		case INETCFG_ADDR_CREATE_STATIC:
-			inetcfg_addr_create_static_srv(callid, &call);
-			break;
-		case INETCFG_ADDR_DELETE:
-			inetcfg_addr_delete_srv(callid, &call);
-			break;
-		case INETCFG_ADDR_GET:
-			inetcfg_addr_get_srv(callid, &call);
-			break;
-		case INETCFG_ADDR_GET_ID:
-			inetcfg_addr_get_id_srv(callid, &call);
-			break;
-		case INETCFG_GET_ADDR_LIST:
-			inetcfg_get_addr_list_srv(callid, &call);
-			break;
-		case INETCFG_GET_LINK_LIST:
-			inetcfg_get_link_list_srv(callid, &call);
-			break;
-		case INETCFG_GET_SROUTE_LIST:
-			inetcfg_get_sroute_list_srv(callid, &call);
-			break;
-		case INETCFG_LINK_GET:
-			inetcfg_link_get_srv(callid, &call);
-			break;
-		case INETCFG_SROUTE_CREATE:
-			inetcfg_sroute_create_srv(callid, &call);
-			break;
-		case INETCFG_SROUTE_DELETE:
-			inetcfg_sroute_delete_srv(callid, &call);
-			break;
-		case INETCFG_SROUTE_GET:
-			inetcfg_sroute_get_srv(callid, &call);
-			break;
-		case INETCFG_SROUTE_GET_ID:
-			inetcfg_sroute_get_id_srv(callid, &call);
-			break;
-		default:
-			async_answer_0(callid, EINVAL);
-		}
-	}
-}
-
-/** @}
- */
Index: uspace/srv/inet/inetcfg.h
===================================================================
--- uspace/srv/inet/inetcfg.h	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(revision )
@@ -1,45 +1,0 @@
-/*
- * Copyright (c) 2012 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup inet
- * @{
- */
-/**
- * @file
- * @brief
- */
-
-#ifndef INETCFG_H_
-#define INETCFG_H_
-
-extern void inet_cfg_conn(ipc_callid_t, ipc_call_t *, void *);
-
-#endif
-
-/** @}
- */
Index: uspace/srv/inet/inetping.c
===================================================================
--- uspace/srv/inet/inetping.c	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(revision )
@@ -1,230 +1,0 @@
-/*
- * Copyright (c) 2012 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup inet
- * @{
- */
-/**
- * @file
- * @brief
- */
-
-#include <async.h>
-#include <errno.h>
-#include <fibril_synch.h>
-#include <io/log.h>
-#include <ipc/inet.h>
-#include <loc.h>
-#include <stdlib.h>
-#include <sys/types.h>
-
-#include "icmp.h"
-#include "icmp_std.h"
-#include "inet.h"
-#include "inetping.h"
-
-static FIBRIL_MUTEX_INITIALIZE(client_list_lock);
-static LIST_INITIALIZE(client_list);
-
-/** Last used session identifier. Protected by @c client_list_lock */
-static uint16_t inetping_ident = 0;
-
-static inetping_client_t *inetping_client_find(uint16_t);
-
-static int inetping_send(inetping_client_t *client, inetping_sdu_t *sdu)
-{
-	return icmp_ping_send(client->ident, sdu);
-}
-
-static int inetping_get_srcaddr(inetping_client_t *client, inet_addr_t *remote,
-    inet_addr_t *local)
-{
-	return inet_get_srcaddr(remote, ICMP_TOS, local);
-}
-
-int inetping_recv(uint16_t ident, inetping_sdu_t *sdu)
-{
-	inetping_client_t *client;
-	async_exch_t *exch;
-	ipc_call_t answer;
-
-	client = inetping_client_find(ident);
-	if (client == NULL) {
-		log_msg(LVL_DEBUG, "Unknown ICMP ident. Dropping.");
-		return ENOENT;
-	}
-
-	exch = async_exchange_begin(client->sess);
-
-	aid_t req = async_send_3(exch, INETPING_EV_RECV, sdu->src.ipv4,
-	    sdu->dest.ipv4, sdu->seq_no, &answer);
-	int rc = async_data_write_start(exch, sdu->data, sdu->size);
-	async_exchange_end(exch);
-
-	if (rc != EOK) {
-		async_wait_for(req, NULL);
-		return rc;
-	}
-
-	sysarg_t retval;
-	async_wait_for(req, &retval);
-	if (retval != EOK) {
-		return retval;
-	}
-
-	return EOK;
-}
-
-static void inetping_send_srv(inetping_client_t *client, ipc_callid_t callid,
-    ipc_call_t *call)
-{
-	inetping_sdu_t sdu;
-	int rc;
-
-	log_msg(LVL_DEBUG, "inetping_send_srv()");
-
-	rc = async_data_write_accept((void **) &sdu.data, false, 0, 0, 0,
-	    &sdu.size);
-	if (rc != EOK) {
-		async_answer_0(callid, rc);
-		return;
-	}
-
-	sdu.src.ipv4 = IPC_GET_ARG1(*call);
-	sdu.dest.ipv4 = IPC_GET_ARG2(*call);
-	sdu.seq_no = IPC_GET_ARG3(*call);
-
-	rc = inetping_send(client, &sdu);
-	free(sdu.data);
-
-	async_answer_0(callid, rc);
-}
-
-static void inetping_get_srcaddr_srv(inetping_client_t *client,
-    ipc_callid_t callid, ipc_call_t *call)
-{
-	inet_addr_t remote;
-	inet_addr_t local;
-	int rc;
-
-	log_msg(LVL_DEBUG, "inetping_get_srcaddr_srv()");
-
-	remote.ipv4 = IPC_GET_ARG1(*call);
-	local.ipv4 = 0;
-
-	rc = inetping_get_srcaddr(client, &remote, &local);
-	async_answer_1(callid, rc, local.ipv4);
-}
-
-static int inetping_client_init(inetping_client_t *client)
-{
-	async_sess_t *sess = async_callback_receive(EXCHANGE_SERIALIZE);
-	if (sess == NULL)
-		return ENOMEM;
-
-	client->sess = sess;
-	link_initialize(&client->client_list);
-
-	fibril_mutex_lock(&client_list_lock);
-	client->ident = ++inetping_ident;
-	list_append(&client->client_list, &client_list);
-	fibril_mutex_unlock(&client_list_lock);
-
-	return EOK;
-}
-
-static void inetping_client_fini(inetping_client_t *client)
-{
-	async_hangup(client->sess);
-	client->sess = NULL;
-
-	fibril_mutex_lock(&client_list_lock);
-	list_remove(&client->client_list);
-	fibril_mutex_unlock(&client_list_lock);
-}
-
-static inetping_client_t *inetping_client_find(uint16_t ident)
-{
-	fibril_mutex_lock(&client_list_lock);
-
-	list_foreach(client_list, link) {
-		inetping_client_t *client = list_get_instance(link,
-		    inetping_client_t, client_list);
-
-		if (client->ident == ident) {
-			fibril_mutex_unlock(&client_list_lock);
-			return client;
-		}
-	}
-
-	fibril_mutex_unlock(&client_list_lock);
-	return NULL;
-}
-
-void inetping_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
-{
-	inetping_client_t client;
-	int rc;
-
-	log_msg(LVL_DEBUG, "inetping_conn()");
-
-	/* Accept the connection */
-	async_answer_0(iid, EOK);
-
-	rc = inetping_client_init(&client);
-	if (rc != EOK)
-		return;
-
-	while (true) {
-		ipc_call_t call;
-		ipc_callid_t callid = async_get_call(&call);
-		sysarg_t method = IPC_GET_IMETHOD(call);
-
-		if (!method) {
-			/* The other side has hung up */
-			async_answer_0(callid, EOK);
-			break;
-		}
-
-		switch (method) {
-		case INETPING_SEND:
-			inetping_send_srv(&client, callid, &call);
-			break;
-		case INETPING_GET_SRCADDR:
-			inetping_get_srcaddr_srv(&client, callid, &call);
-			break;
-		default:
-			async_answer_0(callid, EINVAL);
-		}
-	}
-
-	inetping_client_fini(&client);
-}
-
-/** @}
- */
Index: uspace/srv/inet/inetping.h
===================================================================
--- uspace/srv/inet/inetping.h	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(revision )
@@ -1,46 +1,0 @@
-/*
- * Copyright (c) 2012 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup inet
- * @{
- */
-/**
- * @file
- * @brief
- */
-
-#ifndef INETPING_H_
-#define INETPING_H_
-
-extern void inetping_conn(ipc_callid_t, ipc_call_t *, void *);
-extern int inetping_recv(uint16_t, inetping_sdu_t *);
-
-#endif
-
-/** @}
- */
Index: uspace/srv/inet/pdu.c
===================================================================
--- uspace/srv/inet/pdu.c	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(revision )
@@ -1,268 +1,0 @@
-/*
- * Copyright (c) 2012 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup inet
- * @{
- */
-/**
- * @file
- * @brief
- */
-
-#include <align.h>
-#include <bitops.h>
-#include <byteorder.h>
-#include <errno.h>
-#include <fibril_synch.h>
-#include <io/log.h>
-#include <macros.h>
-#include <mem.h>
-#include <stdlib.h>
-
-#include "inet.h"
-#include "inet_std.h"
-#include "pdu.h"
-
-static FIBRIL_MUTEX_INITIALIZE(ip_ident_lock);
-static uint16_t ip_ident = 0;
-
-/** One's complement addition.
- *
- * Result is a + b + carry.
- */
-static uint16_t inet_ocadd16(uint16_t a, uint16_t b)
-{
-	uint32_t s;
-
-	s = (uint32_t)a + (uint32_t)b;
-	return (s & 0xffff) + (s >> 16);
-}
-
-uint16_t inet_checksum_calc(uint16_t ivalue, void *data, size_t size)
-{
-	uint16_t sum;
-	uint16_t w;
-	size_t words, i;
-	uint8_t *bdata;
-
-	sum = ~ivalue;
-	words = size / 2;
-	bdata = (uint8_t *)data;
-
-	for (i = 0; i < words; i++) {
-		w = ((uint16_t)bdata[2*i] << 8) | bdata[2*i + 1];
-		sum = inet_ocadd16(sum, w);
-	}
-
-	if (size % 2 != 0) {
-		w = ((uint16_t)bdata[2*words] << 8);
-		sum = inet_ocadd16(sum, w);
-	}
-
-	return ~sum;
-}
-
-/** Encode Internet PDU.
- *
- * Encode internet packet into PDU (serialized form). Will encode a
- * fragment of the payload starting at offset @a offs. The resulting
- * PDU will have at most @a mtu bytes. @a *roffs will be set to the offset
- * of remaining payload. If some data is remaining, the MF flag will
- * be set in the header, otherwise the offset will equal @a packet->size.
- *
- * @param packet	Packet to encode
- * @param offs		Offset into packet payload (in bytes)
- * @param mtu		MTU (Maximum Transmission Unit) in bytes
- * @param rdata		Place to store pointer to allocated data buffer
- * @param rsize		Place to store size of allocated data buffer
- * @param roffs		Place to store offset of remaning data
- */
-int inet_pdu_encode(inet_packet_t *packet, size_t offs, size_t mtu,
-    void **rdata, size_t *rsize, size_t *roffs)
-{
-	void *data;
-	size_t size;
-	ip_header_t *hdr;
-	size_t hdr_size;
-	size_t data_offs;
-	uint16_t chksum;
-	uint16_t ident;
-	uint16_t flags_foff;
-	uint16_t foff;
-	size_t fragoff_limit;
-	size_t xfer_size;
-	size_t spc_avail;
-	size_t rem_offs;
-
-	/* Upper bound for fragment offset field */
-	fragoff_limit = 1 << (FF_FRAGOFF_h - FF_FRAGOFF_l);
-
-	/* Verify that total size of datagram is within reasonable bounds */
-	if (offs + packet->size > FRAG_OFFS_UNIT * fragoff_limit)
-		return ELIMIT;
-
-	hdr_size = sizeof(ip_header_t);
-	data_offs = ROUND_UP(hdr_size, 4);
-
-	assert(offs % FRAG_OFFS_UNIT == 0);
-	assert(offs / FRAG_OFFS_UNIT < fragoff_limit);
-
-	/* Value for the fragment offset field */
-	foff = offs / FRAG_OFFS_UNIT;
-
-	if (hdr_size >= mtu)
-		return EINVAL;
-
-	/* Amount of space in the PDU available for payload */
-	spc_avail = mtu - hdr_size;
-	spc_avail -= (spc_avail % FRAG_OFFS_UNIT);
-
-	/* Amount of data (payload) to transfer */
-	xfer_size = min(packet->size - offs, spc_avail);
-
-	/* Total PDU size */
-	size = hdr_size + xfer_size;
-
-	/* Offset of remaining payload */
-	rem_offs = offs + xfer_size;
-
-	/* Flags */
-	flags_foff =
-	    (packet->df ? BIT_V(uint16_t, FF_FLAG_DF) : 0) +
-	    (rem_offs < packet->size ? BIT_V(uint16_t, FF_FLAG_MF) : 0) +
-	    (foff << FF_FRAGOFF_l);
-
-	data = calloc(size, 1);
-	if (data == NULL)
-		return ENOMEM;
-
-	/* Allocate identifier */
-	fibril_mutex_lock(&ip_ident_lock);
-	ident = ++ip_ident;
-	fibril_mutex_unlock(&ip_ident_lock);
-
-	/* Encode header fields */
-	hdr = (ip_header_t *)data;
-	hdr->ver_ihl = (4 << VI_VERSION_l) | (hdr_size / sizeof(uint32_t));
-	hdr->tos = packet->tos;
-	hdr->tot_len = host2uint16_t_be(size);
-	hdr->id = host2uint16_t_be(ident);
-	hdr->flags_foff = host2uint16_t_be(flags_foff);
-	hdr->ttl = packet->ttl;
-	hdr->proto = packet->proto;
-	hdr->chksum = 0;
-	hdr->src_addr = host2uint32_t_be(packet->src.ipv4);
-	hdr->dest_addr = host2uint32_t_be(packet->dest.ipv4);
-
-	/* Compute checksum */
-	chksum = inet_checksum_calc(INET_CHECKSUM_INIT, (void *)hdr, hdr_size);
-	hdr->chksum = host2uint16_t_be(chksum);
-
-	/* Copy payload */
-	memcpy((uint8_t *)data + data_offs, packet->data + offs, xfer_size);
-
-	*rdata = data;
-	*rsize = size;
-	*roffs = rem_offs;
-
-	return EOK;
-}
-
-int inet_pdu_decode(void *data, size_t size, inet_packet_t *packet)
-{
-	ip_header_t *hdr;
-	size_t tot_len;
-	size_t data_offs;
-	uint8_t version;
-	uint16_t ident;
-	uint16_t flags_foff;
-	uint16_t foff;
-
-	log_msg(LVL_DEBUG, "inet_pdu_decode()");
-
-	if (size < sizeof(ip_header_t)) {
-		log_msg(LVL_DEBUG, "PDU too short (%zu)", size);
-		return EINVAL;
-	}
-
-	hdr = (ip_header_t *)data;
-
-	version = BIT_RANGE_EXTRACT(uint8_t, VI_VERSION_h, VI_VERSION_l,
-	    hdr->ver_ihl);
-	if (version != 4) {
-		log_msg(LVL_DEBUG, "Version (%d) != 4", version);
-		return EINVAL;
-	}
-
-	tot_len = uint16_t_be2host(hdr->tot_len);
-	if (tot_len < sizeof(ip_header_t)) {
-		log_msg(LVL_DEBUG, "Total Length too small (%zu)", tot_len);
-		return EINVAL;
-	}
-
-	if (tot_len > size) {
-		log_msg(LVL_DEBUG, "Total Length = %zu > PDU size = %zu",
-			tot_len, size);
-		return EINVAL;
-	}
-
-	ident = uint16_t_be2host(hdr->id);
-	flags_foff = uint16_t_be2host(hdr->flags_foff);
-	foff = BIT_RANGE_EXTRACT(uint16_t, FF_FRAGOFF_h, FF_FRAGOFF_l,
-	    flags_foff);
-	/* XXX Checksum */
-
-	packet->src.ipv4 = uint32_t_be2host(hdr->src_addr);
-	packet->dest.ipv4 = uint32_t_be2host(hdr->dest_addr);
-	packet->tos = hdr->tos;
-	packet->proto = hdr->proto;
-	packet->ttl = hdr->ttl;
-	packet->ident = ident;
-
-	packet->df = (flags_foff & BIT_V(uint16_t, FF_FLAG_DF)) != 0;
-	packet->mf = (flags_foff & BIT_V(uint16_t, FF_FLAG_MF)) != 0;
-	packet->offs = foff * FRAG_OFFS_UNIT;
-
-	/* XXX IP options */
-	data_offs = sizeof(uint32_t) * BIT_RANGE_EXTRACT(uint8_t, VI_IHL_h,
-	    VI_IHL_l, hdr->ver_ihl);
-
-	packet->size = tot_len - data_offs;
-	packet->data = calloc(packet->size, 1);
-	if (packet->data == NULL) {
-		log_msg(LVL_WARN, "Out of memory.");
-		return ENOMEM;
-	}
-
-	memcpy(packet->data, (uint8_t *)data + data_offs, packet->size);
-
-	return EOK;
-}
-
-/** @}
- */
Index: uspace/srv/inet/pdu.h
===================================================================
--- uspace/srv/inet/pdu.h	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(revision )
@@ -1,54 +1,0 @@
-/*
- * Copyright (c) 2012 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup inet
- * @{
- */
-/**
- * @file
- * @brief
- */
-
-#ifndef INET_PDU_H_
-#define INET_PDU_H_
-
-#include <sys/types.h>
-#include "inet.h"
-
-#define INET_CHECKSUM_INIT 0xffff
-
-extern uint16_t inet_checksum_calc(uint16_t, void *, size_t);
-
-extern int inet_pdu_encode(inet_packet_t *, size_t, size_t, void **,
-    size_t *, size_t *);
-extern int inet_pdu_decode(void *, size_t, inet_packet_t *);
-
-#endif
-
-/** @}
- */
Index: uspace/srv/inet/reass.c
===================================================================
--- uspace/srv/inet/reass.c	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(revision )
@@ -1,374 +1,0 @@
-/*
- * Copyright (c) 2012 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup inet
- * @{
- */
-/**
- * @file
- * @brief Datagram reassembly.
- */
-
-#include <errno.h>
-#include <fibril_synch.h>
-#include <io/log.h>
-#include <macros.h>
-#include <mem.h>
-#include <stdlib.h>
-
-#include "inet.h"
-#include "inet_std.h"
-#include "reass.h"
-
-/** Datagram being reassembled.
- *
- * Uniquely identified by (source address, destination address, protocol,
- * identification) per RFC 791 sec. 2.3 / Fragmentation.
- */
-typedef struct {
-	link_t map_link;
-	/** List of fragments, @c reass_frag_t */
-	list_t frags;
-} reass_dgram_t;
-
-/** One datagram fragment */
-typedef struct {
-	link_t dgram_link;
-	inet_packet_t packet;
-} reass_frag_t;
-
-/** Datagram map, list of reass_dgram_t */
-static LIST_INITIALIZE(reass_dgram_map);
-/** Protects access to @c reass_dgram_map */
-static FIBRIL_MUTEX_INITIALIZE(reass_dgram_map_lock);
-
-static reass_dgram_t *reass_dgram_new(void);
-static reass_dgram_t *reass_dgram_get(inet_packet_t *);
-static int reass_dgram_insert_frag(reass_dgram_t *, inet_packet_t *);
-static bool reass_dgram_complete(reass_dgram_t *);
-static void reass_dgram_remove(reass_dgram_t *);
-static int reass_dgram_deliver(reass_dgram_t *);
-static void reass_dgram_destroy(reass_dgram_t *);
-
-/** Queue packet for datagram reassembly.
- *
- * @param packet	Packet
- * @return		EOK on success or ENOMEM.
- */
-int inet_reass_queue_packet(inet_packet_t *packet)
-{
-	reass_dgram_t *rdg;
-	int rc;
-
-	log_msg(LVL_DEBUG, "inet_reass_queue_packet()");
-
-	fibril_mutex_lock(&reass_dgram_map_lock);
-
-	/* Get existing or new datagram */
-	rdg = reass_dgram_get(packet);
-	if (rdg == NULL) {
-		/* Only happens when we are out of memory */
-		fibril_mutex_unlock(&reass_dgram_map_lock);
-		log_msg(LVL_DEBUG, "Allocation failed, packet dropped.");
-		return ENOMEM;
-	}
-
-	/* Insert fragment into the datagram */
-	rc = reass_dgram_insert_frag(rdg, packet);
-	if (rc != EOK)
-		return ENOMEM;
-
-	/* Check if datagram is complete */
-	if (reass_dgram_complete(rdg)) {
-		/* Remove it from the map */
-		reass_dgram_remove(rdg);
-		fibril_mutex_unlock(&reass_dgram_map_lock);
-
-		/* Deliver complete datagram */
-		rc = reass_dgram_deliver(rdg);
-		reass_dgram_destroy(rdg);
-		return rc;
-	}
-
-	fibril_mutex_unlock(&reass_dgram_map_lock);
-	return EOK;
-}
-
-/** Get datagram reassembly structure for packet.
- *
- * @param packet	Packet
- * @return		Datagram reassembly structure matching @a packet
- */
-static reass_dgram_t *reass_dgram_get(inet_packet_t *packet)
-{
-	assert(fibril_mutex_is_locked(&reass_dgram_map_lock));
-
-	list_foreach(reass_dgram_map, link) {
-		reass_dgram_t *rdg = list_get_instance(link, reass_dgram_t,
-		    map_link);
-
-		link_t *f1_link = list_first(&rdg->frags);
-		assert(f1_link != NULL);
-
-		reass_frag_t *f1 = list_get_instance(f1_link, reass_frag_t,
-		    dgram_link);
-
-		if (f1->packet.src.ipv4 == packet->src.ipv4 &&
-		    f1->packet.dest.ipv4 == packet->dest.ipv4 &&
-		    f1->packet.proto == packet->proto &&
-		    f1->packet.ident == packet->ident) {
-			/* Match */
-			return rdg;
-		}
-	}
-
-	/* No existing reassembly structure. Create a new one. */
-	return reass_dgram_new();
-}
-
-/** Create new datagram reassembly structure.
- *
- * @return New datagram reassembly structure.
- */
-static reass_dgram_t *reass_dgram_new(void)
-{
-	reass_dgram_t *rdg;
-
-	rdg = calloc(1, sizeof(reass_dgram_t));
-	if (rdg == NULL)
-		return NULL;
-
-	link_initialize(&rdg->map_link);
-	list_initialize(&rdg->frags);
-
-	return rdg;
-}
-
-static reass_frag_t *reass_frag_new(void)
-{
-	reass_frag_t *frag;
-
-	frag = calloc(1, sizeof(reass_frag_t));
-	if (frag == NULL)
-		return NULL;
-
-	link_initialize(&frag->dgram_link);
-
-	return frag;
-}
-
-static int reass_dgram_insert_frag(reass_dgram_t *rdg, inet_packet_t *packet)
-{
-	reass_frag_t *frag;
-	void *data_copy;
-	link_t *link;
-
-	assert(fibril_mutex_is_locked(&reass_dgram_map_lock));
-
-	frag = reass_frag_new();
-
-	/* Clone the packet */
-
-	data_copy = malloc(packet->size);
-	if (data_copy == NULL)
-		return ENOMEM;
-
-	frag->packet = *packet;
-	frag->packet.data = data_copy;
-
-	/*
-	 * XXX Make resource-consuming attacks harder, eliminate any duplicate
-	 * data immediately. Possibly eliminate redundant packet headers.
-	 */
-
-	/*
-	 * Insert into the list, which is sorted by offs member ascending.
-	 */
-
-	link = list_first(&rdg->frags);
-	while (link != NULL) {
-		reass_frag_t *qf = list_get_instance(link, reass_frag_t,
-		    dgram_link);
-
-		if (qf->packet.offs >= packet->offs)
-			break;
-
-		link = link->next;
-	}
-
-	if (link != NULL)
-		list_insert_after(&frag->dgram_link, link);
-	else
-		list_append(&frag->dgram_link, &rdg->frags);
-
-	return EOK;
-}
-
-/** Check if datagram is complete.
- *
- * @param rdg		Datagram reassembly structure
- * @return		@c true if complete, @c false if not
- */
-static bool reass_dgram_complete(reass_dgram_t *rdg)
-{
-	reass_frag_t *frag, *prev;
-	link_t *link;
-
-	assert(fibril_mutex_is_locked(&reass_dgram_map_lock));
-	assert(!list_empty(&rdg->frags));
-
-	/* First fragment must be at offset zero */
-	frag = list_get_instance(list_first(&rdg->frags), reass_frag_t,
-	    dgram_link);
-	if (frag->packet.offs != 0)
-		return false;
-
-	prev = frag;
-	while (true) {
-		link = frag->dgram_link.next;
-		if (link == NULL)
-			return false;
-
-		/* Each next fragment must follow immediately or overlap */
-		frag = list_get_instance(link, reass_frag_t, dgram_link);
-		if (frag->packet.offs > prev->packet.offs + prev->packet.size)
-			return false;
-
-		/* No more fragments - datagram is complete */
-		if (!frag->packet.mf)
-			return true;
-
-		prev = frag;
-	}
-
-	return false;
-}
-
-/** Remove datagram from reassembly map.
- *
- * @param rdg		Datagram reassembly structure
- */
-static void reass_dgram_remove(reass_dgram_t *rdg)
-{
-	assert(fibril_mutex_is_locked(&reass_dgram_map_lock));
-	list_remove(&rdg->map_link);
-}
-
-/** Deliver complete datagram.
- *
- * @param rdg		Datagram reassembly structure.
- */
-static int reass_dgram_deliver(reass_dgram_t *rdg)
-{
-	size_t dgram_size;
-	size_t fragoff_limit;
-	inet_dgram_t dgram;
-	reass_frag_t *frag;
-	uint8_t proto;
-
-	/*
-	 * Potentially there could be something beyond the first packet
-	 * that has !MF. Make sure we ignore that.
-	 */
-	frag = NULL;
-	list_foreach(rdg->frags, link) {
-		frag = list_get_instance(link, reass_frag_t, dgram_link);
-
-		if (!frag->packet.mf)
-			break;
-	}
-
-	assert(frag != NULL);
-	assert(!frag->packet.mf);
-
-	dgram_size = frag->packet.offs + frag->packet.size;
-
-	/* Upper bound for fragment offset field */
-	fragoff_limit = 1 << (FF_FRAGOFF_h - FF_FRAGOFF_l);
-
-	/* Verify that total size of datagram is within reasonable bounds */
-	if (dgram_size > FRAG_OFFS_UNIT * fragoff_limit)
-		return ELIMIT;
-
-	dgram.data = calloc(dgram_size, 1);
-	if (dgram.data == NULL)
-		return ENOMEM;
-
-	dgram.size = dgram_size;
-	dgram.src = frag->packet.src;
-	dgram.dest = frag->packet.dest;
-	dgram.tos = frag->packet.tos;
-	proto = frag->packet.proto;
-
-	/* Pull together data from individual fragments */
-
-	size_t doffs = 0;
-
-	frag = NULL;
-	list_foreach(rdg->frags, link) {
-		frag = list_get_instance(link, reass_frag_t, dgram_link);
-
-		size_t cb, ce;
-
-		cb = max(doffs, frag->packet.offs);
-		ce = min(dgram_size, frag->packet.offs + frag->packet.size);
-
-		if (ce > cb) {
-			memcpy(dgram.data + cb,
-			    frag->packet.data + cb - frag->packet.offs,
-			    ce - cb);
-		}
-
-		if (!frag->packet.mf)
-			break;
-	}
-
-	return inet_recv_dgram_local(&dgram, proto);
-}
-
-/** Destroy datagram reassembly structure.
- *
- * @param rdg		Datagram reassembly structure.
- */
-static void reass_dgram_destroy(reass_dgram_t *rdg)
-{
-	while (!list_empty(&rdg->frags)) {
-		link_t *flink = list_first(&rdg->frags);
-		reass_frag_t *frag = list_get_instance(flink, reass_frag_t,
-		    dgram_link);
-
-		list_remove(&frag->dgram_link);
-		free(frag->packet.data);
-		free(frag);
-	}
-
-	free(rdg);
-}
-
-/** @}
- */
Index: uspace/srv/inet/reass.h
===================================================================
--- uspace/srv/inet/reass.h	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(revision )
@@ -1,48 +1,0 @@
-/*
- * Copyright (c) 2012 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup inet
- * @{
- */
-/**
- * @file
- * @brief
- */
-
-#ifndef INET_REASS_H_
-#define INET_REASS_H_
-
-#include <sys/types.h>
-#include "inet.h"
-
-extern int inet_reass_queue_packet(inet_packet_t *);
-
-#endif
-
-/** @}
- */
Index: uspace/srv/inet/sroute.c
===================================================================
--- uspace/srv/inet/sroute.c	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(revision )
@@ -1,219 +1,0 @@
-/*
- * Copyright (c) 2012 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup inet
- * @{
- */
-/**
- * @file
- * @brief
- */
-
-#include <bitops.h>
-#include <errno.h>
-#include <fibril_synch.h>
-#include <io/log.h>
-#include <ipc/loc.h>
-#include <stdlib.h>
-#include <str.h>
-
-#include "sroute.h"
-#include "inet.h"
-#include "inet_link.h"
-#include "inet_util.h"
-
-static FIBRIL_MUTEX_INITIALIZE(sroute_list_lock);
-static LIST_INITIALIZE(sroute_list);
-static sysarg_t sroute_id = 0;
-
-inet_sroute_t *inet_sroute_new(void)
-{
-	inet_sroute_t *sroute = calloc(1, sizeof(inet_sroute_t));
-
-	if (sroute == NULL) {
-		log_msg(LVL_ERROR, "Failed allocating static route object. "
-		    "Out of memory.");
-		return NULL;
-	}
-
-	link_initialize(&sroute->sroute_list);
-	fibril_mutex_lock(&sroute_list_lock);
-	sroute->id = ++sroute_id;
-	fibril_mutex_unlock(&sroute_list_lock);
-
-	return sroute;
-}
-
-void inet_sroute_delete(inet_sroute_t *sroute)
-{
-	if (sroute->name != NULL)
-		free(sroute->name);
-	free(sroute);
-}
-
-void inet_sroute_add(inet_sroute_t *sroute)
-{
-	fibril_mutex_lock(&sroute_list_lock);
-	list_append(&sroute->sroute_list, &sroute_list);
-	fibril_mutex_unlock(&sroute_list_lock);
-}
-
-void inet_sroute_remove(inet_sroute_t *sroute)
-{
-	fibril_mutex_lock(&sroute_list_lock);
-	list_remove(&sroute->sroute_list);
-	fibril_mutex_unlock(&sroute_list_lock);
-}
-
-/** Find address object matching address @a addr.
- *
- * @param addr	Address
- */
-inet_sroute_t *inet_sroute_find(inet_addr_t *addr)
-{
-	uint32_t mask;
-	inet_sroute_t *best;
-
-	log_msg(LVL_DEBUG, "inet_sroute_find(%x)", (unsigned)addr->ipv4);
-
-	fibril_mutex_lock(&sroute_list_lock);
-
-	best = NULL;
-
-	list_foreach(sroute_list, link) {
-		inet_sroute_t *sroute = list_get_instance(link,
-		    inet_sroute_t, sroute_list);
-
-		/* Look for the most specific route */
-		if (best != NULL && best->dest.bits >= sroute->dest.bits)
-			continue;
-
-		mask = inet_netmask(sroute->dest.bits);
-		if ((sroute->dest.ipv4 & mask) == (addr->ipv4 & mask)) {
-			fibril_mutex_unlock(&sroute_list_lock);
-			log_msg(LVL_DEBUG, "inet_sroute_find: found %p",
-			    sroute);
-			return sroute;
-		}
-	}
-
-	log_msg(LVL_DEBUG, "inet_sroute_find: Not found");
-	fibril_mutex_unlock(&sroute_list_lock);
-
-	return NULL;
-}
-
-/** Find static route with a specific name.
- *
- * @param name	Address object name
- * @return	Address object
- */
-inet_sroute_t *inet_sroute_find_by_name(const char *name)
-{
-	log_msg(LVL_DEBUG, "inet_sroute_find_by_name('%s')",
-	    name);
-
-	fibril_mutex_lock(&sroute_list_lock);
-
-	list_foreach(sroute_list, link) {
-		inet_sroute_t *sroute = list_get_instance(link,
-		    inet_sroute_t, sroute_list);
-
-		if (str_cmp(sroute->name, name) == 0) {
-			fibril_mutex_unlock(&sroute_list_lock);
-			log_msg(LVL_DEBUG, "inet_sroute_find_by_name: found %p",
-			    sroute);
-			return sroute;
-		}
-	}
-
-	log_msg(LVL_DEBUG, "inet_sroute_find_by_name: Not found");
-	fibril_mutex_unlock(&sroute_list_lock);
-
-	return NULL;
-}
-
-/** Find static route with the given ID.
- *
- * @param id	Address object ID
- * @return	Address object
- */
-inet_sroute_t *inet_sroute_get_by_id(sysarg_t id)
-{
-	log_msg(LVL_DEBUG, "inet_sroute_get_by_id(%zu)", (size_t)id);
-
-	fibril_mutex_lock(&sroute_list_lock);
-
-	list_foreach(sroute_list, link) {
-		inet_sroute_t *sroute = list_get_instance(link,
-		    inet_sroute_t, sroute_list);
-
-		if (sroute->id == id) {
-			fibril_mutex_unlock(&sroute_list_lock);
-			return sroute;
-		}
-	}
-
-	fibril_mutex_unlock(&sroute_list_lock);
-
-	return NULL;
-}
-
-/** Get IDs of all static routes. */
-int inet_sroute_get_id_list(sysarg_t **rid_list, size_t *rcount)
-{
-	sysarg_t *id_list;
-	size_t count, i;
-
-	fibril_mutex_lock(&sroute_list_lock);
-	count = list_count(&sroute_list);
-
-	id_list = calloc(count, sizeof(sysarg_t));
-	if (id_list == NULL) {
-		fibril_mutex_unlock(&sroute_list_lock);
-		return ENOMEM;
-	}
-
-	i = 0;
-	list_foreach(sroute_list, link) {
-		inet_sroute_t *sroute = list_get_instance(link,
-		    inet_sroute_t, sroute_list);
-
-		id_list[i++] = sroute->id;
-	}
-
-	fibril_mutex_unlock(&sroute_list_lock);
-
-	*rid_list = id_list;
-	*rcount = count;
-
-	return EOK;
-}
-
-/** @}
- */
Index: uspace/srv/inet/sroute.h
===================================================================
--- uspace/srv/inet/sroute.h	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(revision )
@@ -1,58 +1,0 @@
-/*
- * Copyright (c) 2012 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup inet
- * @{
- */
-/**
- * @file
- * @brief
- */
-
-#ifndef INET_SROUTE_H_
-#define INET_SROUTE_H_
-
-#include <sys/types.h>
-#include "inet.h"
-
-extern inet_sroute_t *inet_sroute_new(void);
-extern void inet_sroute_delete(inet_sroute_t *);
-extern void inet_sroute_add(inet_sroute_t *);
-extern void inet_sroute_remove(inet_sroute_t *);
-extern inet_sroute_t *inet_sroute_find(inet_addr_t *);
-extern inet_sroute_t *inet_sroute_find_by_name(const char *);
-extern inet_sroute_t *inet_sroute_get_by_id(sysarg_t);
-extern int inet_sroute_send_dgram(inet_sroute_t *, inet_addr_t *,
-    inet_dgram_t *, uint8_t, uint8_t, int);
-extern int inet_sroute_get_id_list(sysarg_t **, size_t *);
-
-
-#endif
-
-/** @}
- */
Index: uspace/srv/net/ethip/Makefile
===================================================================
--- uspace/srv/net/ethip/Makefile	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/ethip/Makefile	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,39 @@
+#
+# Copyright (c) 2012 Jiri Svoboda
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# - Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+# - Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in the
+#   documentation and/or other materials provided with the distribution.
+# - The name of the author may not be used to endorse or promote products
+#   derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+USPACE_PREFIX = ../../..
+BINARY = ethip
+
+SOURCES = \
+	arp.c \
+	atrans.c \
+	ethip.c \
+	ethip_nic.c \
+	pdu.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/net/ethip/arp.c
===================================================================
--- uspace/srv/net/ethip/arp.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/ethip/arp.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2012 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup inet
+ * @{
+ */
+/**
+ * @file
+ * @brief
+ */
+
+#include <errno.h>
+#include <io/log.h>
+#include <inet/iplink_srv.h>
+#include <stdlib.h>
+
+#include "arp.h"
+#include "atrans.h"
+#include "ethip.h"
+#include "ethip_nic.h"
+#include "pdu.h"
+#include "std.h"
+
+/** Time to wait for ARP reply in microseconds */
+#define ARP_REQUEST_TIMEOUT (3 * 1000 * 1000)
+
+static int arp_send_packet(ethip_nic_t *nic, arp_eth_packet_t *packet);
+
+void arp_received(ethip_nic_t *nic, eth_frame_t *frame)
+{
+	int rc;
+	arp_eth_packet_t packet;
+	arp_eth_packet_t reply;
+	ethip_link_addr_t *laddr;
+
+	log_msg(LVL_DEBUG, "arp_received()");
+
+	rc = arp_pdu_decode(frame->data, frame->size, &packet);
+	if (rc != EOK)
+		return;
+
+	log_msg(LVL_DEBUG, "ARP PDU decoded, opcode=%d, tpa=%x",
+	    packet.opcode, packet.target_proto_addr.ipv4);
+
+	laddr = ethip_nic_addr_find(nic, &packet.target_proto_addr);
+	if (laddr != NULL) {
+		log_msg(LVL_DEBUG, "Request/reply to my address");
+
+		(void) atrans_add(&packet.sender_proto_addr,
+		    &packet.sender_hw_addr);
+
+		if (packet.opcode == aop_request) {
+        		reply.opcode = aop_reply;
+        		reply.sender_hw_addr = nic->mac_addr;
+			reply.sender_proto_addr = laddr->addr;
+			reply.target_hw_addr = packet.sender_hw_addr;
+			reply.target_proto_addr = packet.sender_proto_addr;
+
+			arp_send_packet(nic, &reply);
+		}
+	}
+}
+
+int arp_translate(ethip_nic_t *nic, iplink_srv_addr_t *src_addr,
+    iplink_srv_addr_t *ip_addr, mac48_addr_t *mac_addr)
+{
+	int rc;
+	arp_eth_packet_t packet;
+
+	rc = atrans_lookup(ip_addr, mac_addr);
+	if (rc == EOK)
+		return EOK;
+
+	packet.opcode = aop_request;
+	packet.sender_hw_addr = nic->mac_addr;
+	packet.sender_proto_addr = *src_addr;
+	packet.target_hw_addr.addr = MAC48_BROADCAST;
+	packet.target_proto_addr = *ip_addr;
+
+	rc = arp_send_packet(nic, &packet);
+	if (rc != EOK)
+		return rc;
+
+	(void) atrans_wait_timeout(ARP_REQUEST_TIMEOUT);
+
+	return atrans_lookup(ip_addr, mac_addr);
+}
+
+static int arp_send_packet(ethip_nic_t *nic, arp_eth_packet_t *packet)
+{
+	int rc;
+	void *pdata;
+	size_t psize;
+
+	eth_frame_t frame;
+	void *fdata;
+	size_t fsize;
+
+	log_msg(LVL_DEBUG, "arp_send_packet()");
+
+	rc = arp_pdu_encode(packet, &pdata, &psize);
+	if (rc != EOK)
+		return rc;
+
+	frame.dest.addr = packet->target_hw_addr.addr;
+	frame.src.addr =  packet->sender_hw_addr.addr;
+	frame.etype_len = ETYPE_ARP;
+	frame.data = pdata;
+	frame.size = psize;
+
+	rc = eth_pdu_encode(&frame, &fdata, &fsize);
+	if (rc != EOK) {
+		free(pdata);
+		return rc;
+	}
+
+	rc = ethip_nic_send(nic, fdata, fsize);
+	free(fdata);
+	free(pdata);
+
+	return rc;
+
+}
+
+/** @}
+ */
Index: uspace/srv/net/ethip/arp.h
===================================================================
--- uspace/srv/net/ethip/arp.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/ethip/arp.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2012 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup inet
+ * @{
+ */
+/**
+ * @file
+ * @brief
+ */
+
+#ifndef ARP_H_
+#define ARP_H_
+
+#include <inet/iplink_srv.h>
+#include "ethip.h"
+
+extern void arp_received(ethip_nic_t *, eth_frame_t *);
+extern int arp_translate(ethip_nic_t *, iplink_srv_addr_t *,
+    iplink_srv_addr_t *, mac48_addr_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/ethip/atrans.c
===================================================================
--- uspace/srv/net/ethip/atrans.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/ethip/atrans.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2012 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup inet
+ * @{
+ */
+/**
+ * @file
+ * @brief
+ */
+
+#include <adt/list.h>
+#include <errno.h>
+#include <fibril_synch.h>
+#include <inet/iplink_srv.h>
+#include <stdlib.h>
+
+#include "atrans.h"
+#include "ethip.h"
+
+/** Address translation list (of ethip_atrans_t) */
+static FIBRIL_MUTEX_INITIALIZE(atrans_list_lock);
+static LIST_INITIALIZE(atrans_list);
+static FIBRIL_CONDVAR_INITIALIZE(atrans_cv);
+
+static ethip_atrans_t *atrans_find(iplink_srv_addr_t *ip_addr)
+{
+	list_foreach(atrans_list, link) {
+		ethip_atrans_t *atrans = list_get_instance(link,
+		    ethip_atrans_t, atrans_list);
+
+		if (atrans->ip_addr.ipv4 == ip_addr->ipv4)
+			return atrans;
+	}
+
+	return NULL;
+}
+
+int atrans_add(iplink_srv_addr_t *ip_addr, mac48_addr_t *mac_addr)
+{
+	ethip_atrans_t *atrans;
+	ethip_atrans_t *prev;
+
+	atrans = calloc(1, sizeof(ethip_atrans_t));
+	if (atrans == NULL)
+		return ENOMEM;
+
+	atrans->ip_addr = *ip_addr;
+	atrans->mac_addr = *mac_addr;
+
+	fibril_mutex_lock(&atrans_list_lock);
+	prev = atrans_find(ip_addr);
+	if (prev != NULL) {
+		list_remove(&prev->atrans_list);
+		free(prev);
+	}
+
+	list_append(&atrans->atrans_list, &atrans_list);
+	fibril_mutex_unlock(&atrans_list_lock);
+	fibril_condvar_broadcast(&atrans_cv);
+
+	return EOK;
+}
+
+int atrans_remove(iplink_srv_addr_t *ip_addr)
+{
+	ethip_atrans_t *atrans;
+
+	fibril_mutex_lock(&atrans_list_lock);
+	atrans = atrans_find(ip_addr);
+	if (atrans == NULL) {
+		fibril_mutex_unlock(&atrans_list_lock);
+		return ENOENT;
+	}
+
+	list_remove(&atrans->atrans_list);
+	fibril_mutex_unlock(&atrans_list_lock);
+	free(atrans);
+
+	return EOK;
+}
+
+int atrans_lookup(iplink_srv_addr_t *ip_addr, mac48_addr_t *mac_addr)
+{
+	ethip_atrans_t *atrans;
+
+	fibril_mutex_lock(&atrans_list_lock);
+	atrans = atrans_find(ip_addr);
+	if (atrans == NULL) {
+		fibril_mutex_unlock(&atrans_list_lock);
+		return ENOENT;
+	}
+
+	fibril_mutex_unlock(&atrans_list_lock);
+	*mac_addr = atrans->mac_addr;
+	return EOK;
+}
+
+int atrans_wait_timeout(suseconds_t timeout)
+{
+	int rc;
+
+	fibril_mutex_lock(&atrans_list_lock);
+	rc = fibril_condvar_wait_timeout(&atrans_cv, &atrans_list_lock,
+	    timeout);
+	fibril_mutex_unlock(&atrans_list_lock);
+
+	return rc;
+}
+
+/** @}
+ */
Index: uspace/srv/net/ethip/atrans.h
===================================================================
--- uspace/srv/net/ethip/atrans.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/ethip/atrans.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2012 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup inet
+ * @{
+ */
+/**
+ * @file
+ * @brief
+ */
+
+#ifndef ATRANS_H_
+#define ATRANS_H_
+
+#include <inet/iplink_srv.h>
+#include "ethip.h"
+
+extern int atrans_add(iplink_srv_addr_t *, mac48_addr_t *);
+extern int atrans_remove(iplink_srv_addr_t *);
+extern int atrans_lookup(iplink_srv_addr_t *, mac48_addr_t *);
+extern int atrans_wait_timeout(suseconds_t);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/ethip/ethip.c
===================================================================
--- uspace/srv/net/ethip/ethip.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/ethip/ethip.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,288 @@
+/*
+ * Copyright (c) 2012 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup ethip
+ * @{
+ */
+/**
+ * @file
+ * @brief IP link provider for Ethernet
+ *
+ * Based on the IETF RFC 894 standard.
+ */
+
+#include <async.h>
+#include <errno.h>
+#include <inet/iplink_srv.h>
+#include <io/log.h>
+#include <loc.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "arp.h"
+#include "ethip.h"
+#include "ethip_nic.h"
+#include "pdu.h"
+#include "std.h"
+
+#define NAME "eth"
+
+static int ethip_open(iplink_srv_t *srv);
+static int ethip_close(iplink_srv_t *srv);
+static int ethip_send(iplink_srv_t *srv, iplink_srv_sdu_t *sdu);
+static int ethip_get_mtu(iplink_srv_t *srv, size_t *mtu);
+static int ethip_addr_add(iplink_srv_t *srv, iplink_srv_addr_t *addr);
+static int ethip_addr_remove(iplink_srv_t *srv, iplink_srv_addr_t *addr);
+
+static void ethip_client_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg);
+
+static iplink_ops_t ethip_iplink_ops = {
+	.open = ethip_open,
+	.close = ethip_close,
+	.send = ethip_send,
+	.get_mtu = ethip_get_mtu,
+	.addr_add = ethip_addr_add,
+	.addr_remove = ethip_addr_remove
+};
+
+static int ethip_init(void)
+{
+	int rc;
+
+	async_set_client_connection(ethip_client_conn);
+
+	rc = loc_server_register(NAME);
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Failed registering server.");
+		return rc;
+	}
+
+	rc = ethip_nic_discovery_start();
+	if (rc != EOK)
+		return rc;
+
+	return EOK;
+}
+
+int ethip_iplink_init(ethip_nic_t *nic)
+{
+	int rc;
+	service_id_t sid;
+	category_id_t iplink_cat;
+	static unsigned link_num = 0;
+	char *svc_name = NULL;
+
+	log_msg(LVL_DEBUG, "ethip_iplink_init()");
+
+	iplink_srv_init(&nic->iplink);
+	nic->iplink.ops = &ethip_iplink_ops;
+	nic->iplink.arg = nic;
+
+	rc = asprintf(&svc_name, "net/eth%u", ++link_num);
+	if (rc < 0) {
+		log_msg(LVL_ERROR, "Out of memory.");
+		goto error;
+	}
+
+	rc = loc_service_register(svc_name, &sid);
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Failed registering service %s.", svc_name);
+		goto error;
+	}
+
+	nic->iplink_sid = sid;
+
+	rc = loc_category_get_id("iplink", &iplink_cat, IPC_FLAG_BLOCKING);
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Failed resolving category 'iplink'.");
+		goto error;
+	}
+
+	rc = loc_service_add_to_cat(sid, iplink_cat);
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Failed adding %s to category.", svc_name);
+		goto error;
+	}
+
+	return EOK;
+
+error:
+	if (svc_name != NULL)
+		free(svc_name);
+	return rc;
+}
+
+static void ethip_client_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	ethip_nic_t *nic;
+	service_id_t sid;
+
+	sid = (service_id_t)IPC_GET_ARG1(*icall);
+	log_msg(LVL_DEBUG, "ethip_client_conn(%u)", (unsigned)sid);
+	nic = ethip_nic_find_by_iplink_sid(sid);
+	if (nic == NULL) {
+		log_msg(LVL_WARN, "Uknown service ID.");
+		return;
+	}
+
+	iplink_conn(iid, icall, &nic->iplink);
+}
+
+static int ethip_open(iplink_srv_t *srv)
+{
+	log_msg(LVL_DEBUG, "ethip_open()");
+	return EOK;
+}
+
+static int ethip_close(iplink_srv_t *srv)
+{
+	log_msg(LVL_DEBUG, "ethip_close()");
+	return EOK;
+}
+
+static int ethip_send(iplink_srv_t *srv, iplink_srv_sdu_t *sdu)
+{
+	ethip_nic_t *nic = (ethip_nic_t *)srv->arg;
+	eth_frame_t frame;
+	void *data;
+	size_t size;
+	mac48_addr_t dest_mac_addr;
+	int rc;
+
+	log_msg(LVL_DEBUG, "ethip_send()");
+
+	rc = arp_translate(nic, &sdu->lsrc, &sdu->ldest, &dest_mac_addr);
+	if (rc != EOK) {
+		log_msg(LVL_WARN, "Failed to look up IP address 0x%" PRIx32,
+		    sdu->ldest.ipv4);
+		return rc;
+	}
+
+	frame.dest      = dest_mac_addr;
+	frame.src       = nic->mac_addr;
+	frame.etype_len = ETYPE_IP;
+	frame.data = sdu->data;
+	frame.size = sdu->size;
+
+	rc = eth_pdu_encode(&frame, &data, &size);
+	if (rc != EOK)
+		return rc;
+
+	rc = ethip_nic_send(nic, data, size);
+	free(data);
+
+	return rc;
+}
+
+int ethip_received(iplink_srv_t *srv, void *data, size_t size)
+{
+	log_msg(LVL_DEBUG, "ethip_received(): srv=%p", srv);
+	ethip_nic_t *nic = (ethip_nic_t *)srv->arg;
+	eth_frame_t frame;
+	iplink_srv_sdu_t sdu;
+	int rc;
+
+	log_msg(LVL_DEBUG, "ethip_received()");
+
+	log_msg(LVL_DEBUG, " - eth_pdu_decode");
+	rc = eth_pdu_decode(data, size, &frame);
+	if (rc != EOK) {
+		log_msg(LVL_DEBUG, " - eth_pdu_decode failed");
+		return rc;
+	}
+
+	switch (frame.etype_len) {
+	case ETYPE_ARP:
+		arp_received(nic, &frame);
+		break;
+	case ETYPE_IP:
+		log_msg(LVL_DEBUG, " - construct SDU");
+		sdu.lsrc.ipv4 = (192 << 24) | (168 << 16) | (0 << 8) | 1;
+		sdu.ldest.ipv4 = (192 << 24) | (168 << 16) | (0 << 8) | 4;
+		sdu.data = frame.data;
+		sdu.size = frame.size;
+		log_msg(LVL_DEBUG, " - call iplink_ev_recv");
+		rc = iplink_ev_recv(&nic->iplink, &sdu);
+		break;
+	default:
+		log_msg(LVL_DEBUG, "Unknown ethertype 0x%" PRIx16,
+		    frame.etype_len);
+	}
+
+	free(frame.data);
+	return rc;
+}
+
+static int ethip_get_mtu(iplink_srv_t *srv, size_t *mtu)
+{
+	log_msg(LVL_DEBUG, "ethip_get_mtu()");
+	*mtu = 1500;
+	return EOK;
+}
+
+static int ethip_addr_add(iplink_srv_t *srv, iplink_srv_addr_t *addr)
+{
+	ethip_nic_t *nic = (ethip_nic_t *)srv->arg;
+
+	log_msg(LVL_DEBUG, "ethip_addr_add(0x%" PRIx32 ")", addr->ipv4);
+	return ethip_nic_addr_add(nic, addr);
+}
+
+static int ethip_addr_remove(iplink_srv_t *srv, iplink_srv_addr_t *addr)
+{
+	ethip_nic_t *nic = (ethip_nic_t *)srv->arg;
+
+	log_msg(LVL_DEBUG, "ethip_addr_remove(0x%" PRIx32 ")", addr->ipv4);
+	return ethip_nic_addr_add(nic, addr);
+}
+
+int main(int argc, char *argv[])
+{
+	int rc;
+
+	printf(NAME ": HelenOS IP over Ethernet service\n");
+
+	if (log_init(NAME, LVL_DEBUG) != EOK) {
+		printf(NAME ": Failed to initialize logging.\n");
+		return 1;
+	}
+
+	rc = ethip_init();
+	if (rc != EOK)
+		return 1;
+
+	printf(NAME ": Accepting connections.\n");
+	task_retval(0);
+	async_manager();
+
+	/* Not reached */
+	return 0;
+}
+
+/** @}
+ */
Index: uspace/srv/net/ethip/ethip.h
===================================================================
--- uspace/srv/net/ethip/ethip.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/ethip/ethip.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2012 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup ethip
+ * @{
+ */
+/**
+ * @file
+ * @brief
+ */
+
+#ifndef ETHIP_H_
+#define ETHIP_H_
+
+#include <adt/list.h>
+#include <async.h>
+#include <inet/iplink_srv.h>
+#include <loc.h>
+#include <sys/types.h>
+
+#define MAC48_BROADCAST 0xffffffffffff
+
+typedef struct {
+	link_t addr_list;
+	iplink_srv_addr_t addr;
+} ethip_link_addr_t;
+
+/** IEEE MAC-48 identifier */
+typedef struct {
+	/** MAC Address (in lowest 48 bits) */
+	uint64_t addr;
+} mac48_addr_t;
+
+typedef struct ethip_nic {
+	link_t nic_list;
+	service_id_t svc_id;
+	char *svc_name;
+	async_sess_t *sess;
+
+	iplink_srv_t iplink;
+	service_id_t iplink_sid;
+
+	/** MAC address */
+	mac48_addr_t mac_addr;
+	/** List of IP addresses configured on this link */
+	list_t addr_list; /* of ethip_link_addr_t */
+} ethip_nic_t;
+
+/** Ethernet frame */
+typedef struct {
+	/** Destination Address */
+	mac48_addr_t dest;
+	/** Source Address */
+	mac48_addr_t src;
+	/** Ethertype or Length */
+	uint16_t etype_len;
+	/** Payload */
+	void *data;
+	/** Payload size */
+	size_t size;
+} eth_frame_t;
+
+/** ARP opcode */
+typedef enum {
+	/** Request */
+	aop_request,
+	/** Reply */
+	aop_reply
+} arp_opcode_t;
+
+/** ARP packet (for 48-bit MAC addresses and IPv4)
+ *
+ * Internal representation
+ */
+typedef struct {
+	/** Opcode */
+	arp_opcode_t opcode;
+	/** Sender hardware address */
+	mac48_addr_t sender_hw_addr;
+	/** Sender protocol address */
+	iplink_srv_addr_t sender_proto_addr;
+	/** Target hardware address */
+	mac48_addr_t target_hw_addr;
+	/** Target protocol address */
+	iplink_srv_addr_t target_proto_addr;
+} arp_eth_packet_t;
+
+/** Address translation table element */
+typedef struct {
+	link_t atrans_list;
+	iplink_srv_addr_t ip_addr;
+	mac48_addr_t mac_addr;
+} ethip_atrans_t;
+
+extern int ethip_iplink_init(ethip_nic_t *);
+extern int ethip_received(iplink_srv_t *, void *, size_t);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/ethip/ethip_nic.c
===================================================================
--- uspace/srv/net/ethip/ethip_nic.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/ethip/ethip_nic.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,391 @@
+/*
+ * Copyright (c) 2012 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup ethip
+ * @{
+ */
+/**
+ * @file
+ * @brief
+ */
+
+#include <adt/list.h>
+#include <async.h>
+#include <bool.h>
+#include <errno.h>
+#include <fibril_synch.h>
+#include <inet/iplink_srv.h>
+#include <io/log.h>
+#include <loc.h>
+#include <device/nic.h>
+#include <stdlib.h>
+
+#include "ethip.h"
+#include "ethip_nic.h"
+#include "pdu.h"
+
+static int ethip_nic_open(service_id_t sid);
+static void ethip_nic_cb_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg);
+
+static LIST_INITIALIZE(ethip_nic_list);
+static FIBRIL_MUTEX_INITIALIZE(ethip_discovery_lock);
+
+static int ethip_nic_check_new(void)
+{
+	bool already_known;
+	category_id_t iplink_cat;
+	service_id_t *svcs;
+	size_t count, i;
+	int rc;
+
+	fibril_mutex_lock(&ethip_discovery_lock);
+
+	rc = loc_category_get_id("nic", &iplink_cat, IPC_FLAG_BLOCKING);
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Failed resolving category 'nic'.");
+		fibril_mutex_unlock(&ethip_discovery_lock);
+		return ENOENT;
+	}
+
+	rc = loc_category_get_svcs(iplink_cat, &svcs, &count);
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Failed getting list of IP links.");
+		fibril_mutex_unlock(&ethip_discovery_lock);
+		return EIO;
+	}
+
+	for (i = 0; i < count; i++) {
+		already_known = false;
+
+		list_foreach(ethip_nic_list, nic_link) {
+			ethip_nic_t *nic = list_get_instance(nic_link,
+			    ethip_nic_t, nic_list);
+			if (nic->svc_id == svcs[i]) {
+				already_known = true;
+				break;
+			}
+		}
+
+		if (!already_known) {
+			log_msg(LVL_DEBUG, "Found NIC '%lu'",
+			    (unsigned long) svcs[i]);
+			rc = ethip_nic_open(svcs[i]);
+			if (rc != EOK)
+				log_msg(LVL_ERROR, "Could not open NIC.");
+		}
+	}
+
+	fibril_mutex_unlock(&ethip_discovery_lock);
+	return EOK;
+}
+
+static ethip_nic_t *ethip_nic_new(void)
+{
+	ethip_nic_t *nic = calloc(1, sizeof(ethip_nic_t));
+
+	if (nic == NULL) {
+		log_msg(LVL_ERROR, "Failed allocating NIC structure. "
+		    "Out of memory.");
+		return NULL;
+	}
+
+	link_initialize(&nic->nic_list);
+	list_initialize(&nic->addr_list);
+
+	return nic;
+}
+
+static ethip_link_addr_t *ethip_nic_addr_new(iplink_srv_addr_t *addr)
+{
+	ethip_link_addr_t *laddr = calloc(1, sizeof(ethip_link_addr_t));
+
+	if (laddr == NULL) {
+		log_msg(LVL_ERROR, "Failed allocating NIC address structure. "
+		    "Out of memory.");
+		return NULL;
+	}
+
+	link_initialize(&laddr->addr_list);
+	laddr->addr.ipv4 = addr->ipv4;
+	return laddr;
+}
+
+static void ethip_nic_delete(ethip_nic_t *nic)
+{
+	if (nic->svc_name != NULL)
+		free(nic->svc_name);
+	free(nic);
+}
+
+static void ethip_link_addr_delete(ethip_link_addr_t *laddr)
+{
+	free(laddr);
+}
+
+static int ethip_nic_open(service_id_t sid)
+{
+	ethip_nic_t *nic;
+	int rc;
+	bool in_list = false;
+	nic_address_t nic_address;
+
+	log_msg(LVL_DEBUG, "ethip_nic_open()");
+	nic = ethip_nic_new();
+	if (nic == NULL)
+		return ENOMEM;
+
+	rc = loc_service_get_name(sid, &nic->svc_name);
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Failed getting service name.");
+		goto error;
+	}
+
+	nic->sess = loc_service_connect(EXCHANGE_SERIALIZE, sid, 0);
+	if (nic->sess == NULL) {
+		log_msg(LVL_ERROR, "Failed connecting '%s'", nic->svc_name);
+		goto error;
+	}
+
+	nic->svc_id = sid;
+
+	rc = nic_callback_create(nic->sess, ethip_nic_cb_conn, nic);
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Failed creating callback connection "
+		    "from '%s'", nic->svc_name);
+		goto error;
+	}
+
+	log_msg(LVL_DEBUG, "Opened NIC '%s'", nic->svc_name);
+	list_append(&nic->nic_list, &ethip_nic_list);
+	in_list = true;
+
+	rc = ethip_iplink_init(nic);
+	if (rc != EOK)
+		goto error;
+
+	rc = nic_get_address(nic->sess, &nic_address);
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Error getting MAC address of NIC '%s'.",
+		    nic->svc_name);
+		goto error;
+	}
+
+	mac48_decode(nic_address.address, &nic->mac_addr);
+
+	rc = nic_set_state(nic->sess, NIC_STATE_ACTIVE);
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Error activating NIC '%s'.",
+		    nic->svc_name);
+		goto error;
+	}
+
+	log_msg(LVL_DEBUG, "Initialized IP link service, MAC = 0x%" PRIx64,
+	    nic->mac_addr.addr);
+
+	return EOK;
+
+error:
+	if (in_list)
+		list_remove(&nic->nic_list);
+	if (nic->sess != NULL)
+		async_hangup(nic->sess);
+	ethip_nic_delete(nic);
+	return rc;
+}
+
+static void ethip_nic_cat_change_cb(void)
+{
+	(void) ethip_nic_check_new();
+}
+
+static void ethip_nic_addr_changed(ethip_nic_t *nic, ipc_callid_t callid,
+    ipc_call_t *call)
+{
+	log_msg(LVL_DEBUG, "ethip_nic_addr_changed()");
+	async_answer_0(callid, ENOTSUP);
+}
+
+#include <stdio.h>
+static void ethip_nic_received(ethip_nic_t *nic, ipc_callid_t callid,
+    ipc_call_t *call)
+{
+	int rc;
+	void *data;
+	size_t size;
+
+	log_msg(LVL_DEBUG, "ethip_nic_received() nic=%p", nic);
+
+	rc = async_data_write_accept(&data, false, 0, 0, 0, &size);
+	if (rc != EOK) {
+		log_msg(LVL_DEBUG, "data_write_accept() failed");
+		return;
+	}
+
+	log_msg(LVL_DEBUG, "Ethernet PDU contents (%zu bytes)",
+	    size);
+	size_t i;
+	for (i = 0; i < size; i++)
+		printf("%02x ", ((uint8_t *)data)[i]);
+	printf("\n");
+
+	log_msg(LVL_DEBUG, "call ethip_received");
+	rc = ethip_received(&nic->iplink, data, size);
+	log_msg(LVL_DEBUG, "free data");
+	free(data);
+
+	log_msg(LVL_DEBUG, "ethip_nic_received() done, rc=%d", rc);
+	async_answer_0(callid, rc);
+}
+
+static void ethip_nic_device_state(ethip_nic_t *nic, ipc_callid_t callid,
+    ipc_call_t *call)
+{
+	log_msg(LVL_DEBUG, "ethip_nic_device_state()");
+	async_answer_0(callid, ENOTSUP);
+}
+
+static void ethip_nic_cb_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	ethip_nic_t *nic = (ethip_nic_t *)arg;
+
+	log_msg(LVL_DEBUG, "ethnip_nic_cb_conn()");
+
+	while (true) {
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+
+		if (!IPC_GET_IMETHOD(call)) {
+			/* TODO: Handle hangup */
+			return;
+		}
+
+		switch (IPC_GET_IMETHOD(call)) {
+		case NIC_EV_ADDR_CHANGED:
+			ethip_nic_addr_changed(nic, callid, &call);
+			break;
+		case NIC_EV_RECEIVED:
+			ethip_nic_received(nic, callid, &call);
+			break;
+		case NIC_EV_DEVICE_STATE:
+			ethip_nic_device_state(nic, callid, &call);
+			break;
+		default:
+			async_answer_0(callid, ENOTSUP);
+		}
+	}
+}
+
+int ethip_nic_discovery_start(void)
+{
+	int rc;
+
+	rc = loc_register_cat_change_cb(ethip_nic_cat_change_cb);
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Failed registering callback for NIC "
+		    "discovery (%d).", rc);
+		return rc;
+	}
+
+	return ethip_nic_check_new();
+}
+
+ethip_nic_t *ethip_nic_find_by_iplink_sid(service_id_t iplink_sid)
+{
+	log_msg(LVL_DEBUG, "ethip_nic_find_by_iplink_sid(%u)",
+	    (unsigned) iplink_sid);
+
+	list_foreach(ethip_nic_list, link) {
+		log_msg(LVL_DEBUG, "ethip_nic_find_by_iplink_sid - element");
+		ethip_nic_t *nic = list_get_instance(link, ethip_nic_t,
+		    nic_list);
+
+		if (nic->iplink_sid == iplink_sid) {
+			log_msg(LVL_DEBUG, "ethip_nic_find_by_iplink_sid - found %p", nic);
+			return nic;
+		}
+	}
+
+	log_msg(LVL_DEBUG, "ethip_nic_find_by_iplink_sid - not found");
+	return NULL;
+}
+
+int ethip_nic_send(ethip_nic_t *nic, void *data, size_t size)
+{
+	int rc;
+	log_msg(LVL_DEBUG, "ethip_nic_send(size=%zu)", size);
+	rc = nic_send_frame(nic->sess, data, size);
+	log_msg(LVL_DEBUG, "nic_send_frame -> %d", rc);
+	return rc;
+}
+
+int ethip_nic_addr_add(ethip_nic_t *nic, iplink_srv_addr_t *addr)
+{
+	ethip_link_addr_t *laddr;
+
+	log_msg(LVL_DEBUG, "ethip_nic_addr_add()");
+	laddr = ethip_nic_addr_new(addr);
+	if (laddr == NULL)
+		return ENOMEM;
+
+	list_append(&laddr->addr_list, &nic->addr_list);
+	return EOK;
+}
+
+int ethip_nic_addr_remove(ethip_nic_t *nic, iplink_srv_addr_t *addr)
+{
+	ethip_link_addr_t *laddr;
+
+	log_msg(LVL_DEBUG, "ethip_nic_addr_remove()");
+
+	laddr = ethip_nic_addr_find(nic, addr);
+	if (laddr == NULL)
+		return ENOENT;
+
+	list_remove(&laddr->addr_list);
+	ethip_link_addr_delete(laddr);
+	return EOK;
+}
+
+ethip_link_addr_t *ethip_nic_addr_find(ethip_nic_t *nic,
+    iplink_srv_addr_t *addr)
+{
+	log_msg(LVL_DEBUG, "ethip_nic_addr_find()");
+
+	list_foreach(nic->addr_list, link) {
+		ethip_link_addr_t *laddr = list_get_instance(link,
+		    ethip_link_addr_t, addr_list);
+
+		if (addr->ipv4 == laddr->addr.ipv4)
+			return laddr;
+	}
+
+	return NULL;
+}
+
+/** @}
+ */
Index: uspace/srv/net/ethip/ethip_nic.h
===================================================================
--- uspace/srv/net/ethip/ethip_nic.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/ethip/ethip_nic.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2012 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup ethip
+ * @{
+ */
+/**
+ * @file
+ * @brief
+ */
+
+#ifndef ETHIP_NIC_H_
+#define ETHIP_NIC_H_
+
+#include <ipc/loc.h>
+#include "ethip.h"
+
+extern int ethip_nic_discovery_start(void);
+extern ethip_nic_t *ethip_nic_find_by_iplink_sid(service_id_t);
+extern int ethip_nic_send(ethip_nic_t *, void *, size_t);
+extern int ethip_nic_addr_add(ethip_nic_t *, iplink_srv_addr_t *);
+extern int ethip_nic_addr_remove(ethip_nic_t *, iplink_srv_addr_t *);
+extern ethip_link_addr_t *ethip_nic_addr_find(ethip_nic_t *,
+    iplink_srv_addr_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/ethip/pdu.c
===================================================================
--- uspace/srv/net/ethip/pdu.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/ethip/pdu.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,253 @@
+/*
+ * Copyright (c) 2012 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup inet
+ * @{
+ */
+/**
+ * @file
+ * @brief
+ */
+
+#include <byteorder.h>
+#include <errno.h>
+#include <io/log.h>
+#include <macros.h>
+#include <mem.h>
+#include <stdlib.h>
+
+#include "ethip.h"
+#include "std.h"
+#include "pdu.h"
+
+#define MAC48_BYTES 6
+
+/** Encode Ethernet PDU. */
+#include <stdio.h>
+int eth_pdu_encode(eth_frame_t *frame, void **rdata, size_t *rsize)
+{
+	void *data;
+	size_t size;
+	eth_header_t *hdr;
+
+	size = max(sizeof(eth_header_t) + frame->size, ETH_FRAME_MIN_SIZE);
+
+	data = calloc(size, 1);
+	if (data == NULL)
+		return ENOMEM;
+
+	hdr = (eth_header_t *)data;
+	mac48_encode(&frame->src, hdr->src);
+	mac48_encode(&frame->dest, hdr->dest);
+	hdr->etype_len = host2uint16_t_be(frame->etype_len);
+
+	memcpy((uint8_t *)data + sizeof(eth_header_t), frame->data,
+	    frame->size);
+
+	log_msg(LVL_DEBUG, "Encoding Ethernet frame src=%llx dest=%llx etype=%x",
+	    frame->src, frame->dest, frame->etype_len);
+	log_msg(LVL_DEBUG, "Encoded Ethernet frame (%zu bytes)", size);
+	size_t i;
+	for (i = 0; i < size; i++) {
+		printf("%02x ", ((uint8_t *)(data))[sizeof(eth_header_t) + i]);
+	}
+	printf("\n");
+
+
+	*rdata = data;
+	*rsize = size;
+	return EOK;
+}
+
+#include <stdio.h>
+/** Decode Ethernet PDU. */
+int eth_pdu_decode(void *data, size_t size, eth_frame_t *frame)
+{
+	eth_header_t *hdr;
+
+	log_msg(LVL_DEBUG, "eth_pdu_decode()");
+
+	if (size < sizeof(eth_header_t)) {
+		log_msg(LVL_DEBUG, "PDU too short (%zu)", size);
+		return EINVAL;
+	}
+
+	hdr = (eth_header_t *)data;
+
+	frame->size = size - sizeof(eth_header_t);
+	frame->data = calloc(frame->size, 1);
+	if (frame->data == NULL)
+		return ENOMEM;
+
+	mac48_decode(hdr->src, &frame->src);
+	mac48_decode(hdr->dest, &frame->dest);
+	frame->etype_len = uint16_t_be2host(hdr->etype_len);
+
+	memcpy(frame->data, (uint8_t *)data + sizeof(eth_header_t),
+	    frame->size);
+
+	log_msg(LVL_DEBUG, "Decoding Ethernet frame src=%llx dest=%llx etype=%x",
+	    frame->src, frame->dest, frame->etype_len);
+	log_msg(LVL_DEBUG, "Decoded Ethernet frame payload (%zu bytes)", frame->size);
+	size_t i;
+	for (i = 0; i < frame->size; i++) {
+		printf("%02x ", ((uint8_t *)(frame->data))[i]);
+	}
+	printf("\n");
+
+	return EOK;
+}
+
+void mac48_encode(mac48_addr_t *addr, void *buf)
+{
+	uint64_t val;
+	uint8_t *bbuf = (uint8_t *)buf;
+	int i;
+
+	val = addr->addr;
+	for (i = 0; i < MAC48_BYTES; i++)
+		bbuf[i] = (val >> (8 * (MAC48_BYTES - i - 1))) & 0xff;
+}
+
+void mac48_decode(void *data, mac48_addr_t *addr)
+{
+	uint64_t val;
+	uint8_t *bdata = (uint8_t *)data;
+	int i;
+
+	val = 0;
+	for (i = 0; i < MAC48_BYTES; i++)
+		val |= (uint64_t)bdata[i] << (8 * (MAC48_BYTES - i - 1));
+
+	addr->addr = val;
+}
+
+/** Encode ARP PDU. */
+int arp_pdu_encode(arp_eth_packet_t *packet, void **rdata, size_t *rsize)
+{
+	void *data;
+	size_t size;
+	arp_eth_packet_fmt_t *pfmt;
+	uint16_t fopcode;
+
+	log_msg(LVL_DEBUG, "arp_pdu_encode()");
+
+	size = sizeof(arp_eth_packet_fmt_t);
+
+	data = calloc(size, 1);
+	if (data == NULL)
+		return ENOMEM;
+
+	pfmt = (arp_eth_packet_fmt_t *)data;
+
+	switch (packet->opcode) {
+	case aop_request: fopcode = AOP_REQUEST; break;
+	case aop_reply: fopcode = AOP_REPLY; break;
+	default:
+		assert(false);
+		fopcode = 0;
+	}
+
+	pfmt->hw_addr_space = host2uint16_t_be(AHRD_ETHERNET);
+	pfmt->proto_addr_space = host2uint16_t_be(ETYPE_IP);
+	pfmt->hw_addr_size = ETH_ADDR_SIZE;
+	pfmt->proto_addr_size = IPV4_ADDR_SIZE;
+	pfmt->opcode = host2uint16_t_be(fopcode);
+	mac48_encode(&packet->sender_hw_addr, pfmt->sender_hw_addr);
+	pfmt->sender_proto_addr =
+	    host2uint32_t_be(packet->sender_proto_addr.ipv4);
+	mac48_encode(&packet->target_hw_addr, pfmt->target_hw_addr);
+	pfmt->target_proto_addr =
+	    host2uint32_t_be(packet->target_proto_addr.ipv4);
+
+	*rdata = data;
+	*rsize = size;
+	return EOK;
+}
+
+/** Decode ARP PDU. */
+int arp_pdu_decode(void *data, size_t size, arp_eth_packet_t *packet)
+{
+	arp_eth_packet_fmt_t *pfmt;
+
+	log_msg(LVL_DEBUG, "arp_pdu_decode()");
+
+	if (size < sizeof(arp_eth_packet_fmt_t)) {
+		log_msg(LVL_DEBUG, "ARP PDU too short (%zu)", size);
+		return EINVAL;
+	}
+
+	pfmt = (arp_eth_packet_fmt_t *)data;
+
+	if (uint16_t_be2host(pfmt->hw_addr_space) != AHRD_ETHERNET) {
+		log_msg(LVL_DEBUG, "HW address space != %u (%" PRIu16 ")",
+		    AHRD_ETHERNET, uint16_t_be2host(pfmt->hw_addr_space));
+		return EINVAL;
+	}
+
+	if (uint16_t_be2host(pfmt->proto_addr_space) != 0x0800) {
+		log_msg(LVL_DEBUG, "Proto address space != %u (%" PRIu16 ")",
+		    ETYPE_IP, uint16_t_be2host(pfmt->proto_addr_space));
+		return EINVAL;
+	}
+
+	if (pfmt->hw_addr_size != ETH_ADDR_SIZE) {
+		log_msg(LVL_DEBUG, "HW address size != %zu (%zu)",
+		    (size_t)ETH_ADDR_SIZE, (size_t)pfmt->hw_addr_size);
+		return EINVAL;
+	}
+
+	if (pfmt->proto_addr_size != IPV4_ADDR_SIZE) {
+		log_msg(LVL_DEBUG, "Proto address size != %zu (%zu)",
+		    (size_t)IPV4_ADDR_SIZE, (size_t)pfmt->proto_addr_size);
+		return EINVAL;
+	}
+
+	switch (uint16_t_be2host(pfmt->opcode)) {
+	case AOP_REQUEST: packet->opcode = aop_request; break;
+	case AOP_REPLY: packet->opcode = aop_reply; break;
+	default:
+		log_msg(LVL_DEBUG, "Invalid ARP opcode (%" PRIu16 ")",
+		    uint16_t_be2host(pfmt->opcode));
+		return EINVAL;
+	}
+
+	mac48_decode(pfmt->sender_hw_addr, &packet->sender_hw_addr);
+	packet->sender_proto_addr.ipv4 =
+	    uint32_t_be2host(pfmt->sender_proto_addr);
+	mac48_decode(pfmt->target_hw_addr, &packet->target_hw_addr);
+	packet->target_proto_addr.ipv4 =
+	    uint32_t_be2host(pfmt->target_proto_addr);
+	log_msg(LVL_DEBUG, "packet->tpa = %x\n", pfmt->target_proto_addr);
+
+	return EOK;
+}
+
+
+/** @}
+ */
Index: uspace/srv/net/ethip/pdu.h
===================================================================
--- uspace/srv/net/ethip/pdu.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/ethip/pdu.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2012 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup inet
+ * @{
+ */
+/**
+ * @file
+ * @brief
+ */
+
+#ifndef ETH_PDU_H_
+#define ETH_PDU_H_
+
+#include "ethip.h"
+
+extern int eth_pdu_encode(eth_frame_t *, void **, size_t *);
+extern int eth_pdu_decode(void *, size_t, eth_frame_t *);
+extern void mac48_encode(mac48_addr_t *, void *);
+extern void mac48_decode(void *, mac48_addr_t *);
+extern int arp_pdu_encode(arp_eth_packet_t *, void **, size_t *);
+extern int arp_pdu_decode(void *, size_t, arp_eth_packet_t *);
+
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/ethip/std.h
===================================================================
--- uspace/srv/net/ethip/std.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/ethip/std.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2012 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup ethip
+ * @{
+ */
+/**
+ * @file Ethernet, IP/Ethernet standard definitions
+ *
+ */
+
+#ifndef ETHIP_STD_H_
+#define ETHIP_STD_H_
+
+#include <sys/types.h>
+
+#define ETH_ADDR_SIZE 6
+#define IPV4_ADDR_SIZE 4
+#define ETH_FRAME_MIN_SIZE 60
+
+/** Ethernet frame header */
+typedef struct {
+	/** Destination Address */
+	uint8_t dest[ETH_ADDR_SIZE];
+	/** Source Address */
+	uint8_t src[ETH_ADDR_SIZE];
+	/** Ethertype or Length */
+	uint16_t etype_len;
+} eth_header_t;
+
+/** ARP packet format (for 48-bit MAC addresses and IPv4) */
+typedef struct {
+	/** Hardware address space */
+	uint16_t hw_addr_space;
+	/** Protocol address space */
+	uint16_t proto_addr_space;
+	/** Hardware address size */
+	uint8_t hw_addr_size;
+	/** Protocol address size */
+	uint8_t proto_addr_size;
+	/** Opcode */
+	uint16_t opcode;
+	/** Sender hardware address */
+	uint8_t sender_hw_addr[ETH_ADDR_SIZE];
+	/** Sender protocol address */
+	uint32_t sender_proto_addr;
+	/** Target hardware address */
+	uint8_t target_hw_addr[ETH_ADDR_SIZE];
+	/** Target protocol address */
+	uint32_t target_proto_addr;
+} __attribute__((packed)) arp_eth_packet_fmt_t;
+
+enum arp_opcode_fmt {
+	AOP_REQUEST = 1,
+	AOP_REPLY   = 2
+};
+
+enum arp_hw_addr_space {
+	AHRD_ETHERNET = 1
+};
+
+/** IP Ethertype */
+enum ether_type {
+	ETYPE_ARP = 0x0806,
+	ETYPE_IP  = 0x0800
+};
+
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/inet/Makefile
===================================================================
--- uspace/srv/net/inet/Makefile	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/inet/Makefile	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,44 @@
+#
+# Copyright (c) 2012 Jiri Svoboda
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# - Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+# - Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in the
+#   documentation and/or other materials provided with the distribution.
+# - The name of the author may not be used to endorse or promote products
+#   derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+USPACE_PREFIX = ../../..
+BINARY = inet
+
+SOURCES = \
+	addrobj.c \
+	icmp.c \
+	inet.c \
+	inet_link.c \
+	inet_util.c \
+	inetcfg.c \
+	inetping.c \
+	pdu.c \
+	reass.c \
+	sroute.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/net/inet/addrobj.c
===================================================================
--- uspace/srv/net/inet/addrobj.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/inet/addrobj.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 2012 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup inet
+ * @{
+ */
+/**
+ * @file
+ * @brief
+ */
+
+#include <bitops.h>
+#include <errno.h>
+#include <fibril_synch.h>
+#include <io/log.h>
+#include <ipc/loc.h>
+#include <stdlib.h>
+#include <str.h>
+
+#include "addrobj.h"
+#include "inet.h"
+#include "inet_link.h"
+#include "inet_util.h"
+
+static FIBRIL_MUTEX_INITIALIZE(addr_list_lock);
+static LIST_INITIALIZE(addr_list);
+static sysarg_t addr_id = 0;
+
+inet_addrobj_t *inet_addrobj_new(void)
+{
+	inet_addrobj_t *addr = calloc(1, sizeof(inet_addrobj_t));
+
+	if (addr == NULL) {
+		log_msg(LVL_ERROR, "Failed allocating address object. "
+		    "Out of memory.");
+		return NULL;
+	}
+
+	link_initialize(&addr->addr_list);
+	fibril_mutex_lock(&addr_list_lock);
+	addr->id = ++addr_id;
+	fibril_mutex_unlock(&addr_list_lock);
+
+	return addr;
+}
+
+void inet_addrobj_delete(inet_addrobj_t *addr)
+{
+	if (addr->name != NULL)
+		free(addr->name);
+	free(addr);
+}
+
+void inet_addrobj_add(inet_addrobj_t *addr)
+{
+	fibril_mutex_lock(&addr_list_lock);
+	list_append(&addr->addr_list, &addr_list);
+	fibril_mutex_unlock(&addr_list_lock);
+}
+
+void inet_addrobj_remove(inet_addrobj_t *addr)
+{
+	fibril_mutex_lock(&addr_list_lock);
+	list_remove(&addr->addr_list);
+	fibril_mutex_unlock(&addr_list_lock);
+}
+
+/** Find address object matching address @a addr.
+ *
+ * @param addr	Address
+ * @oaram find	iaf_net to find network (using mask),
+ *		iaf_addr to find local address (exact match)
+ */
+inet_addrobj_t *inet_addrobj_find(inet_addr_t *addr, inet_addrobj_find_t find)
+{
+	uint32_t mask;
+
+	log_msg(LVL_DEBUG, "inet_addrobj_find(%x)", (unsigned)addr->ipv4);
+
+	fibril_mutex_lock(&addr_list_lock);
+
+	list_foreach(addr_list, link) {
+		inet_addrobj_t *naddr = list_get_instance(link,
+		    inet_addrobj_t, addr_list);
+
+		mask = inet_netmask(naddr->naddr.bits);
+		if ((naddr->naddr.ipv4 & mask) == (addr->ipv4 & mask)) {
+			fibril_mutex_unlock(&addr_list_lock);
+			log_msg(LVL_DEBUG, "inet_addrobj_find: found %p",
+			    naddr);
+			return naddr;
+		}
+	}
+
+	log_msg(LVL_DEBUG, "inet_addrobj_find: Not found");
+	fibril_mutex_unlock(&addr_list_lock);
+
+	return NULL;
+}
+
+/** Find address object on a link, with a specific name.
+ *
+ * @param name	Address object name
+ * @param ilink	Inet link
+ * @return	Address object
+ */
+inet_addrobj_t *inet_addrobj_find_by_name(const char *name, inet_link_t *ilink)
+{
+	log_msg(LVL_DEBUG, "inet_addrobj_find_by_name('%s', '%s')",
+	    name, ilink->svc_name);
+
+	fibril_mutex_lock(&addr_list_lock);
+
+	list_foreach(addr_list, link) {
+		inet_addrobj_t *naddr = list_get_instance(link,
+		    inet_addrobj_t, addr_list);
+
+		if (naddr->ilink == ilink && str_cmp(naddr->name, name) == 0) {
+			fibril_mutex_unlock(&addr_list_lock);
+			log_msg(LVL_DEBUG, "inet_addrobj_find_by_name: found %p",
+			    naddr);
+			return naddr;
+		}
+	}
+
+	log_msg(LVL_DEBUG, "inet_addrobj_find_by_name: Not found");
+	fibril_mutex_unlock(&addr_list_lock);
+
+	return NULL;
+}
+
+/** Find address object with the given ID.
+ *
+ * @param id	Address object ID
+ * @return	Address object
+ */
+inet_addrobj_t *inet_addrobj_get_by_id(sysarg_t id)
+{
+	log_msg(LVL_DEBUG, "inet_addrobj_get_by_id(%zu)", (size_t)id);
+
+	fibril_mutex_lock(&addr_list_lock);
+
+	list_foreach(addr_list, link) {
+		inet_addrobj_t *naddr = list_get_instance(link,
+		    inet_addrobj_t, addr_list);
+
+		if (naddr->id == id) {
+			fibril_mutex_unlock(&addr_list_lock);
+			return naddr;
+		}
+	}
+
+	fibril_mutex_unlock(&addr_list_lock);
+
+	return NULL;
+}
+
+/** Send datagram from address object */
+int inet_addrobj_send_dgram(inet_addrobj_t *addr, inet_addr_t *ldest,
+    inet_dgram_t *dgram, uint8_t proto, uint8_t ttl, int df)
+{
+	inet_addr_t lsrc_addr;
+	inet_addr_t *ldest_addr;
+
+	lsrc_addr.ipv4 = addr->naddr.ipv4;
+	ldest_addr = &dgram->dest;
+
+	return inet_link_send_dgram(addr->ilink, &lsrc_addr, ldest_addr, dgram,
+	    proto, ttl, df);
+}
+
+/** Get IDs of all address objects. */
+int inet_addrobj_get_id_list(sysarg_t **rid_list, size_t *rcount)
+{
+	sysarg_t *id_list;
+	size_t count, i;
+
+	fibril_mutex_lock(&addr_list_lock);
+	count = list_count(&addr_list);
+
+	id_list = calloc(count, sizeof(sysarg_t));
+	if (id_list == NULL) {
+		fibril_mutex_unlock(&addr_list_lock);
+		return ENOMEM;
+	}
+
+	i = 0;
+	list_foreach(addr_list, link) {
+		inet_addrobj_t *addr = list_get_instance(link,
+		    inet_addrobj_t, addr_list);
+
+		id_list[i++] = addr->id;
+	}
+
+	fibril_mutex_unlock(&addr_list_lock);
+
+	*rid_list = id_list;
+	*rcount = count;
+
+	return EOK;
+}
+
+/** @}
+ */
Index: uspace/srv/net/inet/addrobj.h
===================================================================
--- uspace/srv/net/inet/addrobj.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/inet/addrobj.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2012 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup inet
+ * @{
+ */
+/**
+ * @file
+ * @brief
+ */
+
+#ifndef INET_ADDROBJ_H_
+#define INET_ADDROBJ_H_
+
+#include <sys/types.h>
+#include "inet.h"
+
+typedef enum {
+	/* Find matching network address (using mask) */
+	iaf_net,
+	/* Find exact local address (not using mask) */
+	iaf_addr
+} inet_addrobj_find_t;
+
+extern inet_addrobj_t *inet_addrobj_new(void);
+extern void inet_addrobj_delete(inet_addrobj_t *);
+extern void inet_addrobj_add(inet_addrobj_t *);
+extern void inet_addrobj_remove(inet_addrobj_t *);
+extern inet_addrobj_t *inet_addrobj_find(inet_addr_t *, inet_addrobj_find_t);
+extern inet_addrobj_t *inet_addrobj_find_by_name(const char *, inet_link_t *);
+extern inet_addrobj_t *inet_addrobj_get_by_id(sysarg_t);
+extern int inet_addrobj_send_dgram(inet_addrobj_t *, inet_addr_t *,
+    inet_dgram_t *, uint8_t, uint8_t, int);
+extern int inet_addrobj_get_id_list(sysarg_t **, size_t *);
+
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/inet/icmp.c
===================================================================
--- uspace/srv/net/inet/icmp.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/inet/icmp.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 2012 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup inet
+ * @{
+ */
+/**
+ * @file
+ * @brief
+ */
+
+#include <byteorder.h>
+#include <errno.h>
+#include <io/log.h>
+#include <mem.h>
+#include <stdlib.h>
+
+#include "icmp.h"
+#include "icmp_std.h"
+#include "inet.h"
+#include "inetping.h"
+#include "pdu.h"
+
+/* XXX */
+#define INET_TTL_MAX 255
+
+static int icmp_recv_echo_request(inet_dgram_t *);
+static int icmp_recv_echo_reply(inet_dgram_t *);
+
+int icmp_recv(inet_dgram_t *dgram)
+{
+	uint8_t type;
+
+	log_msg(LVL_DEBUG, "icmp_recv()");
+
+	if (dgram->size < 1)
+		return EINVAL;
+
+	type = *(uint8_t *)dgram->data;
+
+	switch (type) {
+	case ICMP_ECHO_REQUEST:
+		return icmp_recv_echo_request(dgram);
+	case ICMP_ECHO_REPLY:
+		return icmp_recv_echo_reply(dgram);
+	default:
+		break;
+	}
+
+	return EINVAL;
+}
+
+static int icmp_recv_echo_request(inet_dgram_t *dgram)
+{
+	icmp_echo_t *request, *reply;
+	uint16_t checksum;
+	size_t size;
+	inet_dgram_t rdgram;
+	int rc;
+
+	log_msg(LVL_DEBUG, "icmp_recv_echo_request()");
+
+	if (dgram->size < sizeof(icmp_echo_t))
+		return EINVAL;
+
+	request = (icmp_echo_t *)dgram->data;
+	size = dgram->size;
+
+	reply = calloc(size, 1);
+	if (reply == NULL)
+		return ENOMEM;
+
+	memcpy(reply, request, size);
+
+	reply->type = ICMP_ECHO_REPLY;
+	reply->code = 0;
+	reply->checksum = 0;
+
+	checksum = inet_checksum_calc(INET_CHECKSUM_INIT, reply, size);
+	reply->checksum = host2uint16_t_be(checksum);
+
+	rdgram.src = dgram->dest;
+	rdgram.dest = dgram->src;
+	rdgram.tos = ICMP_TOS;
+	rdgram.data = reply;
+	rdgram.size = size;
+
+	rc = inet_route_packet(&rdgram, IP_PROTO_ICMP, INET_TTL_MAX, 0);
+
+	free(reply);
+
+	return rc;
+}
+
+static int icmp_recv_echo_reply(inet_dgram_t *dgram)
+{
+	icmp_echo_t *reply;
+	inetping_sdu_t sdu;
+	uint16_t ident;
+
+	log_msg(LVL_DEBUG, "icmp_recv_echo_reply()");
+
+	if (dgram->size < sizeof(icmp_echo_t))
+		return EINVAL;
+
+	reply = (icmp_echo_t *)dgram->data;
+
+	sdu.src = dgram->src;
+	sdu.dest = dgram->dest;
+	sdu.seq_no = uint16_t_be2host(reply->seq_no);
+	sdu.data = reply + sizeof(icmp_echo_t);
+	sdu.size = dgram->size - sizeof(icmp_echo_t);
+	ident = uint16_t_be2host(reply->ident);
+
+	return inetping_recv(ident, &sdu);
+}
+
+int icmp_ping_send(uint16_t ident, inetping_sdu_t *sdu)
+{
+	inet_dgram_t dgram;
+	icmp_echo_t *request;
+	void *rdata;
+	size_t rsize;
+	uint16_t checksum;
+	int rc;
+
+	rsize = sizeof(icmp_echo_t) + sdu->size;
+	rdata = calloc(rsize, 1);
+	if (rdata == NULL)
+		return ENOMEM;
+
+	request = (icmp_echo_t *)rdata;
+
+	request->type = ICMP_ECHO_REQUEST;
+	request->code = 0;
+	request->checksum = 0;
+	request->ident = host2uint16_t_be(ident);
+	request->seq_no = host2uint16_t_be(sdu->seq_no);
+
+	memcpy(rdata + sizeof(icmp_echo_t), sdu->data, sdu->size);
+
+	checksum = inet_checksum_calc(INET_CHECKSUM_INIT, rdata, rsize);
+	request->checksum = host2uint16_t_be(checksum);
+
+	dgram.src = sdu->src;
+	dgram.dest = sdu->dest;
+	dgram.tos = ICMP_TOS;
+	dgram.data = rdata;
+	dgram.size = rsize;
+
+	rc = inet_route_packet(&dgram, IP_PROTO_ICMP, INET_TTL_MAX, 0);
+
+	free(rdata);
+	return rc;
+}
+
+/** @}
+ */
Index: uspace/srv/net/inet/icmp.h
===================================================================
--- uspace/srv/net/inet/icmp.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/inet/icmp.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2012 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup inet
+ * @{
+ */
+/**
+ * @file
+ * @brief
+ */
+
+#ifndef ICMP_H_
+#define ICMP_H_
+
+#include "inet.h"
+
+extern int icmp_recv(inet_dgram_t *);
+extern int icmp_ping_send(uint16_t, inetping_sdu_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/inet/icmp_std.h
===================================================================
--- uspace/srv/net/inet/icmp_std.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/inet/icmp_std.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2012 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup inet
+ * @{
+ */
+/**
+ * @file ICMP standard definitions
+ *
+ */
+
+#ifndef ICMP_STD_H_
+#define ICMP_STD_H_
+
+#include <sys/types.h>
+
+#define IP_PROTO_ICMP 1
+
+/** Type of service used for ICMP */
+#define ICMP_TOS	0
+
+/** ICMP message type */
+enum icmp_type {
+	ICMP_ECHO_REPLY   = 0,
+	ICMP_ECHO_REQUEST = 8
+};
+
+/** ICMP Echo Request or Reply message header */
+typedef struct {
+	/** ICMP message type */
+	uint8_t type;
+	/** Code (0) */
+	uint8_t code;
+	/** Internet checksum of the ICMP message */
+	uint16_t checksum;
+	/** Indentifier */
+	uint16_t ident;
+	/** Sequence number */
+	uint16_t seq_no;
+} icmp_echo_t;
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/inet/inet.c
===================================================================
--- uspace/srv/net/inet/inet.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/inet/inet.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,450 @@
+/*
+ * Copyright (c) 2012 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup inet
+ * @{
+ */
+/**
+ * @file
+ * @brief Internet Protocol service
+ */
+
+#include <adt/list.h>
+#include <async.h>
+#include <errno.h>
+#include <fibril_synch.h>
+#include <io/log.h>
+#include <ipc/inet.h>
+#include <ipc/services.h>
+#include <loc.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+
+#include "addrobj.h"
+#include "icmp.h"
+#include "icmp_std.h"
+#include "inet.h"
+#include "inetcfg.h"
+#include "inetping.h"
+#include "inet_link.h"
+#include "reass.h"
+#include "sroute.h"
+
+#define NAME "inet"
+
+static void inet_client_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg);
+
+static FIBRIL_MUTEX_INITIALIZE(client_list_lock);
+static LIST_INITIALIZE(client_list);
+
+static int inet_init(void)
+{
+	service_id_t sid;
+	int rc;
+
+	log_msg(LVL_DEBUG, "inet_init()");
+
+	async_set_client_connection(inet_client_conn);
+
+	rc = loc_server_register(NAME);
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Failed registering server (%d).", rc);
+		return EEXIST;
+	}
+
+	rc = loc_service_register_with_iface(SERVICE_NAME_INET, &sid,
+	    INET_PORT_DEFAULT);
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Failed registering service (%d).", rc);
+		return EEXIST;
+	}
+
+	rc = loc_service_register_with_iface(SERVICE_NAME_INETCFG, &sid,
+	    INET_PORT_CFG);
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Failed registering service (%d).", rc);
+		return EEXIST;
+	}
+
+	rc = loc_service_register_with_iface(SERVICE_NAME_INETPING, &sid,
+	    INET_PORT_PING);
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Failed registering service (%d).", rc);
+		return EEXIST;
+	}
+
+	rc = inet_link_discovery_start();
+	if (rc != EOK)
+		return EEXIST;
+
+	return EOK;
+}
+
+static void inet_callback_create_srv(inet_client_t *client, ipc_callid_t callid,
+    ipc_call_t *call)
+{
+	log_msg(LVL_DEBUG, "inet_callback_create_srv()");
+
+	async_sess_t *sess = async_callback_receive(EXCHANGE_SERIALIZE);
+	if (sess == NULL) {
+		async_answer_0(callid, ENOMEM);
+		return;
+	}
+
+	client->sess = sess;
+	async_answer_0(callid, EOK);
+}
+
+static int inet_find_dir(inet_addr_t *src, inet_addr_t *dest, uint8_t tos,
+    inet_dir_t *dir)
+{
+	inet_sroute_t *sr;
+
+	/* XXX Handle case where source address is specified */
+	(void) src;
+
+	dir->aobj = inet_addrobj_find(dest, iaf_net);
+	if (dir->aobj != NULL) {
+		dir->ldest = *dest;
+		dir->dtype = dt_direct;
+	} else {
+		/* No direct path, try using a static route */
+		sr = inet_sroute_find(dest);
+		if (sr != NULL) {
+			dir->aobj = inet_addrobj_find(&sr->router, iaf_net);
+			dir->ldest = sr->router;
+			dir->dtype = dt_router;
+		}
+	}
+
+	if (dir->aobj == NULL) {
+		log_msg(LVL_DEBUG, "inet_send: No route to destination.");
+		return ENOENT;
+	}
+
+	return EOK;
+}
+
+int inet_route_packet(inet_dgram_t *dgram, uint8_t proto, uint8_t ttl,
+    int df)
+{
+	inet_dir_t dir;
+	int rc;
+
+	rc = inet_find_dir(&dgram->src, &dgram->dest, dgram->tos, &dir);
+	if (rc != EOK)
+		return rc;
+
+	return inet_addrobj_send_dgram(dir.aobj, &dir.ldest, dgram,
+	    proto, ttl, df);
+}
+
+static int inet_send(inet_client_t *client, inet_dgram_t *dgram,
+    uint8_t proto, uint8_t ttl, int df)
+{
+	return inet_route_packet(dgram, proto, ttl, df);
+}
+
+int inet_get_srcaddr(inet_addr_t *remote, uint8_t tos, inet_addr_t *local)
+{
+	inet_dir_t dir;
+	int rc;
+
+	rc = inet_find_dir(NULL, remote, tos, &dir);
+	if (rc != EOK)
+		return rc;
+
+	/* XXX dt_local? */
+
+	/* Take source address from the address object */
+	local->ipv4 = dir.aobj->naddr.ipv4;
+	return EOK;
+}
+
+static void inet_get_srcaddr_srv(inet_client_t *client, ipc_callid_t callid,
+    ipc_call_t *call)
+{
+	inet_addr_t remote;
+	uint8_t tos;
+	inet_addr_t local;
+	int rc;
+
+	log_msg(LVL_DEBUG, "inet_get_srcaddr_srv()");
+
+	remote.ipv4 = IPC_GET_ARG1(*call);
+	tos = IPC_GET_ARG2(*call);
+	local.ipv4 = 0;
+
+	rc = inet_get_srcaddr(&remote, tos, &local);
+	async_answer_1(callid, rc, local.ipv4);
+}
+
+static void inet_send_srv(inet_client_t *client, ipc_callid_t callid,
+    ipc_call_t *call)
+{
+	inet_dgram_t dgram;
+	uint8_t ttl;
+	int df;
+	int rc;
+
+	log_msg(LVL_DEBUG, "inet_send_srv()");
+
+	dgram.src.ipv4 = IPC_GET_ARG1(*call);
+	dgram.dest.ipv4 = IPC_GET_ARG2(*call);
+	dgram.tos = IPC_GET_ARG3(*call);
+	ttl = IPC_GET_ARG4(*call);
+	df = IPC_GET_ARG5(*call);
+
+	rc = async_data_write_accept(&dgram.data, false, 0, 0, 0, &dgram.size);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	rc = inet_send(client, &dgram, client->protocol, ttl, df);
+
+	free(dgram.data);
+	async_answer_0(callid, rc);
+}
+
+static void inet_set_proto_srv(inet_client_t *client, ipc_callid_t callid,
+    ipc_call_t *call)
+{
+	sysarg_t proto;
+
+	proto = IPC_GET_ARG1(*call);
+	log_msg(LVL_DEBUG, "inet_set_proto_srv(%lu)", (unsigned long) proto);
+
+	if (proto > UINT8_MAX) {
+		async_answer_0(callid, EINVAL);
+		return;
+	}
+
+	client->protocol = proto;
+	async_answer_0(callid, EOK);
+}
+
+static void inet_client_init(inet_client_t *client)
+{
+	client->sess = NULL;
+
+	fibril_mutex_lock(&client_list_lock);
+	list_append(&client->client_list, &client_list);
+	fibril_mutex_unlock(&client_list_lock);
+}
+
+static void inet_client_fini(inet_client_t *client)
+{
+	async_hangup(client->sess);
+	client->sess = NULL;
+
+	fibril_mutex_lock(&client_list_lock);
+	list_remove(&client->client_list);
+	fibril_mutex_unlock(&client_list_lock);
+}
+
+static void inet_default_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	inet_client_t client;
+
+	log_msg(LVL_DEBUG, "inet_default_conn()");
+
+	/* Accept the connection */
+	async_answer_0(iid, EOK);
+
+	inet_client_init(&client);
+
+	while (true) {
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+		sysarg_t method = IPC_GET_IMETHOD(call);
+
+		if (!method) {
+			/* The other side has hung up */
+			async_answer_0(callid, EOK);
+			return;
+		}
+
+		switch (method) {
+		case INET_CALLBACK_CREATE:
+			inet_callback_create_srv(&client, callid, &call);
+			break;
+		case INET_GET_SRCADDR:
+			inet_get_srcaddr_srv(&client, callid, &call);
+			break;
+		case INET_SEND:
+			inet_send_srv(&client, callid, &call);
+			break;
+		case INET_SET_PROTO:
+			inet_set_proto_srv(&client, callid, &call);
+			break;
+		default:
+			async_answer_0(callid, EINVAL);
+		}
+	}
+
+	inet_client_fini(&client);
+}
+
+static void inet_client_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	sysarg_t port;
+
+	port = IPC_GET_ARG1(*icall);
+
+	switch (port) {
+	case INET_PORT_DEFAULT:
+		inet_default_conn(iid, icall, arg);
+		break;
+	case INET_PORT_CFG:
+		inet_cfg_conn(iid, icall, arg);
+		break;
+	case INET_PORT_PING:
+		inetping_conn(iid, icall, arg);
+		break;
+	default:
+		async_answer_0(iid, ENOTSUP);
+		break;
+	}
+}
+
+static inet_client_t *inet_client_find(uint8_t proto)
+{
+	fibril_mutex_lock(&client_list_lock);
+
+	list_foreach(client_list, link) {
+		inet_client_t *client = list_get_instance(link, inet_client_t,
+		    client_list);
+
+		if (client->protocol == proto) {
+			fibril_mutex_unlock(&client_list_lock);
+			return client;
+		}
+	}
+
+	fibril_mutex_unlock(&client_list_lock);
+	return NULL;
+}
+
+int inet_ev_recv(inet_client_t *client, inet_dgram_t *dgram)
+{
+	async_exch_t *exch = async_exchange_begin(client->sess);
+
+	ipc_call_t answer;
+	aid_t req = async_send_3(exch, INET_EV_RECV, dgram->src.ipv4,
+	    dgram->dest.ipv4, dgram->tos, &answer);
+	int rc = async_data_write_start(exch, dgram->data, dgram->size);
+	async_exchange_end(exch);
+
+	if (rc != EOK) {
+		async_wait_for(req, NULL);
+		return rc;
+	}
+
+	sysarg_t retval;
+	async_wait_for(req, &retval);
+	if (retval != EOK)
+		return retval;
+
+	return EOK;
+}
+
+int inet_recv_dgram_local(inet_dgram_t *dgram, uint8_t proto)
+{
+	inet_client_t *client;
+
+	log_msg(LVL_DEBUG, "inet_recv_dgram_local()");
+
+	/* ICMP messages are handled internally */
+	if (proto == IP_PROTO_ICMP)
+		return icmp_recv(dgram);
+
+	client = inet_client_find(proto);
+	if (client == NULL) {
+		log_msg(LVL_DEBUG, "No client found for protocol 0x%" PRIx8,
+		    proto);
+		return ENOENT;
+	}
+
+	return inet_ev_recv(client, dgram);
+}
+
+int inet_recv_packet(inet_packet_t *packet)
+{
+	inet_addrobj_t *addr;
+	inet_dgram_t dgram;
+
+	addr = inet_addrobj_find(&packet->dest, iaf_addr);
+	if (addr != NULL) {
+		/* Destined for one of the local addresses */
+
+		/* Check if packet is a complete datagram */
+		if (packet->offs == 0 && !packet->mf) {
+			/* It is complete deliver it immediately */
+			dgram.src = packet->src;
+			dgram.dest = packet->dest;
+			dgram.tos = packet->tos;
+			dgram.data = packet->data;
+			dgram.size = packet->size;
+
+			return inet_recv_dgram_local(&dgram, packet->proto);
+		} else {
+			/* It is a fragment, queue it for reassembly */
+			inet_reass_queue_packet(packet);
+		}
+	}
+
+	return ENOENT;
+}
+
+int main(int argc, char *argv[])
+{
+	int rc;
+
+	printf(NAME ": HelenOS Internet Protocol service\n");
+
+	if (log_init(NAME, LVL_DEBUG) != EOK) {
+		printf(NAME ": Failed to initialize logging.\n");
+		return 1;
+	}
+
+	rc = inet_init();
+	if (rc != EOK)
+		return 1;
+
+	printf(NAME ": Accepting connections.\n");
+	task_retval(0);
+	async_manager();
+
+	/* Not reached */
+	return 0;
+}
+
+/** @}
+ */
Index: uspace/srv/net/inet/inet.h
===================================================================
--- uspace/srv/net/inet/inet.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/inet/inet.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2012 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup inet
+ * @{
+ */
+/**
+ * @file
+ * @brief
+ */
+
+#ifndef INET_H_
+#define INET_H_
+
+#include <adt/list.h>
+#include <bool.h>
+#include <inet/iplink.h>
+#include <ipc/loc.h>
+#include <sys/types.h>
+#include <async.h>
+
+/** Inet Client */
+typedef struct {
+	async_sess_t *sess;
+	uint8_t protocol;
+	link_t client_list;
+} inet_client_t;
+
+/** Inetping Client */
+typedef struct {
+	/** Callback session */
+	async_sess_t *sess;
+	/** Session identifier */
+	uint16_t ident;
+	/** Link to client list */
+	link_t client_list;
+} inetping_client_t;
+
+/** Host address */
+typedef struct {
+	uint32_t ipv4;
+} inet_addr_t;
+
+/** Network address */
+typedef struct {
+	/** Address */
+	uint32_t ipv4;
+	/** Number of valid bits in @c ipv4 */
+	int bits;
+} inet_naddr_t;
+
+/** Address object info */
+typedef struct {
+	/** Network address */
+	inet_naddr_t naddr;
+	/** Link service ID */
+	sysarg_t ilink;
+	/** Address object name */
+	char *name;
+} inet_addr_info_t;
+
+/** IP link info */
+typedef struct {
+	/** Link service name */
+	char *name;
+	/** Default MTU */
+	size_t def_mtu;
+} inet_link_info_t;
+
+/** Static route info */
+typedef struct {
+	/** Destination network address */
+	inet_naddr_t dest;
+	/** Router address */
+	inet_addr_t router;
+	/** Static route name */
+	char *name;
+} inet_sroute_info_t;
+
+typedef struct {
+	/** Source address */
+	inet_addr_t src;
+	/** Destination address */
+	inet_addr_t dest;
+	/** Type of service */
+	uint8_t tos;
+	/** Protocol */
+	uint8_t proto;
+	/** Time to live */
+	uint8_t ttl;
+	/** Identifier */
+	uint16_t ident;
+	/** Do not fragment */
+	bool df;
+	/** More fragments */
+	bool mf;
+	/** Offset of fragment into datagram, in bytes */
+	size_t offs;
+	/** Packet data */
+	void *data;
+	/** Packet data size in bytes */
+	size_t size;
+} inet_packet_t;
+
+typedef struct {
+	inet_addr_t src;
+	inet_addr_t dest;
+	uint8_t tos;
+	void *data;
+	size_t size;
+} inet_dgram_t;
+
+typedef struct {
+	link_t link_list;
+	service_id_t svc_id;
+	char *svc_name;
+	async_sess_t *sess;
+	iplink_t *iplink;
+	size_t def_mtu;
+} inet_link_t;
+
+typedef struct {
+	link_t addr_list;
+	sysarg_t id;
+	inet_naddr_t naddr;
+	inet_link_t *ilink;
+	char *name;
+} inet_addrobj_t;
+
+/** Static route configuration */
+typedef struct {
+	link_t sroute_list;
+	sysarg_t id;
+	/** Destination network */
+	inet_naddr_t dest;
+	/** Router via which to route packets */
+	inet_addr_t router;
+	char *name;
+} inet_sroute_t;
+
+typedef enum {
+	/** Destination is on this network node */
+	dt_local,
+	/** Destination is directly reachable */
+	dt_direct,
+	/** Destination is behind a router */
+	dt_router
+} inet_dir_type_t;
+
+/** Direction (next hop) to a destination */
+typedef struct {
+	/** Route type */
+	inet_dir_type_t dtype;
+	/** Address object (direction) */
+	inet_addrobj_t *aobj;
+	/** Local destination address */
+	inet_addr_t ldest;
+} inet_dir_t;
+
+typedef struct {
+	inet_addr_t src;
+	inet_addr_t dest;
+	uint16_t seq_no;
+	void *data;
+	size_t size;
+} inetping_sdu_t;
+
+extern int inet_ev_recv(inet_client_t *, inet_dgram_t *);
+extern int inet_recv_packet(inet_packet_t *);
+extern int inet_route_packet(inet_dgram_t *, uint8_t, uint8_t, int);
+extern int inet_get_srcaddr(inet_addr_t *, uint8_t, inet_addr_t *);
+extern int inet_recv_dgram_local(inet_dgram_t *, uint8_t);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/inet/inet_link.c
===================================================================
--- uspace/srv/net/inet/inet_link.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/inet/inet_link.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,309 @@
+/*
+ * Copyright (c) 2012 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup inet
+ * @{
+ */
+/**
+ * @file
+ * @brief
+ */
+
+#include <bool.h>
+#include <errno.h>
+#include <fibril_synch.h>
+#include <inet/iplink.h>
+#include <io/log.h>
+#include <loc.h>
+#include <stdlib.h>
+#include <str.h>
+
+#include "addrobj.h"
+#include "inet.h"
+#include "inet_link.h"
+#include "pdu.h"
+
+static int inet_link_open(service_id_t sid);
+static int inet_iplink_recv(iplink_t *ilink, iplink_sdu_t *sdu);
+
+static iplink_ev_ops_t inet_iplink_ev_ops = {
+	.recv = inet_iplink_recv
+};
+
+static LIST_INITIALIZE(inet_link_list);
+static FIBRIL_MUTEX_INITIALIZE(inet_discovery_lock);
+
+static int inet_iplink_recv(iplink_t *iplink, iplink_sdu_t *sdu)
+{
+	inet_packet_t packet;
+	int rc;
+
+	log_msg(LVL_DEBUG, "inet_iplink_recv()");
+	rc = inet_pdu_decode(sdu->data, sdu->size, &packet);
+	if (rc != EOK) {
+		log_msg(LVL_DEBUG, "failed decoding PDU");
+		return rc;
+	}
+
+	log_msg(LVL_DEBUG, "call inet_recv_packet()");
+	rc = inet_recv_packet(&packet);
+	log_msg(LVL_DEBUG, "call inet_recv_packet -> %d", rc);
+	free(packet.data);
+
+	return rc;
+}
+
+static int inet_link_check_new(void)
+{
+	bool already_known;
+	category_id_t iplink_cat;
+	service_id_t *svcs;
+	size_t count, i;
+	int rc;
+
+	fibril_mutex_lock(&inet_discovery_lock);
+
+	rc = loc_category_get_id("iplink", &iplink_cat, IPC_FLAG_BLOCKING);
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Failed resolving category 'iplink'.");
+		fibril_mutex_unlock(&inet_discovery_lock);
+		return ENOENT;
+	}
+
+	rc = loc_category_get_svcs(iplink_cat, &svcs, &count);
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Failed getting list of IP links.");
+		fibril_mutex_unlock(&inet_discovery_lock);
+		return EIO;
+	}
+
+	for (i = 0; i < count; i++) {
+		already_known = false;
+
+		list_foreach(inet_link_list, ilink_link) {
+			inet_link_t *ilink = list_get_instance(ilink_link,
+			    inet_link_t, link_list);
+			if (ilink->svc_id == svcs[i]) {
+				already_known = true;
+				break;
+			}
+		}
+
+		if (!already_known) {
+			log_msg(LVL_DEBUG, "Found IP link '%lu'",
+			    (unsigned long) svcs[i]);
+			rc = inet_link_open(svcs[i]);
+			if (rc != EOK)
+				log_msg(LVL_ERROR, "Could not open IP link.");
+		}
+	}
+
+	fibril_mutex_unlock(&inet_discovery_lock);
+	return EOK;
+}
+
+static inet_link_t *inet_link_new(void)
+{
+	inet_link_t *ilink = calloc(1, sizeof(inet_link_t));
+
+	if (ilink == NULL) {
+		log_msg(LVL_ERROR, "Failed allocating link structure. "
+		    "Out of memory.");
+		return NULL;
+	}
+
+	link_initialize(&ilink->link_list);
+
+	return ilink;
+}
+
+static void inet_link_delete(inet_link_t *ilink)
+{
+	if (ilink->svc_name != NULL)
+		free(ilink->svc_name);
+	free(ilink);
+}
+
+static int inet_link_open(service_id_t sid)
+{
+	inet_link_t *ilink;
+	iplink_addr_t iaddr;
+	int rc;
+
+	log_msg(LVL_DEBUG, "inet_link_open()");
+	ilink = inet_link_new();
+	if (ilink == NULL)
+		return ENOMEM;
+
+	ilink->svc_id = sid;
+	ilink->iplink = NULL;
+
+	rc = loc_service_get_name(sid, &ilink->svc_name);
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Failed getting service name.");
+		goto error;
+	}
+
+	ilink->sess = loc_service_connect(EXCHANGE_SERIALIZE, sid, 0);
+	if (ilink->sess == NULL) {
+		log_msg(LVL_ERROR, "Failed connecting '%s'", ilink->svc_name);
+		goto error;
+	}
+
+	rc = iplink_open(ilink->sess, &inet_iplink_ev_ops, &ilink->iplink);
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Failed opening IP link '%s'",
+		    ilink->svc_name);
+		goto error;
+	}
+
+	rc = iplink_get_mtu(ilink->iplink, &ilink->def_mtu);
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Failed determinning MTU of link '%s'",
+		    ilink->svc_name);
+		goto error;
+	}
+
+	log_msg(LVL_DEBUG, "Opened IP link '%s'", ilink->svc_name);
+	list_append(&ilink->link_list, &inet_link_list);
+
+	inet_addrobj_t *addr;
+
+	static int first = 1;
+	/* XXX For testing: set static IP address 192.168.0.4/24 */
+	addr = inet_addrobj_new();
+	if (first) {
+		addr->naddr.ipv4 = (127 << 24) + (0 << 16) + (0 << 8) + 1;
+		first = 0;
+	} else {
+		addr->naddr.ipv4 = (192 << 24) + (168 << 16) + (0 << 8) + 4;
+	}
+	addr->naddr.bits = 24;
+	addr->ilink = ilink;
+	addr->name = str_dup("v4a");
+	inet_addrobj_add(addr);
+
+	iaddr.ipv4 = addr->naddr.ipv4;
+	rc = iplink_addr_add(ilink->iplink, &iaddr);
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Failed setting IP address on internet link.");
+		/* XXX Roll back */
+		return rc;
+	}
+
+	return EOK;
+
+error:
+	if (ilink->iplink != NULL)
+		iplink_close(ilink->iplink);
+	inet_link_delete(ilink);
+	return rc;
+}
+
+static void inet_link_cat_change_cb(void)
+{
+	(void) inet_link_check_new();
+}
+
+int inet_link_discovery_start(void)
+{
+	int rc;
+
+	rc = loc_register_cat_change_cb(inet_link_cat_change_cb);
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Failed registering callback for IP link "
+		    "discovery (%d).", rc);
+		return rc;
+	}
+
+	return inet_link_check_new();
+}
+
+/** Send datagram over Internet link */
+int inet_link_send_dgram(inet_link_t *ilink, inet_addr_t *lsrc,
+    inet_addr_t *ldest, inet_dgram_t *dgram, uint8_t proto, uint8_t ttl, int df)
+{
+	iplink_sdu_t sdu;
+	inet_packet_t packet;
+	int rc;
+	size_t offs, roffs;
+
+	/*
+	 * Fill packet structure. Fragmentation is performed by
+	 * inet_pdu_encode().
+	 */
+	packet.src = dgram->src;
+	packet.dest = dgram->dest;
+	packet.tos = dgram->tos;
+	packet.proto = proto;
+	packet.ttl = ttl;
+	packet.df = df;
+	packet.data = dgram->data;
+	packet.size = dgram->size;
+
+	sdu.lsrc.ipv4 = lsrc->ipv4;
+	sdu.ldest.ipv4 = ldest->ipv4;
+
+	offs = 0;
+	do {
+		/* Encode one fragment */
+		rc = inet_pdu_encode(&packet, offs, ilink->def_mtu, &sdu.data,
+		    &sdu.size, &roffs);
+		if (rc != EOK)
+			return rc;
+
+		/* Send the PDU */
+		rc = iplink_send(ilink->iplink, &sdu);
+		free(sdu.data);
+
+		offs = roffs;
+	} while (offs < packet.size);
+
+	return rc;
+}
+
+inet_link_t *inet_link_get_by_id(sysarg_t link_id)
+{
+	fibril_mutex_lock(&inet_discovery_lock);
+
+	list_foreach(inet_link_list, elem) {
+		inet_link_t *ilink = list_get_instance(elem, inet_link_t,
+		    link_list);
+
+		if (ilink->svc_id == link_id) {
+			fibril_mutex_unlock(&inet_discovery_lock);
+			return ilink;
+		}
+	}
+
+	fibril_mutex_unlock(&inet_discovery_lock);
+	return NULL;
+}
+
+/** @}
+ */
Index: uspace/srv/net/inet/inet_link.h
===================================================================
--- uspace/srv/net/inet/inet_link.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/inet/inet_link.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2012 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup inet
+ * @{
+ */
+/**
+ * @file
+ * @brief
+ */
+
+#ifndef INET_LINK_H_
+#define INET_LINK_H_
+
+#include <sys/types.h>
+#include "inet.h"
+
+extern int inet_link_discovery_start(void);
+extern int inet_link_send_dgram(inet_link_t *, inet_addr_t *,
+    inet_addr_t *, inet_dgram_t *, uint8_t, uint8_t, int);
+extern inet_link_t *inet_link_get_by_id(sysarg_t);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/inet/inet_std.h
===================================================================
--- uspace/srv/net/inet/inet_std.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/inet/inet_std.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2012 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup inet
+ * @{
+ */
+/**
+ * @file IP header definitions
+ *
+ */
+
+#ifndef INET_STD_H_
+#define INET_STD_H_
+
+#include <sys/types.h>
+
+/** Internet Datagram header (fixed part) */
+typedef struct {
+	/** Version, Internet Header Length */
+	uint8_t ver_ihl;
+	/* Type of Service */
+	uint8_t tos;
+	/** Total Length */
+	uint16_t tot_len;
+	/** Identification */
+	uint16_t id;
+	/** Flags, Fragment Offset */
+	uint16_t flags_foff;
+	/** Time to Live */
+	uint8_t ttl;
+	/** Protocol */
+	uint8_t proto;
+	/** Header Checksum */
+	uint16_t chksum;
+	/** Source Address */
+	uint32_t src_addr;
+	/** Destination Address */
+	uint32_t dest_addr;
+} ip_header_t;
+
+/** Bits in ip_header_t.ver_ihl */
+enum ver_ihl_bits {
+	/** Version, highest bit */
+	VI_VERSION_h = 7,
+	/** Version, lowest bit */
+	VI_VERSION_l = 4,
+	/** Internet Header Length, highest bit */
+	VI_IHL_h     = 3,
+	/** Internet Header Length, lowest bit */
+	VI_IHL_l     = 0
+};
+
+/** Bits in ip_header_t.flags_foff */
+enum flags_foff_bits {
+	/** Reserved, must be zero */
+	FF_FLAG_RSVD = 15,
+	/** Don't Fragment */
+	FF_FLAG_DF = 14,
+	/** More Fragments */
+	FF_FLAG_MF = 13,
+	/** Fragment Offset, highest bit */
+	FF_FRAGOFF_h = 12,
+	/** Fragment Offset, lowest bit */
+	FF_FRAGOFF_l = 0
+};
+
+/** Fragment offset is expressed in units of 8 bytes */
+#define FRAG_OFFS_UNIT 8
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/inet/inet_util.c
===================================================================
--- uspace/srv/net/inet/inet_util.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/inet/inet_util.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2012 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup inet
+ * @{
+ */
+/**
+ * @file
+ * @brief
+ */
+
+#include <assert.h>
+#include <bitops.h>
+#include <sys/types.h>
+#include "inet_util.h"
+
+uint32_t inet_netmask(int bits)
+{
+	assert(bits >= 0);
+	assert(bits < 32);
+
+	if (bits == 0)
+		return 0;
+	else
+		return BIT_RANGE(uint32_t, 31, 31 - (bits - 1));
+}
+
+/** @}
+ */
Index: uspace/srv/net/inet/inet_util.h
===================================================================
--- uspace/srv/net/inet/inet_util.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/inet/inet_util.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2012 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup inet
+ * @{
+ */
+/**
+ * @file
+ * @brief
+ */
+
+#ifndef INET_UTIL_H_
+#define INET_UTIL_H_
+
+#include <sys/types.h>
+
+uint32_t inet_netmask(int bits);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/inet/inetcfg.c
===================================================================
--- uspace/srv/net/inet/inetcfg.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/inet/inetcfg.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,631 @@
+/*
+ * Copyright (c) 2012 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup inet
+ * @{
+ */
+/**
+ * @file
+ * @brief
+ */
+
+#include <async.h>
+#include <errno.h>
+#include <macros.h>
+#include <io/log.h>
+#include <ipc/inet.h>
+#include <loc.h>
+#include <stdlib.h>
+#include <str.h>
+#include <sys/types.h>
+
+#include "addrobj.h"
+#include "inet.h"
+#include "inet_link.h"
+#include "inetcfg.h"
+#include "sroute.h"
+
+static int inetcfg_addr_create_static(char *name, inet_naddr_t *naddr,
+    sysarg_t link_id, sysarg_t *addr_id)
+{
+	inet_link_t *ilink;
+	inet_addrobj_t *addr;
+	iplink_addr_t iaddr;
+	int rc;
+
+	ilink = inet_link_get_by_id(link_id);
+	if (ilink == NULL) {
+		log_msg(LVL_DEBUG, "Link %lu not found.",
+		    (unsigned long) link_id);
+		return ENOENT;
+	}
+
+	addr = inet_addrobj_new();
+	if (addr == NULL) {
+		*addr_id = 0;
+		return ENOMEM;
+	}
+
+	addr->naddr = *naddr;
+	addr->ilink = ilink;
+	addr->name = str_dup(name);
+	inet_addrobj_add(addr);
+
+	iaddr.ipv4 = addr->naddr.ipv4;
+	rc = iplink_addr_add(ilink->iplink, &iaddr);
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Failed setting IP address on internet link.");
+		inet_addrobj_remove(addr);
+		inet_addrobj_delete(addr);
+		return rc;
+	}
+
+	return EOK;
+}
+
+static int inetcfg_addr_delete(sysarg_t addr_id)
+{
+	inet_addrobj_t *addr;
+
+	addr = inet_addrobj_get_by_id(addr_id);
+	if (addr == NULL)
+		return ENOENT;
+
+	inet_addrobj_remove(addr);
+	inet_addrobj_delete(addr);
+
+	return EOK;
+}
+
+static int inetcfg_addr_get(sysarg_t addr_id, inet_addr_info_t *ainfo)
+{
+	inet_addrobj_t *addr;
+
+	addr = inet_addrobj_get_by_id(addr_id);
+	if (addr == NULL)
+		return ENOENT;
+
+	ainfo->naddr = addr->naddr;
+	ainfo->ilink = addr->ilink->svc_id;
+	ainfo->name = str_dup(addr->name);
+
+	return EOK;
+}
+
+static int inetcfg_addr_get_id(char *name, sysarg_t link_id, sysarg_t *addr_id)
+{
+	inet_link_t *ilink;
+	inet_addrobj_t *addr;
+
+	ilink = inet_link_get_by_id(link_id);
+	if (ilink == NULL) {
+		log_msg(LVL_DEBUG, "Link %zu not found.", (size_t) link_id);
+		return ENOENT;
+	}
+
+	addr = inet_addrobj_find_by_name(name, ilink);
+	if (addr == NULL) {
+		log_msg(LVL_DEBUG, "Address '%s' not found.", name);
+		return ENOENT;
+	}
+
+	*addr_id = addr->id;
+	return EOK;
+}
+
+static int inetcfg_get_addr_list(sysarg_t **addrs, size_t *count)
+{
+	return inet_addrobj_get_id_list(addrs, count);
+}
+
+static int inetcfg_get_link_list(sysarg_t **addrs, size_t *count)
+{
+	return ENOTSUP;
+}
+
+static int inetcfg_get_sroute_list(sysarg_t **sroutes, size_t *count)
+{
+	return inet_sroute_get_id_list(sroutes, count);
+}
+
+static int inetcfg_link_get(sysarg_t link_id, inet_link_info_t *linfo)
+{
+	inet_link_t *ilink;
+
+	ilink = inet_link_get_by_id(link_id);
+	if (ilink == NULL) {
+		return ENOENT;
+	}
+
+	linfo->name = str_dup(ilink->svc_name);
+	linfo->def_mtu = ilink->def_mtu;
+	return EOK;
+}
+
+static int inetcfg_sroute_create(char *name, inet_naddr_t *dest,
+    inet_addr_t *router, sysarg_t *sroute_id)
+{
+	inet_sroute_t *sroute;
+
+	sroute = inet_sroute_new();
+	if (sroute == NULL) {
+		*sroute_id = 0;
+		return ENOMEM;
+	}
+
+	sroute->dest = *dest;
+	sroute->router = *router;
+	sroute->name = str_dup(name);
+	inet_sroute_add(sroute);
+
+	*sroute_id = sroute->id;
+	return EOK;
+}
+
+static int inetcfg_sroute_delete(sysarg_t sroute_id)
+{
+	inet_sroute_t *sroute;
+
+	sroute = inet_sroute_get_by_id(sroute_id);
+	if (sroute == NULL)
+		return ENOENT;
+
+	inet_sroute_remove(sroute);
+	inet_sroute_delete(sroute);
+
+	return EOK;
+}
+
+static int inetcfg_sroute_get(sysarg_t sroute_id, inet_sroute_info_t *srinfo)
+{
+	inet_sroute_t *sroute;
+
+	sroute = inet_sroute_get_by_id(sroute_id);
+	if (sroute == NULL)
+		return ENOENT;
+
+	srinfo->dest = sroute->dest;
+	srinfo->router = sroute->router;
+	srinfo->name = str_dup(sroute->name);
+
+	return EOK;
+}
+
+static int inetcfg_sroute_get_id(char *name, sysarg_t *sroute_id)
+{
+	inet_sroute_t *sroute;
+
+	sroute = inet_sroute_find_by_name(name);
+	if (sroute == NULL) {
+		log_msg(LVL_DEBUG, "Static route '%s' not found.", name);
+		return ENOENT;
+	}
+
+	*sroute_id = sroute->id;
+	return EOK;
+}
+
+static void inetcfg_addr_create_static_srv(ipc_callid_t callid,
+    ipc_call_t *call)
+{
+	char *name;
+	inet_naddr_t naddr;
+	sysarg_t link_id;
+	sysarg_t addr_id;
+	int rc;
+
+	log_msg(LVL_DEBUG, "inetcfg_addr_create_static_srv()");
+
+	rc = async_data_write_accept((void **) &name, true, 0, LOC_NAME_MAXLEN,
+	    0, NULL);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	naddr.ipv4 = IPC_GET_ARG1(*call);
+	naddr.bits = IPC_GET_ARG2(*call);
+	link_id    = IPC_GET_ARG3(*call);
+
+	addr_id = 0;
+	rc = inetcfg_addr_create_static(name, &naddr, link_id, &addr_id);
+	free(name);
+	async_answer_1(callid, rc, addr_id);
+}
+
+static void inetcfg_addr_delete_srv(ipc_callid_t callid, ipc_call_t *call)
+{
+	sysarg_t addr_id;
+	int rc;
+
+	log_msg(LVL_DEBUG, "inetcfg_addr_delete_srv()");
+
+	addr_id = IPC_GET_ARG1(*call);
+
+	rc = inetcfg_addr_delete(addr_id);
+	async_answer_0(callid, rc);
+}
+
+static void inetcfg_addr_get_srv(ipc_callid_t callid, ipc_call_t *call)
+{
+	ipc_callid_t rcallid;
+	size_t max_size;
+
+	sysarg_t addr_id;
+	inet_addr_info_t ainfo;
+	int rc;
+
+	addr_id = IPC_GET_ARG1(*call);
+	log_msg(LVL_DEBUG, "inetcfg_addr_get_srv()");
+
+	ainfo.naddr.ipv4 = 0;
+	ainfo.naddr.bits = 0;
+	ainfo.ilink = 0;
+	ainfo.name = NULL;
+
+	if (!async_data_read_receive(&rcallid, &max_size)) {
+		async_answer_0(rcallid, EREFUSED);
+		async_answer_0(callid, EREFUSED);
+		return;
+	}
+
+	rc = inetcfg_addr_get(addr_id, &ainfo);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	sysarg_t retval = async_data_read_finalize(rcallid, ainfo.name,
+	    min(max_size, str_size(ainfo.name)));
+	free(ainfo.name);
+
+	async_answer_3(callid, retval, ainfo.naddr.ipv4, ainfo.naddr.bits,
+	    ainfo.ilink);
+}
+
+static void inetcfg_addr_get_id_srv(ipc_callid_t callid, ipc_call_t *call)
+{
+	char *name;
+	sysarg_t link_id;
+	sysarg_t addr_id;
+	int rc;
+
+	log_msg(LVL_DEBUG, "inetcfg_addr_get_id_srv()");
+
+	link_id = IPC_GET_ARG1(*call);
+
+	rc = async_data_write_accept((void **) &name, true, 0, LOC_NAME_MAXLEN,
+	    0, NULL);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	addr_id = 0;
+	rc = inetcfg_addr_get_id(name, link_id, &addr_id);
+	free(name);
+	async_answer_1(callid, rc, addr_id);
+}
+
+static void inetcfg_get_addr_list_srv(ipc_callid_t callid, ipc_call_t *call)
+{
+	ipc_callid_t rcallid;
+	size_t count;
+	size_t max_size;
+	size_t act_size;
+	size_t size;
+	sysarg_t *id_buf;
+	int rc;
+
+	log_msg(LVL_DEBUG, "inetcfg_get_addr_list_srv()");
+
+	if (!async_data_read_receive(&rcallid, &max_size)) {
+		async_answer_0(rcallid, EREFUSED);
+		async_answer_0(callid, EREFUSED);
+		return;
+	}
+
+	rc = inetcfg_get_addr_list(&id_buf, &count);
+	if (rc != EOK) {
+		async_answer_0(rcallid, rc);
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	act_size = count * sizeof(sysarg_t);
+	size = min(act_size, max_size);
+
+	sysarg_t retval = async_data_read_finalize(rcallid, id_buf, size);
+	free(id_buf);
+
+	async_answer_1(callid, retval, act_size);
+}
+
+
+static void inetcfg_get_link_list_srv(ipc_callid_t callid, ipc_call_t *call)
+{
+	ipc_callid_t rcallid;
+	size_t max_size;
+	size_t act_size;
+	size_t size;
+	sysarg_t *id_buf;
+	int rc;
+
+	log_msg(LVL_DEBUG, "inetcfg_get_link_list_srv()");
+
+	if (!async_data_read_receive(&rcallid, &max_size)) {
+		async_answer_0(rcallid, EREFUSED);
+		async_answer_0(callid, EREFUSED);
+		return;
+	}
+
+	rc = inetcfg_get_link_list(&id_buf, &act_size);
+	if (rc != EOK) {
+		async_answer_0(rcallid, rc);
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	size = min(act_size, max_size);
+
+	sysarg_t retval = async_data_read_finalize(rcallid, id_buf, size);
+	free(id_buf);
+
+	async_answer_1(callid, retval, act_size);
+}
+
+static void inetcfg_get_sroute_list_srv(ipc_callid_t callid, ipc_call_t *call)
+{
+	ipc_callid_t rcallid;
+	size_t count;
+	size_t max_size;
+	size_t act_size;
+	size_t size;
+	sysarg_t *id_buf;
+	int rc;
+
+	log_msg(LVL_DEBUG, "inetcfg_get_sroute_list_srv()");
+
+	if (!async_data_read_receive(&rcallid, &max_size)) {
+		async_answer_0(rcallid, EREFUSED);
+		async_answer_0(callid, EREFUSED);
+		return;
+	}
+
+	rc = inetcfg_get_sroute_list(&id_buf, &count);
+	if (rc != EOK) {
+		async_answer_0(rcallid, rc);
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	act_size = count * sizeof(sysarg_t);
+	size = min(act_size, max_size);
+
+	sysarg_t retval = async_data_read_finalize(rcallid, id_buf, size);
+	free(id_buf);
+
+	async_answer_1(callid, retval, act_size);
+}
+
+static void inetcfg_link_get_srv(ipc_callid_t callid, ipc_call_t *call)
+{
+	ipc_callid_t rcallid;
+	size_t max_size;
+
+	sysarg_t link_id;
+	inet_link_info_t linfo;
+	int rc;
+
+	link_id = IPC_GET_ARG1(*call);
+	log_msg(LVL_DEBUG, "inetcfg_link_get_srv()");
+
+	linfo.name = NULL;
+
+	if (!async_data_read_receive(&rcallid, &max_size)) {
+		async_answer_0(rcallid, EREFUSED);
+		async_answer_0(callid, EREFUSED);
+		return;
+	}
+
+	rc = inetcfg_link_get(link_id, &linfo);
+	if (rc != EOK) {
+		async_answer_0(rcallid, rc);
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	sysarg_t retval = async_data_read_finalize(rcallid, linfo.name,
+	    min(max_size, str_size(linfo.name)));
+	free(linfo.name);
+
+	async_answer_1(callid, retval, linfo.def_mtu);
+}
+
+static void inetcfg_sroute_create_srv(ipc_callid_t callid,
+    ipc_call_t *call)
+{
+	char *name;
+	inet_naddr_t dest;
+	inet_addr_t router;
+	sysarg_t sroute_id;
+	int rc;
+
+	log_msg(LVL_DEBUG, "inetcfg_sroute_create_srv()");
+
+	rc = async_data_write_accept((void **) &name, true, 0, LOC_NAME_MAXLEN,
+	    0, NULL);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	dest.ipv4   = IPC_GET_ARG1(*call);
+	dest.bits   = IPC_GET_ARG2(*call);
+	router.ipv4 = IPC_GET_ARG3(*call);
+
+	sroute_id = 0;
+	rc = inetcfg_sroute_create(name, &dest, &router, &sroute_id);
+	free(name);
+	async_answer_1(callid, rc, sroute_id);
+}
+
+static void inetcfg_sroute_delete_srv(ipc_callid_t callid, ipc_call_t *call)
+{
+	sysarg_t sroute_id;
+	int rc;
+
+	log_msg(LVL_DEBUG, "inetcfg_sroute_delete_srv()");
+
+	sroute_id = IPC_GET_ARG1(*call);
+
+	rc = inetcfg_sroute_delete(sroute_id);
+	async_answer_0(callid, rc);
+}
+
+static void inetcfg_sroute_get_srv(ipc_callid_t callid, ipc_call_t *call)
+{
+	ipc_callid_t rcallid;
+	size_t max_size;
+
+	sysarg_t sroute_id;
+	inet_sroute_info_t srinfo;
+	int rc;
+
+	sroute_id = IPC_GET_ARG1(*call);
+	log_msg(LVL_DEBUG, "inetcfg_sroute_get_srv()");
+
+	srinfo.dest.ipv4 = 0;
+	srinfo.dest.bits = 0;
+	srinfo.router.ipv4 = 0;
+	srinfo.name = NULL;
+
+	if (!async_data_read_receive(&rcallid, &max_size)) {
+		async_answer_0(rcallid, EREFUSED);
+		async_answer_0(callid, EREFUSED);
+		return;
+	}
+
+	rc = inetcfg_sroute_get(sroute_id, &srinfo);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	sysarg_t retval = async_data_read_finalize(rcallid, srinfo.name,
+	    min(max_size, str_size(srinfo.name)));
+	free(srinfo.name);
+
+	async_answer_3(callid, retval, srinfo.dest.ipv4, srinfo.dest.bits,
+	    srinfo.router.ipv4);
+}
+
+static void inetcfg_sroute_get_id_srv(ipc_callid_t callid, ipc_call_t *call)
+{
+	char *name;
+	sysarg_t sroute_id;
+	int rc;
+
+	log_msg(LVL_DEBUG, "inetcfg_sroute_get_id_srv()");
+
+	rc = async_data_write_accept((void **) &name, true, 0, LOC_NAME_MAXLEN,
+	    0, NULL);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	sroute_id = 0;
+	rc = inetcfg_sroute_get_id(name, &sroute_id);
+	free(name);
+	async_answer_1(callid, rc, sroute_id);
+}
+
+void inet_cfg_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	log_msg(LVL_DEBUG, "inet_cfg_conn()");
+
+	/* Accept the connection */
+	async_answer_0(iid, EOK);
+
+	while (true) {
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+		sysarg_t method = IPC_GET_IMETHOD(call);
+
+		if (!method) {
+			/* The other side has hung up */
+			async_answer_0(callid, EOK);
+			return;
+		}
+
+		switch (method) {
+		case INETCFG_ADDR_CREATE_STATIC:
+			inetcfg_addr_create_static_srv(callid, &call);
+			break;
+		case INETCFG_ADDR_DELETE:
+			inetcfg_addr_delete_srv(callid, &call);
+			break;
+		case INETCFG_ADDR_GET:
+			inetcfg_addr_get_srv(callid, &call);
+			break;
+		case INETCFG_ADDR_GET_ID:
+			inetcfg_addr_get_id_srv(callid, &call);
+			break;
+		case INETCFG_GET_ADDR_LIST:
+			inetcfg_get_addr_list_srv(callid, &call);
+			break;
+		case INETCFG_GET_LINK_LIST:
+			inetcfg_get_link_list_srv(callid, &call);
+			break;
+		case INETCFG_GET_SROUTE_LIST:
+			inetcfg_get_sroute_list_srv(callid, &call);
+			break;
+		case INETCFG_LINK_GET:
+			inetcfg_link_get_srv(callid, &call);
+			break;
+		case INETCFG_SROUTE_CREATE:
+			inetcfg_sroute_create_srv(callid, &call);
+			break;
+		case INETCFG_SROUTE_DELETE:
+			inetcfg_sroute_delete_srv(callid, &call);
+			break;
+		case INETCFG_SROUTE_GET:
+			inetcfg_sroute_get_srv(callid, &call);
+			break;
+		case INETCFG_SROUTE_GET_ID:
+			inetcfg_sroute_get_id_srv(callid, &call);
+			break;
+		default:
+			async_answer_0(callid, EINVAL);
+		}
+	}
+}
+
+/** @}
+ */
Index: uspace/srv/net/inet/inetcfg.h
===================================================================
--- uspace/srv/net/inet/inetcfg.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/inet/inetcfg.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2012 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup inet
+ * @{
+ */
+/**
+ * @file
+ * @brief
+ */
+
+#ifndef INETCFG_H_
+#define INETCFG_H_
+
+extern void inet_cfg_conn(ipc_callid_t, ipc_call_t *, void *);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/inet/inetping.c
===================================================================
--- uspace/srv/net/inet/inetping.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/inet/inetping.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,230 @@
+/*
+ * Copyright (c) 2012 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup inet
+ * @{
+ */
+/**
+ * @file
+ * @brief
+ */
+
+#include <async.h>
+#include <errno.h>
+#include <fibril_synch.h>
+#include <io/log.h>
+#include <ipc/inet.h>
+#include <loc.h>
+#include <stdlib.h>
+#include <sys/types.h>
+
+#include "icmp.h"
+#include "icmp_std.h"
+#include "inet.h"
+#include "inetping.h"
+
+static FIBRIL_MUTEX_INITIALIZE(client_list_lock);
+static LIST_INITIALIZE(client_list);
+
+/** Last used session identifier. Protected by @c client_list_lock */
+static uint16_t inetping_ident = 0;
+
+static inetping_client_t *inetping_client_find(uint16_t);
+
+static int inetping_send(inetping_client_t *client, inetping_sdu_t *sdu)
+{
+	return icmp_ping_send(client->ident, sdu);
+}
+
+static int inetping_get_srcaddr(inetping_client_t *client, inet_addr_t *remote,
+    inet_addr_t *local)
+{
+	return inet_get_srcaddr(remote, ICMP_TOS, local);
+}
+
+int inetping_recv(uint16_t ident, inetping_sdu_t *sdu)
+{
+	inetping_client_t *client;
+	async_exch_t *exch;
+	ipc_call_t answer;
+
+	client = inetping_client_find(ident);
+	if (client == NULL) {
+		log_msg(LVL_DEBUG, "Unknown ICMP ident. Dropping.");
+		return ENOENT;
+	}
+
+	exch = async_exchange_begin(client->sess);
+
+	aid_t req = async_send_3(exch, INETPING_EV_RECV, sdu->src.ipv4,
+	    sdu->dest.ipv4, sdu->seq_no, &answer);
+	int rc = async_data_write_start(exch, sdu->data, sdu->size);
+	async_exchange_end(exch);
+
+	if (rc != EOK) {
+		async_wait_for(req, NULL);
+		return rc;
+	}
+
+	sysarg_t retval;
+	async_wait_for(req, &retval);
+	if (retval != EOK) {
+		return retval;
+	}
+
+	return EOK;
+}
+
+static void inetping_send_srv(inetping_client_t *client, ipc_callid_t callid,
+    ipc_call_t *call)
+{
+	inetping_sdu_t sdu;
+	int rc;
+
+	log_msg(LVL_DEBUG, "inetping_send_srv()");
+
+	rc = async_data_write_accept((void **) &sdu.data, false, 0, 0, 0,
+	    &sdu.size);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	sdu.src.ipv4 = IPC_GET_ARG1(*call);
+	sdu.dest.ipv4 = IPC_GET_ARG2(*call);
+	sdu.seq_no = IPC_GET_ARG3(*call);
+
+	rc = inetping_send(client, &sdu);
+	free(sdu.data);
+
+	async_answer_0(callid, rc);
+}
+
+static void inetping_get_srcaddr_srv(inetping_client_t *client,
+    ipc_callid_t callid, ipc_call_t *call)
+{
+	inet_addr_t remote;
+	inet_addr_t local;
+	int rc;
+
+	log_msg(LVL_DEBUG, "inetping_get_srcaddr_srv()");
+
+	remote.ipv4 = IPC_GET_ARG1(*call);
+	local.ipv4 = 0;
+
+	rc = inetping_get_srcaddr(client, &remote, &local);
+	async_answer_1(callid, rc, local.ipv4);
+}
+
+static int inetping_client_init(inetping_client_t *client)
+{
+	async_sess_t *sess = async_callback_receive(EXCHANGE_SERIALIZE);
+	if (sess == NULL)
+		return ENOMEM;
+
+	client->sess = sess;
+	link_initialize(&client->client_list);
+
+	fibril_mutex_lock(&client_list_lock);
+	client->ident = ++inetping_ident;
+	list_append(&client->client_list, &client_list);
+	fibril_mutex_unlock(&client_list_lock);
+
+	return EOK;
+}
+
+static void inetping_client_fini(inetping_client_t *client)
+{
+	async_hangup(client->sess);
+	client->sess = NULL;
+
+	fibril_mutex_lock(&client_list_lock);
+	list_remove(&client->client_list);
+	fibril_mutex_unlock(&client_list_lock);
+}
+
+static inetping_client_t *inetping_client_find(uint16_t ident)
+{
+	fibril_mutex_lock(&client_list_lock);
+
+	list_foreach(client_list, link) {
+		inetping_client_t *client = list_get_instance(link,
+		    inetping_client_t, client_list);
+
+		if (client->ident == ident) {
+			fibril_mutex_unlock(&client_list_lock);
+			return client;
+		}
+	}
+
+	fibril_mutex_unlock(&client_list_lock);
+	return NULL;
+}
+
+void inetping_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	inetping_client_t client;
+	int rc;
+
+	log_msg(LVL_DEBUG, "inetping_conn()");
+
+	/* Accept the connection */
+	async_answer_0(iid, EOK);
+
+	rc = inetping_client_init(&client);
+	if (rc != EOK)
+		return;
+
+	while (true) {
+		ipc_call_t call;
+		ipc_callid_t callid = async_get_call(&call);
+		sysarg_t method = IPC_GET_IMETHOD(call);
+
+		if (!method) {
+			/* The other side has hung up */
+			async_answer_0(callid, EOK);
+			break;
+		}
+
+		switch (method) {
+		case INETPING_SEND:
+			inetping_send_srv(&client, callid, &call);
+			break;
+		case INETPING_GET_SRCADDR:
+			inetping_get_srcaddr_srv(&client, callid, &call);
+			break;
+		default:
+			async_answer_0(callid, EINVAL);
+		}
+	}
+
+	inetping_client_fini(&client);
+}
+
+/** @}
+ */
Index: uspace/srv/net/inet/inetping.h
===================================================================
--- uspace/srv/net/inet/inetping.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/inet/inetping.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2012 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup inet
+ * @{
+ */
+/**
+ * @file
+ * @brief
+ */
+
+#ifndef INETPING_H_
+#define INETPING_H_
+
+extern void inetping_conn(ipc_callid_t, ipc_call_t *, void *);
+extern int inetping_recv(uint16_t, inetping_sdu_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/inet/pdu.c
===================================================================
--- uspace/srv/net/inet/pdu.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/inet/pdu.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,268 @@
+/*
+ * Copyright (c) 2012 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup inet
+ * @{
+ */
+/**
+ * @file
+ * @brief
+ */
+
+#include <align.h>
+#include <bitops.h>
+#include <byteorder.h>
+#include <errno.h>
+#include <fibril_synch.h>
+#include <io/log.h>
+#include <macros.h>
+#include <mem.h>
+#include <stdlib.h>
+
+#include "inet.h"
+#include "inet_std.h"
+#include "pdu.h"
+
+static FIBRIL_MUTEX_INITIALIZE(ip_ident_lock);
+static uint16_t ip_ident = 0;
+
+/** One's complement addition.
+ *
+ * Result is a + b + carry.
+ */
+static uint16_t inet_ocadd16(uint16_t a, uint16_t b)
+{
+	uint32_t s;
+
+	s = (uint32_t)a + (uint32_t)b;
+	return (s & 0xffff) + (s >> 16);
+}
+
+uint16_t inet_checksum_calc(uint16_t ivalue, void *data, size_t size)
+{
+	uint16_t sum;
+	uint16_t w;
+	size_t words, i;
+	uint8_t *bdata;
+
+	sum = ~ivalue;
+	words = size / 2;
+	bdata = (uint8_t *)data;
+
+	for (i = 0; i < words; i++) {
+		w = ((uint16_t)bdata[2*i] << 8) | bdata[2*i + 1];
+		sum = inet_ocadd16(sum, w);
+	}
+
+	if (size % 2 != 0) {
+		w = ((uint16_t)bdata[2*words] << 8);
+		sum = inet_ocadd16(sum, w);
+	}
+
+	return ~sum;
+}
+
+/** Encode Internet PDU.
+ *
+ * Encode internet packet into PDU (serialized form). Will encode a
+ * fragment of the payload starting at offset @a offs. The resulting
+ * PDU will have at most @a mtu bytes. @a *roffs will be set to the offset
+ * of remaining payload. If some data is remaining, the MF flag will
+ * be set in the header, otherwise the offset will equal @a packet->size.
+ *
+ * @param packet	Packet to encode
+ * @param offs		Offset into packet payload (in bytes)
+ * @param mtu		MTU (Maximum Transmission Unit) in bytes
+ * @param rdata		Place to store pointer to allocated data buffer
+ * @param rsize		Place to store size of allocated data buffer
+ * @param roffs		Place to store offset of remaning data
+ */
+int inet_pdu_encode(inet_packet_t *packet, size_t offs, size_t mtu,
+    void **rdata, size_t *rsize, size_t *roffs)
+{
+	void *data;
+	size_t size;
+	ip_header_t *hdr;
+	size_t hdr_size;
+	size_t data_offs;
+	uint16_t chksum;
+	uint16_t ident;
+	uint16_t flags_foff;
+	uint16_t foff;
+	size_t fragoff_limit;
+	size_t xfer_size;
+	size_t spc_avail;
+	size_t rem_offs;
+
+	/* Upper bound for fragment offset field */
+	fragoff_limit = 1 << (FF_FRAGOFF_h - FF_FRAGOFF_l);
+
+	/* Verify that total size of datagram is within reasonable bounds */
+	if (offs + packet->size > FRAG_OFFS_UNIT * fragoff_limit)
+		return ELIMIT;
+
+	hdr_size = sizeof(ip_header_t);
+	data_offs = ROUND_UP(hdr_size, 4);
+
+	assert(offs % FRAG_OFFS_UNIT == 0);
+	assert(offs / FRAG_OFFS_UNIT < fragoff_limit);
+
+	/* Value for the fragment offset field */
+	foff = offs / FRAG_OFFS_UNIT;
+
+	if (hdr_size >= mtu)
+		return EINVAL;
+
+	/* Amount of space in the PDU available for payload */
+	spc_avail = mtu - hdr_size;
+	spc_avail -= (spc_avail % FRAG_OFFS_UNIT);
+
+	/* Amount of data (payload) to transfer */
+	xfer_size = min(packet->size - offs, spc_avail);
+
+	/* Total PDU size */
+	size = hdr_size + xfer_size;
+
+	/* Offset of remaining payload */
+	rem_offs = offs + xfer_size;
+
+	/* Flags */
+	flags_foff =
+	    (packet->df ? BIT_V(uint16_t, FF_FLAG_DF) : 0) +
+	    (rem_offs < packet->size ? BIT_V(uint16_t, FF_FLAG_MF) : 0) +
+	    (foff << FF_FRAGOFF_l);
+
+	data = calloc(size, 1);
+	if (data == NULL)
+		return ENOMEM;
+
+	/* Allocate identifier */
+	fibril_mutex_lock(&ip_ident_lock);
+	ident = ++ip_ident;
+	fibril_mutex_unlock(&ip_ident_lock);
+
+	/* Encode header fields */
+	hdr = (ip_header_t *)data;
+	hdr->ver_ihl = (4 << VI_VERSION_l) | (hdr_size / sizeof(uint32_t));
+	hdr->tos = packet->tos;
+	hdr->tot_len = host2uint16_t_be(size);
+	hdr->id = host2uint16_t_be(ident);
+	hdr->flags_foff = host2uint16_t_be(flags_foff);
+	hdr->ttl = packet->ttl;
+	hdr->proto = packet->proto;
+	hdr->chksum = 0;
+	hdr->src_addr = host2uint32_t_be(packet->src.ipv4);
+	hdr->dest_addr = host2uint32_t_be(packet->dest.ipv4);
+
+	/* Compute checksum */
+	chksum = inet_checksum_calc(INET_CHECKSUM_INIT, (void *)hdr, hdr_size);
+	hdr->chksum = host2uint16_t_be(chksum);
+
+	/* Copy payload */
+	memcpy((uint8_t *)data + data_offs, packet->data + offs, xfer_size);
+
+	*rdata = data;
+	*rsize = size;
+	*roffs = rem_offs;
+
+	return EOK;
+}
+
+int inet_pdu_decode(void *data, size_t size, inet_packet_t *packet)
+{
+	ip_header_t *hdr;
+	size_t tot_len;
+	size_t data_offs;
+	uint8_t version;
+	uint16_t ident;
+	uint16_t flags_foff;
+	uint16_t foff;
+
+	log_msg(LVL_DEBUG, "inet_pdu_decode()");
+
+	if (size < sizeof(ip_header_t)) {
+		log_msg(LVL_DEBUG, "PDU too short (%zu)", size);
+		return EINVAL;
+	}
+
+	hdr = (ip_header_t *)data;
+
+	version = BIT_RANGE_EXTRACT(uint8_t, VI_VERSION_h, VI_VERSION_l,
+	    hdr->ver_ihl);
+	if (version != 4) {
+		log_msg(LVL_DEBUG, "Version (%d) != 4", version);
+		return EINVAL;
+	}
+
+	tot_len = uint16_t_be2host(hdr->tot_len);
+	if (tot_len < sizeof(ip_header_t)) {
+		log_msg(LVL_DEBUG, "Total Length too small (%zu)", tot_len);
+		return EINVAL;
+	}
+
+	if (tot_len > size) {
+		log_msg(LVL_DEBUG, "Total Length = %zu > PDU size = %zu",
+			tot_len, size);
+		return EINVAL;
+	}
+
+	ident = uint16_t_be2host(hdr->id);
+	flags_foff = uint16_t_be2host(hdr->flags_foff);
+	foff = BIT_RANGE_EXTRACT(uint16_t, FF_FRAGOFF_h, FF_FRAGOFF_l,
+	    flags_foff);
+	/* XXX Checksum */
+
+	packet->src.ipv4 = uint32_t_be2host(hdr->src_addr);
+	packet->dest.ipv4 = uint32_t_be2host(hdr->dest_addr);
+	packet->tos = hdr->tos;
+	packet->proto = hdr->proto;
+	packet->ttl = hdr->ttl;
+	packet->ident = ident;
+
+	packet->df = (flags_foff & BIT_V(uint16_t, FF_FLAG_DF)) != 0;
+	packet->mf = (flags_foff & BIT_V(uint16_t, FF_FLAG_MF)) != 0;
+	packet->offs = foff * FRAG_OFFS_UNIT;
+
+	/* XXX IP options */
+	data_offs = sizeof(uint32_t) * BIT_RANGE_EXTRACT(uint8_t, VI_IHL_h,
+	    VI_IHL_l, hdr->ver_ihl);
+
+	packet->size = tot_len - data_offs;
+	packet->data = calloc(packet->size, 1);
+	if (packet->data == NULL) {
+		log_msg(LVL_WARN, "Out of memory.");
+		return ENOMEM;
+	}
+
+	memcpy(packet->data, (uint8_t *)data + data_offs, packet->size);
+
+	return EOK;
+}
+
+/** @}
+ */
Index: uspace/srv/net/inet/pdu.h
===================================================================
--- uspace/srv/net/inet/pdu.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/inet/pdu.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2012 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup inet
+ * @{
+ */
+/**
+ * @file
+ * @brief
+ */
+
+#ifndef INET_PDU_H_
+#define INET_PDU_H_
+
+#include <sys/types.h>
+#include "inet.h"
+
+#define INET_CHECKSUM_INIT 0xffff
+
+extern uint16_t inet_checksum_calc(uint16_t, void *, size_t);
+
+extern int inet_pdu_encode(inet_packet_t *, size_t, size_t, void **,
+    size_t *, size_t *);
+extern int inet_pdu_decode(void *, size_t, inet_packet_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/inet/reass.c
===================================================================
--- uspace/srv/net/inet/reass.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/inet/reass.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,374 @@
+/*
+ * Copyright (c) 2012 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup inet
+ * @{
+ */
+/**
+ * @file
+ * @brief Datagram reassembly.
+ */
+
+#include <errno.h>
+#include <fibril_synch.h>
+#include <io/log.h>
+#include <macros.h>
+#include <mem.h>
+#include <stdlib.h>
+
+#include "inet.h"
+#include "inet_std.h"
+#include "reass.h"
+
+/** Datagram being reassembled.
+ *
+ * Uniquely identified by (source address, destination address, protocol,
+ * identification) per RFC 791 sec. 2.3 / Fragmentation.
+ */
+typedef struct {
+	link_t map_link;
+	/** List of fragments, @c reass_frag_t */
+	list_t frags;
+} reass_dgram_t;
+
+/** One datagram fragment */
+typedef struct {
+	link_t dgram_link;
+	inet_packet_t packet;
+} reass_frag_t;
+
+/** Datagram map, list of reass_dgram_t */
+static LIST_INITIALIZE(reass_dgram_map);
+/** Protects access to @c reass_dgram_map */
+static FIBRIL_MUTEX_INITIALIZE(reass_dgram_map_lock);
+
+static reass_dgram_t *reass_dgram_new(void);
+static reass_dgram_t *reass_dgram_get(inet_packet_t *);
+static int reass_dgram_insert_frag(reass_dgram_t *, inet_packet_t *);
+static bool reass_dgram_complete(reass_dgram_t *);
+static void reass_dgram_remove(reass_dgram_t *);
+static int reass_dgram_deliver(reass_dgram_t *);
+static void reass_dgram_destroy(reass_dgram_t *);
+
+/** Queue packet for datagram reassembly.
+ *
+ * @param packet	Packet
+ * @return		EOK on success or ENOMEM.
+ */
+int inet_reass_queue_packet(inet_packet_t *packet)
+{
+	reass_dgram_t *rdg;
+	int rc;
+
+	log_msg(LVL_DEBUG, "inet_reass_queue_packet()");
+
+	fibril_mutex_lock(&reass_dgram_map_lock);
+
+	/* Get existing or new datagram */
+	rdg = reass_dgram_get(packet);
+	if (rdg == NULL) {
+		/* Only happens when we are out of memory */
+		fibril_mutex_unlock(&reass_dgram_map_lock);
+		log_msg(LVL_DEBUG, "Allocation failed, packet dropped.");
+		return ENOMEM;
+	}
+
+	/* Insert fragment into the datagram */
+	rc = reass_dgram_insert_frag(rdg, packet);
+	if (rc != EOK)
+		return ENOMEM;
+
+	/* Check if datagram is complete */
+	if (reass_dgram_complete(rdg)) {
+		/* Remove it from the map */
+		reass_dgram_remove(rdg);
+		fibril_mutex_unlock(&reass_dgram_map_lock);
+
+		/* Deliver complete datagram */
+		rc = reass_dgram_deliver(rdg);
+		reass_dgram_destroy(rdg);
+		return rc;
+	}
+
+	fibril_mutex_unlock(&reass_dgram_map_lock);
+	return EOK;
+}
+
+/** Get datagram reassembly structure for packet.
+ *
+ * @param packet	Packet
+ * @return		Datagram reassembly structure matching @a packet
+ */
+static reass_dgram_t *reass_dgram_get(inet_packet_t *packet)
+{
+	assert(fibril_mutex_is_locked(&reass_dgram_map_lock));
+
+	list_foreach(reass_dgram_map, link) {
+		reass_dgram_t *rdg = list_get_instance(link, reass_dgram_t,
+		    map_link);
+
+		link_t *f1_link = list_first(&rdg->frags);
+		assert(f1_link != NULL);
+
+		reass_frag_t *f1 = list_get_instance(f1_link, reass_frag_t,
+		    dgram_link);
+
+		if (f1->packet.src.ipv4 == packet->src.ipv4 &&
+		    f1->packet.dest.ipv4 == packet->dest.ipv4 &&
+		    f1->packet.proto == packet->proto &&
+		    f1->packet.ident == packet->ident) {
+			/* Match */
+			return rdg;
+		}
+	}
+
+	/* No existing reassembly structure. Create a new one. */
+	return reass_dgram_new();
+}
+
+/** Create new datagram reassembly structure.
+ *
+ * @return New datagram reassembly structure.
+ */
+static reass_dgram_t *reass_dgram_new(void)
+{
+	reass_dgram_t *rdg;
+
+	rdg = calloc(1, sizeof(reass_dgram_t));
+	if (rdg == NULL)
+		return NULL;
+
+	link_initialize(&rdg->map_link);
+	list_initialize(&rdg->frags);
+
+	return rdg;
+}
+
+static reass_frag_t *reass_frag_new(void)
+{
+	reass_frag_t *frag;
+
+	frag = calloc(1, sizeof(reass_frag_t));
+	if (frag == NULL)
+		return NULL;
+
+	link_initialize(&frag->dgram_link);
+
+	return frag;
+}
+
+static int reass_dgram_insert_frag(reass_dgram_t *rdg, inet_packet_t *packet)
+{
+	reass_frag_t *frag;
+	void *data_copy;
+	link_t *link;
+
+	assert(fibril_mutex_is_locked(&reass_dgram_map_lock));
+
+	frag = reass_frag_new();
+
+	/* Clone the packet */
+
+	data_copy = malloc(packet->size);
+	if (data_copy == NULL)
+		return ENOMEM;
+
+	frag->packet = *packet;
+	frag->packet.data = data_copy;
+
+	/*
+	 * XXX Make resource-consuming attacks harder, eliminate any duplicate
+	 * data immediately. Possibly eliminate redundant packet headers.
+	 */
+
+	/*
+	 * Insert into the list, which is sorted by offs member ascending.
+	 */
+
+	link = list_first(&rdg->frags);
+	while (link != NULL) {
+		reass_frag_t *qf = list_get_instance(link, reass_frag_t,
+		    dgram_link);
+
+		if (qf->packet.offs >= packet->offs)
+			break;
+
+		link = link->next;
+	}
+
+	if (link != NULL)
+		list_insert_after(&frag->dgram_link, link);
+	else
+		list_append(&frag->dgram_link, &rdg->frags);
+
+	return EOK;
+}
+
+/** Check if datagram is complete.
+ *
+ * @param rdg		Datagram reassembly structure
+ * @return		@c true if complete, @c false if not
+ */
+static bool reass_dgram_complete(reass_dgram_t *rdg)
+{
+	reass_frag_t *frag, *prev;
+	link_t *link;
+
+	assert(fibril_mutex_is_locked(&reass_dgram_map_lock));
+	assert(!list_empty(&rdg->frags));
+
+	/* First fragment must be at offset zero */
+	frag = list_get_instance(list_first(&rdg->frags), reass_frag_t,
+	    dgram_link);
+	if (frag->packet.offs != 0)
+		return false;
+
+	prev = frag;
+	while (true) {
+		link = frag->dgram_link.next;
+		if (link == NULL)
+			return false;
+
+		/* Each next fragment must follow immediately or overlap */
+		frag = list_get_instance(link, reass_frag_t, dgram_link);
+		if (frag->packet.offs > prev->packet.offs + prev->packet.size)
+			return false;
+
+		/* No more fragments - datagram is complete */
+		if (!frag->packet.mf)
+			return true;
+
+		prev = frag;
+	}
+
+	return false;
+}
+
+/** Remove datagram from reassembly map.
+ *
+ * @param rdg		Datagram reassembly structure
+ */
+static void reass_dgram_remove(reass_dgram_t *rdg)
+{
+	assert(fibril_mutex_is_locked(&reass_dgram_map_lock));
+	list_remove(&rdg->map_link);
+}
+
+/** Deliver complete datagram.
+ *
+ * @param rdg		Datagram reassembly structure.
+ */
+static int reass_dgram_deliver(reass_dgram_t *rdg)
+{
+	size_t dgram_size;
+	size_t fragoff_limit;
+	inet_dgram_t dgram;
+	reass_frag_t *frag;
+	uint8_t proto;
+
+	/*
+	 * Potentially there could be something beyond the first packet
+	 * that has !MF. Make sure we ignore that.
+	 */
+	frag = NULL;
+	list_foreach(rdg->frags, link) {
+		frag = list_get_instance(link, reass_frag_t, dgram_link);
+
+		if (!frag->packet.mf)
+			break;
+	}
+
+	assert(frag != NULL);
+	assert(!frag->packet.mf);
+
+	dgram_size = frag->packet.offs + frag->packet.size;
+
+	/* Upper bound for fragment offset field */
+	fragoff_limit = 1 << (FF_FRAGOFF_h - FF_FRAGOFF_l);
+
+	/* Verify that total size of datagram is within reasonable bounds */
+	if (dgram_size > FRAG_OFFS_UNIT * fragoff_limit)
+		return ELIMIT;
+
+	dgram.data = calloc(dgram_size, 1);
+	if (dgram.data == NULL)
+		return ENOMEM;
+
+	dgram.size = dgram_size;
+	dgram.src = frag->packet.src;
+	dgram.dest = frag->packet.dest;
+	dgram.tos = frag->packet.tos;
+	proto = frag->packet.proto;
+
+	/* Pull together data from individual fragments */
+
+	size_t doffs = 0;
+
+	frag = NULL;
+	list_foreach(rdg->frags, link) {
+		frag = list_get_instance(link, reass_frag_t, dgram_link);
+
+		size_t cb, ce;
+
+		cb = max(doffs, frag->packet.offs);
+		ce = min(dgram_size, frag->packet.offs + frag->packet.size);
+
+		if (ce > cb) {
+			memcpy(dgram.data + cb,
+			    frag->packet.data + cb - frag->packet.offs,
+			    ce - cb);
+		}
+
+		if (!frag->packet.mf)
+			break;
+	}
+
+	return inet_recv_dgram_local(&dgram, proto);
+}
+
+/** Destroy datagram reassembly structure.
+ *
+ * @param rdg		Datagram reassembly structure.
+ */
+static void reass_dgram_destroy(reass_dgram_t *rdg)
+{
+	while (!list_empty(&rdg->frags)) {
+		link_t *flink = list_first(&rdg->frags);
+		reass_frag_t *frag = list_get_instance(flink, reass_frag_t,
+		    dgram_link);
+
+		list_remove(&frag->dgram_link);
+		free(frag->packet.data);
+		free(frag);
+	}
+
+	free(rdg);
+}
+
+/** @}
+ */
Index: uspace/srv/net/inet/reass.h
===================================================================
--- uspace/srv/net/inet/reass.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/inet/reass.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2012 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup inet
+ * @{
+ */
+/**
+ * @file
+ * @brief
+ */
+
+#ifndef INET_REASS_H_
+#define INET_REASS_H_
+
+#include <sys/types.h>
+#include "inet.h"
+
+extern int inet_reass_queue_packet(inet_packet_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/inet/sroute.c
===================================================================
--- uspace/srv/net/inet/sroute.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/inet/sroute.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,219 @@
+/*
+ * Copyright (c) 2012 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup inet
+ * @{
+ */
+/**
+ * @file
+ * @brief
+ */
+
+#include <bitops.h>
+#include <errno.h>
+#include <fibril_synch.h>
+#include <io/log.h>
+#include <ipc/loc.h>
+#include <stdlib.h>
+#include <str.h>
+
+#include "sroute.h"
+#include "inet.h"
+#include "inet_link.h"
+#include "inet_util.h"
+
+static FIBRIL_MUTEX_INITIALIZE(sroute_list_lock);
+static LIST_INITIALIZE(sroute_list);
+static sysarg_t sroute_id = 0;
+
+inet_sroute_t *inet_sroute_new(void)
+{
+	inet_sroute_t *sroute = calloc(1, sizeof(inet_sroute_t));
+
+	if (sroute == NULL) {
+		log_msg(LVL_ERROR, "Failed allocating static route object. "
+		    "Out of memory.");
+		return NULL;
+	}
+
+	link_initialize(&sroute->sroute_list);
+	fibril_mutex_lock(&sroute_list_lock);
+	sroute->id = ++sroute_id;
+	fibril_mutex_unlock(&sroute_list_lock);
+
+	return sroute;
+}
+
+void inet_sroute_delete(inet_sroute_t *sroute)
+{
+	if (sroute->name != NULL)
+		free(sroute->name);
+	free(sroute);
+}
+
+void inet_sroute_add(inet_sroute_t *sroute)
+{
+	fibril_mutex_lock(&sroute_list_lock);
+	list_append(&sroute->sroute_list, &sroute_list);
+	fibril_mutex_unlock(&sroute_list_lock);
+}
+
+void inet_sroute_remove(inet_sroute_t *sroute)
+{
+	fibril_mutex_lock(&sroute_list_lock);
+	list_remove(&sroute->sroute_list);
+	fibril_mutex_unlock(&sroute_list_lock);
+}
+
+/** Find address object matching address @a addr.
+ *
+ * @param addr	Address
+ */
+inet_sroute_t *inet_sroute_find(inet_addr_t *addr)
+{
+	uint32_t mask;
+	inet_sroute_t *best;
+
+	log_msg(LVL_DEBUG, "inet_sroute_find(%x)", (unsigned)addr->ipv4);
+
+	fibril_mutex_lock(&sroute_list_lock);
+
+	best = NULL;
+
+	list_foreach(sroute_list, link) {
+		inet_sroute_t *sroute = list_get_instance(link,
+		    inet_sroute_t, sroute_list);
+
+		/* Look for the most specific route */
+		if (best != NULL && best->dest.bits >= sroute->dest.bits)
+			continue;
+
+		mask = inet_netmask(sroute->dest.bits);
+		if ((sroute->dest.ipv4 & mask) == (addr->ipv4 & mask)) {
+			fibril_mutex_unlock(&sroute_list_lock);
+			log_msg(LVL_DEBUG, "inet_sroute_find: found %p",
+			    sroute);
+			return sroute;
+		}
+	}
+
+	log_msg(LVL_DEBUG, "inet_sroute_find: Not found");
+	fibril_mutex_unlock(&sroute_list_lock);
+
+	return NULL;
+}
+
+/** Find static route with a specific name.
+ *
+ * @param name	Address object name
+ * @return	Address object
+ */
+inet_sroute_t *inet_sroute_find_by_name(const char *name)
+{
+	log_msg(LVL_DEBUG, "inet_sroute_find_by_name('%s')",
+	    name);
+
+	fibril_mutex_lock(&sroute_list_lock);
+
+	list_foreach(sroute_list, link) {
+		inet_sroute_t *sroute = list_get_instance(link,
+		    inet_sroute_t, sroute_list);
+
+		if (str_cmp(sroute->name, name) == 0) {
+			fibril_mutex_unlock(&sroute_list_lock);
+			log_msg(LVL_DEBUG, "inet_sroute_find_by_name: found %p",
+			    sroute);
+			return sroute;
+		}
+	}
+
+	log_msg(LVL_DEBUG, "inet_sroute_find_by_name: Not found");
+	fibril_mutex_unlock(&sroute_list_lock);
+
+	return NULL;
+}
+
+/** Find static route with the given ID.
+ *
+ * @param id	Address object ID
+ * @return	Address object
+ */
+inet_sroute_t *inet_sroute_get_by_id(sysarg_t id)
+{
+	log_msg(LVL_DEBUG, "inet_sroute_get_by_id(%zu)", (size_t)id);
+
+	fibril_mutex_lock(&sroute_list_lock);
+
+	list_foreach(sroute_list, link) {
+		inet_sroute_t *sroute = list_get_instance(link,
+		    inet_sroute_t, sroute_list);
+
+		if (sroute->id == id) {
+			fibril_mutex_unlock(&sroute_list_lock);
+			return sroute;
+		}
+	}
+
+	fibril_mutex_unlock(&sroute_list_lock);
+
+	return NULL;
+}
+
+/** Get IDs of all static routes. */
+int inet_sroute_get_id_list(sysarg_t **rid_list, size_t *rcount)
+{
+	sysarg_t *id_list;
+	size_t count, i;
+
+	fibril_mutex_lock(&sroute_list_lock);
+	count = list_count(&sroute_list);
+
+	id_list = calloc(count, sizeof(sysarg_t));
+	if (id_list == NULL) {
+		fibril_mutex_unlock(&sroute_list_lock);
+		return ENOMEM;
+	}
+
+	i = 0;
+	list_foreach(sroute_list, link) {
+		inet_sroute_t *sroute = list_get_instance(link,
+		    inet_sroute_t, sroute_list);
+
+		id_list[i++] = sroute->id;
+	}
+
+	fibril_mutex_unlock(&sroute_list_lock);
+
+	*rid_list = id_list;
+	*rcount = count;
+
+	return EOK;
+}
+
+/** @}
+ */
Index: uspace/srv/net/inet/sroute.h
===================================================================
--- uspace/srv/net/inet/sroute.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/inet/sroute.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2012 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup inet
+ * @{
+ */
+/**
+ * @file
+ * @brief
+ */
+
+#ifndef INET_SROUTE_H_
+#define INET_SROUTE_H_
+
+#include <sys/types.h>
+#include "inet.h"
+
+extern inet_sroute_t *inet_sroute_new(void);
+extern void inet_sroute_delete(inet_sroute_t *);
+extern void inet_sroute_add(inet_sroute_t *);
+extern void inet_sroute_remove(inet_sroute_t *);
+extern inet_sroute_t *inet_sroute_find(inet_addr_t *);
+extern inet_sroute_t *inet_sroute_find_by_name(const char *);
+extern inet_sroute_t *inet_sroute_get_by_id(sysarg_t);
+extern int inet_sroute_send_dgram(inet_sroute_t *, inet_addr_t *,
+    inet_dgram_t *, uint8_t, uint8_t, int);
+extern int inet_sroute_get_id_list(sysarg_t **, size_t *);
+
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/tcp/Makefile
===================================================================
--- uspace/srv/net/tcp/Makefile	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/tcp/Makefile	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,48 @@
+#
+# Copyright (c) 2011 Jiri Svoboda
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# - Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+# - Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in the
+#   documentation and/or other materials provided with the distribution.
+# - The name of the author may not be used to endorse or promote products
+#   derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+USPACE_PREFIX = ../../..
+LIBS = $(LIBNET_PREFIX)/libnet.a
+EXTRA_CFLAGS = -I$(LIBNET_PREFIX)/include
+BINARY = tcp
+
+SOURCES = \
+	conn.c \
+	iqueue.c \
+	ncsim.c \
+	pdu.c \
+	rqueue.c \
+	segment.c \
+	seq_no.c \
+	sock.c \
+	tcp.c \
+	test.c \
+	tqueue.c \
+	ucall.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/net/tcp/conn.c
===================================================================
--- uspace/srv/net/tcp/conn.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/tcp/conn.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,1278 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup tcp
+ * @{
+ */
+
+/**
+ * @file TCP connection processing and state machine
+ */
+
+#include <adt/list.h>
+#include <bool.h>
+#include <errno.h>
+#include <io/log.h>
+#include <macros.h>
+#include <stdlib.h>
+#include "conn.h"
+#include "iqueue.h"
+#include "segment.h"
+#include "seq_no.h"
+#include "tcp_type.h"
+#include "tqueue.h"
+#include "ucall.h"
+
+#define RCV_BUF_SIZE 4096/*2*/
+#define SND_BUF_SIZE 4096
+
+#define MAX_SEGMENT_LIFETIME	(15*1000*1000) //(2*60*1000*1000)
+#define TIME_WAIT_TIMEOUT	(2*MAX_SEGMENT_LIFETIME)
+
+LIST_INITIALIZE(conn_list);
+FIBRIL_MUTEX_INITIALIZE(conn_list_lock);
+
+static void tcp_conn_seg_process(tcp_conn_t *conn, tcp_segment_t *seg);
+static void tcp_conn_tw_timer_set(tcp_conn_t *conn);
+static void tcp_conn_tw_timer_clear(tcp_conn_t *conn);
+
+/** Create new connection structure.
+ *
+ * @param lsock		Local socket (will be deeply copied)
+ * @param fsock		Foreign socket (will be deeply copied)
+ * @return		New connection or NULL
+ */
+tcp_conn_t *tcp_conn_new(tcp_sock_t *lsock, tcp_sock_t *fsock)
+{
+	tcp_conn_t *conn = NULL;
+	bool tqueue_inited = false;
+
+	/* Allocate connection structure */
+	conn = calloc(1, sizeof(tcp_conn_t));
+	if (conn == NULL)
+		goto error;
+
+	conn->tw_timer = fibril_timer_create();
+	if (conn->tw_timer == NULL)
+		goto error;
+
+	fibril_mutex_initialize(&conn->lock);
+
+	/* One for the user, one for not being in closed state */
+	atomic_set(&conn->refcnt, 2);
+
+	/* Allocate receive buffer */
+	fibril_condvar_initialize(&conn->rcv_buf_cv);
+	conn->rcv_buf_size = RCV_BUF_SIZE;
+	conn->rcv_buf_used = 0;
+	conn->rcv_buf_fin = false;
+
+	conn->rcv_buf = calloc(1, conn->rcv_buf_size);
+	if (conn->rcv_buf == NULL)
+		goto error;
+
+	/** Allocate send buffer */
+	fibril_condvar_initialize(&conn->snd_buf_cv);
+	conn->snd_buf_size = SND_BUF_SIZE;
+	conn->snd_buf_used = 0;
+	conn->snd_buf_fin = false;
+	conn->snd_buf = calloc(1, conn->snd_buf_size);
+	if (conn->snd_buf == NULL)
+		goto error;
+
+	/* Set up receive window. */
+	conn->rcv_wnd = conn->rcv_buf_size;
+
+	/* Initialize incoming segment queue */
+	tcp_iqueue_init(&conn->incoming, conn);
+
+	/* Initialize retransmission queue */
+	if (tcp_tqueue_init(&conn->retransmit, conn) != EOK)
+		goto error;
+
+	tqueue_inited = true;
+
+	/* Connection state change signalling */
+	fibril_condvar_initialize(&conn->cstate_cv);
+
+	conn->cstate_cb = NULL;
+
+	conn->cstate = st_listen;
+	conn->reset = false;
+	conn->deleted = false;
+	conn->ap = ap_passive;
+	conn->fin_is_acked = false;
+	conn->ident.local = *lsock;
+	if (fsock != NULL)
+		conn->ident.foreign = *fsock;
+
+	return conn;
+
+error:
+	if (tqueue_inited)
+		tcp_tqueue_fini(&conn->retransmit);
+	if (conn != NULL && conn->rcv_buf != NULL)
+		free(conn->rcv_buf);
+	if (conn != NULL && conn->snd_buf != NULL)
+		free(conn->snd_buf);
+	if (conn != NULL && conn->tw_timer != NULL)
+		fibril_timer_destroy(conn->tw_timer);
+	if (conn != NULL)
+		free(conn);
+
+	return NULL;
+}
+
+/** Destroy connection structure.
+ *
+ * Connection structure should be destroyed when the folowing condtitions
+ * are met:
+ * (1) user has deleted the connection
+ * (2) the connection has entered closed state
+ * (3) nobody is holding references to the connection
+ *
+ * This happens when @a conn->refcnt is zero as we count (1) and (2)
+ * as special references.
+ *
+ * @param conn		Connection
+ */
+static void tcp_conn_free(tcp_conn_t *conn)
+{
+	log_msg(LVL_DEBUG, "%s: tcp_conn_free(%p)", conn->name, conn);
+	tcp_tqueue_fini(&conn->retransmit);
+
+	if (conn->rcv_buf != NULL)
+		free(conn->rcv_buf);
+	if (conn->snd_buf != NULL)
+		free(conn->snd_buf);
+	if (conn->tw_timer != NULL)
+		fibril_timer_destroy(conn->tw_timer);
+	free(conn);
+}
+
+/** Add reference to connection.
+ *
+ * Increase connection reference count by one.
+ *
+ * @param conn		Connection
+ */
+void tcp_conn_addref(tcp_conn_t *conn)
+{
+	log_msg(LVL_DEBUG, "%s: tcp_conn_addref(%p)", conn->name, conn);
+	atomic_inc(&conn->refcnt);
+}
+
+/** Remove reference from connection.
+ *
+ * Decrease connection reference count by one.
+ *
+ * @param conn		Connection
+ */
+void tcp_conn_delref(tcp_conn_t *conn)
+{
+	log_msg(LVL_DEBUG, "%s: tcp_conn_delref(%p)", conn->name, conn);
+
+	if (atomic_predec(&conn->refcnt) == 0)
+		tcp_conn_free(conn);
+}
+
+/** Delete connection.
+ *
+ * The caller promises not make no further references to @a conn.
+ * TCP will free @a conn eventually.
+ *
+ * @param conn		Connection
+ */
+void tcp_conn_delete(tcp_conn_t *conn)
+{
+	log_msg(LVL_DEBUG, "%s: tcp_conn_delete(%p)", conn->name, conn);
+
+	assert(conn->deleted == false);
+	tcp_conn_delref(conn);
+}
+
+/** Enlist connection.
+ *
+ * Add connection to the connection map.
+ */
+void tcp_conn_add(tcp_conn_t *conn)
+{
+	tcp_conn_addref(conn);
+	fibril_mutex_lock(&conn_list_lock);
+	list_append(&conn->link, &conn_list);
+	fibril_mutex_unlock(&conn_list_lock);
+}
+
+/** Delist connection.
+ *
+ * Remove connection from the connection map.
+ */
+void tcp_conn_remove(tcp_conn_t *conn)
+{
+	fibril_mutex_lock(&conn_list_lock);
+	list_remove(&conn->link);
+	fibril_mutex_unlock(&conn_list_lock);
+	tcp_conn_delref(conn);
+}
+
+static void tcp_conn_state_set(tcp_conn_t *conn, tcp_cstate_t nstate)
+{
+	tcp_cstate_t old_state;
+
+	log_msg(LVL_DEBUG, "tcp_conn_state_set(%p)", conn);
+
+	old_state = conn->cstate;
+	conn->cstate = nstate;
+	fibril_condvar_broadcast(&conn->cstate_cv);
+
+	/* Run user callback function */
+	if (conn->cstate_cb != NULL) {
+		log_msg(LVL_DEBUG, "tcp_conn_state_set() - run user CB");
+		conn->cstate_cb(conn, conn->cstate_cb_arg);
+	} else {
+		log_msg(LVL_DEBUG, "tcp_conn_state_set() - no user CB");
+	}
+
+	assert(old_state != st_closed);
+	if (nstate == st_closed) {
+		/* Drop one reference for now being in closed state */
+		tcp_conn_delref(conn);
+	}
+}
+
+/** Synchronize connection.
+ *
+ * This is the first step of an active connection attempt,
+ * sends out SYN and sets up ISS and SND.xxx.
+ */
+void tcp_conn_sync(tcp_conn_t *conn)
+{
+	/* XXX select ISS */
+	conn->iss = 1;
+	conn->snd_nxt = conn->iss;
+	conn->snd_una = conn->iss;
+	conn->ap = ap_active;
+
+	tcp_tqueue_ctrl_seg(conn, CTL_SYN);
+	tcp_conn_state_set(conn, st_syn_sent);
+}
+
+/** FIN has been sent.
+ *
+ * This function should be called when FIN is sent over the connection,
+ * as a result the connection state is changed appropriately.
+ */
+void tcp_conn_fin_sent(tcp_conn_t *conn)
+{
+	switch (conn->cstate) {
+	case st_syn_received:
+	case st_established:
+		log_msg(LVL_DEBUG, "%s: FIN sent -> Fin-Wait-1", conn->name);
+		tcp_conn_state_set(conn, st_fin_wait_1);
+		break;
+	case st_close_wait:
+		log_msg(LVL_DEBUG, "%s: FIN sent -> Last-Ack", conn->name);
+		tcp_conn_state_set(conn, st_last_ack);
+		break;
+	default:
+		log_msg(LVL_ERROR, "%s: Connection state %d", conn->name,
+		    conn->cstate);
+		assert(false);
+	}
+
+	conn->fin_is_acked = false;
+}
+
+/** Match socket with pattern. */
+static bool tcp_socket_match(tcp_sock_t *sock, tcp_sock_t *patt)
+{
+	log_msg(LVL_DEBUG, "tcp_socket_match(sock=(%x,%u), pat=(%x,%u))",
+	    sock->addr.ipv4, sock->port, patt->addr.ipv4, patt->port);
+
+	if (patt->addr.ipv4 != TCP_IPV4_ANY &&
+	    patt->addr.ipv4 != sock->addr.ipv4)
+		return false;
+
+	if (patt->port != TCP_PORT_ANY &&
+	    patt->port != sock->port)
+		return false;
+
+	log_msg(LVL_DEBUG, " -> match");
+
+	return true;
+}
+
+/** Match socket pair with pattern. */
+static bool tcp_sockpair_match(tcp_sockpair_t *sp, tcp_sockpair_t *pattern)
+{
+	log_msg(LVL_DEBUG, "tcp_sockpair_match(%p, %p)", sp, pattern);
+
+	if (!tcp_socket_match(&sp->local, &pattern->local))
+		return false;
+
+	if (!tcp_socket_match(&sp->foreign, &pattern->foreign))
+		return false;
+
+	return true;
+}
+
+/** Find connection structure for specified socket pair.
+ *
+ * A connection is uniquely identified by a socket pair. Look up our
+ * connection map and return connection structure based on socket pair.
+ * The connection reference count is bumped by one.
+ *
+ * @param sp	Socket pair
+ * @return	Connection structure or NULL if not found.
+ */
+tcp_conn_t *tcp_conn_find_ref(tcp_sockpair_t *sp)
+{
+	log_msg(LVL_DEBUG, "tcp_conn_find_ref(%p)", sp);
+
+	fibril_mutex_lock(&conn_list_lock);
+
+	list_foreach(conn_list, link) {
+		tcp_conn_t *conn = list_get_instance(link, tcp_conn_t, link);
+		tcp_sockpair_t *csp = &conn->ident;
+		log_msg(LVL_DEBUG, "compare with conn (f:(%x,%u), l:(%x,%u))",
+		    csp->foreign.addr.ipv4, csp->foreign.port,
+		    csp->local.addr.ipv4, csp->local.port);
+		if (tcp_sockpair_match(sp, csp)) {
+			tcp_conn_addref(conn);
+			fibril_mutex_unlock(&conn_list_lock);
+			return conn;
+		}
+	}
+
+	fibril_mutex_unlock(&conn_list_lock);
+	return NULL;
+}
+
+/** Reset connection.
+ *
+ * @param conn	Connection
+ */
+static void tcp_conn_reset(tcp_conn_t *conn)
+{
+	log_msg(LVL_DEBUG, "%s: tcp_conn_reset()", conn->name);
+	tcp_conn_state_set(conn, st_closed);
+	conn->reset = true;
+
+	tcp_conn_tw_timer_clear(conn);
+	tcp_tqueue_clear(&conn->retransmit);
+
+	fibril_condvar_broadcast(&conn->rcv_buf_cv);
+	fibril_condvar_broadcast(&conn->snd_buf_cv);
+}
+
+/** Signal to the user that connection has been reset.
+ *
+ * Send an out-of-band signal to the user.
+ */
+static void tcp_reset_signal(tcp_conn_t *conn)
+{
+	/* TODO */
+	log_msg(LVL_DEBUG, "%s: tcp_reset_signal()", conn->name);
+}
+
+/** Determine if SYN has been received.
+ *
+ * @param conn	Connection
+ * @return	@c true if SYN has been received, @c false otherwise.
+ */
+bool tcp_conn_got_syn(tcp_conn_t *conn)
+{
+	switch (conn->cstate) {
+	case st_listen:
+	case st_syn_sent:
+		return false;
+	case st_syn_received:
+	case st_established:
+	case st_fin_wait_1:
+	case st_fin_wait_2:
+	case st_close_wait:
+	case st_closing:
+	case st_last_ack:
+	case st_time_wait:
+		return true;
+	case st_closed:
+		log_msg(LVL_WARN, "state=%d", (int) conn->cstate);
+		assert(false);
+	}
+
+	assert(false);
+}
+
+/** Segment arrived in Listen state.
+ *
+ * @param conn		Connection
+ * @param seg		Segment
+ */
+static void tcp_conn_sa_listen(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	log_msg(LVL_DEBUG, "tcp_conn_sa_listen(%p, %p)", conn, seg);
+
+	if ((seg->ctrl & CTL_RST) != 0) {
+		log_msg(LVL_DEBUG, "Ignoring incoming RST.");
+		return;
+	}
+
+	if ((seg->ctrl & CTL_ACK) != 0) {
+		log_msg(LVL_DEBUG, "Incoming ACK, send acceptable RST.");
+		tcp_reply_rst(&conn->ident, seg);
+		return;
+	}
+
+	if ((seg->ctrl & CTL_SYN) == 0) {
+		log_msg(LVL_DEBUG, "SYN not present. Ignoring segment.");
+		return;
+	}
+
+	log_msg(LVL_DEBUG, "Got SYN, sending SYN, ACK.");
+
+	conn->rcv_nxt = seg->seq + 1;
+	conn->irs = seg->seq;
+
+
+	log_msg(LVL_DEBUG, "rcv_nxt=%u", conn->rcv_nxt);
+
+	if (seg->len > 1)
+		log_msg(LVL_WARN, "SYN combined with data, ignoring data.");
+
+	/* XXX select ISS */
+	conn->iss = 1;
+	conn->snd_nxt = conn->iss;
+	conn->snd_una = conn->iss;
+
+	/*
+	 * Surprisingly the spec does not deal with initial window setting.
+	 * Set SND.WND = SEG.WND and set SND.WL1 so that next segment
+	 * will always be accepted as new window setting.
+	 */
+	conn->snd_wnd = seg->wnd;
+	conn->snd_wl1 = seg->seq;
+	conn->snd_wl2 = seg->seq;
+
+	tcp_conn_state_set(conn, st_syn_received);
+
+	tcp_tqueue_ctrl_seg(conn, CTL_SYN | CTL_ACK /* XXX */);
+
+	tcp_segment_delete(seg);
+}
+
+/** Segment arrived in Syn-Sent state.
+ *
+ * @param conn		Connection
+ * @param seg		Segment
+ */
+static void tcp_conn_sa_syn_sent(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	log_msg(LVL_DEBUG, "tcp_conn_sa_syn_sent(%p, %p)", conn, seg);
+
+	if ((seg->ctrl & CTL_ACK) != 0) {
+		log_msg(LVL_DEBUG, "snd_una=%u, seg.ack=%u, snd_nxt=%u",
+		    conn->snd_una, seg->ack, conn->snd_nxt);
+		if (!seq_no_ack_acceptable(conn, seg->ack)) {
+			if ((seg->ctrl & CTL_RST) == 0) {
+				log_msg(LVL_WARN, "ACK not acceptable, send RST");
+				tcp_reply_rst(&conn->ident, seg);
+			} else {
+				log_msg(LVL_WARN, "RST,ACK not acceptable, drop");
+			}
+			return;
+		}
+	}
+
+	if ((seg->ctrl & CTL_RST) != 0) {
+		/* If we get here, we have either an acceptable ACK or no ACK */
+		if ((seg->ctrl & CTL_ACK) != 0) {
+			log_msg(LVL_DEBUG, "%s: Connection reset. -> Closed",
+			    conn->name);
+			/* Reset connection */
+			tcp_conn_reset(conn);
+			return;
+		} else {
+			log_msg(LVL_DEBUG, "%s: RST without ACK, drop",
+			    conn->name);
+			return;
+		}
+	}
+
+	/* XXX precedence */
+
+	if ((seg->ctrl & CTL_SYN) == 0) {
+		log_msg(LVL_DEBUG, "No SYN bit, ignoring segment.");
+		return;
+	}
+
+	conn->rcv_nxt = seg->seq + 1;
+	conn->irs = seg->seq;
+
+	if ((seg->ctrl & CTL_ACK) != 0) {
+		conn->snd_una = seg->ack;
+
+		/*
+		 * Prune acked segments from retransmission queue and
+		 * possibly transmit more data.
+		 */
+		tcp_tqueue_ack_received(conn);
+	}
+
+	log_msg(LVL_DEBUG, "Sent SYN, got SYN.");
+
+	/*
+	 * Surprisingly the spec does not deal with initial window setting.
+	 * Set SND.WND = SEG.WND and set SND.WL1 so that next segment
+	 * will always be accepted as new window setting.
+	 */
+	log_msg(LVL_DEBUG, "SND.WND := %" PRIu32 ", SND.WL1 := %" PRIu32 ", "
+	    "SND.WL2 = %" PRIu32, seg->wnd, seg->seq, seg->seq);
+	conn->snd_wnd = seg->wnd;
+	conn->snd_wl1 = seg->seq;
+	conn->snd_wl2 = seg->seq;
+
+	if (seq_no_syn_acked(conn)) {
+		log_msg(LVL_DEBUG, "%s: syn acked -> Established", conn->name);
+		tcp_conn_state_set(conn, st_established);
+		tcp_tqueue_ctrl_seg(conn, CTL_ACK /* XXX */);
+	} else {
+		log_msg(LVL_DEBUG, "%s: syn not acked -> Syn-Received",
+		    conn->name);
+		tcp_conn_state_set(conn, st_syn_received);
+		tcp_tqueue_ctrl_seg(conn, CTL_SYN | CTL_ACK /* XXX */);
+	}
+
+	tcp_segment_delete(seg);
+}
+
+/** Segment arrived in state where segments are processed in sequence order.
+ *
+ * Queue segment in incoming segments queue for processing.
+ *
+ * @param conn		Connection
+ * @param seg		Segment
+ */
+static void tcp_conn_sa_queue(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	tcp_segment_t *pseg;
+
+	log_msg(LVL_DEBUG, "tcp_conn_sa_seq(%p, %p)", conn, seg);
+
+	/* Discard unacceptable segments ("old duplicates") */
+	if (!seq_no_segment_acceptable(conn, seg)) {
+		log_msg(LVL_DEBUG, "Replying ACK to unacceptable segment.");
+		tcp_tqueue_ctrl_seg(conn, CTL_ACK);
+		tcp_segment_delete(seg);
+		return;
+	}
+
+	/* Queue for processing */
+	tcp_iqueue_insert_seg(&conn->incoming, seg);
+
+	/*
+	 * Process all segments from incoming queue that are ready.
+	 * Unacceptable segments are discarded by tcp_iqueue_get_ready_seg().
+	 *
+	 * XXX Need to return ACK for unacceptable segments
+	 */
+	while (tcp_iqueue_get_ready_seg(&conn->incoming, &pseg) == EOK)
+		tcp_conn_seg_process(conn, pseg);
+}
+
+/** Process segment RST field.
+ *
+ * @param conn		Connection
+ * @param seg		Segment
+ * @return		cp_done if we are done with this segment, cp_continue
+ *			if not
+ */
+static cproc_t tcp_conn_seg_proc_rst(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	if ((seg->ctrl & CTL_RST) == 0)
+		return cp_continue;
+
+	switch (conn->cstate) {
+	case st_syn_received:
+		/* XXX In case of passive open, revert to Listen state */
+		if (conn->ap == ap_passive) {
+			tcp_conn_state_set(conn, st_listen);
+			/* XXX Revert conn->ident */
+			tcp_conn_tw_timer_clear(conn);
+			tcp_tqueue_clear(&conn->retransmit);
+		} else {
+			tcp_conn_reset(conn);
+		}
+		break;
+	case st_established:
+	case st_fin_wait_1:
+	case st_fin_wait_2:
+	case st_close_wait:
+		/* General "connection reset" signal */
+		tcp_reset_signal(conn);
+		tcp_conn_reset(conn);
+		break;
+	case st_closing:
+	case st_last_ack:
+	case st_time_wait:
+		tcp_conn_reset(conn);
+		break;
+	case st_listen:
+	case st_syn_sent:
+	case st_closed:
+		assert(false);
+	}
+
+	return cp_done;
+}
+
+/** Process segment security and precedence fields.
+ *
+ * @param conn		Connection
+ * @param seg		Segment
+ * @return		cp_done if we are done with this segment, cp_continue
+ *			if not
+ */
+static cproc_t tcp_conn_seg_proc_sp(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	/* TODO */
+	return cp_continue;
+}
+
+/** Process segment SYN field.
+ *
+ * @param conn		Connection
+ * @param seg		Segment
+ * @return		cp_done if we are done with this segment, cp_continue
+ *			if not
+ */
+static cproc_t tcp_conn_seg_proc_syn(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	if ((seg->ctrl & CTL_SYN) == 0)
+		return cp_continue;
+
+	/*
+	 * Assert SYN is in receive window, otherwise this step should not
+	 * be reached.
+	 */
+	assert(seq_no_in_rcv_wnd(conn, seg->seq));
+
+	log_msg(LVL_WARN, "SYN is in receive window, should send reset. XXX");
+
+	/*
+	 * TODO
+	 *
+	 * Send a reset, resond "reset" to all outstanding RECEIVEs and SEND,
+	 * flush segment queues. Send unsolicited "connection reset" signal
+	 * to user, connection -> closed state, delete TCB, return.
+	 */
+	return cp_done;
+}
+
+/** Process segment ACK field in Syn-Received state.
+ *
+ * @param conn		Connection
+ * @param seg		Segment
+ * @return		cp_done if we are done with this segment, cp_continue
+ *			if not
+ */
+static cproc_t tcp_conn_seg_proc_ack_sr(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	if (!seq_no_ack_acceptable(conn, seg->ack)) {
+		/* ACK is not acceptable, send RST. */
+		log_msg(LVL_WARN, "Segment ACK not acceptable, sending RST.");
+		tcp_reply_rst(&conn->ident, seg);
+		tcp_segment_delete(seg);
+		return cp_done;
+	}
+
+	log_msg(LVL_DEBUG, "%s: SYN ACKed -> Established", conn->name);
+
+	tcp_conn_state_set(conn, st_established);
+
+	/* XXX Not mentioned in spec?! */
+	conn->snd_una = seg->ack;
+
+	return cp_continue;
+}
+
+/** Process segment ACK field in Established state.
+ *
+ * @param conn		Connection
+ * @param seg		Segment
+ * @return		cp_done if we are done with this segment, cp_continue
+ *			if not
+ */
+static cproc_t tcp_conn_seg_proc_ack_est(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	log_msg(LVL_DEBUG, "tcp_conn_seg_proc_ack_est(%p, %p)", conn, seg);
+
+	log_msg(LVL_DEBUG, "SEG.ACK=%u, SND.UNA=%u, SND.NXT=%u",
+	    (unsigned)seg->ack, (unsigned)conn->snd_una,
+	    (unsigned)conn->snd_nxt);
+
+	if (!seq_no_ack_acceptable(conn, seg->ack)) {
+		log_msg(LVL_DEBUG, "ACK not acceptable.");
+		if (!seq_no_ack_duplicate(conn, seg->ack)) {
+			log_msg(LVL_WARN, "Not acceptable, not duplicate. "
+			    "Send ACK and drop.");
+			/* Not acceptable, not duplicate. Send ACK and drop. */
+			tcp_tqueue_ctrl_seg(conn, CTL_ACK);
+			tcp_segment_delete(seg);
+			return cp_done;
+		} else {
+			log_msg(LVL_DEBUG, "Ignoring duplicate ACK.");
+		}
+	} else {
+		/* Update SND.UNA */
+		conn->snd_una = seg->ack;
+	}
+
+	if (seq_no_new_wnd_update(conn, seg)) {
+		conn->snd_wnd = seg->wnd;
+		conn->snd_wl1 = seg->seq;
+		conn->snd_wl2 = seg->ack;
+
+		log_msg(LVL_DEBUG, "Updating send window, SND.WND=%" PRIu32
+		    ", SND.WL1=%" PRIu32 ", SND.WL2=%" PRIu32,
+		    conn->snd_wnd, conn->snd_wl1, conn->snd_wl2);
+	}
+
+	/*
+	 * Prune acked segments from retransmission queue and
+	 * possibly transmit more data.
+	 */
+	tcp_tqueue_ack_received(conn);
+
+	return cp_continue;
+}
+
+/** Process segment ACK field in Fin-Wait-1 state.
+ *
+ * @param conn		Connection
+ * @param seg		Segment
+ * @return		cp_done if we are done with this segment, cp_continue
+ *			if not
+ */
+static cproc_t tcp_conn_seg_proc_ack_fw1(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	if (tcp_conn_seg_proc_ack_est(conn, seg) == cp_done)
+		return cp_done;
+
+	if (conn->fin_is_acked) {
+		log_msg(LVL_DEBUG, "%s: FIN acked -> Fin-Wait-2", conn->name);
+		tcp_conn_state_set(conn, st_fin_wait_2);
+	}
+
+	return cp_continue;
+}
+
+/** Process segment ACK field in Fin-Wait-2 state.
+ *
+ * @param conn		Connection
+ * @param seg		Segment
+ * @return		cp_done if we are done with this segment, cp_continue
+ *			if not
+ */
+static cproc_t tcp_conn_seg_proc_ack_fw2(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	if (tcp_conn_seg_proc_ack_est(conn, seg) == cp_done)
+		return cp_done;
+
+	/* TODO */
+	return cp_continue;
+}
+
+/** Process segment ACK field in Close-Wait state.
+ *
+ * @param conn		Connection
+ * @param seg		Segment
+ * @return		cp_done if we are done with this segment, cp_continue
+ *			if not
+ */
+static cproc_t tcp_conn_seg_proc_ack_cw(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	/* The same processing as in Established state */
+	return tcp_conn_seg_proc_ack_est(conn, seg);
+}
+
+/** Process segment ACK field in Closing state.
+ *
+ * @param conn		Connection
+ * @param seg		Segment
+ * @return		cp_done if we are done with this segment, cp_continue
+ *			if not
+ */
+static cproc_t tcp_conn_seg_proc_ack_cls(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	if (tcp_conn_seg_proc_ack_est(conn, seg) == cp_done)
+		return cp_done;
+
+	/* TODO */
+	return cp_continue;
+}
+
+/** Process segment ACK field in Last-Ack state.
+ *
+ * @param conn		Connection
+ * @param seg		Segment
+ * @return		cp_done if we are done with this segment, cp_continue
+ *			if not
+ */
+static cproc_t tcp_conn_seg_proc_ack_la(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	if (tcp_conn_seg_proc_ack_est(conn, seg) == cp_done)
+		return cp_done;
+
+	if (conn->fin_is_acked) {
+		log_msg(LVL_DEBUG, "%s: FIN acked -> Closed", conn->name);
+		tcp_conn_remove(conn);
+		tcp_conn_state_set(conn, st_closed);
+		return cp_done;
+	}
+
+	return cp_continue;
+}
+
+/** Process segment ACK field in Time-Wait state.
+ *
+ * @param conn		Connection
+ * @param seg		Segment
+ * @return		cp_done if we are done with this segment, cp_continue
+ *			if not
+ */
+static cproc_t tcp_conn_seg_proc_ack_tw(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	/* Nothing to do */
+	return cp_continue;
+}
+
+/** Process segment ACK field.
+ *
+ * @param conn		Connection
+ * @param seg		Segment
+ * @return		cp_done if we are done with this segment, cp_continue
+ *			if not
+ */
+static cproc_t tcp_conn_seg_proc_ack(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	log_msg(LVL_DEBUG, "%s: tcp_conn_seg_proc_ack(%p, %p)",
+	    conn->name, conn, seg);
+
+	if ((seg->ctrl & CTL_ACK) == 0) {
+		log_msg(LVL_WARN, "Segment has no ACK. Dropping.");
+		tcp_segment_delete(seg);
+		return cp_done;
+	}
+
+	switch (conn->cstate) {
+	case st_syn_received:
+		return tcp_conn_seg_proc_ack_sr(conn, seg);
+	case st_established:
+		return tcp_conn_seg_proc_ack_est(conn, seg);
+	case st_fin_wait_1:
+		return tcp_conn_seg_proc_ack_fw1(conn, seg);
+	case st_fin_wait_2:
+		return tcp_conn_seg_proc_ack_fw2(conn, seg);
+	case st_close_wait:
+		return tcp_conn_seg_proc_ack_cw(conn, seg);
+	case st_closing:
+		return tcp_conn_seg_proc_ack_cls(conn, seg);
+	case st_last_ack:
+		return tcp_conn_seg_proc_ack_la(conn, seg);
+	case st_time_wait:
+		return tcp_conn_seg_proc_ack_tw(conn, seg);
+	case st_listen:
+	case st_syn_sent:
+	case st_closed:
+		assert(false);
+	}
+
+	assert(false);
+}
+
+/** Process segment URG field.
+ *
+ * @param conn		Connection
+ * @param seg		Segment
+ * @return		cp_done if we are done with this segment, cp_continue
+ *			if not
+ */
+static cproc_t tcp_conn_seg_proc_urg(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	return cp_continue;
+}
+
+/** Process segment text.
+ *
+ * @param conn		Connection
+ * @param seg		Segment
+ * @return		cp_done if we are done with this segment, cp_continue
+ *			if not
+ */
+static cproc_t tcp_conn_seg_proc_text(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	size_t text_size;
+	size_t xfer_size;
+
+	log_msg(LVL_DEBUG, "%s: tcp_conn_seg_proc_text(%p, %p)",
+	    conn->name, conn, seg);
+
+	switch (conn->cstate) {
+	case st_established:
+	case st_fin_wait_1:
+	case st_fin_wait_2:
+		/* OK */
+		break;
+	case st_close_wait:
+	case st_closing:
+	case st_last_ack:
+	case st_time_wait:
+		/* Invalid since FIN has been received. Ignore text. */
+		return cp_continue;
+	case st_listen:
+	case st_syn_sent:
+	case st_syn_received:
+	case st_closed:
+		assert(false);
+	}
+
+	/*
+	 * Process segment text
+	 */
+	assert(seq_no_segment_ready(conn, seg));
+
+	/* Trim anything outside our receive window */
+	tcp_conn_trim_seg_to_wnd(conn, seg);
+
+	/* Determine how many bytes to copy */
+	text_size = tcp_segment_text_size(seg);
+	xfer_size = min(text_size, conn->rcv_buf_size - conn->rcv_buf_used);
+
+	/* Copy data to receive buffer */
+	tcp_segment_text_copy(seg, conn->rcv_buf + conn->rcv_buf_used,
+	    xfer_size);
+	conn->rcv_buf_used += xfer_size;
+
+	/* Signal to the receive function that new data has arrived */
+	fibril_condvar_broadcast(&conn->rcv_buf_cv);
+
+	log_msg(LVL_DEBUG, "Received %zu bytes of data.", xfer_size);
+
+	/* Advance RCV.NXT */
+	conn->rcv_nxt += xfer_size;
+
+	/* Update receive window. XXX Not an efficient strategy. */
+	conn->rcv_wnd -= xfer_size;
+
+	/* Send ACK */
+	if (xfer_size > 0)
+		tcp_tqueue_ctrl_seg(conn, CTL_ACK);
+
+	if (xfer_size < seg->len) {
+		/* Trim part of segment which we just received */
+		tcp_conn_trim_seg_to_wnd(conn, seg);
+	} else {
+		log_msg(LVL_DEBUG, "%s: Nothing left in segment, dropping "
+		    "(xfer_size=%zu, SEG.LEN=%zu, seg->ctrl=%u)",
+		    conn->name, xfer_size, seg->len, (unsigned)seg->ctrl);
+		/* Nothing left in segment */
+		tcp_segment_delete(seg);
+		return cp_done;
+	}
+
+	return cp_continue;
+}
+
+/** Process segment FIN field.
+ *
+ * @param conn		Connection
+ * @param seg		Segment
+ * @return		cp_done if we are done with this segment, cp_continue
+ *			if not
+ */
+static cproc_t tcp_conn_seg_proc_fin(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	log_msg(LVL_DEBUG, "%s: tcp_conn_seg_proc_fin(%p, %p)",
+	    conn->name, conn, seg);
+	log_msg(LVL_DEBUG, " seg->len=%zu, seg->ctl=%u", (size_t) seg->len,
+	    (unsigned) seg->ctrl);
+
+	/* Only process FIN if no text is left in segment. */
+	if (tcp_segment_text_size(seg) == 0 && (seg->ctrl & CTL_FIN) != 0) {
+		log_msg(LVL_DEBUG, " - FIN found in segment.");
+
+		/* Send ACK */
+		tcp_tqueue_ctrl_seg(conn, CTL_ACK);
+
+		conn->rcv_nxt++;
+		conn->rcv_wnd--;
+
+		/* Change connection state */
+		switch (conn->cstate) {
+		case st_listen:
+		case st_syn_sent:
+		case st_closed:
+			/* Connection not synchronized */
+			assert(false);
+		case st_syn_received:
+		case st_established:
+			log_msg(LVL_DEBUG, "%s: FIN received -> Close-Wait",
+			    conn->name);
+			tcp_conn_state_set(conn, st_close_wait);
+			break;
+		case st_fin_wait_1:
+			log_msg(LVL_DEBUG, "%s: FIN received -> Closing",
+			    conn->name);
+			tcp_conn_state_set(conn, st_closing);
+			break;
+		case st_fin_wait_2:
+			log_msg(LVL_DEBUG, "%s: FIN received -> Time-Wait",
+			    conn->name);
+			tcp_conn_state_set(conn, st_time_wait);
+			/* Start the Time-Wait timer */
+			tcp_conn_tw_timer_set(conn);
+			break;
+		case st_close_wait:
+		case st_closing:
+		case st_last_ack:
+			/* Do nothing */
+			break;
+		case st_time_wait:
+			/* Restart the Time-Wait timer */
+			tcp_conn_tw_timer_set(conn);
+			break;
+		}
+
+		/* Add FIN to the receive buffer */
+		conn->rcv_buf_fin = true;
+		fibril_condvar_broadcast(&conn->rcv_buf_cv);
+
+		tcp_segment_delete(seg);
+		return cp_done;
+	}
+
+	return cp_continue;
+}
+
+/** Process incoming segment.
+ *
+ * We are in connection state where segments are processed in order
+ * of sequence number. This processes one segment taken from the
+ * connection incoming segments queue.
+ *
+ * @param conn		Connection
+ * @param seg		Segment
+ */
+static void tcp_conn_seg_process(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	log_msg(LVL_DEBUG, "tcp_conn_seg_process(%p, %p)", conn, seg);
+	tcp_segment_dump(seg);
+
+	/* Check whether segment is acceptable */
+	/* XXX Permit valid ACKs, URGs and RSTs */
+/*	if (!seq_no_segment_acceptable(conn, seg)) {
+		log_msg(LVL_WARN, "Segment not acceptable, dropping.");
+		if ((seg->ctrl & CTL_RST) == 0) {
+			tcp_tqueue_ctrl_seg(conn, CTL_ACK);
+		}
+		return;
+	}
+*/
+
+	if (tcp_conn_seg_proc_rst(conn, seg) == cp_done)
+		return;
+
+	if (tcp_conn_seg_proc_sp(conn, seg) == cp_done)
+		return;
+
+	if (tcp_conn_seg_proc_syn(conn, seg) == cp_done)
+		return;
+
+	if (tcp_conn_seg_proc_ack(conn, seg) == cp_done)
+		return;
+
+	if (tcp_conn_seg_proc_urg(conn, seg) == cp_done)
+		return;
+
+	if (tcp_conn_seg_proc_text(conn, seg) == cp_done)
+		return;
+
+	if (tcp_conn_seg_proc_fin(conn, seg) == cp_done)
+		return;
+
+	/*
+	 * If anything is left from the segment, insert it back into the
+	 * incoming segments queue.
+	 */
+	if (seg->len > 0) {
+		log_msg(LVL_DEBUG, "Re-insert segment %p. seg->len=%zu",
+		    seg, (size_t) seg->len);
+		tcp_iqueue_insert_seg(&conn->incoming, seg);
+	} else {
+		tcp_segment_delete(seg);
+	}
+}
+
+/** Segment arrived on a connection.
+ *
+ * @param conn		Connection
+ * @param seg		Segment
+ */
+void tcp_conn_segment_arrived(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	log_msg(LVL_DEBUG, "%c: tcp_conn_segment_arrived(%p)",
+	    conn->name, seg);
+
+	switch (conn->cstate) {
+	case st_listen:
+		tcp_conn_sa_listen(conn, seg); break;
+	case st_syn_sent:
+		tcp_conn_sa_syn_sent(conn, seg); break;
+	case st_syn_received:
+	case st_established:
+	case st_fin_wait_1:
+	case st_fin_wait_2:
+	case st_close_wait:
+	case st_closing:
+	case st_last_ack:
+	case st_time_wait:
+		/* Process segments in order of sequence number */
+		tcp_conn_sa_queue(conn, seg); break;
+	case st_closed:
+		log_msg(LVL_DEBUG, "state=%d", (int) conn->cstate);
+		assert(false);
+	}
+}
+
+/** Time-Wait timeout handler.
+ *
+ * @param arg	Connection
+ */
+static void tw_timeout_func(void *arg)
+{
+	tcp_conn_t *conn = (tcp_conn_t *) arg;
+
+	log_msg(LVL_DEBUG, "tw_timeout_func(%p)", conn);
+
+	fibril_mutex_lock(&conn->lock);
+
+	if (conn->cstate == st_closed) {
+		log_msg(LVL_DEBUG, "Connection already closed.");
+		fibril_mutex_unlock(&conn->lock);
+		tcp_conn_delref(conn);
+		return;
+	}
+
+	log_msg(LVL_DEBUG, "%s: TW Timeout -> Closed", conn->name);
+	tcp_conn_remove(conn);
+	tcp_conn_state_set(conn, st_closed);
+
+	fibril_mutex_unlock(&conn->lock);
+	tcp_conn_delref(conn);
+}
+
+/** Start or restart the Time-Wait timeout.
+ *
+ * @param conn		Connection
+ */
+void tcp_conn_tw_timer_set(tcp_conn_t *conn)
+{
+	tcp_conn_addref(conn);
+	fibril_timer_set(conn->tw_timer, TIME_WAIT_TIMEOUT, tw_timeout_func,
+	    (void *)conn);
+}
+
+/** Clear the Time-Wait timeout.
+ *
+ * @param conn		Connection
+ */
+void tcp_conn_tw_timer_clear(tcp_conn_t *conn)
+{
+	if (fibril_timer_clear(conn->tw_timer) == fts_active)
+		tcp_conn_delref(conn);
+}
+
+/** Trim segment to the receive window.
+ *
+ * @param conn		Connection
+ * @param seg		Segment
+ */
+void tcp_conn_trim_seg_to_wnd(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	uint32_t left, right;
+
+	seq_no_seg_trim_calc(conn, seg, &left, &right);
+	tcp_segment_trim(seg, left, right);
+}
+
+/** Handle unexpected segment received on a socket pair.
+ *
+ * We reply with an RST unless the received segment has RST.
+ *
+ * @param sp		Socket pair which received the segment
+ * @param seg		Unexpected segment
+ */
+void tcp_unexpected_segment(tcp_sockpair_t *sp, tcp_segment_t *seg)
+{
+	log_msg(LVL_DEBUG, "tcp_unexpected_segment(%p, %p)", sp, seg);
+
+	if ((seg->ctrl & CTL_RST) == 0)
+		tcp_reply_rst(sp, seg);
+}
+
+/** Compute flipped socket pair for response.
+ *
+ * Flipped socket pair has local and foreign sockets exchanged.
+ *
+ * @param sp		Socket pair
+ * @param fsp		Place to store flipped socket pair
+ */
+void tcp_sockpair_flipped(tcp_sockpair_t *sp, tcp_sockpair_t *fsp)
+{
+	fsp->local = sp->foreign;
+	fsp->foreign = sp->local;
+}
+
+/** Send RST in response to an incoming segment.
+ *
+ * @param sp		Socket pair which received the segment
+ * @param seg		Incoming segment
+ */
+void tcp_reply_rst(tcp_sockpair_t *sp, tcp_segment_t *seg)
+{
+	tcp_segment_t *rseg;
+
+	log_msg(LVL_DEBUG, "tcp_reply_rst(%p, %p)", sp, seg);
+
+	rseg = tcp_segment_make_rst(seg);
+	tcp_transmit_segment(sp, rseg);
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/net/tcp/conn.h
===================================================================
--- uspace/srv/net/tcp/conn.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/tcp/conn.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup tcp
+ * @{
+ */
+/** @file TCP connection processing and state machine
+ */
+
+#ifndef CONN_H
+#define CONN_H
+
+#include <bool.h>
+#include "tcp_type.h"
+
+extern tcp_conn_t *tcp_conn_new(tcp_sock_t *, tcp_sock_t *);
+extern void tcp_conn_delete(tcp_conn_t *);
+extern void tcp_conn_add(tcp_conn_t *);
+extern void tcp_conn_remove(tcp_conn_t *);
+extern void tcp_conn_sync(tcp_conn_t *);
+extern void tcp_conn_fin_sent(tcp_conn_t *);
+extern void tcp_conn_ack_of_fin_rcvd(tcp_conn_t *);
+extern tcp_conn_t *tcp_conn_find_ref(tcp_sockpair_t *);
+extern void tcp_conn_addref(tcp_conn_t *);
+extern void tcp_conn_delref(tcp_conn_t *);
+extern bool tcp_conn_got_syn(tcp_conn_t *);
+extern void tcp_conn_segment_arrived(tcp_conn_t *, tcp_segment_t *);
+extern void tcp_conn_trim_seg_to_wnd(tcp_conn_t *, tcp_segment_t *);
+extern void tcp_unexpected_segment(tcp_sockpair_t *, tcp_segment_t *);
+extern void tcp_sockpair_flipped(tcp_sockpair_t *, tcp_sockpair_t *);
+extern void tcp_reply_rst(tcp_sockpair_t *, tcp_segment_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/tcp/iqueue.c
===================================================================
--- uspace/srv/net/tcp/iqueue.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/tcp/iqueue.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup tcp
+ * @{
+ */
+
+/**
+ * @file Connection incoming segments queue
+ *
+ * Segments are sorted in order of their sequence number.
+ */
+
+#include <adt/list.h>
+#include <errno.h>
+#include <io/log.h>
+#include <stdlib.h>
+#include "iqueue.h"
+#include "segment.h"
+#include "seq_no.h"
+#include "tcp_type.h"
+
+/** Initialize incoming segments queue.
+ *
+ * @param iqueue	Incoming queue
+ * @param conn		Connection the queue is associated with
+ */
+void tcp_iqueue_init(tcp_iqueue_t *iqueue, tcp_conn_t *conn)
+{
+	list_initialize(&iqueue->list);
+	iqueue->conn = conn;
+}
+
+/** Insert segment into incoming queue.
+ *
+ * @param iqueue	Incoming queue
+ * @param seg		Segment
+ */
+void tcp_iqueue_insert_seg(tcp_iqueue_t *iqueue, tcp_segment_t *seg)
+{
+	tcp_iqueue_entry_t *iqe;
+	tcp_iqueue_entry_t *qe;
+	link_t *link;
+	log_msg(LVL_DEBUG, "tcp_iqueue_insert_seg()");
+
+	iqe = calloc(1, sizeof(tcp_iqueue_entry_t));
+	if (iqe == NULL) {
+		log_msg(LVL_ERROR, "Failed allocating IQE.");
+		return;
+	}
+
+	iqe->seg = seg;
+
+	/* Sort by sequence number */
+
+	link = list_first(&iqueue->list);
+	while (link != NULL) {
+		qe = list_get_instance(link,
+		    tcp_iqueue_entry_t, link);
+
+		if (seq_no_seg_cmp(iqueue->conn, iqe->seg, qe->seg) >= 0)
+			break;
+	}
+
+	if (link != NULL)
+		list_insert_before(&iqe->link, &qe->link);
+	else
+		list_append(&iqe->link, &iqueue->list);
+}
+
+/** Get next ready segment from incoming queue.
+ *
+ * Return the segment with the earliest sequence number if it is ready.
+ * A segment is ready if its SEG.SEQ is earlier or equal to RCV.NXT.
+ *
+ * @param iqueue	Incoming queue
+ * @param seg		Place to store pointer to segment
+ * @return		EOK on success, ENOENT if no segment is ready
+ */
+int tcp_iqueue_get_ready_seg(tcp_iqueue_t *iqueue, tcp_segment_t **seg)
+{
+	tcp_iqueue_entry_t *iqe;
+	link_t *link;
+
+	log_msg(LVL_DEBUG, "tcp_get_ready_seg()");
+
+	link = list_first(&iqueue->list);
+	if (link == NULL) {
+		log_msg(LVL_DEBUG, "iqueue is empty");
+		return ENOENT;
+	}
+
+	iqe = list_get_instance(link, tcp_iqueue_entry_t, link);
+
+	while (!seq_no_segment_acceptable(iqueue->conn, iqe->seg)) {
+		log_msg(LVL_DEBUG, "Skipping unacceptable segment (RCV.NXT=%"
+		    PRIu32 ", RCV.NXT+RCV.WND=%" PRIu32 ", SEG.SEQ=%" PRIu32
+		    ", SEG.LEN=%" PRIu32 ")", iqueue->conn->rcv_nxt,
+		    iqueue->conn->rcv_nxt + iqueue->conn->rcv_wnd,
+		    iqe->seg->seq, iqe->seg->len);
+
+		list_remove(&iqe->link);
+		tcp_segment_delete(iqe->seg);
+
+         	link = list_first(&iqueue->list);
+		if (link == NULL) {
+			log_msg(LVL_DEBUG, "iqueue is empty");
+			return ENOENT;
+		}
+
+		iqe = list_get_instance(link, tcp_iqueue_entry_t, link);
+	}
+
+	/* Do not return segments that are not ready for processing */
+	if (!seq_no_segment_ready(iqueue->conn, iqe->seg)) {
+		log_msg(LVL_DEBUG, "Next segment not ready: SEG.SEQ=%u, "
+		    "RCV.NXT=%u, SEG.LEN=%u", iqe->seg->seq,
+		    iqueue->conn->rcv_nxt, iqe->seg->len);
+		return ENOENT;
+	}
+
+	log_msg(LVL_DEBUG, "Returning ready segment %p", iqe->seg);
+	list_remove(&iqe->link);
+	*seg = iqe->seg;
+
+	return EOK;
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/net/tcp/iqueue.h
===================================================================
--- uspace/srv/net/tcp/iqueue.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/tcp/iqueue.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup tcp
+ * @{
+ */
+/** @file Connection incoming segments queue
+ */
+
+#ifndef IQUEUE_H
+#define IQUEUE_H
+
+#include "tcp_type.h"
+
+extern void tcp_iqueue_init(tcp_iqueue_t *, tcp_conn_t *);
+extern void tcp_iqueue_insert_seg(tcp_iqueue_t *, tcp_segment_t *);
+extern int tcp_iqueue_get_ready_seg(tcp_iqueue_t *, tcp_segment_t **);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/tcp/ncsim.c
===================================================================
--- uspace/srv/net/tcp/ncsim.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/tcp/ncsim.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup tcp
+ * @{
+ */
+
+/**
+ * @file Network condition simulator
+ *
+ * Simulate network conditions for testing the reliability implementation:
+ *    - variable latency
+ *    - frame drop
+ */
+
+#include <adt/list.h>
+#include <async.h>
+#include <errno.h>
+#include <io/log.h>
+#include <stdlib.h>
+#include <thread.h>
+#include "conn.h"
+#include "ncsim.h"
+#include "rqueue.h"
+#include "segment.h"
+#include "tcp_type.h"
+
+static list_t sim_queue;
+static fibril_mutex_t sim_queue_lock;
+static fibril_condvar_t sim_queue_cv;
+
+/** Initialize segment receive queue. */
+void tcp_ncsim_init(void)
+{
+	list_initialize(&sim_queue);
+	fibril_mutex_initialize(&sim_queue_lock);
+	fibril_condvar_initialize(&sim_queue_cv);
+}
+
+/** Bounce segment through simulator into receive queue.
+ *
+ * @param sp	Socket pair, oriented for transmission
+ * @param seg	Segment
+ */
+void tcp_ncsim_bounce_seg(tcp_sockpair_t *sp, tcp_segment_t *seg)
+{
+	tcp_squeue_entry_t *sqe;
+	tcp_squeue_entry_t *old_qe;
+	link_t *link;
+
+	log_msg(LVL_DEBUG, "tcp_ncsim_bounce_seg()");
+	tcp_rqueue_bounce_seg(sp, seg);
+	return;
+
+	if (0 /*random() % 4 == 3*/) {
+		/* Drop segment */
+		log_msg(LVL_ERROR, "NCSim dropping segment");
+		tcp_segment_delete(seg);
+		return;
+	}
+
+	sqe = calloc(1, sizeof(tcp_squeue_entry_t));
+	if (sqe == NULL) {
+		log_msg(LVL_ERROR, "Failed allocating SQE.");
+		return;
+	}
+
+	sqe->delay = random() % (1000 * 1000);
+	sqe->sp = *sp;
+	sqe->seg = seg;
+
+	fibril_mutex_lock(&sim_queue_lock);
+
+	link = list_first(&sim_queue);
+	while (link != NULL && sqe->delay > 0) {
+		old_qe = list_get_instance(link, tcp_squeue_entry_t, link);
+		if (sqe->delay < old_qe->delay)
+			break;
+
+		sqe->delay -= old_qe->delay;
+
+		link = link->next;
+		if (link == &sim_queue.head)
+			link = NULL;
+	}
+
+	if (link != NULL)
+		list_insert_after(&sqe->link, link);
+	else
+		list_append(&sqe->link, &sim_queue);
+
+	fibril_condvar_broadcast(&sim_queue_cv);
+	fibril_mutex_unlock(&sim_queue_lock);
+}
+
+/** Network condition simulator handler thread. */
+static void tcp_ncsim_thread(void *arg)
+{
+	link_t *link;
+	tcp_squeue_entry_t *sqe;
+	int rc;
+
+	log_msg(LVL_DEBUG, "tcp_ncsim_thread()");
+
+
+	while (true) {
+		fibril_mutex_lock(&sim_queue_lock);
+
+		while (list_empty(&sim_queue))
+			fibril_condvar_wait(&sim_queue_cv, &sim_queue_lock);
+
+		do {
+			link = list_first(&sim_queue);
+			sqe = list_get_instance(link, tcp_squeue_entry_t, link);
+
+			log_msg(LVL_DEBUG, "NCSim - Sleep");
+			rc = fibril_condvar_wait_timeout(&sim_queue_cv,
+			    &sim_queue_lock, sqe->delay);
+		} while (rc != ETIMEOUT);
+
+		list_remove(link);
+		fibril_mutex_unlock(&sim_queue_lock);
+
+		log_msg(LVL_DEBUG, "NCSim - End Sleep");
+		tcp_rqueue_bounce_seg(&sqe->sp, sqe->seg);
+		free(sqe);
+	}
+}
+
+/** Start simulator handler thread. */
+void tcp_ncsim_thread_start(void)
+{
+	thread_id_t tid;
+        int rc;
+
+	log_msg(LVL_DEBUG, "tcp_ncsim_thread_start()");
+
+	rc = thread_create(tcp_ncsim_thread, NULL, "ncsim", &tid);
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Failed creating ncsim thread.");
+		return;
+	}
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/net/tcp/ncsim.h
===================================================================
--- uspace/srv/net/tcp/ncsim.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/tcp/ncsim.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup tcp
+ * @{
+ */
+/** @file Network condition simulator
+ */
+
+#ifndef NCSIM_H
+#define NCSIM_H
+
+#include "tcp_type.h"
+
+extern void tcp_ncsim_init(void);
+extern void tcp_ncsim_bounce_seg(tcp_sockpair_t *, tcp_segment_t *);
+extern void tcp_ncsim_thread_start(void);
+
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/tcp/pdu.c
===================================================================
--- uspace/srv/net/tcp/pdu.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/tcp/pdu.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,314 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup tcp
+ * @{
+ */
+
+/**
+ * @file TCP header encoding and decoding
+ */
+
+#include <bitops.h>
+#include <byteorder.h>
+#include <errno.h>
+#include <mem.h>
+#include <stdlib.h>
+#include "pdu.h"
+#include "segment.h"
+#include "seq_no.h"
+#include "std.h"
+#include "tcp_type.h"
+
+#define TCP_CHECKSUM_INIT 0xffff
+
+/** One's complement addition.
+ *
+ * Result is a + b + carry.
+ */
+static uint16_t tcp_ocadd16(uint16_t a, uint16_t b)
+{
+	uint32_t s;
+
+	s = (uint32_t)a + (uint32_t)b;
+	return (s & 0xffff) + (s >> 16);
+}
+
+static uint16_t tcp_checksum_calc(uint16_t ivalue, void *data, size_t size)
+{
+	uint16_t sum;
+	uint16_t w;
+	size_t words, i;
+	uint8_t *bdata;
+
+	sum = ~ivalue;
+	words = size / 2;
+	bdata = (uint8_t *)data;
+
+	for (i = 0; i < words; i++) {
+		w = ((uint16_t)bdata[2*i] << 8) | bdata[2*i + 1];
+		sum = tcp_ocadd16(sum, w);
+	}
+
+	if (size % 2 != 0) {
+		w = ((uint16_t)bdata[2*words] << 8);
+		sum = tcp_ocadd16(sum, w);
+	}
+
+	return ~sum;
+}
+
+static void tcp_header_decode_flags(uint16_t doff_flags, tcp_control_t *rctl)
+{
+	tcp_control_t ctl;
+
+	ctl = 0;
+
+	if ((doff_flags & BIT_V(uint16_t, DF_URG)) != 0)
+		ctl |= 0 /* XXX */;
+	if ((doff_flags & BIT_V(uint16_t, DF_ACK)) != 0)
+		ctl |= CTL_ACK;
+	if ((doff_flags & BIT_V(uint16_t, DF_PSH)) != 0)
+		ctl |= 0 /* XXX */;
+	if ((doff_flags & BIT_V(uint16_t, DF_RST)) != 0)
+		ctl |= CTL_RST;
+	if ((doff_flags & BIT_V(uint16_t, DF_SYN)) != 0)
+		ctl |= CTL_SYN;
+	if ((doff_flags & BIT_V(uint16_t, DF_FIN)) != 0)
+		ctl |= CTL_FIN;
+
+	*rctl = ctl;
+}
+
+static void tcp_header_encode_flags(tcp_control_t ctl, uint16_t doff_flags0,
+    uint16_t *rdoff_flags)
+{
+	uint16_t doff_flags;
+
+	doff_flags = doff_flags0;
+
+	if ((ctl & CTL_ACK) != 0)
+		doff_flags |= BIT_V(uint16_t, DF_ACK);
+	if ((ctl & CTL_RST) != 0)
+		doff_flags |= BIT_V(uint16_t, DF_RST);
+	if ((ctl & CTL_SYN) != 0)
+		doff_flags |= BIT_V(uint16_t, DF_SYN);
+	if ((ctl & CTL_FIN) != 0)
+		doff_flags |= BIT_V(uint16_t, DF_FIN);
+
+	*rdoff_flags = doff_flags;
+}
+
+static void tcp_header_setup(tcp_sockpair_t *sp, tcp_segment_t *seg, tcp_header_t *hdr)
+{
+	uint16_t doff_flags;
+	uint16_t doff;
+
+	hdr->src_port = host2uint16_t_be(sp->local.port);
+	hdr->dest_port = host2uint16_t_be(sp->foreign.port);
+	hdr->seq = host2uint32_t_be(seg->seq);
+	hdr->ack = host2uint32_t_be(seg->ack);
+
+	doff = (sizeof(tcp_header_t) / sizeof(uint32_t)) << DF_DATA_OFFSET_l;
+	tcp_header_encode_flags(seg->ctrl, doff, &doff_flags);
+
+	hdr->doff_flags = host2uint16_t_be(doff_flags);
+	hdr->window = host2uint16_t_be(seg->wnd);
+	hdr->checksum = 0;
+	hdr->urg_ptr = host2uint16_t_be(seg->up);
+}
+
+static void tcp_phdr_setup(tcp_pdu_t *pdu, tcp_phdr_t *phdr)
+{
+	phdr->src_addr = host2uint32_t_be(pdu->src_addr.ipv4);
+	phdr->dest_addr = host2uint32_t_be(pdu->dest_addr.ipv4);
+	phdr->zero = 0;
+	phdr->protocol = 6; /* XXX Magic number */
+	phdr->tcp_length = host2uint16_t_be(pdu->header_size + pdu->text_size);
+}
+
+static void tcp_header_decode(tcp_header_t *hdr, tcp_segment_t *seg)
+{
+	tcp_header_decode_flags(uint16_t_be2host(hdr->doff_flags), &seg->ctrl);
+	seg->seq = uint32_t_be2host(hdr->seq);
+	seg->ack = uint32_t_be2host(hdr->ack);
+	seg->wnd = uint16_t_be2host(hdr->window);
+	seg->up = uint16_t_be2host(hdr->urg_ptr);
+}
+
+static int tcp_header_encode(tcp_sockpair_t *sp, tcp_segment_t *seg,
+    void **header, size_t *size)
+{
+	tcp_header_t *hdr;
+
+	hdr = calloc(1, sizeof(tcp_header_t));
+	if (hdr == NULL)
+		return ENOMEM;
+
+	tcp_header_setup(sp, seg, hdr);
+	*header = hdr;
+	*size = sizeof(tcp_header_t);
+
+	return EOK;
+}
+
+static tcp_pdu_t *tcp_pdu_new(void)
+{
+	return calloc(1, sizeof(tcp_pdu_t));
+}
+
+/** Create PDU with the specified header and text data.
+ *
+ * Note that you still need to set addresses in the returned PDU.
+ *
+ * @param hdr		Header data
+ * @param hdr_size      Header size in bytes
+ * @param text		Text data
+ * @param text_size	Text size in bytes
+ * @return		New PDU
+ */
+tcp_pdu_t *tcp_pdu_create(void *hdr, size_t hdr_size, void *text,
+    size_t text_size)
+{
+	tcp_pdu_t *pdu;
+
+	pdu = tcp_pdu_new();
+	if (pdu == NULL)
+		return NULL;
+
+	pdu->header = malloc(hdr_size);
+	pdu->text = malloc(text_size);
+	if (pdu->header == NULL || pdu->text == NULL)
+		goto error;
+
+	memcpy(pdu->header, hdr, hdr_size);
+	memcpy(pdu->text, text, text_size);
+
+	pdu->header_size = hdr_size;
+	pdu->text_size = text_size;
+
+	return pdu;
+
+error:
+	if (pdu->header != NULL)
+		free(pdu->header);
+	if (pdu->text != NULL)
+		free(pdu->text);
+
+	return NULL;
+}
+
+void tcp_pdu_delete(tcp_pdu_t *pdu)
+{
+	free(pdu->header);
+	free(pdu->text);
+	free(pdu);
+}
+
+static uint16_t tcp_pdu_checksum_calc(tcp_pdu_t *pdu)
+{
+	uint16_t cs_phdr;
+	uint16_t cs_headers;
+	uint16_t cs_all;
+	tcp_phdr_t phdr;
+
+	tcp_phdr_setup(pdu, &phdr);
+	cs_phdr = tcp_checksum_calc(TCP_CHECKSUM_INIT, (void *)&phdr,
+	    sizeof(tcp_phdr_t));
+	cs_headers = tcp_checksum_calc(cs_phdr, pdu->header, pdu->header_size);
+	cs_all = tcp_checksum_calc(cs_headers, pdu->text, pdu->text_size);
+
+	return cs_all;
+}
+
+static void tcp_pdu_set_checksum(tcp_pdu_t *pdu, uint16_t checksum)
+{
+	tcp_header_t *hdr;
+
+	hdr = (tcp_header_t *)pdu->header;
+	hdr->checksum = host2uint16_t_be(checksum);
+}
+
+/** Decode incoming PDU */
+int tcp_pdu_decode(tcp_pdu_t *pdu, tcp_sockpair_t *sp, tcp_segment_t **seg)
+{
+	tcp_segment_t *nseg;
+	tcp_header_t *hdr;
+
+	nseg = tcp_segment_make_data(0, pdu->text, pdu->text_size);
+	if (nseg == NULL)
+		return ENOMEM;
+
+	tcp_header_decode(pdu->header, nseg);
+	nseg->len += seq_no_control_len(nseg->ctrl);
+
+	hdr = (tcp_header_t *)pdu->header;
+
+	sp->local.port = uint16_t_be2host(hdr->dest_port);
+	sp->local.addr = pdu->dest_addr;
+	sp->foreign.port = uint16_t_be2host(hdr->src_port);
+	sp->foreign.addr = pdu->src_addr;
+
+	*seg = nseg;
+	return EOK;
+}
+
+/** Encode outgoing PDU */
+int tcp_pdu_encode(tcp_sockpair_t *sp, tcp_segment_t *seg, tcp_pdu_t **pdu)
+{
+	tcp_pdu_t *npdu;
+	size_t text_size;
+	uint16_t checksum;
+
+	npdu = tcp_pdu_new();
+	if (npdu == NULL)
+		return ENOMEM;
+
+	npdu->src_addr = sp->local.addr;
+	npdu->dest_addr = sp->foreign.addr;
+	tcp_header_encode(sp, seg, &npdu->header, &npdu->header_size);
+
+	text_size = tcp_segment_text_size(seg);
+	npdu->text = calloc(1, text_size);
+	if (npdu->text == NULL)
+		return ENOMEM;
+
+	npdu->text_size = text_size;
+	memcpy(npdu->text, seg->data, text_size);
+
+	/* Checksum calculation */
+	checksum = tcp_pdu_checksum_calc(npdu);
+	tcp_pdu_set_checksum(npdu, checksum);
+
+	*pdu = npdu;
+	return EOK;
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/net/tcp/pdu.h
===================================================================
--- uspace/srv/net/tcp/pdu.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/tcp/pdu.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup tcp
+ * @{
+ */
+/** @file TCP PDU (encoded Protocol Data Unit) handling
+ */
+
+#ifndef PDU_H
+#define PDU_H
+
+#include <sys/types.h>
+#include "std.h"
+#include "tcp_type.h"
+
+extern tcp_pdu_t *tcp_pdu_create(void *, size_t, void *, size_t);
+extern void tcp_pdu_delete(tcp_pdu_t *);
+extern int tcp_pdu_decode(tcp_pdu_t *, tcp_sockpair_t *, tcp_segment_t **);
+extern int tcp_pdu_encode(tcp_sockpair_t *, tcp_segment_t *, tcp_pdu_t **);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/tcp/rqueue.c
===================================================================
--- uspace/srv/net/tcp/rqueue.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/tcp/rqueue.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup tcp
+ * @{
+ */
+
+/**
+ * @file Global segment receive queue
+ */
+
+#include <adt/prodcons.h>
+#include <errno.h>
+#include <io/log.h>
+#include <stdlib.h>
+#include <thread.h>
+#include "conn.h"
+#include "pdu.h"
+#include "rqueue.h"
+#include "segment.h"
+#include "tcp_type.h"
+#include "ucall.h"
+
+/** Transcode bounced segments.
+ *
+ * If defined, segments bounced via the internal debugging loopback will
+ * be encoded to a PDU and the decoded. Otherwise they will be bounced back
+ * directly without passing the encoder-decoder.
+ */
+#define BOUNCE_TRANSCODE
+
+static prodcons_t rqueue;
+
+/** Initialize segment receive queue. */
+void tcp_rqueue_init(void)
+{
+	prodcons_initialize(&rqueue);
+}
+
+/** Bounce segment directy into receive queue without constructing the PDU.
+ *
+ * This is for testing purposes only.
+ *
+ * @param sp	Socket pair, oriented for transmission
+ * @param seg	Segment
+ */
+void tcp_rqueue_bounce_seg(tcp_sockpair_t *sp, tcp_segment_t *seg)
+{
+	tcp_sockpair_t rident;
+
+	log_msg(LVL_DEBUG, "tcp_rqueue_bounce_seg()");
+
+#ifdef BOUNCE_TRANSCODE
+	tcp_pdu_t *pdu;
+	tcp_segment_t *dseg;
+
+	if (tcp_pdu_encode(sp, seg, &pdu) != EOK) {
+		log_msg(LVL_WARN, "Not enough memory. Segment dropped.");
+		return;
+	}
+
+	if (tcp_pdu_decode(pdu, &rident, &dseg) != EOK) {
+		log_msg(LVL_WARN, "Not enough memory. Segment dropped.");
+		return;
+	}
+
+	tcp_pdu_delete(pdu);
+
+	/** Insert decoded segment into rqueue */
+	tcp_rqueue_insert_seg(&rident, dseg);
+	tcp_segment_delete(seg);
+#else
+	/* Reverse the identification */
+	tcp_sockpair_flipped(sp, &rident);
+
+	/* Insert segment back into rqueue */
+	tcp_rqueue_insert_seg(&rident, seg);
+#endif
+}
+
+/** Insert segment into receive queue.
+ *
+ * @param sp	Socket pair, oriented for reception
+ * @param seg	Segment
+ */
+void tcp_rqueue_insert_seg(tcp_sockpair_t *sp, tcp_segment_t *seg)
+{
+	tcp_rqueue_entry_t *rqe;
+	log_msg(LVL_DEBUG, "tcp_rqueue_insert_seg()");
+
+	tcp_segment_dump(seg);
+
+	rqe = calloc(1, sizeof(tcp_rqueue_entry_t));
+	if (rqe == NULL) {
+		log_msg(LVL_ERROR, "Failed allocating RQE.");
+		return;
+	}
+
+	rqe->sp = *sp;
+	rqe->seg = seg;
+
+	prodcons_produce(&rqueue, &rqe->link);
+}
+
+/** Receive queue handler thread. */
+static void tcp_rqueue_thread(void *arg)
+{
+	link_t *link;
+	tcp_rqueue_entry_t *rqe;
+
+	log_msg(LVL_DEBUG, "tcp_rqueue_thread()");
+
+	while (true) {
+		link = prodcons_consume(&rqueue);
+		rqe = list_get_instance(link, tcp_rqueue_entry_t, link);
+
+		tcp_as_segment_arrived(&rqe->sp, rqe->seg);
+	}
+}
+
+/** Start receive queue handler thread. */
+void tcp_rqueue_thread_start(void)
+{
+	thread_id_t tid;
+        int rc;
+
+	log_msg(LVL_DEBUG, "tcp_rqueue_thread_start()");
+
+	rc = thread_create(tcp_rqueue_thread, NULL, "rqueue", &tid);
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Failed creating rqueue thread.");
+		return;
+	}
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/net/tcp/rqueue.h
===================================================================
--- uspace/srv/net/tcp/rqueue.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/tcp/rqueue.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup tcp
+ * @{
+ */
+/** @file Global segment receive queue
+ */
+
+#ifndef RQUEUE_H
+#define RQUEUE_H
+
+#include "tcp_type.h"
+
+extern void tcp_rqueue_init(void);
+extern void tcp_rqueue_bounce_seg(tcp_sockpair_t *, tcp_segment_t *);
+extern void tcp_rqueue_insert_seg(tcp_sockpair_t *, tcp_segment_t *);
+extern void tcp_rqueue_handler(void *);
+extern void tcp_rqueue_thread_start(void);
+
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/tcp/segment.c
===================================================================
--- uspace/srv/net/tcp/segment.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/tcp/segment.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,261 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup tcp
+ * @{
+ */
+
+/**
+ * @file Segment processing
+ */
+
+#include <io/log.h>
+#include <mem.h>
+#include <stdlib.h>
+#include "segment.h"
+#include "seq_no.h"
+#include "tcp_type.h"
+
+/** Alocate new segment structure. */
+tcp_segment_t *tcp_segment_new(void)
+{
+	return calloc(1, sizeof(tcp_segment_t));
+}
+
+/** Delete segment. */
+void tcp_segment_delete(tcp_segment_t *seg)
+{
+	free(seg);
+}
+
+/** Create duplicate of segment.
+ *
+ * @param seg	Segment
+ * @return 	Duplicate segment
+ */
+tcp_segment_t *tcp_segment_dup(tcp_segment_t *seg)
+{
+	tcp_segment_t *scopy;
+	size_t tsize;
+
+	scopy = tcp_segment_new();
+	if (scopy == NULL)
+		return NULL;
+
+	scopy->ctrl = seg->ctrl;
+	scopy->seq = seg->seq;
+	scopy->ack = seg->ack;
+	scopy->len = seg->len;
+	scopy->wnd = seg->wnd;
+	scopy->up = seg->up;
+
+	tsize = tcp_segment_text_size(seg);
+	scopy->data = calloc(tsize, 1);
+	if (scopy->data == NULL) {
+		free(scopy);
+		return NULL;
+	}
+
+	memcpy(scopy->data, seg->data, tsize);
+	scopy->dfptr = scopy->data;
+
+	return scopy;
+}
+
+/** Create a control-only segment.
+ *
+  * @return	Segment
+ */
+tcp_segment_t *tcp_segment_make_ctrl(tcp_control_t ctrl)
+{
+	tcp_segment_t *seg;
+
+	seg = tcp_segment_new();
+	if (seg == NULL)
+		return NULL;
+
+	seg->ctrl = ctrl;
+	seg->len = seq_no_control_len(ctrl);
+
+	return seg;
+}
+
+/** Create an RST segment.
+ *
+ * @param seg	Segment we are replying to
+ * @return	RST segment
+ */
+tcp_segment_t *tcp_segment_make_rst(tcp_segment_t *seg)
+{
+	tcp_segment_t *rseg;
+
+	rseg = tcp_segment_new();
+	if (rseg == NULL)
+		return NULL;
+
+	if ((seg->ctrl & CTL_ACK) == 0) {
+		rseg->ctrl = CTL_RST | CTL_ACK;
+		rseg->seq = 0;
+		rseg->ack = seg->seq + seg->len;
+	} else {
+		rseg->ctrl = CTL_RST;
+		rseg->seq = seg->ack;
+	}
+
+	return rseg;
+}
+
+/** Create a control segment.
+ *
+  * @return	Segment
+ */
+tcp_segment_t *tcp_segment_make_data(tcp_control_t ctrl, void *data,
+    size_t size)
+{
+	tcp_segment_t *seg;
+
+	seg = tcp_segment_new();
+	if (seg == NULL)
+		return NULL;
+
+	seg->ctrl = ctrl;
+	seg->len = seq_no_control_len(ctrl) + size;
+
+	seg->dfptr = seg->data = malloc(size);
+	if (seg->dfptr == NULL) {
+		free(seg);
+		return NULL;
+	}
+
+	memcpy(seg->data, data, size);
+
+	return seg;
+}
+
+
+/** Trim segment from left and right by the specified amount.
+ *
+ * Trim any text or control to remove the specified amount of sequence
+ * numbers from the left (lower sequence numbers) and right side
+ * (higher sequence numbers) of the segment.
+ *
+ * @param seg		Segment, will be modified in place
+ * @param left		Amount of sequence numbers to trim from the left
+ * @param right		Amount of sequence numbers to trim from the right
+ */
+void tcp_segment_trim(tcp_segment_t *seg, uint32_t left, uint32_t right)
+{
+	uint32_t t_size;
+
+	assert(left + right <= seg->len);
+
+	/* Special case, entire segment trimmed from left */
+	if (left == seg->len) {
+		seg->seq = seg->seq + seg->len;
+		seg->len = 0;
+		return;
+	}
+
+	/* Special case, entire segment trimmed from right */
+	if (right == seg->len) {
+		seg->len = 0;
+		return;
+	}
+
+	/* General case */
+
+	t_size = tcp_segment_text_size(seg);
+
+	if (left > 0 && (seg->ctrl & CTL_SYN) != 0) {
+		/* Trim SYN */
+		seg->ctrl &= ~CTL_SYN;
+		seg->seq++;
+		seg->len--;
+		left--;
+	}
+
+	if (right > 0 && (seg->ctrl & CTL_FIN) != 0) {
+		/* Trim FIN */
+		seg->ctrl &= ~CTL_FIN;
+		seg->len--;
+		right--;
+	}
+
+	if (left > 0 || right > 0) {
+		/* Trim segment text */
+		assert(left + right <= t_size);
+
+		seg->data += left;
+		seg->len -= left + right;
+	}
+}
+
+/** Copy out text data from segment.
+ *
+ * Data is copied from the beginning of the segment text up to @a size bytes.
+ * @a size must not be greater than the size of the segment text, but
+ * it can be less.
+ *
+ * @param seg	Segment
+ * @param buf	Destination buffer
+ * @param size	Size of destination buffer
+ */
+void tcp_segment_text_copy(tcp_segment_t *seg, void *buf, size_t size)
+{
+	assert(size <= tcp_segment_text_size(seg));
+	memcpy(buf, seg->data, size);
+}
+
+/** Return number of bytes in segment text.
+ *
+ * @param seg	Segment
+ * @return	Number of bytes in segment text
+ */
+size_t tcp_segment_text_size(tcp_segment_t *seg)
+{
+	return seg->len - seq_no_control_len(seg->ctrl);
+}
+
+/** Dump segment contents to log.
+ *
+ * @param seg	Segment
+ */
+void tcp_segment_dump(tcp_segment_t *seg)
+{
+	log_msg(LVL_DEBUG, "Segment dump:");
+	log_msg(LVL_DEBUG, " - ctrl = %u", (unsigned)seg->ctrl);
+	log_msg(LVL_DEBUG, " - seq = % " PRIu32, seg->seq);
+	log_msg(LVL_DEBUG, " - ack = % " PRIu32, seg->ack);
+	log_msg(LVL_DEBUG, " - len = % " PRIu32, seg->len);
+	log_msg(LVL_DEBUG, " - wnd = % " PRIu32, seg->wnd);
+	log_msg(LVL_DEBUG, " - up = % " PRIu32, seg->up);
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/net/tcp/segment.h
===================================================================
--- uspace/srv/net/tcp/segment.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/tcp/segment.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup tcp
+ * @{
+ */
+/** @file Segment processing
+ */
+
+#ifndef SEGMENT_H
+#define SEGMENT_H
+
+#include <sys/types.h>
+#include "tcp_type.h"
+
+extern tcp_segment_t *tcp_segment_new(void);
+extern void tcp_segment_delete(tcp_segment_t *);
+extern tcp_segment_t *tcp_segment_dup(tcp_segment_t *);
+extern tcp_segment_t *tcp_segment_make_ctrl(tcp_control_t);
+extern tcp_segment_t *tcp_segment_make_rst(tcp_segment_t *);
+extern tcp_segment_t *tcp_segment_make_data(tcp_control_t, void *, size_t);
+extern void tcp_segment_trim(tcp_segment_t *, uint32_t, uint32_t);
+extern void tcp_segment_text_copy(tcp_segment_t *, void *, size_t);
+extern size_t tcp_segment_text_size(tcp_segment_t *);
+extern void tcp_segment_dump(tcp_segment_t *);
+
+
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/tcp/seq_no.c
===================================================================
--- uspace/srv/net/tcp/seq_no.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/tcp/seq_no.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,243 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup tcp
+ * @{
+ */
+
+/**
+ * @file Sequence number computations
+ */
+
+#include <assert.h>
+#include <bool.h>
+#include <sys/types.h>
+#include "seq_no.h"
+#include "tcp_type.h"
+
+/** a <= b < c modulo sequence space */
+static bool seq_no_le_lt(uint32_t a, uint32_t b, uint32_t c)
+{
+	if (a <= c) {
+		return (a <= b) && (b < c);
+	} else {
+		return (b < c) || (a <= b);
+	}
+}
+
+/** a < b <= c modulo sequence space */
+static bool seq_no_lt_le(uint32_t a, uint32_t b, uint32_t c)
+{
+	if (a <= c) {
+		return (a < b) && (b <= c);
+	} else {
+		return (b <= c) || (a < b);
+	}
+}
+
+/** Determine wheter ack is acceptable (new acknowledgement) */
+bool seq_no_ack_acceptable(tcp_conn_t *conn, uint32_t seg_ack)
+{
+	/* SND.UNA < SEG.ACK <= SND.NXT */
+	return seq_no_lt_le(conn->snd_una, seg_ack, conn->snd_nxt);
+}
+
+/** Determine wheter ack is duplicate.
+ *
+ * ACK is duplicate if it refers to a sequence number that has
+ * aleady been acked (SEG.ACK <= SND.UNA).
+ */
+bool seq_no_ack_duplicate(tcp_conn_t *conn, uint32_t seg_ack)
+{
+	uint32_t diff;
+
+	/*
+	 * There does not seem to be a three-point comparison
+	 * equivalent of SEG.ACK < SND.UNA. Thus we do it
+	 * on a best-effort basis, based on the difference.
+	 * [-2^31, 0) means less-than, 0 means equal, [0, 2^31)
+	 * means greater-than. Less-than or equal means duplicate.
+	 */
+	diff = seg_ack - conn->snd_una;
+	return diff == 0 || (diff & (0x1 << 31)) != 0;
+}
+
+/** Determine if sequence number is in receive window. */
+bool seq_no_in_rcv_wnd(tcp_conn_t *conn, uint32_t sn)
+{
+	return seq_no_le_lt(conn->rcv_nxt, sn, conn->rcv_nxt + conn->rcv_wnd);
+}
+
+/** Determine segment has new window update.
+ *
+ * Window update is new if either SND.WL1 < SEG.SEQ or
+ * (SND.WL1 = SEG.SEQ and SND.WL2 <= SEG.ACK).
+ */
+bool seq_no_new_wnd_update(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	bool n_seq, n_ack;
+
+	assert(seq_no_segment_acceptable(conn, seg));
+
+	/*
+	 * We make use of the fact that the peer should not ACK anything
+	 * beyond our send window (we surely haven't sent that yet)
+	 * as we should have filtered those acks out.
+	 * We use SND.UNA+SND.WND as the third point of comparison.
+	 */
+
+	n_seq = seq_no_lt_le(conn->snd_wl1, seg->seq,
+	    conn->snd_una + conn->snd_wnd);
+
+	n_ack = conn->snd_wl1 == seg->seq &&
+	    seq_no_le_lt(conn->snd_wl2, seg->ack,
+	    conn->snd_una + conn->snd_wnd + 1);
+
+	return n_seq || n_ack;
+}
+
+/** Determine if segment is ready for processing.
+ *
+ * Assuming segment is acceptable, a segment is ready if it intersects
+ * RCV.NXT, that is we can process it immediately.
+ */
+bool seq_no_segment_ready(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	assert(seq_no_segment_acceptable(conn, seg));
+
+	return seq_no_le_lt(seg->seq, conn->rcv_nxt, seg->seq + seg->len + 1);
+}
+
+/** Determine whether segment is fully acked */
+bool seq_no_segment_acked(tcp_conn_t *conn, tcp_segment_t *seg, uint32_t ack)
+{
+	assert(seg->len > 0);
+	return seq_no_lt_le(seg->seq, seg->seq + seg->len, ack);
+}
+
+/** Determine whether initial SYN is acked */
+bool seq_no_syn_acked(tcp_conn_t *conn)
+{
+	return seq_no_lt_le(conn->iss, conn->snd_una, conn->snd_nxt);
+}
+
+/** Determine whether segment overlaps the receive window */
+bool seq_no_segment_acceptable(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	bool b_in, e_in;
+
+	b_in = seq_no_le_lt(conn->rcv_nxt, seg->seq, conn->rcv_nxt
+	    + conn->rcv_wnd);
+
+	e_in = seq_no_le_lt(conn->rcv_nxt, seg->seq + seg->len - 1,
+	    conn->rcv_nxt + conn->rcv_wnd);
+
+	if (seg->len == 0 && conn->rcv_wnd == 0) {
+		return seg->seq == conn->rcv_nxt;
+	} else if (seg->len == 0 && conn->rcv_wnd != 0) {
+		return b_in;
+	} else if (seg->len > 0 && conn->rcv_wnd == 0) {
+		return false;
+	} else {
+		return b_in || e_in;
+	}
+}
+
+/** Determine size that control bits occupy in sequence space. */
+uint32_t seq_no_control_len(tcp_control_t ctrl)
+{
+	uint32_t len = 0;
+
+	if ((ctrl & CTL_SYN) != 0)
+		++len;
+
+	if ((ctrl & CTL_FIN) != 0)
+		++len;
+
+	return len;
+}
+
+/** Calculate the amount of trim needed to fit segment in receive window. */
+void seq_no_seg_trim_calc(tcp_conn_t *conn, tcp_segment_t *seg,
+    uint32_t *left, uint32_t *right)
+{
+	assert(seq_no_segment_acceptable(conn, seg));
+
+	/*
+	 * If RCV.NXT is between SEG.SEQ and RCV.NXT+RCV.WND, then
+	 * left trim amount is positive
+	 */
+	if (seq_no_lt_le(seg->seq, conn->rcv_nxt,
+	    conn->rcv_nxt + conn->rcv_wnd)) {
+		*left = conn->rcv_nxt - seg->seq;
+	} else {
+		*left = 0;
+	}
+
+	/*
+	 * If SEG.SEQ+SEG.LEN is between SEG.SEQ and RCV.NXT+RCV.WND,
+	 * then right trim is zero.
+	 */
+	if (seq_no_lt_le(seg->seq - 1, seg->seq + seg->len,
+	    conn->rcv_nxt + conn->rcv_wnd)) {
+		*right = 0;
+	} else {
+		*right = (seg->seq + seg->len) -
+		    (conn->rcv_nxt + conn->rcv_wnd);
+	}
+}
+
+/** Segment order comparison.
+ *
+ * Compare sequence order of two acceptable segments.
+ *
+ * @param conn		Connection
+ * @param sa		Segment A
+ * @param sb		Segment B
+ *
+ * @return		-1, 0, 1, resp. if A < B, A == B, A > B in terms
+ *			of sequence order of the beginning of the segment.
+ */
+int seq_no_seg_cmp(tcp_conn_t *conn, tcp_segment_t *sa, tcp_segment_t *sb)
+{
+	assert(seq_no_segment_acceptable(conn, sa));
+	assert(seq_no_segment_acceptable(conn, sb));
+
+	if (seq_no_lt_le(sa->seq, sb->seq, conn->rcv_nxt + conn->rcv_wnd))
+		return -1;
+
+	if (seq_no_lt_le(sb->seq, sa->seq, conn->rcv_nxt + conn->rcv_wnd))
+		return +1;
+
+	assert(sa->seq == sb->seq);
+	return 0;
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/net/tcp/seq_no.h
===================================================================
--- uspace/srv/net/tcp/seq_no.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/tcp/seq_no.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup tcp
+ * @{
+ */
+/** @file Sequence number computations
+ */
+
+#ifndef SEQ_NO_H
+#define SEQ_NO_H
+
+#include <sys/types.h>
+#include "tcp_type.h"
+
+extern bool seq_no_ack_acceptable(tcp_conn_t *, uint32_t);
+extern bool seq_no_ack_duplicate(tcp_conn_t *, uint32_t);
+extern bool seq_no_in_rcv_wnd(tcp_conn_t *, uint32_t);
+extern bool seq_no_new_wnd_update(tcp_conn_t *, tcp_segment_t *);
+extern bool seq_no_segment_acked(tcp_conn_t *, tcp_segment_t *, uint32_t);
+extern bool seq_no_syn_acked(tcp_conn_t *);
+extern bool seq_no_segment_ready(tcp_conn_t *, tcp_segment_t *);
+extern bool seq_no_segment_acceptable(tcp_conn_t *, tcp_segment_t *);
+extern void seq_no_seg_trim_calc(tcp_conn_t *, tcp_segment_t *, uint32_t *,
+    uint32_t *);
+extern int seq_no_seg_cmp(tcp_conn_t *, tcp_segment_t *, tcp_segment_t *);
+
+extern uint32_t seq_no_control_len(tcp_control_t);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/tcp/sock.c
===================================================================
--- uspace/srv/net/tcp/sock.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/tcp/sock.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,841 @@
+/*
+ * Copyright (c) 2008 Lukas Mejdrech
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup tcp
+ * @{
+ */
+
+/**
+ * @file Socket provider
+ */
+
+#include <async.h>
+#include <errno.h>
+#include <inet/inet.h>
+#include <io/log.h>
+#include <ipc/services.h>
+#include <ipc/socket.h>
+#include <net/modules.h>
+#include <net/socket.h>
+#include <ns.h>
+
+#include "sock.h"
+#include "std.h"
+#include "tcp.h"
+#include "tcp_type.h"
+#include "ucall.h"
+
+#define FRAGMENT_SIZE 1024
+
+#define MAX_BACKLOG 128
+
+/** Free ports pool start. */
+#define TCP_FREE_PORTS_START		1025
+
+/** Free ports pool end. */
+#define TCP_FREE_PORTS_END		65535
+
+static int last_used_port = TCP_FREE_PORTS_START - 1;
+static socket_ports_t gsock;
+
+static void tcp_sock_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg);
+static void tcp_sock_cstate_cb(tcp_conn_t *conn, void *arg);
+
+int tcp_sock_init(void)
+{
+	int rc;
+
+	socket_ports_initialize(&gsock);
+
+	async_set_client_connection(tcp_sock_connection);
+
+	rc = service_register(SERVICE_TCP);
+	if (rc != EOK)
+		return EEXIST;
+
+	return EOK;
+}
+
+static void tcp_free_sock_data(socket_core_t *sock_core)
+{
+	tcp_sockdata_t *socket;
+
+	socket = (tcp_sockdata_t *)sock_core->specific_data;
+	(void)socket;
+}
+
+static void tcp_sock_notify_data(socket_core_t *sock_core)
+{
+	log_msg(LVL_DEBUG, "tcp_sock_notify_data(%d)", sock_core->socket_id);
+	async_exch_t *exch = async_exchange_begin(sock_core->sess);
+	async_msg_5(exch, NET_SOCKET_RECEIVED, (sysarg_t)sock_core->socket_id,
+	    FRAGMENT_SIZE, 0, 0, 1);
+	async_exchange_end(exch);
+}
+
+static void tcp_sock_notify_aconn(socket_core_t *lsock_core)
+{
+	log_msg(LVL_DEBUG, "tcp_sock_notify_aconn(%d)", lsock_core->socket_id);
+	async_exch_t *exch = async_exchange_begin(lsock_core->sess);
+	async_msg_5(exch, NET_SOCKET_ACCEPTED, (sysarg_t)lsock_core->socket_id,
+	    FRAGMENT_SIZE, 0, 0, 0);
+	async_exchange_end(exch);
+}
+
+static void tcp_sock_socket(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
+{
+	tcp_sockdata_t *sock;
+	socket_core_t *sock_core;
+	int sock_id;
+	int rc;
+	ipc_call_t answer;
+
+	log_msg(LVL_DEBUG, "tcp_sock_socket()");
+	sock = calloc(sizeof(tcp_sockdata_t), 1);
+	if (sock == NULL) {
+		async_answer_0(callid, ENOMEM);
+		return;
+	}
+
+	fibril_mutex_initialize(&sock->lock);
+	sock->client = client;
+	sock->laddr.ipv4 = TCP_IPV4_ANY;
+	sock->lconn = NULL;
+	sock->backlog = 0;
+	list_initialize(&sock->ready);
+
+	sock_id = SOCKET_GET_SOCKET_ID(call);
+	rc = socket_create(&client->sockets, client->sess, sock, &sock_id);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	sock_core = socket_cores_find(&client->sockets, sock_id);
+	assert(sock_core != NULL);
+	sock->sock_core = sock_core;
+
+	refresh_answer(&answer, NULL);
+	SOCKET_SET_SOCKET_ID(answer, sock_id);
+
+	SOCKET_SET_DATA_FRAGMENT_SIZE(answer, FRAGMENT_SIZE);
+	SOCKET_SET_HEADER_SIZE(answer, sizeof(tcp_header_t));
+	answer_call(callid, EOK, &answer, 3);
+}
+
+static void tcp_sock_bind(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
+{
+	int rc;
+	struct sockaddr *addr;
+	size_t addr_len;
+	socket_core_t *sock_core;
+	tcp_sockdata_t *socket;
+
+	log_msg(LVL_DEBUG, "tcp_sock_bind()");
+	log_msg(LVL_DEBUG, " - async_data_write_accept");
+	rc = async_data_write_accept((void **) &addr, false, 0, 0, 0, &addr_len);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	log_msg(LVL_DEBUG, " - call socket_bind");
+	rc = socket_bind(&client->sockets, &gsock, SOCKET_GET_SOCKET_ID(call),
+	    addr, addr_len, TCP_FREE_PORTS_START, TCP_FREE_PORTS_END,
+	    last_used_port);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	log_msg(LVL_DEBUG, " - call socket_cores_find");
+	sock_core = socket_cores_find(&client->sockets, SOCKET_GET_SOCKET_ID(call));
+	if (sock_core != NULL) {
+		socket = (tcp_sockdata_t *)sock_core->specific_data;
+		/* XXX Anything to do? */
+		(void) socket;
+	}
+
+	log_msg(LVL_DEBUG, " - success");
+	async_answer_0(callid, EOK);
+}
+
+static void tcp_sock_listen(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
+{
+	int socket_id;
+	int backlog;
+	socket_core_t *sock_core;
+	tcp_sockdata_t *socket;
+	tcp_error_t trc;
+	tcp_sock_t lsocket;
+	tcp_sock_t fsocket;
+	tcp_conn_t *conn;
+	tcp_sock_lconn_t *lconn;
+	int i;
+
+	log_msg(LVL_DEBUG, "tcp_sock_listen()");
+
+	socket_id = SOCKET_GET_SOCKET_ID(call);
+	backlog = SOCKET_GET_BACKLOG(call);
+
+	if (backlog < 0) {
+		async_answer_0(callid, EINVAL);
+		return;
+	}
+
+	if (backlog > MAX_BACKLOG)
+		backlog = MAX_BACKLOG;
+
+	sock_core = socket_cores_find(&client->sockets, socket_id);
+	if (sock_core == NULL) {
+		async_answer_0(callid, ENOTSOCK);
+		return;
+	}
+
+	socket = (tcp_sockdata_t *)sock_core->specific_data;
+
+	/*
+	 * Prepare @c backlog listening connections.
+	 */
+	fibril_mutex_lock(&socket->lock);
+
+	socket->backlog = backlog;
+	socket->lconn = calloc(sizeof(tcp_conn_t *), backlog);
+	if (socket->lconn == NULL) {
+		fibril_mutex_unlock(&socket->lock);
+		async_answer_0(callid, ENOMEM);
+		return;
+	}
+
+	log_msg(LVL_DEBUG, " - open connections");
+
+	lsocket.addr.ipv4 = TCP_IPV4_ANY;
+	lsocket.port = sock_core->port;
+	fsocket.addr.ipv4 = TCP_IPV4_ANY;
+	fsocket.port = TCP_PORT_ANY;
+
+	for (i = 0; i < backlog; i++) {
+
+		lconn = calloc(sizeof(tcp_sock_lconn_t), 1);
+		if (lconn == NULL) {
+			/* XXX Clean up */
+			fibril_mutex_unlock(&socket->lock);
+			async_answer_0(callid, ENOMEM);
+			return;
+		}
+
+		trc = tcp_uc_open(&lsocket, &fsocket, ap_passive,
+		    tcp_open_nonblock, &conn);
+		if (conn == NULL) {
+			/* XXX Clean up */
+			fibril_mutex_unlock(&socket->lock);
+			async_answer_0(callid, ENOMEM);
+			return;
+		}
+
+		tcp_uc_set_cstate_cb(conn, tcp_sock_cstate_cb, lconn);
+
+		assert(trc == TCP_EOK);
+		conn->name = (char *)"S";
+
+		lconn->conn = conn;
+		lconn->socket = socket;
+		link_initialize(&lconn->ready_list);
+		socket->lconn[i] = lconn;
+	}
+
+	fibril_mutex_unlock(&socket->lock);
+	async_answer_0(callid, EOK);
+}
+
+static void tcp_sock_connect(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
+{
+	int rc;
+	struct sockaddr_in *addr;
+	int socket_id;
+	size_t addr_len;
+	socket_core_t *sock_core;
+	tcp_sockdata_t *socket;
+	tcp_error_t trc;
+	tcp_sock_t lsocket;
+	tcp_sock_t fsocket;
+
+	log_msg(LVL_DEBUG, "tcp_sock_connect()");
+
+	rc = async_data_write_accept((void **) &addr, false, 0, 0, 0, &addr_len);
+	if (rc != EOK || addr_len != sizeof(struct sockaddr_in)) {
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	socket_id = SOCKET_GET_SOCKET_ID(call);
+
+	sock_core = socket_cores_find(&client->sockets, socket_id);
+	if (sock_core == NULL) {
+		async_answer_0(callid, ENOTSOCK);
+		return;
+	}
+
+	socket = (tcp_sockdata_t *)sock_core->specific_data;
+	if (sock_core->port <= 0) {
+		rc = socket_bind_free_port(&gsock, sock_core,
+		    TCP_FREE_PORTS_START, TCP_FREE_PORTS_END,
+		    last_used_port);
+		if (rc != EOK) {
+			async_answer_0(callid, rc);
+			return;
+		}
+
+		last_used_port = sock_core->port;
+	}
+
+	fibril_mutex_lock(&socket->lock);
+
+	if (socket->laddr.ipv4 == TCP_IPV4_ANY) {
+		/* Determine local IP address */
+		inet_addr_t loc_addr, rem_addr;
+
+		rem_addr.ipv4 = uint32_t_be2host(addr->sin_addr.s_addr);
+		rc = inet_get_srcaddr(&rem_addr, 0, &loc_addr);
+		if (rc != EOK) {
+			fibril_mutex_unlock(&socket->lock);
+			async_answer_0(callid, rc);
+			log_msg(LVL_DEBUG, "tcp_sock_connect: Failed to "
+			    "determine local address.");
+			return;
+		}
+
+		socket->laddr.ipv4 = loc_addr.ipv4;
+		log_msg(LVL_DEBUG, "Local IP address is %x", socket->laddr.ipv4);
+	}
+
+	lsocket.addr.ipv4 = socket->laddr.ipv4;
+	lsocket.port = sock_core->port;
+	fsocket.addr.ipv4 = uint32_t_be2host(addr->sin_addr.s_addr);
+	fsocket.port = uint16_t_be2host(addr->sin_port);
+
+	trc = tcp_uc_open(&lsocket, &fsocket, ap_active, 0, &socket->conn);
+
+	if (socket->conn != NULL)
+		socket->conn->name = (char *)"C";
+
+	fibril_mutex_unlock(&socket->lock);
+
+	switch (trc) {
+	case TCP_EOK:
+		rc = EOK;
+		break;
+	case TCP_ERESET:
+		rc = ECONNREFUSED;
+		break;
+	default:
+		assert(false);
+	}
+
+	async_answer_0(callid, rc);
+
+	/* Push one fragment notification to client's queue */
+	tcp_sock_notify_data(sock_core);
+	log_msg(LVL_DEBUG, "tcp_sock_connect(): notify conn\n");
+}
+
+static void tcp_sock_accept(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
+{
+	ipc_call_t answer;
+	int socket_id;
+	int asock_id;
+	socket_core_t *sock_core;
+	socket_core_t *asock_core;
+	tcp_sockdata_t *socket;
+	tcp_sockdata_t *asocket;
+	tcp_error_t trc;
+	tcp_sock_t lsocket;
+	tcp_sock_t fsocket;
+	tcp_conn_t *conn;
+	tcp_conn_t *rconn;
+	tcp_sock_lconn_t *lconn;
+	int rc;
+
+	log_msg(LVL_DEBUG, "tcp_sock_accept()");
+
+	socket_id = SOCKET_GET_SOCKET_ID(call);
+	asock_id = SOCKET_GET_NEW_SOCKET_ID(call);
+
+	sock_core = socket_cores_find(&client->sockets, socket_id);
+	if (sock_core == NULL) {
+		async_answer_0(callid, ENOTSOCK);
+		return;
+	}
+
+	socket = (tcp_sockdata_t *)sock_core->specific_data;
+	fibril_mutex_lock(&socket->lock);
+
+	log_msg(LVL_DEBUG, " - verify socket->conn");
+	if (socket->conn != NULL) {
+		fibril_mutex_unlock(&socket->lock);
+		async_answer_0(callid, EINVAL);
+		return;
+	}
+
+	if (list_empty(&socket->ready)) {
+		fibril_mutex_unlock(&socket->lock);
+		async_answer_0(callid, ENOENT);
+		return;
+	}
+
+	lconn = list_get_instance(list_first(&socket->ready),
+	    tcp_sock_lconn_t, ready_list);
+	list_remove(&lconn->ready_list);
+
+	conn = lconn->conn;
+	tcp_uc_set_cstate_cb(conn, NULL, NULL);
+
+	/* Replenish listening connection */
+
+	lsocket.addr.ipv4 = TCP_IPV4_ANY;
+	lsocket.port = sock_core->port;
+	fsocket.addr.ipv4 = TCP_IPV4_ANY;
+	fsocket.port = TCP_PORT_ANY;
+
+	trc = tcp_uc_open(&lsocket, &fsocket, ap_passive, tcp_open_nonblock,
+	    &rconn);
+	if (rconn == NULL) {
+		/* XXX Clean up */
+		fibril_mutex_unlock(&socket->lock);
+		async_answer_0(callid, ENOMEM);
+		return;
+	}
+
+	tcp_uc_set_cstate_cb(rconn, tcp_sock_cstate_cb, lconn);
+
+	assert(trc == TCP_EOK);
+	rconn->name = (char *)"S";
+
+	lconn->conn = rconn;
+
+	/* Allocate socket for accepted connection */
+
+	log_msg(LVL_DEBUG, "tcp_sock_accept(): allocate asocket\n");
+	asocket = calloc(sizeof(tcp_sockdata_t), 1);
+	if (asocket == NULL) {
+		fibril_mutex_unlock(&socket->lock);
+		async_answer_0(callid, ENOMEM);
+		return;
+	}
+
+	fibril_mutex_initialize(&asocket->lock);
+	asocket->client = client;
+	asocket->conn = conn;
+	log_msg(LVL_DEBUG, "tcp_sock_accept():create asocket\n");
+
+	rc = socket_create(&client->sockets, client->sess, asocket, &asock_id);
+	if (rc != EOK) {
+		fibril_mutex_unlock(&socket->lock);
+		async_answer_0(callid, rc);
+		return;
+	}
+	log_msg(LVL_DEBUG, "tcp_sock_accept(): find acore\n");
+
+	asock_core = socket_cores_find(&client->sockets, asock_id);
+	assert(asock_core != NULL);
+
+	refresh_answer(&answer, NULL);
+
+	SOCKET_SET_DATA_FRAGMENT_SIZE(answer, FRAGMENT_SIZE);
+	SOCKET_SET_SOCKET_ID(answer, asock_id);
+	SOCKET_SET_ADDRESS_LENGTH(answer, sizeof(struct sockaddr_in));
+
+	answer_call(callid, asock_core->socket_id, &answer, 3);
+
+	/* Push one fragment notification to client's queue */
+	log_msg(LVL_DEBUG, "tcp_sock_accept(): notify data\n");
+	tcp_sock_notify_data(asock_core);
+	fibril_mutex_unlock(&socket->lock);
+}
+
+static void tcp_sock_send(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
+{
+	int socket_id;
+	int fragments;
+	int index;
+	socket_core_t *sock_core;
+	tcp_sockdata_t *socket;
+	ipc_call_t answer;
+	ipc_callid_t wcallid;
+	size_t length;
+	uint8_t buffer[FRAGMENT_SIZE];
+	tcp_error_t trc;
+	int rc;
+
+	log_msg(LVL_DEBUG, "tcp_sock_send()");
+	socket_id = SOCKET_GET_SOCKET_ID(call);
+	fragments = SOCKET_GET_DATA_FRAGMENTS(call);
+	SOCKET_GET_FLAGS(call);
+
+	sock_core = socket_cores_find(&client->sockets, socket_id);
+	if (sock_core == NULL) {
+		async_answer_0(callid, ENOTSOCK);
+		return;
+	}
+
+	socket = (tcp_sockdata_t *)sock_core->specific_data;
+	fibril_mutex_lock(&socket->lock);
+
+	if (socket->conn == NULL) {
+		fibril_mutex_unlock(&socket->lock);
+		async_answer_0(callid, ENOTCONN);
+		return;
+	}
+
+	for (index = 0; index < fragments; index++) {
+		if (!async_data_write_receive(&wcallid, &length)) {
+			fibril_mutex_unlock(&socket->lock);
+			async_answer_0(callid, EINVAL);
+			return;
+		}
+
+		if (length > FRAGMENT_SIZE)
+			length = FRAGMENT_SIZE;
+
+		rc = async_data_write_finalize(wcallid, buffer, length);
+		if (rc != EOK) {
+			fibril_mutex_unlock(&socket->lock);
+			async_answer_0(callid, rc);
+			return;
+		}
+
+		trc = tcp_uc_send(socket->conn, buffer, length, 0);
+
+		switch (trc) {
+		case TCP_EOK:
+			rc = EOK;
+			break;
+		case TCP_ENOTEXIST:
+			rc = ENOTCONN;
+			break;
+		case TCP_ECLOSING:
+			rc = ENOTCONN;
+			break;
+		case TCP_ERESET:
+			rc = ECONNABORTED;
+			break;
+		default:
+			assert(false);
+		}
+
+		if (rc != EOK) {
+			fibril_mutex_unlock(&socket->lock);
+			async_answer_0(callid, rc);
+			return;
+		}
+	}
+
+	refresh_answer(&answer, NULL);
+	SOCKET_SET_DATA_FRAGMENT_SIZE(answer, FRAGMENT_SIZE);
+	answer_call(callid, EOK, &answer, 2);
+	fibril_mutex_unlock(&socket->lock);
+}
+
+static void tcp_sock_sendto(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
+{
+	log_msg(LVL_DEBUG, "tcp_sock_sendto()");
+	async_answer_0(callid, ENOTSUP);
+}
+
+static void tcp_sock_recvfrom(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
+{
+	int socket_id;
+	int flags;
+	size_t addr_length, length;
+	socket_core_t *sock_core;
+	tcp_sockdata_t *socket;
+	ipc_call_t answer;
+	ipc_callid_t rcallid;
+	uint8_t buffer[FRAGMENT_SIZE];
+	size_t data_len;
+	xflags_t xflags;
+	tcp_error_t trc;
+	struct sockaddr_in addr;
+	tcp_sock_t *rsock;
+	int rc;
+
+	log_msg(LVL_DEBUG, "%p: tcp_sock_recv[from]()", client);
+
+	socket_id = SOCKET_GET_SOCKET_ID(call);
+	flags = SOCKET_GET_FLAGS(call);
+
+	sock_core = socket_cores_find(&client->sockets, socket_id);
+	if (sock_core == NULL) {
+		async_answer_0(callid, ENOTSOCK);
+		return;
+	}
+
+	socket = (tcp_sockdata_t *)sock_core->specific_data;
+	fibril_mutex_lock(&socket->lock);
+
+	if (socket->conn == NULL) {
+		fibril_mutex_unlock(&socket->lock);
+		async_answer_0(callid, ENOTCONN);
+		return;
+	}
+
+	(void)flags;
+
+	trc = tcp_uc_receive(socket->conn, buffer, FRAGMENT_SIZE, &data_len,
+	    &xflags);
+	log_msg(LVL_DEBUG, "**** tcp_uc_receive done");
+
+	switch (trc) {
+	case TCP_EOK:
+		rc = EOK;
+		break;
+	case TCP_ENOTEXIST:
+	case TCP_ECLOSING:
+		rc = ENOTCONN;
+		break;
+	case TCP_ERESET:
+		rc = ECONNABORTED;
+		break;
+	default:
+		assert(false);
+	}
+
+	log_msg(LVL_DEBUG, "**** tcp_uc_receive -> %d", rc);
+	if (rc != EOK) {
+		fibril_mutex_unlock(&socket->lock);
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	if (IPC_GET_IMETHOD(call) == NET_SOCKET_RECVFROM) {
+		/* Fill addr */
+		rsock = &socket->conn->ident.foreign;
+		addr.sin_family = AF_INET;
+		addr.sin_addr.s_addr = host2uint32_t_be(rsock->addr.ipv4);
+		addr.sin_port = host2uint16_t_be(rsock->port);
+
+		log_msg(LVL_DEBUG, "addr read receive");
+		if (!async_data_read_receive(&rcallid, &addr_length)) {
+			fibril_mutex_unlock(&socket->lock);
+			async_answer_0(callid, EINVAL);
+			return;
+		}
+
+		if (addr_length > sizeof(addr))
+			addr_length = sizeof(addr);
+
+		log_msg(LVL_DEBUG, "addr read finalize");
+		rc = async_data_read_finalize(rcallid, &addr, addr_length);
+		if (rc != EOK) {
+			fibril_mutex_unlock(&socket->lock);
+			async_answer_0(callid, EINVAL);
+			return;
+		}
+	}
+
+	log_msg(LVL_DEBUG, "data read receive");
+	if (!async_data_read_receive(&rcallid, &length)) {
+		fibril_mutex_unlock(&socket->lock);
+		async_answer_0(callid, EINVAL);
+		return;
+	}
+
+	if (length > data_len)
+		length = data_len;
+
+	log_msg(LVL_DEBUG, "data read finalize");
+	rc = async_data_read_finalize(rcallid, buffer, length);
+
+	if (length < data_len && rc == EOK)
+		rc = EOVERFLOW;
+
+	SOCKET_SET_READ_DATA_LENGTH(answer, length);
+	answer_call(callid, EOK, &answer, 1);
+
+	/* Push one fragment notification to client's queue */
+	tcp_sock_notify_data(sock_core);
+	fibril_mutex_unlock(&socket->lock);
+}
+
+static void tcp_sock_close(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
+{
+	int socket_id;
+	socket_core_t *sock_core;
+	tcp_sockdata_t *socket;
+	tcp_error_t trc;
+	int rc;
+	uint8_t buffer[FRAGMENT_SIZE];
+	size_t data_len;
+	xflags_t xflags;
+
+	log_msg(LVL_DEBUG, "tcp_sock_close()");
+	socket_id = SOCKET_GET_SOCKET_ID(call);
+
+	sock_core = socket_cores_find(&client->sockets, socket_id);
+	if (sock_core == NULL) {
+		async_answer_0(callid, ENOTSOCK);
+		return;
+	}
+
+	socket = (tcp_sockdata_t *)sock_core->specific_data;
+	fibril_mutex_lock(&socket->lock);
+
+	if (socket->conn != NULL) {
+		trc = tcp_uc_close(socket->conn);
+		if (trc != TCP_EOK && trc != TCP_ENOTEXIST) {
+			fibril_mutex_unlock(&socket->lock);
+			async_answer_0(callid, EBADF);
+			return;
+		}
+
+		/* Drain incoming data. This should really be done in the background. */
+		do {
+			trc = tcp_uc_receive(socket->conn, buffer,
+			    FRAGMENT_SIZE, &data_len, &xflags);
+		} while (trc == TCP_EOK);
+
+		tcp_uc_delete(socket->conn);
+	}
+
+	rc = socket_destroy(NULL, socket_id, &client->sockets, &gsock,
+	    tcp_free_sock_data);
+	if (rc != EOK) {
+		fibril_mutex_unlock(&socket->lock);
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	fibril_mutex_unlock(&socket->lock);
+	async_answer_0(callid, EOK);
+}
+
+static void tcp_sock_getsockopt(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
+{
+	log_msg(LVL_DEBUG, "tcp_sock_getsockopt()");
+	async_answer_0(callid, ENOTSUP);
+}
+
+static void tcp_sock_setsockopt(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
+{
+	log_msg(LVL_DEBUG, "tcp_sock_setsockopt()");
+	async_answer_0(callid, ENOTSUP);
+}
+
+/** Called when connection state changes. */
+static void tcp_sock_cstate_cb(tcp_conn_t *conn, void *arg)
+{
+	tcp_conn_status_t cstatus;
+	tcp_sock_lconn_t *lconn = (tcp_sock_lconn_t *)arg;
+	tcp_sockdata_t *socket = lconn->socket;
+
+	log_msg(LVL_DEBUG, "tcp_sock_cstate_cb()");
+	fibril_mutex_lock(&socket->lock);
+	assert(conn == lconn->conn);
+
+	tcp_uc_status(conn, &cstatus);
+	if (cstatus.cstate != st_established) {
+		fibril_mutex_unlock(&socket->lock);
+		return;
+	}
+
+	assert_link_not_used(&lconn->ready_list);
+	list_append(&lconn->ready_list, &socket->ready);
+
+	log_msg(LVL_DEBUG, "tcp_sock_cstate_cb(): notify accept");
+
+	/* Push one accept notification to client's queue */
+	tcp_sock_notify_aconn(socket->sock_core);
+	fibril_mutex_unlock(&socket->lock);
+}
+
+static void tcp_sock_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	ipc_callid_t callid;
+	ipc_call_t call;
+	tcp_client_t client;
+
+	/* Accept the connection */
+	async_answer_0(iid, EOK);
+
+	client.sess = async_callback_receive(EXCHANGE_SERIALIZE);
+	socket_cores_initialize(&client.sockets);
+
+	while (true) {
+		callid = async_get_call(&call);
+		if (!IPC_GET_IMETHOD(call))
+			break;
+
+		log_msg(LVL_DEBUG, "tcp_sock_connection: METHOD=%d\n",
+		    (int)IPC_GET_IMETHOD(call));
+
+		switch (IPC_GET_IMETHOD(call)) {
+		case NET_SOCKET:
+			tcp_sock_socket(&client, callid, call);
+			break;
+		case NET_SOCKET_BIND:
+			tcp_sock_bind(&client, callid, call);
+			break;
+		case NET_SOCKET_LISTEN:
+			tcp_sock_listen(&client, callid, call);
+			break;
+		case NET_SOCKET_CONNECT:
+			tcp_sock_connect(&client, callid, call);
+			break;
+		case NET_SOCKET_ACCEPT:
+			tcp_sock_accept(&client, callid, call);
+			break;
+		case NET_SOCKET_SEND:
+			tcp_sock_send(&client, callid, call);
+			break;
+		case NET_SOCKET_SENDTO:
+			tcp_sock_sendto(&client, callid, call);
+			break;
+		case NET_SOCKET_RECV:
+		case NET_SOCKET_RECVFROM:
+			tcp_sock_recvfrom(&client, callid, call);
+			break;
+		case NET_SOCKET_CLOSE:
+			tcp_sock_close(&client, callid, call);
+			break;
+		case NET_SOCKET_GETSOCKOPT:
+			tcp_sock_getsockopt(&client, callid, call);
+			break;
+		case NET_SOCKET_SETSOCKOPT:
+			tcp_sock_setsockopt(&client, callid, call);
+			break;
+		default:
+			async_answer_0(callid, ENOTSUP);
+			break;
+		}
+	}
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/net/tcp/sock.h
===================================================================
--- uspace/srv/net/tcp/sock.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/tcp/sock.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup tcp
+ * @{
+ */
+/** @file Socket provider
+ */
+
+#ifndef SOCK_H
+#define SOCK_H
+
+#include <async.h>
+
+extern int tcp_sock_init(void);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/tcp/std.h
===================================================================
--- uspace/srv/net/tcp/std.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/tcp/std.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup tcp
+ * @{
+ */
+/** @file TCP header definitions
+ *
+ * Based on IETF RFC 793
+ */
+
+#ifndef STD_H
+#define STD_H
+
+#include <sys/types.h>
+
+/** TCP Header (fixed part) */
+typedef struct {
+	/** Source port */
+	uint16_t src_port;
+	/** Destination port */
+	uint16_t dest_port;
+	/** Sequence number */
+	uint32_t seq;
+	/** Acknowledgement number */
+	uint32_t ack;
+	/** Data Offset, Reserved, Flags */
+	uint16_t doff_flags;
+	/** Window */
+	uint16_t window;
+	/* Checksum */
+	uint16_t checksum;
+	/** Urgent pointer */
+	uint16_t urg_ptr;
+} tcp_header_t;
+
+/** Bits in tcp_header_t.doff_flags */
+enum doff_flags_bits {
+	DF_DATA_OFFSET_h	= 15,
+	DF_DATA_OFFSET_l	= 12,
+	DF_URG			= 5,
+	DF_ACK			= 4,
+	DF_PSH			= 3,
+	DF_RST			= 2,
+	DF_SYN			= 1,
+	DF_FIN			= 0
+};
+
+/** TCP pseudo header */
+typedef struct {
+	/** Source address */
+	uint32_t src_addr;
+	/** Destination address */
+	uint32_t dest_addr;
+	/** Zero */
+	uint8_t zero;
+	/** Protocol */
+	uint8_t protocol;
+	/** TCP length */
+	uint16_t tcp_length;
+} tcp_phdr_t;
+
+/** Option kind */
+enum opt_kind {
+	/** End of option list */
+	OPT_END_LIST		= 0,
+	/** No-operation */
+	OPT_NOP			= 1,
+	/** Maximum segment size */
+	OPT_MAX_SEG_SIZE	= 2
+};
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/tcp/tcp.c
===================================================================
--- uspace/srv/net/tcp/tcp.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/tcp/tcp.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,230 @@
+/*
+ * Copyright (c) 2012 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup tcp
+ * @{
+ */
+
+/**
+ * @file TCP (Transmission Control Protocol) network module
+ */
+
+#include <async.h>
+#include <bitops.h>
+#include <byteorder.h>
+#include <errno.h>
+#include <inet/inet.h>
+#include <io/log.h>
+#include <stdio.h>
+#include <task.h>
+
+#include "ncsim.h"
+#include "pdu.h"
+#include "rqueue.h"
+#include "sock.h"
+#include "std.h"
+#include "tcp.h"
+#include "test.h"
+
+#define NAME       "tcp"
+
+#define IP_PROTO_TCP 6
+
+static int tcp_inet_ev_recv(inet_dgram_t *dgram);
+static void tcp_received_pdu(tcp_pdu_t *pdu);
+
+static inet_ev_ops_t tcp_inet_ev_ops = {
+	.recv = tcp_inet_ev_recv
+};
+
+/** Received datagram callback */
+static int tcp_inet_ev_recv(inet_dgram_t *dgram)
+{
+	uint8_t *pdu_raw;
+	size_t pdu_raw_size;
+
+	log_msg(LVL_DEBUG, "tcp_inet_ev_recv()");
+
+	pdu_raw = dgram->data;
+	pdu_raw_size = dgram->size;
+
+	/* Split into header and payload. */
+
+	log_msg(LVL_DEBUG, "tcp_inet_ev_recv() - split header/payload");
+
+	tcp_pdu_t *pdu;
+	size_t hdr_size;
+	tcp_header_t *hdr;
+	uint32_t data_offset;
+
+	if (pdu_raw_size < sizeof(tcp_header_t)) {
+		log_msg(LVL_WARN, "pdu_raw_size = %zu < sizeof(tcp_header_t) = %zu",
+		    pdu_raw_size, sizeof(tcp_header_t));
+		return EINVAL;
+	}
+
+	hdr = (tcp_header_t *)pdu_raw;
+	data_offset = BIT_RANGE_EXTRACT(uint32_t, DF_DATA_OFFSET_h, DF_DATA_OFFSET_l,
+	    uint16_t_be2host(hdr->doff_flags));
+
+	hdr_size = sizeof(uint32_t) * data_offset;
+
+	if (pdu_raw_size < hdr_size) {
+		log_msg(LVL_WARN, "pdu_raw_size = %zu < hdr_size = %zu",
+		    pdu_raw_size, hdr_size);
+		return EINVAL;
+	}
+
+	if (hdr_size < sizeof(tcp_header_t)) {
+		log_msg(LVL_WARN, "hdr_size = %zu < sizeof(tcp_header_t) = %zu",
+		    hdr_size, sizeof(tcp_header_t));		return EINVAL;
+	}
+
+	log_msg(LVL_DEBUG, "pdu_raw_size=%zu, hdr_size=%zu",
+	    pdu_raw_size, hdr_size);
+	pdu = tcp_pdu_create(pdu_raw, hdr_size, pdu_raw + hdr_size,
+	    pdu_raw_size - hdr_size);
+	if (pdu == NULL) {
+		log_msg(LVL_WARN, "Failed creating PDU. Dropped.");
+		return ENOMEM;
+	}
+
+	pdu->src_addr.ipv4 = dgram->src.ipv4;
+	pdu->dest_addr.ipv4 = dgram->dest.ipv4;
+	log_msg(LVL_DEBUG, "src: 0x%08x, dest: 0x%08x",
+	    pdu->src_addr.ipv4, pdu->dest_addr.ipv4);
+
+	tcp_received_pdu(pdu);
+	tcp_pdu_delete(pdu);
+
+	return EOK;
+}
+
+/** Transmit PDU over network layer. */
+void tcp_transmit_pdu(tcp_pdu_t *pdu)
+{
+	int rc;
+	uint8_t *pdu_raw;
+	size_t pdu_raw_size;
+	inet_dgram_t dgram;
+
+	pdu_raw_size = pdu->header_size + pdu->text_size;
+	pdu_raw = malloc(pdu_raw_size);
+	if (pdu_raw == NULL) {
+		log_msg(LVL_ERROR, "Failed to transmit PDU. Out of memory.");
+		return;
+	}
+
+	memcpy(pdu_raw, pdu->header, pdu->header_size);
+	memcpy(pdu_raw + pdu->header_size, pdu->text,
+	    pdu->text_size);
+
+	dgram.src.ipv4 = pdu->src_addr.ipv4;
+	dgram.dest.ipv4 = pdu->dest_addr.ipv4;
+	dgram.tos = 0;
+	dgram.data = pdu_raw;
+	dgram.size = pdu_raw_size;
+
+	rc = inet_send(&dgram, INET_TTL_MAX, 0);
+	if (rc != EOK)
+		log_msg(LVL_ERROR, "Failed to transmit PDU.");
+}
+
+/** Process received PDU. */
+static void tcp_received_pdu(tcp_pdu_t *pdu)
+{
+	tcp_segment_t *dseg;
+	tcp_sockpair_t rident;
+
+	log_msg(LVL_DEBUG, "tcp_received_pdu()");
+
+	if (tcp_pdu_decode(pdu, &rident, &dseg) != EOK) {
+		log_msg(LVL_WARN, "Not enough memory. PDU dropped.");
+		return;
+	}
+
+	/* Insert decoded segment into rqueue */
+	tcp_rqueue_insert_seg(&rident, dseg);
+}
+
+static int tcp_init(void)
+{
+	int rc;
+
+	log_msg(LVL_DEBUG, "tcp_init()");
+
+	tcp_rqueue_init();
+	tcp_rqueue_thread_start();
+
+	tcp_ncsim_init();
+	tcp_ncsim_thread_start();
+
+	if (0) tcp_test();
+
+	rc = inet_init(IP_PROTO_TCP, &tcp_inet_ev_ops);
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Failed connecting to internet service.");
+		return ENOENT;
+	}
+
+	rc = tcp_sock_init();
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Failed initializing socket service.");
+		return ENOENT;
+	}
+
+	return EOK;
+}
+
+int main(int argc, char **argv)
+{
+	int rc;
+
+	printf(NAME ": TCP (Transmission Control Protocol) network module\n");
+
+	rc = log_init(NAME, LVL_DEBUG);
+	if (rc != EOK) {
+		printf(NAME ": Failed to initialize log.\n");
+		return 1;
+	}
+
+	rc = tcp_init();
+	if (rc != EOK)
+		return 1;
+
+	printf(NAME ": Accepting connections.\n");
+	task_retval(0);
+	async_manager();
+
+	/* Not reached */
+	return 0;
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/net/tcp/tcp.h
===================================================================
--- uspace/srv/net/tcp/tcp.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/tcp/tcp.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup tcp
+ * @{
+ */
+/** @file TCP (Transmission Control Protocol) network module
+ */
+
+#ifndef TCP_H
+#define TCP_H
+
+#include <async.h>
+#include "tcp_type.h"
+
+extern void tcp_transmit_pdu(tcp_pdu_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/tcp/tcp_type.h
===================================================================
--- uspace/srv/net/tcp/tcp_type.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/tcp/tcp_type.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,363 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup tcp
+ * @{
+ */
+/** @file TCP type definitions
+ */
+
+#ifndef TCP_TYPE_H
+#define TCP_TYPE_H
+
+#include <adt/list.h>
+#include <async.h>
+#include <bool.h>
+#include <fibril_synch.h>
+#include <socket_core.h>
+#include <sys/types.h>
+
+struct tcp_conn;
+
+typedef enum {
+	/** Listen */
+	st_listen,
+	/** Syn-sent */
+	st_syn_sent,
+	/** Syn-received */
+	st_syn_received,
+	/** Established */
+	st_established,
+	/** Fin-wait-1 */
+	st_fin_wait_1,
+	/** Fin-wait-2 */
+	st_fin_wait_2,
+	/** Close-wait */
+	st_close_wait,
+	/** Closing */
+	st_closing,
+	/** Last-ack */
+	st_last_ack,
+	/** Time-wait */
+	st_time_wait,
+	/** Closed */
+	st_closed
+} tcp_cstate_t;
+
+/** Error codes returned by TCP user calls (per the spec). */
+typedef enum {
+	/* OK */
+	TCP_EOK,
+	/* Connection aborted due to user timeout */
+	TCP_EABORTED,
+	/* Connection already exists */
+	TCP_EEXISTS,
+	/* Connection closing */
+	TCP_ECLOSING,
+	/* Connection does not exist */
+	TCP_ENOTEXIST,
+	/* Connection illegal for this process */
+	TCP_EILLEGAL,
+	/* Connection not open */
+	TCP_ENOTOPEN,
+	/* Connection reset */
+	TCP_ERESET,
+	/* Foreign socket unspecified */
+	TCP_EUNSPEC,
+	/* Insufficient resources */
+	TCP_ENORES,
+	/* Precedence not allowed */
+	TCP_EINVPREC,
+	/* Security/compartment not allowed */
+	TCP_EINVCOMP
+} tcp_error_t;
+
+typedef enum {
+	XF_PUSH		= 0x1,
+	XF_URGENT	= 0x2
+} xflags_t;
+
+typedef enum {
+	CTL_SYN		= 0x1,
+	CTL_FIN		= 0x2,
+	CTL_RST		= 0x4,
+	CTL_ACK		= 0x8
+} tcp_control_t;
+
+typedef struct {
+	uint32_t ipv4;
+} netaddr_t;
+
+typedef struct {
+	netaddr_t addr;
+	uint16_t port;
+} tcp_sock_t;
+
+enum netaddr {
+	TCP_IPV4_ANY = 0
+};
+
+enum tcp_port {
+	TCP_PORT_ANY = 0
+};
+
+typedef struct {
+	tcp_sock_t local;
+	tcp_sock_t foreign;
+} tcp_sockpair_t;
+
+/** Connection incoming segments queue */
+typedef struct {
+	struct tcp_conn *conn;
+	list_t list;
+} tcp_iqueue_t;
+
+/** Retransmission queue */
+typedef struct {
+	struct tcp_conn *conn;
+	list_t list;
+
+	/** Retransmission timer */
+	fibril_timer_t *timer;
+} tcp_tqueue_t;
+
+typedef enum {
+	ap_active,
+	ap_passive
+} acpass_t;
+
+typedef enum {
+	tcp_open_nonblock = 1
+} tcp_open_flags_t;
+
+typedef struct tcp_conn tcp_conn_t;
+
+/** Connection state change callback function */
+typedef void (*tcp_cstate_cb_t)(tcp_conn_t *, void *);
+
+/** Connection */
+struct tcp_conn {
+	char *name;
+	link_t link;
+
+	/** Connection state change callback function */
+	tcp_cstate_cb_t cstate_cb;
+	/** Argument to @c cstate_cb */
+	void *cstate_cb_arg;
+
+	/** Connection identification (local and foreign socket) */
+	tcp_sockpair_t ident;
+
+	/** Active or passive connection */
+	acpass_t ap;
+
+	/** Protects access to connection structure */
+	fibril_mutex_t lock;
+	/** Reference count */
+	atomic_t refcnt;
+
+	/** Connection state */
+	tcp_cstate_t cstate;
+	/** True if connection was reset */
+	bool reset;
+	/** True if connection was deleted by user */
+	bool deleted;
+	/** Signalled when @c cstate changes */
+	fibril_condvar_t cstate_cv;
+
+	/** Set when FIN is removed from the retransmission queue */
+	bool fin_is_acked;
+
+	/** Queue of incoming segments */
+	tcp_iqueue_t incoming;
+
+	/** Retransmission queue */
+	tcp_tqueue_t retransmit;
+
+	/** Time-Wait timeout timer */
+	fibril_timer_t *tw_timer;
+
+	/** Receive buffer */
+	uint8_t *rcv_buf;
+	/** Receive buffer size */
+	size_t rcv_buf_size;
+	/** Receive buffer number of bytes used */
+	size_t rcv_buf_used;
+	/** Receive buffer contains FIN */
+	bool rcv_buf_fin;
+	/** Receive buffer CV. Broadcast when new data is inserted */
+	fibril_condvar_t rcv_buf_cv;
+
+	/** Send buffer */
+	uint8_t *snd_buf;
+	/** Send buffer size */
+	size_t snd_buf_size;
+	/** Send buffer number of bytes used */
+	size_t snd_buf_used;
+	/** Send buffer contains FIN */
+	bool snd_buf_fin;
+	/** Send buffer CV. Broadcast when space is made available in buffer */
+	fibril_condvar_t snd_buf_cv;
+
+	/** Send unacknowledged */
+	uint32_t snd_una;
+	/** Send next */
+	uint32_t snd_nxt;
+	/** Send window */
+	uint32_t snd_wnd;
+	/** Send urgent pointer */
+	uint32_t snd_up;
+	/** Segment sequence number used for last window update */
+	uint32_t snd_wl1;
+	/** Segment acknowledgement number used for last window update */
+	uint32_t snd_wl2;
+	/** Initial send sequence number */
+	uint32_t iss;
+
+	/** Receive next */
+	uint32_t rcv_nxt;
+	/** Receive window */
+	uint32_t rcv_wnd;
+	/** Receive urgent pointer */
+	uint32_t rcv_up;
+	/** Initial receive sequence number */
+	uint32_t irs;
+};
+
+/** Data returned by Status user call */
+typedef struct {
+	/** Connection state */
+	tcp_cstate_t cstate;
+} tcp_conn_status_t;
+
+typedef struct {
+	/** SYN, FIN */
+	tcp_control_t ctrl;
+
+	/** Segment sequence number */
+	uint32_t seq;
+	/** Segment acknowledgement number */
+	uint32_t ack;
+	/** Segment length in sequence space */
+	uint32_t len;
+	/** Segment window */
+	uint32_t wnd;
+	/** Segment urgent pointer */
+	uint32_t up;
+
+	/** Segment data, may be moved when trimming segment */
+	void *data;
+	/** Segment data, original pointer used to free data */
+	void *dfptr;
+} tcp_segment_t;
+
+
+typedef struct {
+	link_t link;
+	tcp_sockpair_t sp;
+	tcp_segment_t *seg;
+} tcp_rqueue_entry_t;
+
+/** NCSim queue entry */
+typedef struct {
+	link_t link;
+	suseconds_t delay;
+	tcp_sockpair_t sp;
+	tcp_segment_t *seg;
+} tcp_squeue_entry_t;
+
+typedef struct {
+	link_t link;
+	tcp_segment_t *seg;
+} tcp_iqueue_entry_t;
+
+/** Retransmission queue entry */
+typedef struct {
+	link_t link;
+	tcp_conn_t *conn;
+	tcp_segment_t *seg;
+} tcp_tqueue_entry_t;
+
+typedef enum {
+	cp_continue,
+	cp_done
+} cproc_t;
+
+/** Encoded PDU */
+typedef struct {
+	/** Source address */
+	netaddr_t src_addr;
+	/** Destination address */
+	netaddr_t dest_addr;
+
+	/** Encoded header */
+	void *header;
+	/** Encoded header size */
+	size_t header_size;
+	/** Text */
+	void *text;
+	/** Text size */
+	size_t text_size;
+} tcp_pdu_t;
+
+typedef struct {
+	async_sess_t *sess;
+	socket_cores_t sockets;
+} tcp_client_t;
+
+typedef struct tcp_sockdata {
+	/** Lock */
+	fibril_mutex_t lock;
+	/** Socket core */
+	socket_core_t *sock_core;
+	/** Client */
+	tcp_client_t *client;
+	/** Connection */
+	tcp_conn_t *conn;
+	/** Local address */
+	netaddr_t laddr;
+	/** Backlog size */
+	int backlog;
+	/** Array of listening connections, @c backlog elements */
+	struct tcp_sock_lconn **lconn;
+	/** List of connections (from lconn) that are ready to be accepted */
+	list_t ready;
+} tcp_sockdata_t;
+
+typedef struct tcp_sock_lconn {
+	tcp_conn_t *conn;
+	tcp_sockdata_t *socket;
+	int index;
+	link_t ready_list;
+} tcp_sock_lconn_t;
+
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/tcp/test.c
===================================================================
--- uspace/srv/net/tcp/test.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/tcp/test.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup tcp
+ * @{
+ */
+
+/**
+ * @file Internal TCP test
+ */
+
+#include <async.h>
+#include <errno.h>
+#include <stdio.h>
+#include <thread.h>
+#include <str.h>
+#include "tcp_type.h"
+#include "ucall.h"
+
+#include "test.h"
+
+#define RCV_BUF_SIZE 64
+
+static void test_srv(void *arg)
+{
+	tcp_conn_t *conn;
+	tcp_sock_t lsock;
+	tcp_sock_t fsock;
+	char rcv_buf[RCV_BUF_SIZE + 1];
+	size_t rcvd;
+	xflags_t xflags;
+
+	printf("test_srv()\n");
+	lsock.port = 80;
+	lsock.addr.ipv4 = 0x7f000001;
+	fsock.port = 1024;
+	fsock.addr.ipv4 = 0x7f000001;
+	printf("S: User open...\n");
+	tcp_uc_open(&lsock, &fsock, ap_passive, 0, &conn);
+	conn->name = (char *) "S";
+
+	while (true) {
+		printf("S: User receive...\n");
+		tcp_uc_receive(conn, rcv_buf, RCV_BUF_SIZE, &rcvd, &xflags);
+		if (rcvd == 0) {
+			printf("S: End of data reached.\n");
+			break;
+		}
+		rcv_buf[rcvd] = '\0';
+		printf("S: User received %zu bytes '%s'.\n", rcvd, rcv_buf);
+
+		async_usleep(1000*1000*2);
+	}
+
+	async_usleep(/*10**/1000*1000);
+
+	printf("S: User close...\n");
+	tcp_uc_close(conn);
+
+	printf("test_srv() terminating\n");
+}
+
+static void test_cli(void *arg)
+{
+	tcp_conn_t *conn;
+	tcp_sock_t lsock;
+	tcp_sock_t fsock;
+	const char *msg = "Hello World!";
+
+	printf("test_cli()\n");
+
+	lsock.port = 1024;
+	lsock.addr.ipv4 = 0x7f000001;
+	fsock.port = 80;
+	fsock.addr.ipv4 = 0x7f000001;
+
+	async_usleep(1000*1000*3);
+	printf("C: User open...\n");
+	tcp_uc_open(&lsock, &fsock, ap_active, 0, &conn);
+	conn->name = (char *) "C";
+
+	async_usleep(1000*1000*10);
+	printf("C: User send...\n");
+	tcp_uc_send(conn, (void *)msg, str_size(msg), 0);
+
+	async_usleep(1000*1000*20/**20*2*/);
+	printf("C: User close...\n");
+	tcp_uc_close(conn);
+}
+
+void tcp_test(void)
+{
+	thread_id_t srv_tid;
+	thread_id_t cli_tid;
+	int rc;
+
+	printf("tcp_test()\n");
+
+	async_usleep(1000*1000);
+
+	if (0) {
+		rc = thread_create(test_srv, NULL, "test_srv", &srv_tid);
+		if (rc != EOK) {
+			printf("Failed to create server thread.\n");
+			return;
+		}
+	}
+
+	if (0) {
+		rc = thread_create(test_cli, NULL, "test_cli", &cli_tid);
+		if (rc != EOK) {
+			printf("Failed to create client thread.\n");
+			return;
+		}
+	}
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/net/tcp/test.h
===================================================================
--- uspace/srv/net/tcp/test.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/tcp/test.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup tcp
+ * @{
+ */
+/** @file Internal TCP test
+ */
+
+#ifndef TEST_H
+#define TEST_H
+
+extern void tcp_test(void);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/tcp/tqueue.c
===================================================================
--- uspace/srv/net/tcp/tqueue.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/tcp/tqueue.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,381 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup tcp
+ * @{
+ */
+
+/**
+ * @file TCP transmission queue
+ */
+
+#include <adt/list.h>
+#include <errno.h>
+#include <fibril_synch.h>
+#include <byteorder.h>
+#include <io/log.h>
+#include <macros.h>
+#include <mem.h>
+#include <stdlib.h>
+#include "conn.h"
+#include "ncsim.h"
+#include "pdu.h"
+#include "rqueue.h"
+#include "segment.h"
+#include "seq_no.h"
+#include "tqueue.h"
+#include "tcp.h"
+#include "tcp_type.h"
+
+#define RETRANSMIT_TIMEOUT	(2*1000*1000)
+
+static void retransmit_timeout_func(void *arg);
+static void tcp_tqueue_timer_set(tcp_conn_t *conn);
+static void tcp_tqueue_timer_clear(tcp_conn_t *conn);
+
+int tcp_tqueue_init(tcp_tqueue_t *tqueue, tcp_conn_t *conn)
+{
+	tqueue->conn = conn;
+	tqueue->timer = fibril_timer_create();
+	if (tqueue->timer == NULL)
+		return ENOMEM;
+
+	list_initialize(&tqueue->list);
+
+	return EOK;
+}
+
+void tcp_tqueue_clear(tcp_tqueue_t *tqueue)
+{
+	tcp_tqueue_timer_clear(tqueue->conn);
+}
+
+void tcp_tqueue_fini(tcp_tqueue_t *tqueue)
+{
+	if (tqueue->timer != NULL) {
+		fibril_timer_destroy(tqueue->timer);
+		tqueue->timer = NULL;
+	}
+}
+
+void tcp_tqueue_ctrl_seg(tcp_conn_t *conn, tcp_control_t ctrl)
+{
+	tcp_segment_t *seg;
+
+	log_msg(LVL_DEBUG, "tcp_tqueue_ctrl_seg(%p, %u)", conn, ctrl);
+
+	seg = tcp_segment_make_ctrl(ctrl);
+	tcp_tqueue_seg(conn, seg);
+}
+
+void tcp_tqueue_seg(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	tcp_segment_t *rt_seg;
+	tcp_tqueue_entry_t *tqe;
+
+	log_msg(LVL_DEBUG, "%s: tcp_tqueue_seg(%p, %p)", conn->name, conn,
+	    seg);
+
+	/*
+	 * Add segment to retransmission queue
+	 */
+
+	if (seg->len > 0) {
+		rt_seg = tcp_segment_dup(seg);
+		if (rt_seg == NULL) {
+			log_msg(LVL_ERROR, "Memory allocation failed.");
+			/* XXX Handle properly */
+			return;
+		}
+
+		tqe = calloc(1, sizeof(tcp_tqueue_entry_t));
+		if (tqe == NULL) {
+			log_msg(LVL_ERROR, "Memory allocation failed.");
+			/* XXX Handle properly */
+			return;
+		}
+
+		tqe->conn = conn;
+		tqe->seg = rt_seg;
+		rt_seg->seq = conn->snd_nxt;
+
+		list_append(&tqe->link, &conn->retransmit.list);
+
+		/* Set retransmission timer */
+		tcp_tqueue_timer_set(conn);
+	}
+
+	tcp_prepare_transmit_segment(conn, seg);
+}
+
+void tcp_prepare_transmit_segment(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	/*
+	 * Always send ACK once we have received SYN, except for RST segments.
+	 * (Spec says we should always send ACK once connection has been
+	 * established.)
+	 */
+	if (tcp_conn_got_syn(conn) && (seg->ctrl & CTL_RST) == 0)
+		seg->ctrl |= CTL_ACK;
+
+	seg->seq = conn->snd_nxt;
+	conn->snd_nxt += seg->len;
+
+	tcp_conn_transmit_segment(conn, seg);
+}
+
+/** Transmit data from the send buffer.
+ *
+ * @param conn	Connection
+ */
+void tcp_tqueue_new_data(tcp_conn_t *conn)
+{
+	size_t avail_wnd;
+	size_t xfer_seqlen;
+	size_t snd_buf_seqlen;
+	size_t data_size;
+	tcp_control_t ctrl;
+	bool send_fin;
+
+	tcp_segment_t *seg;
+
+	log_msg(LVL_DEBUG, "%s: tcp_tqueue_new_data()", conn->name);
+
+	/* Number of free sequence numbers in send window */
+	avail_wnd = (conn->snd_una + conn->snd_wnd) - conn->snd_nxt;
+	snd_buf_seqlen = conn->snd_buf_used + (conn->snd_buf_fin ? 1 : 0);
+
+	xfer_seqlen = min(snd_buf_seqlen, avail_wnd);
+	log_msg(LVL_DEBUG, "%s: snd_buf_seqlen = %zu, SND.WND = %zu, "
+	    "xfer_seqlen = %zu", conn->name, snd_buf_seqlen, conn->snd_wnd,
+	    xfer_seqlen);
+
+	if (xfer_seqlen == 0)
+		return;
+
+	/* XXX Do not always send immediately */
+
+	send_fin = conn->snd_buf_fin && xfer_seqlen == snd_buf_seqlen;
+	data_size = xfer_seqlen - (send_fin ? 1 : 0);
+
+	if (send_fin) {
+		log_msg(LVL_DEBUG, "%s: Sending out FIN.", conn->name);
+		/* We are sending out FIN */
+		ctrl = CTL_FIN;
+	} else {
+		ctrl = 0;
+	}
+
+	seg = tcp_segment_make_data(ctrl, conn->snd_buf, data_size);
+	if (seg == NULL) {
+		log_msg(LVL_ERROR, "Memory allocation failure.");
+		return;
+	}
+
+	/* Remove data from send buffer */
+	memmove(conn->snd_buf, conn->snd_buf + data_size,
+	    conn->snd_buf_used - data_size);
+	conn->snd_buf_used -= data_size;
+
+	if (send_fin)
+		conn->snd_buf_fin = false;
+
+	fibril_condvar_broadcast(&conn->snd_buf_cv);
+
+	if (send_fin)
+		tcp_conn_fin_sent(conn);
+
+	tcp_tqueue_seg(conn, seg);
+}
+
+/** Remove ACKed segments from retransmission queue and possibly transmit
+ * more data.
+ *
+ * This should be called when SND.UNA is updated due to incoming ACK.
+ */
+void tcp_tqueue_ack_received(tcp_conn_t *conn)
+{
+	link_t *cur, *next;
+
+	log_msg(LVL_DEBUG, "%s: tcp_tqueue_ack_received(%p)", conn->name,
+	    conn);
+
+	cur = conn->retransmit.list.head.next;
+
+	while (cur != &conn->retransmit.list.head) {
+		next = cur->next;
+
+		tcp_tqueue_entry_t *tqe = list_get_instance(cur,
+		    tcp_tqueue_entry_t, link);
+
+		if (seq_no_segment_acked(conn, tqe->seg, conn->snd_una)) {
+			/* Remove acknowledged segment */
+			list_remove(cur);
+
+			if ((tqe->seg->ctrl & CTL_FIN) != 0) {
+				log_msg(LVL_DEBUG, "Fin has been acked");
+				log_msg(LVL_DEBUG, "SND.UNA=%" PRIu32
+				    " SEG.SEQ=%" PRIu32 " SEG.LEN=%" PRIu32,
+				    conn->snd_una, tqe->seg->seq, tqe->seg->len);
+				/* Our FIN has been acked */
+				conn->fin_is_acked = true;
+			}
+
+			tcp_segment_delete(tqe->seg);
+			free(tqe);
+
+			/* Reset retransmission timer */
+			tcp_tqueue_timer_set(conn);
+		}
+
+		cur = next;
+	}
+
+	/* Clear retransmission timer if the queue is empty. */
+	if (list_empty(&conn->retransmit.list))
+		tcp_tqueue_timer_clear(conn);
+
+	/* Possibly transmit more data */
+	tcp_tqueue_new_data(conn);
+}
+
+void tcp_conn_transmit_segment(tcp_conn_t *conn, tcp_segment_t *seg)
+{
+	log_msg(LVL_DEBUG, "%s: tcp_conn_transmit_segment(%p, %p)",
+	    conn->name, conn, seg);
+
+	seg->wnd = conn->rcv_wnd;
+
+	if ((seg->ctrl & CTL_ACK) != 0)
+		seg->ack = conn->rcv_nxt;
+	else
+		seg->ack = 0;
+
+	tcp_transmit_segment(&conn->ident, seg);
+}
+
+void tcp_transmit_segment(tcp_sockpair_t *sp, tcp_segment_t *seg)
+{
+	log_msg(LVL_DEBUG, "tcp_transmit_segment(f:(%x,%u),l:(%x,%u), %p)",
+	    sp->foreign.addr.ipv4, sp->foreign.port,
+	    sp->local.addr.ipv4, sp->local.port, seg);
+
+	log_msg(LVL_DEBUG, "SEG.SEQ=%" PRIu32 ", SEG.WND=%" PRIu32,
+	    seg->seq, seg->wnd);
+
+	tcp_segment_dump(seg);
+/*
+	tcp_pdu_prepare(conn, seg, &data, &len);
+	tcp_pdu_transmit(data, len);
+*/
+//	tcp_rqueue_bounce_seg(sp, seg);
+//	tcp_ncsim_bounce_seg(sp, seg);
+
+	tcp_pdu_t *pdu;
+
+	if (tcp_pdu_encode(sp, seg, &pdu) != EOK) {
+		log_msg(LVL_WARN, "Not enough memory. Segment dropped.");
+		return;
+	}
+
+	tcp_transmit_pdu(pdu);
+	tcp_pdu_delete(pdu);
+}
+
+static void retransmit_timeout_func(void *arg)
+{
+	tcp_conn_t *conn = (tcp_conn_t *) arg;
+	tcp_tqueue_entry_t *tqe;
+	tcp_segment_t *rt_seg;
+	link_t *link;
+
+	log_msg(LVL_DEBUG, "### %s: retransmit_timeout_func(%p)", conn->name, conn);
+
+	fibril_mutex_lock(&conn->lock);
+
+	if (conn->cstate == st_closed) {
+		log_msg(LVL_DEBUG, "Connection already closed.");
+		fibril_mutex_unlock(&conn->lock);
+		tcp_conn_delref(conn);
+		return;
+	}
+
+	link = list_first(&conn->retransmit.list);
+	if (link == NULL) {
+		log_msg(LVL_DEBUG, "Nothing to retransmit");
+		fibril_mutex_unlock(&conn->lock);
+		tcp_conn_delref(conn);
+		return;
+	}
+
+	tqe = list_get_instance(link, tcp_tqueue_entry_t, link);
+
+	rt_seg = tcp_segment_dup(tqe->seg);
+	if (rt_seg == NULL) {
+		log_msg(LVL_ERROR, "Memory allocation failed.");
+		fibril_mutex_unlock(&conn->lock);
+		tcp_conn_delref(conn);
+		/* XXX Handle properly */
+		return;
+	}
+
+	log_msg(LVL_DEBUG, "### %s: retransmitting segment", conn->name);
+	tcp_conn_transmit_segment(tqe->conn, rt_seg);
+
+	/* Reset retransmission timer */
+	tcp_tqueue_timer_set(tqe->conn);
+
+	fibril_mutex_unlock(&conn->lock);
+	tcp_conn_delref(conn);
+}
+
+/** Set or re-set retransmission timer */
+static void tcp_tqueue_timer_set(tcp_conn_t *conn)
+{
+	log_msg(LVL_DEBUG, "### %s: tcp_tqueue_timer_set()", conn->name);
+
+	/* Clear first to make sure we update refcnt correctly */
+	tcp_tqueue_timer_clear(conn);
+
+	tcp_conn_addref(conn);
+	fibril_timer_set(conn->retransmit.timer, RETRANSMIT_TIMEOUT,
+	    retransmit_timeout_func, (void *) conn);
+}
+
+/** Clear retransmission timer */
+static void tcp_tqueue_timer_clear(tcp_conn_t *conn)
+{
+	log_msg(LVL_DEBUG, "### %s: tcp_tqueue_timer_clear()", conn->name);
+
+	if (fibril_timer_clear(conn->retransmit.timer) == fts_active)
+		tcp_conn_delref(conn);
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/net/tcp/tqueue.h
===================================================================
--- uspace/srv/net/tcp/tqueue.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/tcp/tqueue.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup tcp
+ * @{
+ */
+/** @file TCP transmission queue
+ */
+
+#ifndef TQUEUE_H
+#define TQUEUE_H
+
+#include "std.h"
+#include "tcp_type.h"
+
+extern int tcp_tqueue_init(tcp_tqueue_t *, tcp_conn_t *);
+extern void tcp_tqueue_clear(tcp_tqueue_t *);
+extern void tcp_tqueue_fini(tcp_tqueue_t *);
+extern void tcp_tqueue_ctrl_seg(tcp_conn_t *, tcp_control_t);
+extern void tcp_tqueue_seg(tcp_conn_t *, tcp_segment_t *);
+extern void tcp_tqueue_new_data(tcp_conn_t *);
+extern void tcp_tqueue_ack_received(tcp_conn_t *);
+extern void tcp_prepare_transmit_segment(tcp_conn_t *, tcp_segment_t *);
+extern void tcp_conn_transmit_segment(tcp_conn_t *, tcp_segment_t *);
+extern void tcp_transmit_segment(tcp_sockpair_t *, tcp_segment_t *);
+extern void tcp_header_setup(tcp_conn_t *, tcp_segment_t *, tcp_header_t *);
+extern void tcp_phdr_setup(tcp_conn_t *, tcp_segment_t *, tcp_phdr_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/tcp/ucall.c
===================================================================
--- uspace/srv/net/tcp/ucall.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/tcp/ucall.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,346 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup tcp
+ * @{
+ */
+
+/**
+ * @file TCP entry points (close to those defined in the RFC)
+ */
+
+#include <fibril_synch.h>
+#include <io/log.h>
+#include <macros.h>
+#include <mem.h>
+#include "conn.h"
+#include "tcp_type.h"
+#include "tqueue.h"
+#include "ucall.h"
+
+/*
+ * User calls
+ */
+
+/** OPEN user call
+ *
+ * @param lsock		Local socket
+ * @param fsock		Foreign socket
+ * @param acpass	Active/passive
+ * @param oflags	Open flags
+ * @param conn		Connection
+ *
+ * Unlike in the spec we allow specifying the local address. This means
+ * the implementation does not need to magically guess it, especially
+ * considering there can be more than one local address.
+ *
+ * XXX We should be able to call active open on an existing listening
+ * connection.
+ * XXX We should be able to get connection structure immediately, before
+ * establishment.
+ */
+tcp_error_t tcp_uc_open(tcp_sock_t *lsock, tcp_sock_t *fsock, acpass_t acpass,
+    tcp_open_flags_t oflags, tcp_conn_t **conn)
+{
+	tcp_conn_t *nconn;
+
+	log_msg(LVL_DEBUG, "tcp_uc_open(%p, %p, %s, %s, %p)",
+	    lsock, fsock, acpass == ap_active ? "active" : "passive",
+	    oflags == tcp_open_nonblock ? "nonblock" : "none", conn);
+
+	nconn = tcp_conn_new(lsock, fsock);
+	tcp_conn_add(nconn);
+
+	if (acpass == ap_active) {
+		/* Synchronize (initiate) connection */
+		tcp_conn_sync(nconn);
+	}
+
+	if (oflags == tcp_open_nonblock) {
+		*conn = nconn;
+		return TCP_EOK;
+	}
+
+	/* Wait for connection to be established or reset */
+	log_msg(LVL_DEBUG, "tcp_uc_open: Wait for connection.");
+	fibril_mutex_lock(&nconn->lock);
+	while (nconn->cstate == st_listen ||
+	    nconn->cstate == st_syn_sent ||
+	    nconn->cstate == st_syn_received) {
+		fibril_condvar_wait(&nconn->cstate_cv, &nconn->lock);
+	}
+
+	if (nconn->cstate != st_established) {
+		log_msg(LVL_DEBUG, "tcp_uc_open: Connection was reset.");
+		assert(nconn->cstate == st_closed);
+		fibril_mutex_unlock(&nconn->lock);
+		return TCP_ERESET;
+	}
+
+	fibril_mutex_unlock(&nconn->lock);
+	log_msg(LVL_DEBUG, "tcp_uc_open: Connection was established.");
+
+	*conn = nconn;
+	log_msg(LVL_DEBUG, "tcp_uc_open -> %p", nconn);
+	return TCP_EOK;
+}
+
+/** SEND user call */
+tcp_error_t tcp_uc_send(tcp_conn_t *conn, void *data, size_t size,
+    xflags_t flags)
+{
+	size_t buf_free;
+	size_t xfer_size;
+
+	log_msg(LVL_DEBUG, "%s: tcp_uc_send()", conn->name);
+
+	fibril_mutex_lock(&conn->lock);
+
+	if (conn->cstate == st_closed) {
+		fibril_mutex_unlock(&conn->lock);
+		return TCP_ENOTEXIST;
+	}
+
+	if (conn->cstate == st_listen) {
+		/* Change connection to active */
+		tcp_conn_sync(conn);
+	}
+
+
+	if (conn->snd_buf_fin) {
+		fibril_mutex_unlock(&conn->lock);
+		return TCP_ECLOSING;
+	}
+
+	while (size > 0) {
+		buf_free = conn->snd_buf_size - conn->snd_buf_used;
+		while (buf_free == 0 && !conn->reset) {
+			log_msg(LVL_DEBUG, "%s: buf_free == 0, waiting.",
+			    conn->name);
+			fibril_condvar_wait(&conn->snd_buf_cv, &conn->lock);
+			buf_free = conn->snd_buf_size - conn->snd_buf_used;
+		}
+
+		if (conn->reset) {
+			fibril_mutex_unlock(&conn->lock);
+			return TCP_ERESET;
+		}
+
+		xfer_size = min(size, buf_free);
+
+		/* Copy data to buffer */
+		memcpy(conn->snd_buf + conn->snd_buf_used, data, xfer_size);
+		data += xfer_size;
+		conn->snd_buf_used += xfer_size;
+		size -= xfer_size;
+
+		tcp_tqueue_new_data(conn);
+	}
+
+	tcp_tqueue_new_data(conn);
+	fibril_mutex_unlock(&conn->lock);
+
+	return TCP_EOK;
+}
+
+/** RECEIVE user call */
+tcp_error_t tcp_uc_receive(tcp_conn_t *conn, void *buf, size_t size,
+    size_t *rcvd, xflags_t *xflags)
+{
+	size_t xfer_size;
+
+	log_msg(LVL_DEBUG, "%s: tcp_uc_receive()", conn->name);
+
+	fibril_mutex_lock(&conn->lock);
+
+	if (conn->cstate == st_closed) {
+		fibril_mutex_unlock(&conn->lock);
+		return TCP_ENOTEXIST;
+	}
+
+	/* Wait for data to become available */
+	while (conn->rcv_buf_used == 0 && !conn->rcv_buf_fin && !conn->reset) {
+		log_msg(LVL_DEBUG, "tcp_uc_receive() - wait for data");
+		fibril_condvar_wait(&conn->rcv_buf_cv, &conn->lock);
+	}
+
+	if (conn->rcv_buf_used == 0) {
+		*rcvd = 0;
+		*xflags = 0;
+
+		if (conn->rcv_buf_fin) {
+			/* End of data, peer closed connection */
+			fibril_mutex_unlock(&conn->lock);
+			return TCP_ECLOSING;
+		} else {
+			/* Connection was reset */
+			assert(conn->reset);
+			fibril_mutex_unlock(&conn->lock);
+			return TCP_ERESET;
+		}
+	}
+
+	/* Copy data from receive buffer to user buffer */
+	xfer_size = min(size, conn->rcv_buf_used);
+	memcpy(buf, conn->rcv_buf, xfer_size);
+	*rcvd = xfer_size;
+
+	/* Remove data from receive buffer */
+	memmove(conn->rcv_buf, conn->rcv_buf + xfer_size, conn->rcv_buf_used -
+	    xfer_size);
+	conn->rcv_buf_used -= xfer_size;
+	conn->rcv_wnd += xfer_size;
+
+	/* TODO */
+	*xflags = 0;
+
+	/* Send new size of receive window */
+	tcp_tqueue_ctrl_seg(conn, CTL_ACK);
+
+	log_msg(LVL_DEBUG, "%s: tcp_uc_receive() - returning %zu bytes",
+	    conn->name, xfer_size);
+
+	fibril_mutex_unlock(&conn->lock);
+
+	return TCP_EOK;
+}
+
+/** CLOSE user call */
+tcp_error_t tcp_uc_close(tcp_conn_t *conn)
+{
+	log_msg(LVL_DEBUG, "%s: tcp_uc_close()", conn->name);
+
+	fibril_mutex_lock(&conn->lock);
+
+	if (conn->cstate == st_closed) {
+		fibril_mutex_unlock(&conn->lock);
+		return TCP_ENOTEXIST;
+	}
+
+	if (conn->snd_buf_fin) {
+		fibril_mutex_unlock(&conn->lock);
+		return TCP_ECLOSING;
+	}
+
+	conn->snd_buf_fin = true;
+	tcp_tqueue_new_data(conn);
+
+	fibril_mutex_unlock(&conn->lock);
+	return TCP_EOK;
+}
+
+/** ABORT user call */
+void tcp_uc_abort(tcp_conn_t *conn)
+{
+	log_msg(LVL_DEBUG, "tcp_uc_abort()");
+}
+
+/** STATUS user call */
+void tcp_uc_status(tcp_conn_t *conn, tcp_conn_status_t *cstatus)
+{
+	log_msg(LVL_DEBUG, "tcp_uc_status()");
+	cstatus->cstate = conn->cstate;
+}
+
+/** Delete connection user call.
+ *
+ * (Not in spec.) Inform TCP that the user is done with this connection
+ * and will not make any further calls/references to it. TCP can deallocate
+ * the connection from now on.
+ */
+void tcp_uc_delete(tcp_conn_t *conn)
+{
+	log_msg(LVL_DEBUG, "tcp_uc_delete()");
+	tcp_conn_delete(conn);
+}
+
+void tcp_uc_set_cstate_cb(tcp_conn_t *conn, tcp_cstate_cb_t cb, void *arg)
+{
+	log_msg(LVL_DEBUG, "tcp_uc_set_ctate_cb(%p, %p, %p)",
+	    conn, cb, arg);
+
+	conn->cstate_cb = cb;
+	conn->cstate_cb_arg = arg;
+}
+
+/*
+ * Arriving segments
+ */
+
+/** Segment arrived */
+void tcp_as_segment_arrived(tcp_sockpair_t *sp, tcp_segment_t *seg)
+{
+	tcp_conn_t *conn;
+
+	log_msg(LVL_DEBUG, "tcp_as_segment_arrived(f:(%x,%u), l:(%x,%u))",
+	    sp->foreign.addr.ipv4, sp->foreign.port,
+	    sp->local.addr.ipv4, sp->local.port);
+
+	conn = tcp_conn_find_ref(sp);
+	if (conn == NULL) {
+		log_msg(LVL_WARN, "No connection found.");
+		tcp_unexpected_segment(sp, seg);
+		return;
+	}
+
+	fibril_mutex_lock(&conn->lock);
+
+	if (conn->cstate == st_closed) {
+		log_msg(LVL_WARN, "Connection is closed.");
+		tcp_unexpected_segment(sp, seg);
+		fibril_mutex_unlock(&conn->lock);
+		tcp_conn_delref(conn);
+		return;
+	}
+
+	if (conn->ident.foreign.addr.ipv4 == TCP_IPV4_ANY)
+		conn->ident.foreign.addr.ipv4 = sp->foreign.addr.ipv4;
+	if (conn->ident.foreign.port == TCP_PORT_ANY)
+		conn->ident.foreign.port = sp->foreign.port;
+	if (conn->ident.local.addr.ipv4 == TCP_IPV4_ANY)
+		conn->ident.local.addr.ipv4 = sp->local.addr.ipv4;
+
+	tcp_conn_segment_arrived(conn, seg);
+
+	fibril_mutex_unlock(&conn->lock);
+	tcp_conn_delref(conn);
+}
+
+/*
+ * Timeouts
+ */
+
+/** User timeout */
+void tcp_to_user(void)
+{
+	log_msg(LVL_DEBUG, "tcp_to_user()");
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/net/tcp/ucall.h
===================================================================
--- uspace/srv/net/tcp/ucall.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/tcp/ucall.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup tcp
+ * @{
+ */
+/** @file TCP user calls (close to those defined in the RFC)
+ */
+
+#ifndef UCALL_H
+#define UCALL_H
+
+#include <sys/types.h>
+#include "tcp_type.h"
+
+/*
+ * User calls
+ */
+extern tcp_error_t tcp_uc_open(tcp_sock_t *, tcp_sock_t *, acpass_t,
+    tcp_open_flags_t, tcp_conn_t **);
+extern tcp_error_t tcp_uc_send(tcp_conn_t *, void *, size_t, xflags_t);
+extern tcp_error_t tcp_uc_receive(tcp_conn_t *, void *, size_t, size_t *, xflags_t *);
+extern tcp_error_t tcp_uc_close(tcp_conn_t *);
+extern void tcp_uc_abort(tcp_conn_t *);
+extern void tcp_uc_status(tcp_conn_t *, tcp_conn_status_t *);
+extern void tcp_uc_delete(tcp_conn_t *);
+extern void tcp_uc_set_cstate_cb(tcp_conn_t *, tcp_cstate_cb_t, void *);
+
+/*
+ * Arriving segments
+ */
+extern void tcp_as_segment_arrived(tcp_sockpair_t *, tcp_segment_t *);
+
+/*
+ * Timeouts
+ */
+extern void tcp_to_user(void);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/udp/Makefile
===================================================================
--- uspace/srv/net/udp/Makefile	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/udp/Makefile	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,43 @@
+#
+# Copyright (c) 2012 Jiri Svoboda
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# - Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+# - Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in the
+#   documentation and/or other materials provided with the distribution.
+# - The name of the author may not be used to endorse or promote products
+#   derived from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+USPACE_PREFIX = ../../..
+LIBS = $(LIBNET_PREFIX)/libnet.a
+EXTRA_CFLAGS = -I$(LIBNET_PREFIX)/include
+BINARY = udp
+
+SOURCES = \
+	assoc.c \
+	msg.c \
+	sock.c \
+	pdu.c \
+	ucall.c \
+	udp.c \
+	udp_inet.c
+
+include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/net/udp/assoc.c
===================================================================
--- uspace/srv/net/udp/assoc.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/udp/assoc.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,411 @@
+/*
+ * Copyright (c) 2012 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup udp
+ * @{
+ */
+
+/**
+ * @file UDP associations
+ */
+
+#include <adt/list.h>
+#include <bool.h>
+#include <fibril_synch.h>
+#include <io/log.h>
+#include <stdlib.h>
+
+#include "assoc.h"
+#include "msg.h"
+#include "pdu.h"
+#include "ucall.h"
+#include "udp_inet.h"
+#include "udp_type.h"
+
+LIST_INITIALIZE(assoc_list);
+FIBRIL_MUTEX_INITIALIZE(assoc_list_lock);
+
+static udp_assoc_t *udp_assoc_find_ref(udp_sockpair_t *);
+static int udp_assoc_queue_msg(udp_assoc_t *, udp_sockpair_t *, udp_msg_t *);
+static bool udp_socket_match(udp_sock_t *, udp_sock_t *);
+static bool udp_sockpair_match(udp_sockpair_t *, udp_sockpair_t *);
+
+/** Create new association structure.
+ *
+ * @param lsock		Local socket (will be deeply copied)
+ * @param fsock		Foreign socket (will be deeply copied)
+ * @return		New association or NULL
+ */
+udp_assoc_t *udp_assoc_new(udp_sock_t *lsock, udp_sock_t *fsock)
+{
+	udp_assoc_t *assoc = NULL;
+
+	/* Allocate association structure */
+	assoc = calloc(1, sizeof(udp_assoc_t));
+	if (assoc == NULL)
+		goto error;
+
+	fibril_mutex_initialize(&assoc->lock);
+
+	/* One for the user */
+	atomic_set(&assoc->refcnt, 1);
+
+	/* Initialize receive queue */
+	list_initialize(&assoc->rcv_queue);
+	fibril_condvar_initialize(&assoc->rcv_queue_cv);
+
+	if (lsock != NULL)
+		assoc->ident.local = *lsock;
+	if (fsock != NULL)
+		assoc->ident.foreign = *fsock;
+
+	return assoc;
+error:
+	return NULL;
+}
+
+/** Destroy association structure.
+ *
+ * Association structure should be destroyed when the folowing conditions
+ * are met:
+ * (1) user has deleted the association
+ * (2) nobody is holding references to the association
+ *
+ * This happens when @a assoc->refcnt is zero as we count (1)
+ * as an extra reference.
+ *
+ * @param assoc		Association
+ */
+static void udp_assoc_free(udp_assoc_t *assoc)
+{
+	log_msg(LVL_DEBUG, "%s: udp_assoc_free(%p)", assoc->name, assoc);
+
+	while (!list_empty(&assoc->rcv_queue)) {
+		link_t *link = list_first(&assoc->rcv_queue);
+		udp_rcv_queue_entry_t *rqe = list_get_instance(link,
+		    udp_rcv_queue_entry_t, link);
+		list_remove(link);
+
+		udp_msg_delete(rqe->msg);
+		free(rqe);
+	}
+
+	free(assoc);
+}
+
+/** Add reference to association.
+ *
+ * Increase association reference count by one.
+ *
+ * @param assoc		Association
+ */
+void udp_assoc_addref(udp_assoc_t *assoc)
+{
+	log_msg(LVL_DEBUG, "%s: upd_assoc_addref(%p)", assoc->name, assoc);
+	atomic_inc(&assoc->refcnt);
+}
+
+/** Remove reference from association.
+ *
+ * Decrease association reference count by one.
+ *
+ * @param assoc		Association
+ */
+void udp_assoc_delref(udp_assoc_t *assoc)
+{
+	log_msg(LVL_DEBUG, "%s: udp_assoc_delref(%p)", assoc->name, assoc);
+
+	if (atomic_predec(&assoc->refcnt) == 0)
+		udp_assoc_free(assoc);
+}
+
+/** Delete association.
+ *
+ * The caller promises not make no further references to @a assoc.
+ * UDP will free @a assoc eventually.
+ *
+ * @param assoc		Association
+ */
+void udp_assoc_delete(udp_assoc_t *assoc)
+{
+	log_msg(LVL_DEBUG, "%s: udp_assoc_delete(%p)", assoc->name, assoc);
+
+	assert(assoc->deleted == false);
+	udp_assoc_delref(assoc);
+	assoc->deleted = true;
+}
+
+/** Enlist association.
+ *
+ * Add association to the association map.
+ */
+void udp_assoc_add(udp_assoc_t *assoc)
+{
+	udp_assoc_addref(assoc);
+	fibril_mutex_lock(&assoc_list_lock);
+	list_append(&assoc->link, &assoc_list);
+	fibril_mutex_unlock(&assoc_list_lock);
+}
+
+/** Delist association.
+ *
+ * Remove association from the association map.
+ */
+void udp_assoc_remove(udp_assoc_t *assoc)
+{
+	fibril_mutex_lock(&assoc_list_lock);
+	list_remove(&assoc->link);
+	fibril_mutex_unlock(&assoc_list_lock);
+	udp_assoc_delref(assoc);
+}
+
+/** Set foreign socket in association.
+ *
+ * @param assoc		Association
+ * @param fsock		Foreign socket (deeply copied)
+ */
+void udp_assoc_set_foreign(udp_assoc_t *assoc, udp_sock_t *fsock)
+{
+	log_msg(LVL_DEBUG, "udp_assoc_set_foreign(%p, %p)", assoc, fsock);
+	fibril_mutex_lock(&assoc->lock);
+	assoc->ident.foreign = *fsock;
+	fibril_mutex_unlock(&assoc->lock);
+}
+
+/** Set local socket in association.
+ *
+ * @param assoc		Association
+ * @param fsock		Foreign socket (deeply copied)
+ */
+void udp_assoc_set_local(udp_assoc_t *assoc, udp_sock_t *lsock)
+{
+	log_msg(LVL_DEBUG, "udp_assoc_set_local(%p, %p)", assoc, lsock);
+	fibril_mutex_lock(&assoc->lock);
+	assoc->ident.local = *lsock;
+	fibril_mutex_unlock(&assoc->lock);
+}
+
+/** Send message to association.
+ *
+ * @param assoc		Association
+ * @param fsock		Foreign socket or NULL not to override @a assoc
+ * @param msg		Message
+ *
+ * @return		EOK on success
+ *			EINVAL if foreign socket is not set
+ *			ENOMEM if out of resources
+ *			EIO if no route to destination exists
+ */
+int udp_assoc_send(udp_assoc_t *assoc, udp_sock_t *fsock, udp_msg_t *msg)
+{
+	udp_pdu_t *pdu;
+	udp_sockpair_t sp;
+	int rc;
+
+	log_msg(LVL_DEBUG, "udp_assoc_send(%p, %p, %p)",
+	    assoc, fsock, msg);
+
+	/* @a fsock can be used to override the foreign socket */
+	sp = assoc->ident;
+	if (fsock != NULL)
+		sp.foreign = *fsock;
+
+	if (sp.foreign.addr.ipv4 == 0 || sp.foreign.port == 0)
+		return EINVAL;
+
+	rc = udp_pdu_encode(&sp, msg, &pdu);
+	if (rc != EOK)
+		return ENOMEM;
+
+	rc = udp_transmit_pdu(pdu);
+	if (rc != EOK)
+		return EIO;
+
+	udp_pdu_delete(pdu);
+
+	return EOK;
+}
+
+/** Get a received message.
+ *
+ * Pull one message from the association's receive queue.
+ */
+int udp_assoc_recv(udp_assoc_t *assoc, udp_msg_t **msg, udp_sock_t *fsock)
+{
+	link_t *link;
+	udp_rcv_queue_entry_t *rqe;
+
+	log_msg(LVL_DEBUG, "udp_assoc_recv()");
+
+	fibril_mutex_lock(&assoc->lock);
+	while (list_empty(&assoc->rcv_queue)) {
+		log_msg(LVL_DEBUG, "udp_assoc_recv() - waiting");
+		fibril_condvar_wait(&assoc->rcv_queue_cv, &assoc->lock);
+	}
+
+	log_msg(LVL_DEBUG, "udp_assoc_recv() - got a message");
+	link = list_first(&assoc->rcv_queue);
+	rqe = list_get_instance(link, udp_rcv_queue_entry_t, link);
+	list_remove(link);
+	fibril_mutex_unlock(&assoc->lock);
+
+	*msg = rqe->msg;
+	*fsock = rqe->sp.foreign;
+	free(rqe);
+
+	return EOK;
+}
+
+/** Message received.
+ *
+ * Find the association to which the message belongs and queue it.
+ */
+void udp_assoc_received(udp_sockpair_t *rsp, udp_msg_t *msg)
+{
+	udp_assoc_t *assoc;
+	int rc;
+
+	log_msg(LVL_DEBUG, "udp_assoc_received(%p, %p)", rsp, msg);
+
+	assoc = udp_assoc_find_ref(rsp);
+	if (assoc == NULL) {
+		log_msg(LVL_DEBUG, "No association found. Message dropped.");
+		/* XXX Generate ICMP error. */
+		/* XXX Might propagate error directly by error return. */
+		return;
+	}
+
+	rc = udp_assoc_queue_msg(assoc, rsp, msg);
+	if (rc != EOK) {
+		log_msg(LVL_DEBUG, "Out of memory. Message dropped.");
+		/* XXX Generate ICMP error? */
+	}
+}
+
+static int udp_assoc_queue_msg(udp_assoc_t *assoc, udp_sockpair_t *sp,
+    udp_msg_t *msg)
+{
+	udp_rcv_queue_entry_t *rqe;
+
+	log_msg(LVL_DEBUG, "udp_assoc_queue_msg(%p, %p, %p)",
+	    assoc, sp, msg);
+
+	rqe = calloc(1, sizeof(udp_rcv_queue_entry_t));
+	if (rqe == NULL)
+		return ENOMEM;
+
+	link_initialize(&rqe->link);
+	rqe->sp = *sp;
+	rqe->msg = msg;
+
+	fibril_mutex_lock(&assoc->lock);
+	list_append(&rqe->link, &assoc->rcv_queue);
+	fibril_mutex_unlock(&assoc->lock);
+
+	fibril_condvar_broadcast(&assoc->rcv_queue_cv);
+
+	return EOK;
+}
+
+/** Match socket with pattern. */
+static bool udp_socket_match(udp_sock_t *sock, udp_sock_t *patt)
+{
+	log_msg(LVL_DEBUG, "udp_socket_match(sock=(%x,%u), pat=(%x,%u))",
+	    sock->addr.ipv4, sock->port, patt->addr.ipv4, patt->port);
+
+	if (patt->addr.ipv4 != UDP_IPV4_ANY &&
+	    patt->addr.ipv4 != sock->addr.ipv4)
+		return false;
+
+	if (patt->port != UDP_PORT_ANY &&
+	    patt->port != sock->port)
+		return false;
+
+	log_msg(LVL_DEBUG, " -> match");
+
+	return true;
+}
+
+/** Match socket pair with pattern. */
+static bool udp_sockpair_match(udp_sockpair_t *sp, udp_sockpair_t *pattern)
+{
+	log_msg(LVL_DEBUG, "udp_sockpair_match(%p, %p)", sp, pattern);
+
+	if (!udp_socket_match(&sp->local, &pattern->local))
+		return false;
+
+	if (!udp_socket_match(&sp->foreign, &pattern->foreign))
+		return false;
+
+	log_msg(LVL_DEBUG, "Socket pair matched.");
+	return true;
+}
+
+
+/** Find association structure for specified socket pair.
+ *
+ * An association is uniquely identified by a socket pair. Look up our
+ * association map and return association structure based on socket pair.
+ * The association reference count is bumped by one.
+ *
+ * @param sp	Socket pair
+ * @return	Association structure or NULL if not found.
+ */
+static udp_assoc_t *udp_assoc_find_ref(udp_sockpair_t *sp)
+{
+	log_msg(LVL_DEBUG, "udp_assoc_find_ref(%p)", sp);
+
+	fibril_mutex_lock(&assoc_list_lock);
+
+	list_foreach(assoc_list, link) {
+		udp_assoc_t *assoc = list_get_instance(link, udp_assoc_t, link);
+		udp_sockpair_t *asp = &assoc->ident;
+		log_msg(LVL_DEBUG, "compare with assoc (f:(%x,%u), l:(%x,%u))",
+		    asp->foreign.addr.ipv4, asp->foreign.port,
+		    asp->local.addr.ipv4, asp->local.port);
+
+		/* Skip unbound associations */
+		if (asp->local.port == UDP_PORT_ANY)
+			continue;
+
+		if (udp_sockpair_match(sp, asp)) {
+			log_msg(LVL_DEBUG, "Returning assoc %p", assoc);
+			udp_assoc_addref(assoc);
+			fibril_mutex_unlock(&assoc_list_lock);
+			return assoc;
+		}
+	}
+
+	fibril_mutex_unlock(&assoc_list_lock);
+	return NULL;
+}
+
+
+/**
+ * @}
+ */
Index: uspace/srv/net/udp/assoc.h
===================================================================
--- uspace/srv/net/udp/assoc.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/udp/assoc.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2012 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup udp
+ * @{
+ */
+/** @file UDP associations
+ */
+
+#ifndef ASSOC_H
+#define ASSOC_H
+
+#include <sys/types.h>
+#include "udp_type.h"
+
+extern udp_assoc_t *udp_assoc_new(udp_sock_t *, udp_sock_t *);
+extern void udp_assoc_delete(udp_assoc_t *);
+extern void udp_assoc_add(udp_assoc_t *);
+extern void udp_assoc_remove(udp_assoc_t *);
+extern void udp_assoc_addref(udp_assoc_t *);
+extern void udp_assoc_delref(udp_assoc_t *);
+extern void udp_assoc_set_foreign(udp_assoc_t *, udp_sock_t *);
+extern void udp_assoc_set_local(udp_assoc_t *, udp_sock_t *);
+extern int udp_assoc_send(udp_assoc_t *, udp_sock_t *, udp_msg_t *);
+extern int udp_assoc_recv(udp_assoc_t *, udp_msg_t **, udp_sock_t *);
+extern void udp_assoc_received(udp_sockpair_t *, udp_msg_t *);
+
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/udp/msg.c
===================================================================
--- uspace/srv/net/udp/msg.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/udp/msg.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2012 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup udp
+ * @{
+ */
+
+/**
+ * @file UDP message
+ */
+
+#include <io/log.h>
+#include <stdlib.h>
+
+#include "msg.h"
+#include "udp_type.h"
+
+/** Alocate new segment structure. */
+udp_msg_t *udp_msg_new(void)
+{
+	return calloc(1, sizeof(udp_msg_t));
+}
+
+/** Delete segment. */
+void udp_msg_delete(udp_msg_t *msg)
+{
+	free(msg);
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/net/udp/msg.h
===================================================================
--- uspace/srv/net/udp/msg.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/udp/msg.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2012 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup udp
+ * @{
+ */
+/** @file UDP message
+ */
+
+#ifndef MSG_H
+#define MSG_H
+
+#include "udp_type.h"
+
+extern udp_msg_t *udp_msg_new(void);
+extern void udp_msg_delete(udp_msg_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/udp/pdu.c
===================================================================
--- uspace/srv/net/udp/pdu.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/udp/pdu.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 2012 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup udp
+ * @{
+ */
+
+/**
+ * @file UDP PDU encoding and decoding
+ */
+
+#include <bitops.h>
+#include <byteorder.h>
+#include <errno.h>
+#include <mem.h>
+#include <stdlib.h>
+
+#include "msg.h"
+#include "pdu.h"
+#include "std.h"
+#include "udp_type.h"
+
+#define UDP_CHECKSUM_INIT 0xffff
+
+/** One's complement addition.
+ *
+ * Result is a + b + carry.
+ */
+static uint16_t udp_ocadd16(uint16_t a, uint16_t b)
+{
+	uint32_t s;
+
+	s = (uint32_t)a + (uint32_t)b;
+	return (s & 0xffff) + (s >> 16);
+}
+
+static uint16_t udp_checksum_calc(uint16_t ivalue, void *data, size_t size)
+{
+	uint16_t sum;
+	uint16_t w;
+	size_t words, i;
+	uint8_t *bdata;
+
+	sum = ~ivalue;
+	words = size / 2;
+	bdata = (uint8_t *)data;
+
+	for (i = 0; i < words; i++) {
+		w = ((uint16_t)bdata[2*i] << 8) | bdata[2*i + 1];
+		sum = udp_ocadd16(sum, w);
+	}
+
+	if (size % 2 != 0) {
+		w = ((uint16_t)bdata[2*words] << 8);
+		sum = udp_ocadd16(sum, w);
+	}
+
+	return ~sum;
+}
+
+static void udp_phdr_setup(udp_pdu_t *pdu, udp_phdr_t *phdr)
+{
+	phdr->src_addr = host2uint32_t_be(pdu->src.ipv4);
+	phdr->dest_addr = host2uint32_t_be(pdu->dest.ipv4);
+	phdr->zero = 0;
+	phdr->protocol = IP_PROTO_UDP;
+	phdr->udp_length = host2uint16_t_be(pdu->data_size);
+}
+
+udp_pdu_t *udp_pdu_new(void)
+{
+	return calloc(1, sizeof(udp_pdu_t));
+}
+
+void udp_pdu_delete(udp_pdu_t *pdu)
+{
+	free(pdu->data);
+	free(pdu);
+}
+
+static uint16_t udp_pdu_checksum_calc(udp_pdu_t *pdu)
+{
+	uint16_t cs_phdr;
+	uint16_t cs_all;
+	udp_phdr_t phdr;
+
+	udp_phdr_setup(pdu, &phdr);
+	cs_phdr = udp_checksum_calc(UDP_CHECKSUM_INIT, (void *)&phdr,
+	    sizeof(udp_phdr_t));
+	cs_all = udp_checksum_calc(cs_phdr, pdu->data, pdu->data_size);
+
+	return cs_all;
+}
+
+static void udp_pdu_set_checksum(udp_pdu_t *pdu, uint16_t checksum)
+{
+	udp_header_t *hdr;
+
+	hdr = (udp_header_t *)pdu->data;
+	hdr->checksum = host2uint16_t_be(checksum);
+}
+
+/** Decode incoming PDU */
+int udp_pdu_decode(udp_pdu_t *pdu, udp_sockpair_t *sp, udp_msg_t **msg)
+{
+	udp_msg_t *nmsg;
+	udp_header_t *hdr;
+	void *text;
+	size_t text_size;
+	uint16_t length;
+	uint16_t checksum;
+
+	if (pdu->data_size < sizeof(udp_header_t))
+		return EINVAL;
+
+	text = pdu->data + sizeof(udp_header_t);
+	text_size = pdu->data_size - sizeof(udp_header_t);
+
+	hdr = (udp_header_t *)pdu->data;
+
+	sp->foreign.port = uint16_t_be2host(hdr->src_port);
+	sp->foreign.addr = pdu->src;
+	sp->local.port = uint16_t_be2host(hdr->dest_port);
+	sp->local.addr = pdu->dest;
+
+	length = uint16_t_be2host(hdr->length);
+	checksum = uint16_t_be2host(hdr->checksum);
+	(void) checksum;
+
+	if (length < sizeof(udp_header_t) ||
+	    length > sizeof(udp_header_t) + text_size)
+		return EINVAL;
+
+	nmsg = udp_msg_new();
+	if (nmsg == NULL)
+		return ENOMEM;
+
+	nmsg->data = text;
+	nmsg->data_size = length - sizeof(udp_header_t);
+
+	*msg = nmsg;
+	return EOK;
+}
+
+/** Encode outgoing PDU */
+int udp_pdu_encode(udp_sockpair_t *sp, udp_msg_t *msg, udp_pdu_t **pdu)
+{
+	udp_pdu_t *npdu;
+	udp_header_t *hdr;
+	uint16_t checksum;
+
+	npdu = udp_pdu_new();
+	if (npdu == NULL)
+		return ENOMEM;
+
+	npdu->src = sp->local.addr;
+	npdu->dest = sp->foreign.addr;
+
+	npdu->data_size = sizeof(udp_header_t) + msg->data_size;
+	npdu->data = calloc(1, npdu->data_size);
+	if (npdu->data == NULL) {
+		udp_pdu_delete(npdu);
+		return ENOMEM;
+	}
+
+	hdr = (udp_header_t *)npdu->data;
+	hdr->src_port = host2uint16_t_be(sp->local.port);
+	hdr->dest_port = host2uint16_t_be(sp->foreign.port);
+	hdr->length = host2uint16_t_be(npdu->data_size);
+	hdr->checksum = 0;
+
+	memcpy((uint8_t *)npdu->data + sizeof(udp_header_t), msg->data,
+	    msg->data_size);
+
+	/* Checksum calculation */
+	checksum = udp_pdu_checksum_calc(npdu);
+	udp_pdu_set_checksum(npdu, checksum);
+
+	*pdu = npdu;
+	return EOK;
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/net/udp/pdu.h
===================================================================
--- uspace/srv/net/udp/pdu.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/udp/pdu.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2012 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup udp
+ * @{
+ */
+/** @file UDP PDU (encoded Protocol Data Unit) handling
+ */
+
+#ifndef PDU_H
+#define PDU_H
+
+#include <sys/types.h>
+#include "std.h"
+#include "udp_type.h"
+
+extern udp_pdu_t *udp_pdu_new(void);
+extern void udp_pdu_delete(udp_pdu_t *);
+extern int udp_pdu_decode(udp_pdu_t *, udp_sockpair_t *, udp_msg_t **);
+extern int udp_pdu_encode(udp_sockpair_t *, udp_msg_t *, udp_pdu_t **);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/udp/sock.c
===================================================================
--- uspace/srv/net/udp/sock.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/udp/sock.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,605 @@
+/*
+ * Copyright (c) 2008 Lukas Mejdrech
+ * Copyright (c) 2012 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup udp
+ * @{
+ */
+
+/**
+ * @file Socket provider
+ */
+
+#include <async.h>
+#include <byteorder.h>
+#include <errno.h>
+#include <inet/inet.h>
+#include <io/log.h>
+#include <ipc/services.h>
+#include <ipc/socket.h>
+#include <net/modules.h>
+#include <net/socket.h>
+#include <ns.h>
+
+#include "sock.h"
+#include "std.h"
+#include "udp_type.h"
+#include "ucall.h"
+
+#define FRAGMENT_SIZE 1024
+
+/** Free ports pool start. */
+#define UDP_FREE_PORTS_START		1025
+
+/** Free ports pool end. */
+#define UDP_FREE_PORTS_END		65535
+
+static int last_used_port = UDP_FREE_PORTS_START - 1;
+static socket_ports_t gsock;
+
+static void udp_sock_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg);
+
+int udp_sock_init(void)
+{
+	int rc;
+
+	socket_ports_initialize(&gsock);
+
+	async_set_client_connection(udp_sock_connection);
+
+	rc = service_register(SERVICE_UDP);
+	if (rc != EOK)
+		return EEXIST;
+
+	return EOK;
+}
+
+static void udp_free_sock_data(socket_core_t *sock_core)
+{
+	udp_sockdata_t *socket;
+
+	socket = (udp_sockdata_t *)sock_core->specific_data;
+	(void)socket;
+}
+
+static void udp_sock_notify_data(socket_core_t *sock_core)
+{
+	log_msg(LVL_DEBUG, "udp_sock_notify_data(%d)", sock_core->socket_id);
+	async_exch_t *exch = async_exchange_begin(sock_core->sess);
+	async_msg_5(exch, NET_SOCKET_RECEIVED, (sysarg_t)sock_core->socket_id,
+	    FRAGMENT_SIZE, 0, 0, 1);
+	async_exchange_end(exch);
+}
+
+static void udp_sock_socket(udp_client_t *client, ipc_callid_t callid, ipc_call_t call)
+{
+	udp_sockdata_t *sock;
+	socket_core_t *sock_core;
+	int sock_id;
+	int rc;
+	ipc_call_t answer;
+
+	log_msg(LVL_DEBUG, "udp_sock_socket()");
+	sock = calloc(sizeof(udp_sockdata_t), 1);
+	if (sock == NULL) {
+		async_answer_0(callid, ENOMEM);
+		return;
+	}
+
+	fibril_mutex_initialize(&sock->lock);
+	sock->client = client;
+
+	rc = udp_uc_create(&sock->assoc);
+	if (rc != EOK) {
+		udp_uc_destroy(sock->assoc);
+		free(sock);
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	sock_id = SOCKET_GET_SOCKET_ID(call);
+	rc = socket_create(&client->sockets, client->sess, sock, &sock_id);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	sock_core = socket_cores_find(&client->sockets, sock_id);
+	assert(sock_core != NULL);
+	sock->sock_core = sock_core;
+
+
+	refresh_answer(&answer, NULL);
+	SOCKET_SET_SOCKET_ID(answer, sock_id);
+
+	SOCKET_SET_DATA_FRAGMENT_SIZE(answer, FRAGMENT_SIZE);
+	SOCKET_SET_HEADER_SIZE(answer, sizeof(udp_header_t));
+	answer_call(callid, EOK, &answer, 3);
+}
+
+static void udp_sock_bind(udp_client_t *client, ipc_callid_t callid, ipc_call_t call)
+{
+	int rc;
+	struct sockaddr_in *addr;
+	size_t addr_size;
+	socket_core_t *sock_core;
+	udp_sockdata_t *socket;
+	udp_sock_t fsock;
+	udp_error_t urc;
+
+	log_msg(LVL_DEBUG, "udp_sock_bind()");
+	log_msg(LVL_DEBUG, " - async_data_write_accept");
+
+	addr = NULL;
+
+	rc = async_data_write_accept((void **) &addr, false, 0, 0, 0, &addr_size);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		goto out;
+	}
+
+	log_msg(LVL_DEBUG, " - call socket_bind");
+	rc = socket_bind(&client->sockets, &gsock, SOCKET_GET_SOCKET_ID(call),
+	    addr, addr_size, UDP_FREE_PORTS_START, UDP_FREE_PORTS_END,
+	    last_used_port);
+	if (rc != EOK) {
+		async_answer_0(callid, rc);
+		goto out;
+	}
+
+	if (addr_size != sizeof(struct sockaddr_in)) {
+		async_answer_0(callid, EINVAL);
+		goto out;
+	}
+
+	log_msg(LVL_DEBUG, " - call socket_cores_find");
+	sock_core = socket_cores_find(&client->sockets, SOCKET_GET_SOCKET_ID(call));
+	if (sock_core == NULL) {
+		async_answer_0(callid, ENOENT);
+		goto out;
+	}
+
+	socket = (udp_sockdata_t *)sock_core->specific_data;
+
+	fsock.addr.ipv4 = uint32_t_be2host(addr->sin_addr.s_addr);
+	fsock.port = sock_core->port;
+	urc = udp_uc_set_local(socket->assoc, &fsock);
+
+	switch (urc) {
+	case UDP_EOK:
+		rc = EOK;
+		break;
+/*	case TCP_ENOTEXIST:
+		rc = ENOTCONN;
+		break;
+	case TCP_ECLOSING:
+		rc = ENOTCONN;
+		break;
+	case TCP_ERESET:
+		rc = ECONNABORTED;
+		break;*/
+	default:
+		assert(false);
+	}
+
+	udp_sock_notify_data(sock_core);
+
+	log_msg(LVL_DEBUG, " - success");
+	async_answer_0(callid, rc);
+out:
+	if (addr != NULL)
+		free(addr);
+}
+
+static void udp_sock_listen(udp_client_t *client, ipc_callid_t callid, ipc_call_t call)
+{
+	log_msg(LVL_DEBUG, "udp_sock_listen()");
+	async_answer_0(callid, ENOTSUP);
+}
+
+static void udp_sock_connect(udp_client_t *client, ipc_callid_t callid, ipc_call_t call)
+{
+	log_msg(LVL_DEBUG, "udp_sock_connect()");
+	async_answer_0(callid, ENOTSUP);
+}
+
+static void udp_sock_accept(udp_client_t *client, ipc_callid_t callid, ipc_call_t call)
+{
+	log_msg(LVL_DEBUG, "udp_sock_accept()");
+	async_answer_0(callid, ENOTSUP);
+}
+
+static void udp_sock_sendto(udp_client_t *client, ipc_callid_t callid, ipc_call_t call)
+{
+	int socket_id;
+	int fragments;
+	int index;
+	struct sockaddr_in *addr;
+	size_t addr_size;
+	socket_core_t *sock_core;
+	udp_sockdata_t *socket;
+	udp_sock_t fsock, *fsockp;
+	ipc_call_t answer;
+	ipc_callid_t wcallid;
+	size_t length;
+	uint8_t buffer[FRAGMENT_SIZE];
+	udp_error_t urc;
+	int rc;
+
+	log_msg(LVL_DEBUG, "udp_sock_send()");
+
+	addr = NULL;
+
+	if (IPC_GET_IMETHOD(call) == NET_SOCKET_SENDTO) {
+		rc = async_data_write_accept((void **) &addr, false,
+		    0, 0, 0, &addr_size);
+		if (rc != EOK) {
+			async_answer_0(callid, rc);
+			goto out;
+		}
+
+		if (addr_size != sizeof(struct sockaddr_in)) {
+			async_answer_0(callid, EINVAL);
+			goto out;
+		}
+
+		fsock.addr.ipv4 = uint32_t_be2host(addr->sin_addr.s_addr);
+		fsock.port = uint16_t_be2host(addr->sin_port);
+		fsockp = &fsock;
+	} else {
+		fsockp = NULL;
+	}
+
+	socket_id = SOCKET_GET_SOCKET_ID(call);
+	fragments = SOCKET_GET_DATA_FRAGMENTS(call);
+	SOCKET_GET_FLAGS(call);
+
+	sock_core = socket_cores_find(&client->sockets, socket_id);
+	if (sock_core == NULL) {
+		async_answer_0(callid, ENOTSOCK);
+		goto out;
+	}
+
+	if (sock_core->port == 0) {
+		/* Implicitly bind socket to port */
+		rc = socket_bind(&client->sockets, &gsock, SOCKET_GET_SOCKET_ID(call),
+		    addr, addr_size, UDP_FREE_PORTS_START, UDP_FREE_PORTS_END,
+		    last_used_port);
+		if (rc != EOK) {
+			async_answer_0(callid, rc);
+			goto out;
+		}
+
+		udp_sock_notify_data(sock_core);
+	}
+
+	socket = (udp_sockdata_t *)sock_core->specific_data;
+	fibril_mutex_lock(&socket->lock);
+
+	if (socket->assoc->ident.local.addr.ipv4 == UDP_IPV4_ANY) {
+		/* Determine local IP address */
+		inet_addr_t loc_addr, rem_addr;
+
+		rem_addr.ipv4 = fsockp ? fsock.addr.ipv4 :
+		    socket->assoc->ident.foreign.addr.ipv4;
+
+		rc = inet_get_srcaddr(&rem_addr, 0, &loc_addr);
+		if (rc != EOK) {
+			fibril_mutex_unlock(&socket->lock);
+			async_answer_0(callid, rc);
+			log_msg(LVL_DEBUG, "udp_sock_sendto: Failed to "
+			    "determine local address.");
+			return;
+		}
+
+		socket->assoc->ident.local.addr.ipv4 = loc_addr.ipv4;
+		log_msg(LVL_DEBUG, "Local IP address is %x",
+		    socket->assoc->ident.local.addr.ipv4);
+	}
+
+
+	assert(socket->assoc != NULL);
+
+	for (index = 0; index < fragments; index++) {
+		if (!async_data_write_receive(&wcallid, &length)) {
+			fibril_mutex_unlock(&socket->lock);
+			async_answer_0(callid, EINVAL);
+			goto out;
+		}
+
+		if (length > FRAGMENT_SIZE)
+			length = FRAGMENT_SIZE;
+
+		rc = async_data_write_finalize(wcallid, buffer, length);
+		if (rc != EOK) {
+			fibril_mutex_unlock(&socket->lock);
+			async_answer_0(callid, rc);
+			goto out;
+		}
+
+		urc = udp_uc_send(socket->assoc, fsockp, buffer, length, 0);
+
+		switch (urc) {
+		case UDP_EOK:
+			rc = EOK;
+			break;
+/*		case TCP_ENOTEXIST:
+			rc = ENOTCONN;
+			break;
+		case TCP_ECLOSING:
+			rc = ENOTCONN;
+			break;
+		case TCP_ERESET:
+			rc = ECONNABORTED;
+			break;*/
+		default:
+			assert(false);
+		}
+
+		if (rc != EOK) {
+			fibril_mutex_unlock(&socket->lock);
+			async_answer_0(callid, rc);
+			goto out;
+		}
+	}
+
+	refresh_answer(&answer, NULL);
+	SOCKET_SET_DATA_FRAGMENT_SIZE(answer, FRAGMENT_SIZE);
+	answer_call(callid, EOK, &answer, 2);
+	fibril_mutex_unlock(&socket->lock);
+out:
+	if (addr != NULL)
+		free(addr);
+}
+
+static void udp_sock_recvfrom(udp_client_t *client, ipc_callid_t callid, ipc_call_t call)
+{
+	int socket_id;
+	int flags;
+	size_t addr_length, length;
+	socket_core_t *sock_core;
+	udp_sockdata_t *socket;
+	ipc_call_t answer;
+	ipc_callid_t rcallid;
+	uint8_t buffer[FRAGMENT_SIZE];
+	size_t data_len;
+	xflags_t xflags;
+	udp_error_t urc;
+	struct sockaddr_in addr;
+	udp_sock_t rsock;
+	int rc;
+
+	log_msg(LVL_DEBUG, "%p: udp_sock_recv[from]()", client);
+
+	socket_id = SOCKET_GET_SOCKET_ID(call);
+	flags = SOCKET_GET_FLAGS(call);
+
+	sock_core = socket_cores_find(&client->sockets, socket_id);
+	if (sock_core == NULL) {
+		async_answer_0(callid, ENOTSOCK);
+		return;
+	}
+
+	socket = (udp_sockdata_t *)sock_core->specific_data;
+	fibril_mutex_lock(&socket->lock);
+
+	if (socket->assoc == NULL) {
+		fibril_mutex_unlock(&socket->lock);
+		async_answer_0(callid, ENOTCONN);
+		return;
+	}
+
+	(void)flags;
+
+	urc = udp_uc_receive(socket->assoc, buffer, FRAGMENT_SIZE, &data_len,
+	    &xflags, &rsock);
+	log_msg(LVL_DEBUG, "**** udp_uc_receive done, data_len=%zu", data_len);
+
+	switch (urc) {
+	case UDP_EOK:
+		rc = EOK;
+		break;
+/*	case TCP_ENOTEXIST:
+	case TCP_ECLOSING:
+		rc = ENOTCONN;
+		break;
+	case TCP_ERESET:
+		rc = ECONNABORTED;
+		break;*/
+	default:
+		assert(false);
+	}
+
+	log_msg(LVL_DEBUG, "**** udp_uc_receive -> %d", rc);
+	if (rc != EOK) {
+		fibril_mutex_unlock(&socket->lock);
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	if (IPC_GET_IMETHOD(call) == NET_SOCKET_RECVFROM) {
+		/* Fill addr */
+		addr.sin_family = AF_INET;
+		addr.sin_addr.s_addr = host2uint32_t_be(rsock.addr.ipv4);
+		addr.sin_port = host2uint16_t_be(rsock.port);
+
+		log_msg(LVL_DEBUG, "addr read receive");
+		if (!async_data_read_receive(&rcallid, &addr_length)) {
+			fibril_mutex_unlock(&socket->lock);
+			async_answer_0(callid, EINVAL);
+			return;
+		}
+
+		if (addr_length > sizeof(addr))
+			addr_length = sizeof(addr);
+
+		log_msg(LVL_DEBUG, "addr read finalize");
+		rc = async_data_read_finalize(rcallid, &addr, addr_length);
+		if (rc != EOK) {
+			fibril_mutex_unlock(&socket->lock);
+			async_answer_0(callid, EINVAL);
+			return;
+		}
+	}
+
+	log_msg(LVL_DEBUG, "data read receive");
+	if (!async_data_read_receive(&rcallid, &length)) {
+		fibril_mutex_unlock(&socket->lock);
+		async_answer_0(callid, EINVAL);
+		return;
+	}
+
+	if (length > data_len)
+		length = data_len;
+
+	log_msg(LVL_DEBUG, "data read finalize");
+	rc = async_data_read_finalize(rcallid, buffer, length);
+
+	if (length < data_len && rc == EOK)
+		rc = EOVERFLOW;
+
+	log_msg(LVL_DEBUG, "read_data_length <- %zu", length);
+	SOCKET_SET_READ_DATA_LENGTH(answer, length);
+	SOCKET_SET_ADDRESS_LENGTH(answer, sizeof(addr));
+	answer_call(callid, EOK, &answer, 3);
+
+	/* Push one fragment notification to client's queue */
+	udp_sock_notify_data(sock_core);
+	fibril_mutex_unlock(&socket->lock);
+}
+
+static void udp_sock_close(udp_client_t *client, ipc_callid_t callid, ipc_call_t call)
+{
+	int socket_id;
+	socket_core_t *sock_core;
+	udp_sockdata_t *socket;
+	int rc;
+
+	log_msg(LVL_DEBUG, "tcp_sock_close()");
+	socket_id = SOCKET_GET_SOCKET_ID(call);
+
+	sock_core = socket_cores_find(&client->sockets, socket_id);
+	if (sock_core == NULL) {
+		async_answer_0(callid, ENOTSOCK);
+		return;
+	}
+
+	socket = (udp_sockdata_t *)sock_core->specific_data;
+	fibril_mutex_lock(&socket->lock);
+
+	assert(socket->assoc != NULL);
+	udp_uc_destroy(socket->assoc);
+
+	rc = socket_destroy(NULL, socket_id, &client->sockets, &gsock,
+	    udp_free_sock_data);
+	if (rc != EOK) {
+		fibril_mutex_unlock(&socket->lock);
+		async_answer_0(callid, rc);
+		return;
+	}
+
+	fibril_mutex_unlock(&socket->lock);
+	async_answer_0(callid, EOK);
+}
+
+static void udp_sock_getsockopt(udp_client_t *client, ipc_callid_t callid, ipc_call_t call)
+{
+	log_msg(LVL_DEBUG, "udp_sock_getsockopt()");
+	async_answer_0(callid, ENOTSUP);
+}
+
+static void udp_sock_setsockopt(udp_client_t *client, ipc_callid_t callid, ipc_call_t call)
+{
+	log_msg(LVL_DEBUG, "udp_sock_setsockopt()");
+	async_answer_0(callid, ENOTSUP);
+}
+
+static void udp_sock_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
+{
+	ipc_callid_t callid;
+	ipc_call_t call;
+	udp_client_t client;
+
+	/* Accept the connection */
+	async_answer_0(iid, EOK);
+
+	client.sess = async_callback_receive(EXCHANGE_SERIALIZE);
+	socket_cores_initialize(&client.sockets);
+
+	while (true) {
+		log_msg(LVL_DEBUG, "udp_sock_connection: wait");
+		callid = async_get_call(&call);
+		if (!IPC_GET_IMETHOD(call))
+			break;
+
+		log_msg(LVL_DEBUG, "udp_sock_connection: METHOD=%d",
+		    (int)IPC_GET_IMETHOD(call));
+
+		switch (IPC_GET_IMETHOD(call)) {
+		case NET_SOCKET:
+			udp_sock_socket(&client, callid, call);
+			break;
+		case NET_SOCKET_BIND:
+			udp_sock_bind(&client, callid, call);
+			break;
+		case NET_SOCKET_LISTEN:
+			udp_sock_listen(&client, callid, call);
+			break;
+		case NET_SOCKET_CONNECT:
+			udp_sock_connect(&client, callid, call);
+			break;
+		case NET_SOCKET_ACCEPT:
+			udp_sock_accept(&client, callid, call);
+			break;
+		case NET_SOCKET_SEND:
+		case NET_SOCKET_SENDTO:
+			udp_sock_sendto(&client, callid, call);
+			break;
+		case NET_SOCKET_RECV:
+		case NET_SOCKET_RECVFROM:
+			udp_sock_recvfrom(&client, callid, call);
+			break;
+		case NET_SOCKET_CLOSE:
+			udp_sock_close(&client, callid, call);
+			break;
+		case NET_SOCKET_GETSOCKOPT:
+			udp_sock_getsockopt(&client, callid, call);
+			break;
+		case NET_SOCKET_SETSOCKOPT:
+			udp_sock_setsockopt(&client, callid, call);
+			break;
+		default:
+			async_answer_0(callid, ENOTSUP);
+			break;
+		}
+	}
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/net/udp/sock.h
===================================================================
--- uspace/srv/net/udp/sock.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/udp/sock.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2012 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup udp
+ * @{
+ */
+/** @file Socket provider
+ */
+
+#ifndef SOCK_H
+#define SOCK_H
+
+#include <async.h>
+
+extern int udp_sock_init(void);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/udp/std.h
===================================================================
--- uspace/srv/net/udp/std.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/udp/std.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2012 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup udp
+ * @{
+ */
+/** @file UDP standard definitions
+ *
+ * Based on IETF RFC 768
+ */
+
+#ifndef STD_H
+#define STD_H
+
+#include <sys/types.h>
+
+#define IP_PROTO_UDP 17
+
+/** UDP Header */
+typedef struct {
+	/** Source port */
+	uint16_t src_port;
+	/** Destination port */
+	uint16_t dest_port;
+	/** Length (header + data) */
+	uint16_t length;
+	/* Checksum */
+	uint16_t checksum;
+} udp_header_t;
+
+/** UDP pseudo header */
+typedef struct {
+	/** Source address */
+	uint32_t src_addr;
+	/** Destination address */
+	uint32_t dest_addr;
+	/** Zero */
+	uint8_t zero;
+	/** Protocol */
+	uint8_t protocol;
+	/** TCP length */
+	uint16_t udp_length;
+} udp_phdr_t;
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/udp/ucall.c
===================================================================
--- uspace/srv/net/udp/ucall.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/udp/ucall.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2012 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup tcp
+ * @{
+ */
+
+/**
+ * @file UDP user calls
+ */
+
+#include <io/log.h>
+#include <macros.h>
+
+#include "assoc.h"
+#include "msg.h"
+#include "udp_type.h"
+#include "ucall.h"
+
+udp_error_t udp_uc_create(udp_assoc_t **assoc)
+{
+	udp_assoc_t *nassoc;
+
+	log_msg(LVL_DEBUG, "udp_uc_create()");
+	nassoc = udp_assoc_new(NULL, NULL);
+	if (nassoc == NULL)
+		return UDP_ENORES;
+
+	udp_assoc_add(nassoc);
+	*assoc = nassoc;
+	return UDP_EOK;
+}
+
+udp_error_t udp_uc_set_foreign(udp_assoc_t *assoc, udp_sock_t *fsock)
+{
+	log_msg(LVL_DEBUG, "udp_uc_set_foreign(%p, %p)", assoc, fsock);
+
+	udp_assoc_set_foreign(assoc, fsock);
+	return UDP_EOK;
+}
+
+udp_error_t udp_uc_set_local(udp_assoc_t *assoc, udp_sock_t *lsock)
+{
+	log_msg(LVL_DEBUG, "udp_uc_set_local(%p, %p)", assoc, lsock);
+
+	udp_assoc_set_local(assoc, lsock);
+	return UDP_EOK;
+}
+
+udp_error_t udp_uc_send(udp_assoc_t *assoc, udp_sock_t *fsock, void *data,
+    size_t size, xflags_t flags)
+{
+	int rc;
+	udp_msg_t msg;
+
+	log_msg(LVL_DEBUG, "%s: udp_uc_send()", assoc->name);
+
+	msg.data = data;
+	msg.data_size = size;
+
+	rc = udp_assoc_send(assoc, fsock, &msg);
+	switch (rc) {
+	case ENOMEM:
+		return UDP_ENORES;
+	case EINVAL:
+		return UDP_EUNSPEC;
+	case EIO:
+		return UDP_ENOROUTE;
+	}
+	return UDP_EOK;
+}
+
+udp_error_t udp_uc_receive(udp_assoc_t *assoc, void *buf, size_t size,
+    size_t *rcvd, xflags_t *xflags, udp_sock_t *fsock)
+{
+	size_t xfer_size;
+	udp_msg_t *msg;
+	int rc;
+
+	log_msg(LVL_DEBUG, "%s: udp_uc_receive()", assoc->name);
+	rc = udp_assoc_recv(assoc, &msg, fsock);
+	switch (rc) {
+	}
+
+	xfer_size = min(size, msg->data_size);
+	memcpy(buf, msg->data, xfer_size);
+	*rcvd = xfer_size;
+	udp_msg_delete(msg);
+
+	return UDP_EOK;
+}
+
+void udp_uc_status(udp_assoc_t *assoc, udp_assoc_status_t *astatus)
+{
+	log_msg(LVL_DEBUG, "udp_uc_status()");
+//	cstatus->cstate = conn->cstate;
+}
+
+void udp_uc_destroy(udp_assoc_t *assoc)
+{
+	log_msg(LVL_DEBUG, "udp_uc_destroy()");
+	udp_assoc_remove(assoc);
+	udp_assoc_delete(assoc);
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/net/udp/ucall.h
===================================================================
--- uspace/srv/net/udp/ucall.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/udp/ucall.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2012 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup udp
+ * @{
+ */
+/** @file UDP user calls
+ */
+
+#ifndef UCALL_H
+#define UCALL_H
+
+#include <sys/types.h>
+#include "udp_type.h"
+
+extern udp_error_t udp_uc_create(udp_assoc_t **);
+extern udp_error_t udp_uc_set_foreign(udp_assoc_t *, udp_sock_t *);
+extern udp_error_t udp_uc_set_local(udp_assoc_t *, udp_sock_t *);
+extern udp_error_t udp_uc_send(udp_assoc_t *, udp_sock_t *, void *, size_t,
+    xflags_t);
+extern udp_error_t udp_uc_receive(udp_assoc_t *, void *, size_t, size_t *,
+    xflags_t *, udp_sock_t *);
+extern void udp_uc_status(udp_assoc_t *, udp_assoc_status_t *);
+extern void udp_uc_destroy(udp_assoc_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/udp/udp.c
===================================================================
--- uspace/srv/net/udp/udp.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/udp/udp.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2012 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup udp
+ * @{
+ */
+
+/**
+ * @file UDP (User Datagram Protocol) service
+ */
+
+#include <async.h>
+#include <errno.h>
+#include <io/log.h>
+#include <stdio.h>
+#include <task.h>
+
+#include "udp_inet.h"
+#include "sock.h"
+
+#define NAME       "udp"
+
+static int udp_init(void)
+{
+	int rc;
+
+	log_msg(LVL_DEBUG, "udp_init()");
+
+	rc = udp_inet_init();
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Failed connecting to internet service.");
+		return ENOENT;
+	}
+
+	rc = udp_sock_init();
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Failed initializing socket service.");
+		return ENOENT;
+	}
+
+	return EOK;
+}
+
+int main(int argc, char **argv)
+{
+	int rc;
+
+	printf(NAME ": UDP (User Datagram Protocol) service\n");
+
+	rc = log_init(NAME, LVL_DEBUG);
+	if (rc != EOK) {
+		printf(NAME ": Failed to initialize log.\n");
+		return 1;
+	}
+
+	rc = udp_init();
+	if (rc != EOK)
+		return 1;
+
+	printf(NAME ": Accepting connections.\n");
+	task_retval(0);
+	async_manager();
+
+	/* Not reached */
+	return 0;
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/net/udp/udp_inet.c
===================================================================
--- uspace/srv/net/udp/udp_inet.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/udp/udp_inet.c	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2012 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup udp
+ * @{
+ */
+
+/**
+ * @file
+ */
+
+#include <bitops.h>
+#include <byteorder.h>
+#include <errno.h>
+#include <inet/inet.h>
+#include <io/log.h>
+#include <stdio.h>
+#include <task.h>
+
+#include "assoc.h"
+#include "pdu.h"
+#include "std.h"
+#include "udp_inet.h"
+#include "udp_type.h"
+
+static int udp_inet_ev_recv(inet_dgram_t *dgram);
+static void udp_received_pdu(udp_pdu_t *pdu);
+
+static inet_ev_ops_t udp_inet_ev_ops = {
+	.recv = udp_inet_ev_recv
+};
+
+/** Received datagram callback */
+static int udp_inet_ev_recv(inet_dgram_t *dgram)
+{
+	udp_pdu_t *pdu;
+
+	log_msg(LVL_DEBUG, "udp_inet_ev_recv()");
+
+	pdu = udp_pdu_new();
+	pdu->data = dgram->data;
+	pdu->data_size = dgram->size;
+
+	pdu->src.ipv4 = dgram->src.ipv4;
+	pdu->dest.ipv4 = dgram->dest.ipv4;
+	log_msg(LVL_DEBUG, "src: 0x%08x, dest: 0x%08x",
+	    pdu->src.ipv4, pdu->dest.ipv4);
+
+	udp_received_pdu(pdu);
+	udp_pdu_delete(pdu);
+
+	return EOK;
+}
+
+/** Transmit PDU over network layer. */
+int udp_transmit_pdu(udp_pdu_t *pdu)
+{
+	int rc;
+	inet_dgram_t dgram;
+
+	log_msg(LVL_DEBUG, "udp_transmit_pdu()");
+
+	dgram.src.ipv4 = pdu->src.ipv4;
+	dgram.dest.ipv4 = pdu->dest.ipv4;
+	dgram.tos = 0;
+	dgram.data = pdu->data;
+	dgram.size = pdu->data_size;
+
+	rc = inet_send(&dgram, INET_TTL_MAX, 0);
+	if (rc != EOK)
+		log_msg(LVL_ERROR, "Failed to transmit PDU.");
+
+	return rc;
+}
+
+/** Process received PDU. */
+static void udp_received_pdu(udp_pdu_t *pdu)
+{
+	udp_msg_t *dmsg;
+	udp_sockpair_t rident;
+
+	log_msg(LVL_DEBUG, "udp_received_pdu()");
+
+	if (udp_pdu_decode(pdu, &rident, &dmsg) != EOK) {
+		log_msg(LVL_WARN, "Not enough memory. PDU dropped.");
+		return;
+	}
+
+	/*
+	 * Insert decoded message into appropriate receive queue.
+	 * This transfers ownership of dmsg to the callee, we do not
+	 * free it.
+	 */
+	udp_assoc_received(&rident, dmsg);
+}
+
+int udp_inet_init(void)
+{
+	int rc;
+
+	log_msg(LVL_DEBUG, "udp_inet_init()");
+
+	rc = inet_init(IP_PROTO_UDP, &udp_inet_ev_ops);
+	if (rc != EOK) {
+		log_msg(LVL_ERROR, "Failed connecting to internet service.");
+		return ENOENT;
+	}
+
+	return EOK;
+}
+
+/**
+ * @}
+ */
Index: uspace/srv/net/udp/udp_inet.h
===================================================================
--- uspace/srv/net/udp/udp_inet.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/udp/udp_inet.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2011 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup udp
+ * @{
+ */
+/** @file
+ */
+
+#ifndef UDP_INET_H
+#define UDP_INET_H
+
+#include "udp_type.h"
+
+extern int udp_inet_init(void);
+extern int udp_transmit_pdu(udp_pdu_t *);
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/net/udp/udp_type.h
===================================================================
--- uspace/srv/net/udp/udp_type.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
+++ uspace/srv/net/udp/udp_type.h	(revision 69a93df73c1354a0d5b5d6a1278f8d030537f534)
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2012 Jiri Svoboda
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup udp
+ * @{
+ */
+/** @file UDP type definitions
+ */
+
+#ifndef UDP_TYPE_H
+#define UDP_TYPE_H
+
+#include <fibril_synch.h>
+#include <socket_core.h>
+#include <sys/types.h>
+
+typedef enum {
+	UDP_EOK,
+	/* Insufficient resources */
+	UDP_ENORES,
+	/* Foreign socket unspecified */
+	UDP_EUNSPEC,
+	/* No route to destination */
+	UDP_ENOROUTE
+} udp_error_t;
+
+typedef enum {
+	XF_DUMMY	= 0x1
+} xflags_t;
+
+typedef struct {
+	uint32_t ipv4;
+} netaddr_t;
+
+enum netaddr {
+	UDP_IPV4_ANY = 0
+};
+
+enum tcp_port {
+	UDP_PORT_ANY = 0
+};
+
+typedef struct {
+	netaddr_t addr;
+	uint16_t port;
+} udp_sock_t;
+
+typedef struct {
+	udp_sock_t local;
+	udp_sock_t foreign;
+} udp_sockpair_t;
+
+/** Unencoded UDP message (datagram) */
+typedef struct {
+	/** Message data */
+	void *data;
+	/** Message data size */
+	size_t data_size;
+} udp_msg_t;
+
+/** Encoded PDU */
+typedef struct {
+	/** Source address */
+	netaddr_t src;
+	/** Destination address */
+	netaddr_t dest;
+
+	/** Encoded PDU data including header */
+	void *data;
+	/** Encoded PDU data size */
+	size_t data_size;
+} udp_pdu_t;
+
+typedef struct {
+	async_sess_t *sess;
+	socket_cores_t sockets;
+} udp_client_t;
+
+/** UDP association
+ *
+ * This is a rough equivalent of a TCP connection endpoint. It allows
+ * sending and receiving UDP datagrams and it is uniquely identified
+ * by a socket pair.
+ */
+typedef struct {
+	char *name;
+	link_t link;
+
+	/** Association identification (local and foreign socket) */
+	udp_sockpair_t ident;
+
+	/** True if association was deleted by user */
+	bool deleted;
+
+	/** Protects access to association structure */
+	fibril_mutex_t lock;
+	/** Reference count */
+	atomic_t refcnt;
+
+	/** Receive queue */
+	list_t rcv_queue;
+	/** Receive queue CV. Broadcast when new datagram is inserted */
+	fibril_condvar_t rcv_queue_cv;
+} udp_assoc_t;
+
+typedef struct {
+} udp_assoc_status_t;
+
+typedef struct udp_sockdata {
+	/** Lock */
+	fibril_mutex_t lock;
+	/** Socket core */
+	socket_core_t *sock_core;
+	/** Client */
+	udp_client_t *client;
+	/** Connection */
+	udp_assoc_t *assoc;
+} udp_sockdata_t;
+
+typedef struct {
+	/** Link to receive queue */
+	link_t link;
+	/** Socket pair */
+	udp_sockpair_t sp;
+	/** Message */
+	udp_msg_t *msg;
+} udp_rcv_queue_entry_t;
+
+#endif
+
+/** @}
+ */
Index: uspace/srv/tcp/Makefile
===================================================================
--- uspace/srv/tcp/Makefile	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(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: uspace/srv/tcp/conn.c
===================================================================
--- uspace/srv/tcp/conn.c	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(revision )
@@ -1,1278 +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;
-}
-
-/** Match socket with pattern. */
-static bool tcp_socket_match(tcp_sock_t *sock, tcp_sock_t *patt)
-{
-	log_msg(LVL_DEBUG, "tcp_socket_match(sock=(%x,%u), pat=(%x,%u))",
-	    sock->addr.ipv4, sock->port, patt->addr.ipv4, patt->port);
-
-	if (patt->addr.ipv4 != TCP_IPV4_ANY &&
-	    patt->addr.ipv4 != sock->addr.ipv4)
-		return false;
-
-	if (patt->port != TCP_PORT_ANY &&
-	    patt->port != sock->port)
-		return false;
-
-	log_msg(LVL_DEBUG, " -> match");
-
-	return true;
-}
-
-/** Match socket pair with pattern. */
-static bool tcp_sockpair_match(tcp_sockpair_t *sp, tcp_sockpair_t *pattern)
-{
-	log_msg(LVL_DEBUG, "tcp_sockpair_match(%p, %p)", sp, pattern);
-
-	if (!tcp_socket_match(&sp->local, &pattern->local))
-		return false;
-
-	if (!tcp_socket_match(&sp->foreign, &pattern->foreign))
-		return false;
-
-	return true;
-}
-
-/** Find connection structure for specified socket pair.
- *
- * A connection is uniquely identified by a socket pair. Look up our
- * connection map and return connection structure based on socket pair.
- * The connection reference count is bumped by one.
- *
- * @param sp	Socket pair
- * @return	Connection structure or NULL if not found.
- */
-tcp_conn_t *tcp_conn_find_ref(tcp_sockpair_t *sp)
-{
-	log_msg(LVL_DEBUG, "tcp_conn_find_ref(%p)", sp);
-
-	fibril_mutex_lock(&conn_list_lock);
-
-	list_foreach(conn_list, link) {
-		tcp_conn_t *conn = list_get_instance(link, tcp_conn_t, link);
-		tcp_sockpair_t *csp = &conn->ident;
-		log_msg(LVL_DEBUG, "compare with conn (f:(%x,%u), l:(%x,%u))",
-		    csp->foreign.addr.ipv4, csp->foreign.port,
-		    csp->local.addr.ipv4, csp->local.port);
-		if (tcp_sockpair_match(sp, csp)) {
-			tcp_conn_addref(conn);
-			fibril_mutex_unlock(&conn_list_lock);
-			return conn;
-		}
-	}
-
-	fibril_mutex_unlock(&conn_list_lock);
-	return NULL;
-}
-
-/** Reset connection.
- *
- * @param conn	Connection
- */
-static void tcp_conn_reset(tcp_conn_t *conn)
-{
-	log_msg(LVL_DEBUG, "%s: tcp_conn_reset()", conn->name);
-	tcp_conn_state_set(conn, st_closed);
-	conn->reset = true;
-
-	tcp_conn_tw_timer_clear(conn);
-	tcp_tqueue_clear(&conn->retransmit);
-
-	fibril_condvar_broadcast(&conn->rcv_buf_cv);
-	fibril_condvar_broadcast(&conn->snd_buf_cv);
-}
-
-/** Signal to the user that connection has been reset.
- *
- * Send an out-of-band signal to the user.
- */
-static void tcp_reset_signal(tcp_conn_t *conn)
-{
-	/* TODO */
-	log_msg(LVL_DEBUG, "%s: tcp_reset_signal()", conn->name);
-}
-
-/** Determine if SYN has been received.
- *
- * @param conn	Connection
- * @return	@c true if SYN has been received, @c false otherwise.
- */
-bool tcp_conn_got_syn(tcp_conn_t *conn)
-{
-	switch (conn->cstate) {
-	case st_listen:
-	case st_syn_sent:
-		return false;
-	case st_syn_received:
-	case st_established:
-	case st_fin_wait_1:
-	case st_fin_wait_2:
-	case st_close_wait:
-	case st_closing:
-	case st_last_ack:
-	case st_time_wait:
-		return true;
-	case st_closed:
-		log_msg(LVL_WARN, "state=%d", (int) conn->cstate);
-		assert(false);
-	}
-
-	assert(false);
-}
-
-/** Segment arrived in Listen state.
- *
- * @param conn		Connection
- * @param seg		Segment
- */
-static void tcp_conn_sa_listen(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	log_msg(LVL_DEBUG, "tcp_conn_sa_listen(%p, %p)", conn, seg);
-
-	if ((seg->ctrl & CTL_RST) != 0) {
-		log_msg(LVL_DEBUG, "Ignoring incoming RST.");
-		return;
-	}
-
-	if ((seg->ctrl & CTL_ACK) != 0) {
-		log_msg(LVL_DEBUG, "Incoming ACK, send acceptable RST.");
-		tcp_reply_rst(&conn->ident, seg);
-		return;
-	}
-
-	if ((seg->ctrl & CTL_SYN) == 0) {
-		log_msg(LVL_DEBUG, "SYN not present. Ignoring segment.");
-		return;
-	}
-
-	log_msg(LVL_DEBUG, "Got SYN, sending SYN, ACK.");
-
-	conn->rcv_nxt = seg->seq + 1;
-	conn->irs = seg->seq;
-
-
-	log_msg(LVL_DEBUG, "rcv_nxt=%u", conn->rcv_nxt);
-
-	if (seg->len > 1)
-		log_msg(LVL_WARN, "SYN combined with data, ignoring data.");
-
-	/* XXX select ISS */
-	conn->iss = 1;
-	conn->snd_nxt = conn->iss;
-	conn->snd_una = conn->iss;
-
-	/*
-	 * Surprisingly the spec does not deal with initial window setting.
-	 * Set SND.WND = SEG.WND and set SND.WL1 so that next segment
-	 * will always be accepted as new window setting.
-	 */
-	conn->snd_wnd = seg->wnd;
-	conn->snd_wl1 = seg->seq;
-	conn->snd_wl2 = seg->seq;
-
-	tcp_conn_state_set(conn, st_syn_received);
-
-	tcp_tqueue_ctrl_seg(conn, CTL_SYN | CTL_ACK /* XXX */);
-
-	tcp_segment_delete(seg);
-}
-
-/** Segment arrived in Syn-Sent state.
- *
- * @param conn		Connection
- * @param seg		Segment
- */
-static void tcp_conn_sa_syn_sent(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	log_msg(LVL_DEBUG, "tcp_conn_sa_syn_sent(%p, %p)", conn, seg);
-
-	if ((seg->ctrl & CTL_ACK) != 0) {
-		log_msg(LVL_DEBUG, "snd_una=%u, seg.ack=%u, snd_nxt=%u",
-		    conn->snd_una, seg->ack, conn->snd_nxt);
-		if (!seq_no_ack_acceptable(conn, seg->ack)) {
-			if ((seg->ctrl & CTL_RST) == 0) {
-				log_msg(LVL_WARN, "ACK not acceptable, send RST");
-				tcp_reply_rst(&conn->ident, seg);
-			} else {
-				log_msg(LVL_WARN, "RST,ACK not acceptable, drop");
-			}
-			return;
-		}
-	}
-
-	if ((seg->ctrl & CTL_RST) != 0) {
-		/* If we get here, we have either an acceptable ACK or no ACK */
-		if ((seg->ctrl & CTL_ACK) != 0) {
-			log_msg(LVL_DEBUG, "%s: Connection reset. -> Closed",
-			    conn->name);
-			/* Reset connection */
-			tcp_conn_reset(conn);
-			return;
-		} else {
-			log_msg(LVL_DEBUG, "%s: RST without ACK, drop",
-			    conn->name);
-			return;
-		}
-	}
-
-	/* XXX precedence */
-
-	if ((seg->ctrl & CTL_SYN) == 0) {
-		log_msg(LVL_DEBUG, "No SYN bit, ignoring segment.");
-		return;
-	}
-
-	conn->rcv_nxt = seg->seq + 1;
-	conn->irs = seg->seq;
-
-	if ((seg->ctrl & CTL_ACK) != 0) {
-		conn->snd_una = seg->ack;
-
-		/*
-		 * Prune acked segments from retransmission queue and
-		 * possibly transmit more data.
-		 */
-		tcp_tqueue_ack_received(conn);
-	}
-
-	log_msg(LVL_DEBUG, "Sent SYN, got SYN.");
-
-	/*
-	 * Surprisingly the spec does not deal with initial window setting.
-	 * Set SND.WND = SEG.WND and set SND.WL1 so that next segment
-	 * will always be accepted as new window setting.
-	 */
-	log_msg(LVL_DEBUG, "SND.WND := %" PRIu32 ", SND.WL1 := %" PRIu32 ", "
-	    "SND.WL2 = %" PRIu32, seg->wnd, seg->seq, seg->seq);
-	conn->snd_wnd = seg->wnd;
-	conn->snd_wl1 = seg->seq;
-	conn->snd_wl2 = seg->seq;
-
-	if (seq_no_syn_acked(conn)) {
-		log_msg(LVL_DEBUG, "%s: syn acked -> Established", conn->name);
-		tcp_conn_state_set(conn, st_established);
-		tcp_tqueue_ctrl_seg(conn, CTL_ACK /* XXX */);
-	} else {
-		log_msg(LVL_DEBUG, "%s: syn not acked -> Syn-Received",
-		    conn->name);
-		tcp_conn_state_set(conn, st_syn_received);
-		tcp_tqueue_ctrl_seg(conn, CTL_SYN | CTL_ACK /* XXX */);
-	}
-
-	tcp_segment_delete(seg);
-}
-
-/** Segment arrived in state where segments are processed in sequence order.
- *
- * Queue segment in incoming segments queue for processing.
- *
- * @param conn		Connection
- * @param seg		Segment
- */
-static void tcp_conn_sa_queue(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	tcp_segment_t *pseg;
-
-	log_msg(LVL_DEBUG, "tcp_conn_sa_seq(%p, %p)", conn, seg);
-
-	/* Discard unacceptable segments ("old duplicates") */
-	if (!seq_no_segment_acceptable(conn, seg)) {
-		log_msg(LVL_DEBUG, "Replying ACK to unacceptable segment.");
-		tcp_tqueue_ctrl_seg(conn, CTL_ACK);
-		tcp_segment_delete(seg);
-		return;
-	}
-
-	/* Queue for processing */
-	tcp_iqueue_insert_seg(&conn->incoming, seg);
-
-	/*
-	 * Process all segments from incoming queue that are ready.
-	 * Unacceptable segments are discarded by tcp_iqueue_get_ready_seg().
-	 *
-	 * XXX Need to return ACK for unacceptable segments
-	 */
-	while (tcp_iqueue_get_ready_seg(&conn->incoming, &pseg) == EOK)
-		tcp_conn_seg_process(conn, pseg);
-}
-
-/** Process segment RST field.
- *
- * @param conn		Connection
- * @param seg		Segment
- * @return		cp_done if we are done with this segment, cp_continue
- *			if not
- */
-static cproc_t tcp_conn_seg_proc_rst(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	if ((seg->ctrl & CTL_RST) == 0)
-		return cp_continue;
-
-	switch (conn->cstate) {
-	case st_syn_received:
-		/* XXX In case of passive open, revert to Listen state */
-		if (conn->ap == ap_passive) {
-			tcp_conn_state_set(conn, st_listen);
-			/* XXX Revert conn->ident */
-			tcp_conn_tw_timer_clear(conn);
-			tcp_tqueue_clear(&conn->retransmit);
-		} else {
-			tcp_conn_reset(conn);
-		}
-		break;
-	case st_established:
-	case st_fin_wait_1:
-	case st_fin_wait_2:
-	case st_close_wait:
-		/* General "connection reset" signal */
-		tcp_reset_signal(conn);
-		tcp_conn_reset(conn);
-		break;
-	case st_closing:
-	case st_last_ack:
-	case st_time_wait:
-		tcp_conn_reset(conn);
-		break;
-	case st_listen:
-	case st_syn_sent:
-	case st_closed:
-		assert(false);
-	}
-
-	return cp_done;
-}
-
-/** Process segment security and precedence fields.
- *
- * @param conn		Connection
- * @param seg		Segment
- * @return		cp_done if we are done with this segment, cp_continue
- *			if not
- */
-static cproc_t tcp_conn_seg_proc_sp(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	/* TODO */
-	return cp_continue;
-}
-
-/** Process segment SYN field.
- *
- * @param conn		Connection
- * @param seg		Segment
- * @return		cp_done if we are done with this segment, cp_continue
- *			if not
- */
-static cproc_t tcp_conn_seg_proc_syn(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	if ((seg->ctrl & CTL_SYN) == 0)
-		return cp_continue;
-
-	/*
-	 * Assert SYN is in receive window, otherwise this step should not
-	 * be reached.
-	 */
-	assert(seq_no_in_rcv_wnd(conn, seg->seq));
-
-	log_msg(LVL_WARN, "SYN is in receive window, should send reset. XXX");
-
-	/*
-	 * TODO
-	 *
-	 * Send a reset, resond "reset" to all outstanding RECEIVEs and SEND,
-	 * flush segment queues. Send unsolicited "connection reset" signal
-	 * to user, connection -> closed state, delete TCB, return.
-	 */
-	return cp_done;
-}
-
-/** Process segment ACK field in Syn-Received state.
- *
- * @param conn		Connection
- * @param seg		Segment
- * @return		cp_done if we are done with this segment, cp_continue
- *			if not
- */
-static cproc_t tcp_conn_seg_proc_ack_sr(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	if (!seq_no_ack_acceptable(conn, seg->ack)) {
-		/* ACK is not acceptable, send RST. */
-		log_msg(LVL_WARN, "Segment ACK not acceptable, sending RST.");
-		tcp_reply_rst(&conn->ident, seg);
-		tcp_segment_delete(seg);
-		return cp_done;
-	}
-
-	log_msg(LVL_DEBUG, "%s: SYN ACKed -> Established", conn->name);
-
-	tcp_conn_state_set(conn, st_established);
-
-	/* XXX Not mentioned in spec?! */
-	conn->snd_una = seg->ack;
-
-	return cp_continue;
-}
-
-/** Process segment ACK field in Established state.
- *
- * @param conn		Connection
- * @param seg		Segment
- * @return		cp_done if we are done with this segment, cp_continue
- *			if not
- */
-static cproc_t tcp_conn_seg_proc_ack_est(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	log_msg(LVL_DEBUG, "tcp_conn_seg_proc_ack_est(%p, %p)", conn, seg);
-
-	log_msg(LVL_DEBUG, "SEG.ACK=%u, SND.UNA=%u, SND.NXT=%u",
-	    (unsigned)seg->ack, (unsigned)conn->snd_una,
-	    (unsigned)conn->snd_nxt);
-
-	if (!seq_no_ack_acceptable(conn, seg->ack)) {
-		log_msg(LVL_DEBUG, "ACK not acceptable.");
-		if (!seq_no_ack_duplicate(conn, seg->ack)) {
-			log_msg(LVL_WARN, "Not acceptable, not duplicate. "
-			    "Send ACK and drop.");
-			/* Not acceptable, not duplicate. Send ACK and drop. */
-			tcp_tqueue_ctrl_seg(conn, CTL_ACK);
-			tcp_segment_delete(seg);
-			return cp_done;
-		} else {
-			log_msg(LVL_DEBUG, "Ignoring duplicate ACK.");
-		}
-	} else {
-		/* Update SND.UNA */
-		conn->snd_una = seg->ack;
-	}
-
-	if (seq_no_new_wnd_update(conn, seg)) {
-		conn->snd_wnd = seg->wnd;
-		conn->snd_wl1 = seg->seq;
-		conn->snd_wl2 = seg->ack;
-
-		log_msg(LVL_DEBUG, "Updating send window, SND.WND=%" PRIu32
-		    ", SND.WL1=%" PRIu32 ", SND.WL2=%" PRIu32,
-		    conn->snd_wnd, conn->snd_wl1, conn->snd_wl2);
-	}
-
-	/*
-	 * Prune acked segments from retransmission queue and
-	 * possibly transmit more data.
-	 */
-	tcp_tqueue_ack_received(conn);
-
-	return cp_continue;
-}
-
-/** Process segment ACK field in Fin-Wait-1 state.
- *
- * @param conn		Connection
- * @param seg		Segment
- * @return		cp_done if we are done with this segment, cp_continue
- *			if not
- */
-static cproc_t tcp_conn_seg_proc_ack_fw1(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	if (tcp_conn_seg_proc_ack_est(conn, seg) == cp_done)
-		return cp_done;
-
-	if (conn->fin_is_acked) {
-		log_msg(LVL_DEBUG, "%s: FIN acked -> Fin-Wait-2", conn->name);
-		tcp_conn_state_set(conn, st_fin_wait_2);
-	}
-
-	return cp_continue;
-}
-
-/** Process segment ACK field in Fin-Wait-2 state.
- *
- * @param conn		Connection
- * @param seg		Segment
- * @return		cp_done if we are done with this segment, cp_continue
- *			if not
- */
-static cproc_t tcp_conn_seg_proc_ack_fw2(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	if (tcp_conn_seg_proc_ack_est(conn, seg) == cp_done)
-		return cp_done;
-
-	/* TODO */
-	return cp_continue;
-}
-
-/** Process segment ACK field in Close-Wait state.
- *
- * @param conn		Connection
- * @param seg		Segment
- * @return		cp_done if we are done with this segment, cp_continue
- *			if not
- */
-static cproc_t tcp_conn_seg_proc_ack_cw(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	/* The same processing as in Established state */
-	return tcp_conn_seg_proc_ack_est(conn, seg);
-}
-
-/** Process segment ACK field in Closing state.
- *
- * @param conn		Connection
- * @param seg		Segment
- * @return		cp_done if we are done with this segment, cp_continue
- *			if not
- */
-static cproc_t tcp_conn_seg_proc_ack_cls(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	if (tcp_conn_seg_proc_ack_est(conn, seg) == cp_done)
-		return cp_done;
-
-	/* TODO */
-	return cp_continue;
-}
-
-/** Process segment ACK field in Last-Ack state.
- *
- * @param conn		Connection
- * @param seg		Segment
- * @return		cp_done if we are done with this segment, cp_continue
- *			if not
- */
-static cproc_t tcp_conn_seg_proc_ack_la(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	if (tcp_conn_seg_proc_ack_est(conn, seg) == cp_done)
-		return cp_done;
-
-	if (conn->fin_is_acked) {
-		log_msg(LVL_DEBUG, "%s: FIN acked -> Closed", conn->name);
-		tcp_conn_remove(conn);
-		tcp_conn_state_set(conn, st_closed);
-		return cp_done;
-	}
-
-	return cp_continue;
-}
-
-/** Process segment ACK field in Time-Wait state.
- *
- * @param conn		Connection
- * @param seg		Segment
- * @return		cp_done if we are done with this segment, cp_continue
- *			if not
- */
-static cproc_t tcp_conn_seg_proc_ack_tw(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	/* Nothing to do */
-	return cp_continue;
-}
-
-/** Process segment ACK field.
- *
- * @param conn		Connection
- * @param seg		Segment
- * @return		cp_done if we are done with this segment, cp_continue
- *			if not
- */
-static cproc_t tcp_conn_seg_proc_ack(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	log_msg(LVL_DEBUG, "%s: tcp_conn_seg_proc_ack(%p, %p)",
-	    conn->name, conn, seg);
-
-	if ((seg->ctrl & CTL_ACK) == 0) {
-		log_msg(LVL_WARN, "Segment has no ACK. Dropping.");
-		tcp_segment_delete(seg);
-		return cp_done;
-	}
-
-	switch (conn->cstate) {
-	case st_syn_received:
-		return tcp_conn_seg_proc_ack_sr(conn, seg);
-	case st_established:
-		return tcp_conn_seg_proc_ack_est(conn, seg);
-	case st_fin_wait_1:
-		return tcp_conn_seg_proc_ack_fw1(conn, seg);
-	case st_fin_wait_2:
-		return tcp_conn_seg_proc_ack_fw2(conn, seg);
-	case st_close_wait:
-		return tcp_conn_seg_proc_ack_cw(conn, seg);
-	case st_closing:
-		return tcp_conn_seg_proc_ack_cls(conn, seg);
-	case st_last_ack:
-		return tcp_conn_seg_proc_ack_la(conn, seg);
-	case st_time_wait:
-		return tcp_conn_seg_proc_ack_tw(conn, seg);
-	case st_listen:
-	case st_syn_sent:
-	case st_closed:
-		assert(false);
-	}
-
-	assert(false);
-}
-
-/** Process segment URG field.
- *
- * @param conn		Connection
- * @param seg		Segment
- * @return		cp_done if we are done with this segment, cp_continue
- *			if not
- */
-static cproc_t tcp_conn_seg_proc_urg(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	return cp_continue;
-}
-
-/** Process segment text.
- *
- * @param conn		Connection
- * @param seg		Segment
- * @return		cp_done if we are done with this segment, cp_continue
- *			if not
- */
-static cproc_t tcp_conn_seg_proc_text(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	size_t text_size;
-	size_t xfer_size;
-
-	log_msg(LVL_DEBUG, "%s: tcp_conn_seg_proc_text(%p, %p)",
-	    conn->name, conn, seg);
-
-	switch (conn->cstate) {
-	case st_established:
-	case st_fin_wait_1:
-	case st_fin_wait_2:
-		/* OK */
-		break;
-	case st_close_wait:
-	case st_closing:
-	case st_last_ack:
-	case st_time_wait:
-		/* Invalid since FIN has been received. Ignore text. */
-		return cp_continue;
-	case st_listen:
-	case st_syn_sent:
-	case st_syn_received:
-	case st_closed:
-		assert(false);
-	}
-
-	/*
-	 * Process segment text
-	 */
-	assert(seq_no_segment_ready(conn, seg));
-
-	/* Trim anything outside our receive window */
-	tcp_conn_trim_seg_to_wnd(conn, seg);
-
-	/* Determine how many bytes to copy */
-	text_size = tcp_segment_text_size(seg);
-	xfer_size = min(text_size, conn->rcv_buf_size - conn->rcv_buf_used);
-
-	/* Copy data to receive buffer */
-	tcp_segment_text_copy(seg, conn->rcv_buf + conn->rcv_buf_used,
-	    xfer_size);
-	conn->rcv_buf_used += xfer_size;
-
-	/* Signal to the receive function that new data has arrived */
-	fibril_condvar_broadcast(&conn->rcv_buf_cv);
-
-	log_msg(LVL_DEBUG, "Received %zu bytes of data.", xfer_size);
-
-	/* Advance RCV.NXT */
-	conn->rcv_nxt += xfer_size;
-
-	/* Update receive window. XXX Not an efficient strategy. */
-	conn->rcv_wnd -= xfer_size;
-
-	/* Send ACK */
-	if (xfer_size > 0)
-		tcp_tqueue_ctrl_seg(conn, CTL_ACK);
-
-	if (xfer_size < seg->len) {
-		/* Trim part of segment which we just received */
-		tcp_conn_trim_seg_to_wnd(conn, seg);
-	} else {
-		log_msg(LVL_DEBUG, "%s: Nothing left in segment, dropping "
-		    "(xfer_size=%zu, SEG.LEN=%zu, seg->ctrl=%u)",
-		    conn->name, xfer_size, seg->len, (unsigned)seg->ctrl);
-		/* Nothing left in segment */
-		tcp_segment_delete(seg);
-		return cp_done;
-	}
-
-	return cp_continue;
-}
-
-/** Process segment FIN field.
- *
- * @param conn		Connection
- * @param seg		Segment
- * @return		cp_done if we are done with this segment, cp_continue
- *			if not
- */
-static cproc_t tcp_conn_seg_proc_fin(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	log_msg(LVL_DEBUG, "%s: tcp_conn_seg_proc_fin(%p, %p)",
-	    conn->name, conn, seg);
-	log_msg(LVL_DEBUG, " seg->len=%zu, seg->ctl=%u", (size_t) seg->len,
-	    (unsigned) seg->ctrl);
-
-	/* Only process FIN if no text is left in segment. */
-	if (tcp_segment_text_size(seg) == 0 && (seg->ctrl & CTL_FIN) != 0) {
-		log_msg(LVL_DEBUG, " - FIN found in segment.");
-
-		/* Send ACK */
-		tcp_tqueue_ctrl_seg(conn, CTL_ACK);
-
-		conn->rcv_nxt++;
-		conn->rcv_wnd--;
-
-		/* Change connection state */
-		switch (conn->cstate) {
-		case st_listen:
-		case st_syn_sent:
-		case st_closed:
-			/* Connection not synchronized */
-			assert(false);
-		case st_syn_received:
-		case st_established:
-			log_msg(LVL_DEBUG, "%s: FIN received -> Close-Wait",
-			    conn->name);
-			tcp_conn_state_set(conn, st_close_wait);
-			break;
-		case st_fin_wait_1:
-			log_msg(LVL_DEBUG, "%s: FIN received -> Closing",
-			    conn->name);
-			tcp_conn_state_set(conn, st_closing);
-			break;
-		case st_fin_wait_2:
-			log_msg(LVL_DEBUG, "%s: FIN received -> Time-Wait",
-			    conn->name);
-			tcp_conn_state_set(conn, st_time_wait);
-			/* Start the Time-Wait timer */
-			tcp_conn_tw_timer_set(conn);
-			break;
-		case st_close_wait:
-		case st_closing:
-		case st_last_ack:
-			/* Do nothing */
-			break;
-		case st_time_wait:
-			/* Restart the Time-Wait timer */
-			tcp_conn_tw_timer_set(conn);
-			break;
-		}
-
-		/* Add FIN to the receive buffer */
-		conn->rcv_buf_fin = true;
-		fibril_condvar_broadcast(&conn->rcv_buf_cv);
-
-		tcp_segment_delete(seg);
-		return cp_done;
-	}
-
-	return cp_continue;
-}
-
-/** Process incoming segment.
- *
- * We are in connection state where segments are processed in order
- * of sequence number. This processes one segment taken from the
- * connection incoming segments queue.
- *
- * @param conn		Connection
- * @param seg		Segment
- */
-static void tcp_conn_seg_process(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	log_msg(LVL_DEBUG, "tcp_conn_seg_process(%p, %p)", conn, seg);
-	tcp_segment_dump(seg);
-
-	/* Check whether segment is acceptable */
-	/* XXX Permit valid ACKs, URGs and RSTs */
-/*	if (!seq_no_segment_acceptable(conn, seg)) {
-		log_msg(LVL_WARN, "Segment not acceptable, dropping.");
-		if ((seg->ctrl & CTL_RST) == 0) {
-			tcp_tqueue_ctrl_seg(conn, CTL_ACK);
-		}
-		return;
-	}
-*/
-
-	if (tcp_conn_seg_proc_rst(conn, seg) == cp_done)
-		return;
-
-	if (tcp_conn_seg_proc_sp(conn, seg) == cp_done)
-		return;
-
-	if (tcp_conn_seg_proc_syn(conn, seg) == cp_done)
-		return;
-
-	if (tcp_conn_seg_proc_ack(conn, seg) == cp_done)
-		return;
-
-	if (tcp_conn_seg_proc_urg(conn, seg) == cp_done)
-		return;
-
-	if (tcp_conn_seg_proc_text(conn, seg) == cp_done)
-		return;
-
-	if (tcp_conn_seg_proc_fin(conn, seg) == cp_done)
-		return;
-
-	/*
-	 * If anything is left from the segment, insert it back into the
-	 * incoming segments queue.
-	 */
-	if (seg->len > 0) {
-		log_msg(LVL_DEBUG, "Re-insert segment %p. seg->len=%zu",
-		    seg, (size_t) seg->len);
-		tcp_iqueue_insert_seg(&conn->incoming, seg);
-	} else {
-		tcp_segment_delete(seg);
-	}
-}
-
-/** Segment arrived on a connection.
- *
- * @param conn		Connection
- * @param seg		Segment
- */
-void tcp_conn_segment_arrived(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	log_msg(LVL_DEBUG, "%c: tcp_conn_segment_arrived(%p)",
-	    conn->name, seg);
-
-	switch (conn->cstate) {
-	case st_listen:
-		tcp_conn_sa_listen(conn, seg); break;
-	case st_syn_sent:
-		tcp_conn_sa_syn_sent(conn, seg); break;
-	case st_syn_received:
-	case st_established:
-	case st_fin_wait_1:
-	case st_fin_wait_2:
-	case st_close_wait:
-	case st_closing:
-	case st_last_ack:
-	case st_time_wait:
-		/* Process segments in order of sequence number */
-		tcp_conn_sa_queue(conn, seg); break;
-	case st_closed:
-		log_msg(LVL_DEBUG, "state=%d", (int) conn->cstate);
-		assert(false);
-	}
-}
-
-/** Time-Wait timeout handler.
- *
- * @param arg	Connection
- */
-static void tw_timeout_func(void *arg)
-{
-	tcp_conn_t *conn = (tcp_conn_t *) arg;
-
-	log_msg(LVL_DEBUG, "tw_timeout_func(%p)", conn);
-
-	fibril_mutex_lock(&conn->lock);
-
-	if (conn->cstate == st_closed) {
-		log_msg(LVL_DEBUG, "Connection already closed.");
-		fibril_mutex_unlock(&conn->lock);
-		tcp_conn_delref(conn);
-		return;
-	}
-
-	log_msg(LVL_DEBUG, "%s: TW Timeout -> Closed", conn->name);
-	tcp_conn_remove(conn);
-	tcp_conn_state_set(conn, st_closed);
-
-	fibril_mutex_unlock(&conn->lock);
-	tcp_conn_delref(conn);
-}
-
-/** Start or restart the Time-Wait timeout.
- *
- * @param conn		Connection
- */
-void tcp_conn_tw_timer_set(tcp_conn_t *conn)
-{
-	tcp_conn_addref(conn);
-	fibril_timer_set(conn->tw_timer, TIME_WAIT_TIMEOUT, tw_timeout_func,
-	    (void *)conn);
-}
-
-/** Clear the Time-Wait timeout.
- *
- * @param conn		Connection
- */
-void tcp_conn_tw_timer_clear(tcp_conn_t *conn)
-{
-	if (fibril_timer_clear(conn->tw_timer) == fts_active)
-		tcp_conn_delref(conn);
-}
-
-/** Trim segment to the receive window.
- *
- * @param conn		Connection
- * @param seg		Segment
- */
-void tcp_conn_trim_seg_to_wnd(tcp_conn_t *conn, tcp_segment_t *seg)
-{
-	uint32_t left, right;
-
-	seq_no_seg_trim_calc(conn, seg, &left, &right);
-	tcp_segment_trim(seg, left, right);
-}
-
-/** Handle unexpected segment received on a socket pair.
- *
- * We reply with an RST unless the received segment has RST.
- *
- * @param sp		Socket pair which received the segment
- * @param seg		Unexpected segment
- */
-void tcp_unexpected_segment(tcp_sockpair_t *sp, tcp_segment_t *seg)
-{
-	log_msg(LVL_DEBUG, "tcp_unexpected_segment(%p, %p)", sp, seg);
-
-	if ((seg->ctrl & CTL_RST) == 0)
-		tcp_reply_rst(sp, seg);
-}
-
-/** Compute flipped socket pair for response.
- *
- * Flipped socket pair has local and foreign sockets exchanged.
- *
- * @param sp		Socket pair
- * @param fsp		Place to store flipped socket pair
- */
-void tcp_sockpair_flipped(tcp_sockpair_t *sp, tcp_sockpair_t *fsp)
-{
-	fsp->local = sp->foreign;
-	fsp->foreign = sp->local;
-}
-
-/** Send RST in response to an incoming segment.
- *
- * @param sp		Socket pair which received the segment
- * @param seg		Incoming segment
- */
-void tcp_reply_rst(tcp_sockpair_t *sp, tcp_segment_t *seg)
-{
-	tcp_segment_t *rseg;
-
-	log_msg(LVL_DEBUG, "tcp_reply_rst(%p, %p)", sp, seg);
-
-	rseg = tcp_segment_make_rst(seg);
-	tcp_transmit_segment(sp, rseg);
-}
-
-/**
- * @}
- */
Index: uspace/srv/tcp/conn.h
===================================================================
--- uspace/srv/tcp/conn.h	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(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: uspace/srv/tcp/iqueue.c
===================================================================
--- uspace/srv/tcp/iqueue.c	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(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: uspace/srv/tcp/iqueue.h
===================================================================
--- uspace/srv/tcp/iqueue.h	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(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: uspace/srv/tcp/ncsim.c
===================================================================
--- uspace/srv/tcp/ncsim.c	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(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: uspace/srv/tcp/ncsim.h
===================================================================
--- uspace/srv/tcp/ncsim.h	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(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: uspace/srv/tcp/pdu.c
===================================================================
--- uspace/srv/tcp/pdu.c	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(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);
-}
-
-/** Decode incoming PDU */
-int tcp_pdu_decode(tcp_pdu_t *pdu, tcp_sockpair_t *sp, tcp_segment_t **seg)
-{
-	tcp_segment_t *nseg;
-	tcp_header_t *hdr;
-
-	nseg = tcp_segment_make_data(0, pdu->text, pdu->text_size);
-	if (nseg == NULL)
-		return ENOMEM;
-
-	tcp_header_decode(pdu->header, nseg);
-	nseg->len += seq_no_control_len(nseg->ctrl);
-
-	hdr = (tcp_header_t *)pdu->header;
-
-	sp->local.port = uint16_t_be2host(hdr->dest_port);
-	sp->local.addr = pdu->dest_addr;
-	sp->foreign.port = uint16_t_be2host(hdr->src_port);
-	sp->foreign.addr = pdu->src_addr;
-
-	*seg = nseg;
-	return EOK;
-}
-
-/** Encode outgoing PDU */
-int tcp_pdu_encode(tcp_sockpair_t *sp, tcp_segment_t *seg, tcp_pdu_t **pdu)
-{
-	tcp_pdu_t *npdu;
-	size_t text_size;
-	uint16_t checksum;
-
-	npdu = tcp_pdu_new();
-	if (npdu == NULL)
-		return ENOMEM;
-
-	npdu->src_addr = sp->local.addr;
-	npdu->dest_addr = sp->foreign.addr;
-	tcp_header_encode(sp, seg, &npdu->header, &npdu->header_size);
-
-	text_size = tcp_segment_text_size(seg);
-	npdu->text = calloc(1, text_size);
-	if (npdu->text == NULL)
-		return ENOMEM;
-
-	npdu->text_size = text_size;
-	memcpy(npdu->text, seg->data, text_size);
-
-	/* Checksum calculation */
-	checksum = tcp_pdu_checksum_calc(npdu);
-	tcp_pdu_set_checksum(npdu, checksum);
-
-	*pdu = npdu;
-	return EOK;
-}
-
-/**
- * @}
- */
Index: uspace/srv/tcp/pdu.h
===================================================================
--- uspace/srv/tcp/pdu.h	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(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: uspace/srv/tcp/rqueue.c
===================================================================
--- uspace/srv/tcp/rqueue.c	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(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: uspace/srv/tcp/rqueue.h
===================================================================
--- uspace/srv/tcp/rqueue.h	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(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: uspace/srv/tcp/segment.c
===================================================================
--- uspace/srv/tcp/segment.c	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(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: uspace/srv/tcp/segment.h
===================================================================
--- uspace/srv/tcp/segment.h	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(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: uspace/srv/tcp/seq_no.c
===================================================================
--- uspace/srv/tcp/seq_no.c	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(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: uspace/srv/tcp/seq_no.h
===================================================================
--- uspace/srv/tcp/seq_no.h	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(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: uspace/srv/tcp/sock.c
===================================================================
--- uspace/srv/tcp/sock.c	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(revision )
@@ -1,841 +1,0 @@
-/*
- * Copyright (c) 2008 Lukas Mejdrech
- * Copyright (c) 2011 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup tcp
- * @{
- */
-
-/**
- * @file Socket provider
- */
-
-#include <async.h>
-#include <errno.h>
-#include <inet/inet.h>
-#include <io/log.h>
-#include <ipc/services.h>
-#include <ipc/socket.h>
-#include <net/modules.h>
-#include <net/socket.h>
-#include <ns.h>
-
-#include "sock.h"
-#include "std.h"
-#include "tcp.h"
-#include "tcp_type.h"
-#include "ucall.h"
-
-#define FRAGMENT_SIZE 1024
-
-#define MAX_BACKLOG 128
-
-/** Free ports pool start. */
-#define TCP_FREE_PORTS_START		1025
-
-/** Free ports pool end. */
-#define TCP_FREE_PORTS_END		65535
-
-static int last_used_port = TCP_FREE_PORTS_START - 1;
-static socket_ports_t gsock;
-
-static void tcp_sock_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg);
-static void tcp_sock_cstate_cb(tcp_conn_t *conn, void *arg);
-
-int tcp_sock_init(void)
-{
-	int rc;
-
-	socket_ports_initialize(&gsock);
-
-	async_set_client_connection(tcp_sock_connection);
-
-	rc = service_register(SERVICE_TCP);
-	if (rc != EOK)
-		return EEXIST;
-
-	return EOK;
-}
-
-static void tcp_free_sock_data(socket_core_t *sock_core)
-{
-	tcp_sockdata_t *socket;
-
-	socket = (tcp_sockdata_t *)sock_core->specific_data;
-	(void)socket;
-}
-
-static void tcp_sock_notify_data(socket_core_t *sock_core)
-{
-	log_msg(LVL_DEBUG, "tcp_sock_notify_data(%d)", sock_core->socket_id);
-	async_exch_t *exch = async_exchange_begin(sock_core->sess);
-	async_msg_5(exch, NET_SOCKET_RECEIVED, (sysarg_t)sock_core->socket_id,
-	    FRAGMENT_SIZE, 0, 0, 1);
-	async_exchange_end(exch);
-}
-
-static void tcp_sock_notify_aconn(socket_core_t *lsock_core)
-{
-	log_msg(LVL_DEBUG, "tcp_sock_notify_aconn(%d)", lsock_core->socket_id);
-	async_exch_t *exch = async_exchange_begin(lsock_core->sess);
-	async_msg_5(exch, NET_SOCKET_ACCEPTED, (sysarg_t)lsock_core->socket_id,
-	    FRAGMENT_SIZE, 0, 0, 0);
-	async_exchange_end(exch);
-}
-
-static void tcp_sock_socket(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
-{
-	tcp_sockdata_t *sock;
-	socket_core_t *sock_core;
-	int sock_id;
-	int rc;
-	ipc_call_t answer;
-
-	log_msg(LVL_DEBUG, "tcp_sock_socket()");
-	sock = calloc(sizeof(tcp_sockdata_t), 1);
-	if (sock == NULL) {
-		async_answer_0(callid, ENOMEM);
-		return;
-	}
-
-	fibril_mutex_initialize(&sock->lock);
-	sock->client = client;
-	sock->laddr.ipv4 = TCP_IPV4_ANY;
-	sock->lconn = NULL;
-	sock->backlog = 0;
-	list_initialize(&sock->ready);
-
-	sock_id = SOCKET_GET_SOCKET_ID(call);
-	rc = socket_create(&client->sockets, client->sess, sock, &sock_id);
-	if (rc != EOK) {
-		async_answer_0(callid, rc);
-		return;
-	}
-
-	sock_core = socket_cores_find(&client->sockets, sock_id);
-	assert(sock_core != NULL);
-	sock->sock_core = sock_core;
-
-	refresh_answer(&answer, NULL);
-	SOCKET_SET_SOCKET_ID(answer, sock_id);
-
-	SOCKET_SET_DATA_FRAGMENT_SIZE(answer, FRAGMENT_SIZE);
-	SOCKET_SET_HEADER_SIZE(answer, sizeof(tcp_header_t));
-	answer_call(callid, EOK, &answer, 3);
-}
-
-static void tcp_sock_bind(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
-{
-	int rc;
-	struct sockaddr *addr;
-	size_t addr_len;
-	socket_core_t *sock_core;
-	tcp_sockdata_t *socket;
-
-	log_msg(LVL_DEBUG, "tcp_sock_bind()");
-	log_msg(LVL_DEBUG, " - async_data_write_accept");
-	rc = async_data_write_accept((void **) &addr, false, 0, 0, 0, &addr_len);
-	if (rc != EOK) {
-		async_answer_0(callid, rc);
-		return;
-	}
-
-	log_msg(LVL_DEBUG, " - call socket_bind");
-	rc = socket_bind(&client->sockets, &gsock, SOCKET_GET_SOCKET_ID(call),
-	    addr, addr_len, TCP_FREE_PORTS_START, TCP_FREE_PORTS_END,
-	    last_used_port);
-	if (rc != EOK) {
-		async_answer_0(callid, rc);
-		return;
-	}
-
-	log_msg(LVL_DEBUG, " - call socket_cores_find");
-	sock_core = socket_cores_find(&client->sockets, SOCKET_GET_SOCKET_ID(call));
-	if (sock_core != NULL) {
-		socket = (tcp_sockdata_t *)sock_core->specific_data;
-		/* XXX Anything to do? */
-		(void) socket;
-	}
-
-	log_msg(LVL_DEBUG, " - success");
-	async_answer_0(callid, EOK);
-}
-
-static void tcp_sock_listen(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
-{
-	int socket_id;
-	int backlog;
-	socket_core_t *sock_core;
-	tcp_sockdata_t *socket;
-	tcp_error_t trc;
-	tcp_sock_t lsocket;
-	tcp_sock_t fsocket;
-	tcp_conn_t *conn;
-	tcp_sock_lconn_t *lconn;
-	int i;
-
-	log_msg(LVL_DEBUG, "tcp_sock_listen()");
-
-	socket_id = SOCKET_GET_SOCKET_ID(call);
-	backlog = SOCKET_GET_BACKLOG(call);
-
-	if (backlog < 0) {
-		async_answer_0(callid, EINVAL);
-		return;
-	}
-
-	if (backlog > MAX_BACKLOG)
-		backlog = MAX_BACKLOG;
-
-	sock_core = socket_cores_find(&client->sockets, socket_id);
-	if (sock_core == NULL) {
-		async_answer_0(callid, ENOTSOCK);
-		return;
-	}
-
-	socket = (tcp_sockdata_t *)sock_core->specific_data;
-
-	/*
-	 * Prepare @c backlog listening connections.
-	 */
-	fibril_mutex_lock(&socket->lock);
-
-	socket->backlog = backlog;
-	socket->lconn = calloc(sizeof(tcp_conn_t *), backlog);
-	if (socket->lconn == NULL) {
-		fibril_mutex_unlock(&socket->lock);
-		async_answer_0(callid, ENOMEM);
-		return;
-	}
-
-	log_msg(LVL_DEBUG, " - open connections");
-
-	lsocket.addr.ipv4 = TCP_IPV4_ANY;
-	lsocket.port = sock_core->port;
-	fsocket.addr.ipv4 = TCP_IPV4_ANY;
-	fsocket.port = TCP_PORT_ANY;
-
-	for (i = 0; i < backlog; i++) {
-
-		lconn = calloc(sizeof(tcp_sock_lconn_t), 1);
-		if (lconn == NULL) {
-			/* XXX Clean up */
-			fibril_mutex_unlock(&socket->lock);
-			async_answer_0(callid, ENOMEM);
-			return;
-		}
-
-		trc = tcp_uc_open(&lsocket, &fsocket, ap_passive,
-		    tcp_open_nonblock, &conn);
-		if (conn == NULL) {
-			/* XXX Clean up */
-			fibril_mutex_unlock(&socket->lock);
-			async_answer_0(callid, ENOMEM);
-			return;
-		}
-
-		tcp_uc_set_cstate_cb(conn, tcp_sock_cstate_cb, lconn);
-
-		assert(trc == TCP_EOK);
-		conn->name = (char *)"S";
-
-		lconn->conn = conn;
-		lconn->socket = socket;
-		link_initialize(&lconn->ready_list);
-		socket->lconn[i] = lconn;
-	}
-
-	fibril_mutex_unlock(&socket->lock);
-	async_answer_0(callid, EOK);
-}
-
-static void tcp_sock_connect(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
-{
-	int rc;
-	struct sockaddr_in *addr;
-	int socket_id;
-	size_t addr_len;
-	socket_core_t *sock_core;
-	tcp_sockdata_t *socket;
-	tcp_error_t trc;
-	tcp_sock_t lsocket;
-	tcp_sock_t fsocket;
-
-	log_msg(LVL_DEBUG, "tcp_sock_connect()");
-
-	rc = async_data_write_accept((void **) &addr, false, 0, 0, 0, &addr_len);
-	if (rc != EOK || addr_len != sizeof(struct sockaddr_in)) {
-		async_answer_0(callid, rc);
-		return;
-	}
-
-	socket_id = SOCKET_GET_SOCKET_ID(call);
-
-	sock_core = socket_cores_find(&client->sockets, socket_id);
-	if (sock_core == NULL) {
-		async_answer_0(callid, ENOTSOCK);
-		return;
-	}
-
-	socket = (tcp_sockdata_t *)sock_core->specific_data;
-	if (sock_core->port <= 0) {
-		rc = socket_bind_free_port(&gsock, sock_core,
-		    TCP_FREE_PORTS_START, TCP_FREE_PORTS_END,
-		    last_used_port);
-		if (rc != EOK) {
-			async_answer_0(callid, rc);
-			return;
-		}
-
-		last_used_port = sock_core->port;
-	}
-
-	fibril_mutex_lock(&socket->lock);
-
-	if (socket->laddr.ipv4 == TCP_IPV4_ANY) {
-		/* Determine local IP address */
-		inet_addr_t loc_addr, rem_addr;
-
-		rem_addr.ipv4 = uint32_t_be2host(addr->sin_addr.s_addr);
-		rc = inet_get_srcaddr(&rem_addr, 0, &loc_addr);
-		if (rc != EOK) {
-			fibril_mutex_unlock(&socket->lock);
-			async_answer_0(callid, rc);
-			log_msg(LVL_DEBUG, "tcp_sock_connect: Failed to "
-			    "determine local address.");
-			return;
-		}
-
-		socket->laddr.ipv4 = loc_addr.ipv4;
-		log_msg(LVL_DEBUG, "Local IP address is %x", socket->laddr.ipv4);
-	}
-
-	lsocket.addr.ipv4 = socket->laddr.ipv4;
-	lsocket.port = sock_core->port;
-	fsocket.addr.ipv4 = uint32_t_be2host(addr->sin_addr.s_addr);
-	fsocket.port = uint16_t_be2host(addr->sin_port);
-
-	trc = tcp_uc_open(&lsocket, &fsocket, ap_active, 0, &socket->conn);
-
-	if (socket->conn != NULL)
-		socket->conn->name = (char *)"C";
-
-	fibril_mutex_unlock(&socket->lock);
-
-	switch (trc) {
-	case TCP_EOK:
-		rc = EOK;
-		break;
-	case TCP_ERESET:
-		rc = ECONNREFUSED;
-		break;
-	default:
-		assert(false);
-	}
-
-	async_answer_0(callid, rc);
-
-	/* Push one fragment notification to client's queue */
-	tcp_sock_notify_data(sock_core);
-	log_msg(LVL_DEBUG, "tcp_sock_connect(): notify conn\n");
-}
-
-static void tcp_sock_accept(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
-{
-	ipc_call_t answer;
-	int socket_id;
-	int asock_id;
-	socket_core_t *sock_core;
-	socket_core_t *asock_core;
-	tcp_sockdata_t *socket;
-	tcp_sockdata_t *asocket;
-	tcp_error_t trc;
-	tcp_sock_t lsocket;
-	tcp_sock_t fsocket;
-	tcp_conn_t *conn;
-	tcp_conn_t *rconn;
-	tcp_sock_lconn_t *lconn;
-	int rc;
-
-	log_msg(LVL_DEBUG, "tcp_sock_accept()");
-
-	socket_id = SOCKET_GET_SOCKET_ID(call);
-	asock_id = SOCKET_GET_NEW_SOCKET_ID(call);
-
-	sock_core = socket_cores_find(&client->sockets, socket_id);
-	if (sock_core == NULL) {
-		async_answer_0(callid, ENOTSOCK);
-		return;
-	}
-
-	socket = (tcp_sockdata_t *)sock_core->specific_data;
-	fibril_mutex_lock(&socket->lock);
-
-	log_msg(LVL_DEBUG, " - verify socket->conn");
-	if (socket->conn != NULL) {
-		fibril_mutex_unlock(&socket->lock);
-		async_answer_0(callid, EINVAL);
-		return;
-	}
-
-	if (list_empty(&socket->ready)) {
-		fibril_mutex_unlock(&socket->lock);
-		async_answer_0(callid, ENOENT);
-		return;
-	}
-
-	lconn = list_get_instance(list_first(&socket->ready),
-	    tcp_sock_lconn_t, ready_list);
-	list_remove(&lconn->ready_list);
-
-	conn = lconn->conn;
-	tcp_uc_set_cstate_cb(conn, NULL, NULL);
-
-	/* Replenish listening connection */
-
-	lsocket.addr.ipv4 = TCP_IPV4_ANY;
-	lsocket.port = sock_core->port;
-	fsocket.addr.ipv4 = TCP_IPV4_ANY;
-	fsocket.port = TCP_PORT_ANY;
-
-	trc = tcp_uc_open(&lsocket, &fsocket, ap_passive, tcp_open_nonblock,
-	    &rconn);
-	if (rconn == NULL) {
-		/* XXX Clean up */
-		fibril_mutex_unlock(&socket->lock);
-		async_answer_0(callid, ENOMEM);
-		return;
-	}
-
-	tcp_uc_set_cstate_cb(rconn, tcp_sock_cstate_cb, lconn);
-
-	assert(trc == TCP_EOK);
-	rconn->name = (char *)"S";
-
-	lconn->conn = rconn;
-
-	/* Allocate socket for accepted connection */
-
-	log_msg(LVL_DEBUG, "tcp_sock_accept(): allocate asocket\n");
-	asocket = calloc(sizeof(tcp_sockdata_t), 1);
-	if (asocket == NULL) {
-		fibril_mutex_unlock(&socket->lock);
-		async_answer_0(callid, ENOMEM);
-		return;
-	}
-
-	fibril_mutex_initialize(&asocket->lock);
-	asocket->client = client;
-	asocket->conn = conn;
-	log_msg(LVL_DEBUG, "tcp_sock_accept():create asocket\n");
-
-	rc = socket_create(&client->sockets, client->sess, asocket, &asock_id);
-	if (rc != EOK) {
-		fibril_mutex_unlock(&socket->lock);
-		async_answer_0(callid, rc);
-		return;
-	}
-	log_msg(LVL_DEBUG, "tcp_sock_accept(): find acore\n");
-
-	asock_core = socket_cores_find(&client->sockets, asock_id);
-	assert(asock_core != NULL);
-
-	refresh_answer(&answer, NULL);
-
-	SOCKET_SET_DATA_FRAGMENT_SIZE(answer, FRAGMENT_SIZE);
-	SOCKET_SET_SOCKET_ID(answer, asock_id);
-	SOCKET_SET_ADDRESS_LENGTH(answer, sizeof(struct sockaddr_in));
-
-	answer_call(callid, asock_core->socket_id, &answer, 3);
-
-	/* Push one fragment notification to client's queue */
-	log_msg(LVL_DEBUG, "tcp_sock_accept(): notify data\n");
-	tcp_sock_notify_data(asock_core);
-	fibril_mutex_unlock(&socket->lock);
-}
-
-static void tcp_sock_send(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
-{
-	int socket_id;
-	int fragments;
-	int index;
-	socket_core_t *sock_core;
-	tcp_sockdata_t *socket;
-	ipc_call_t answer;
-	ipc_callid_t wcallid;
-	size_t length;
-	uint8_t buffer[FRAGMENT_SIZE];
-	tcp_error_t trc;
-	int rc;
-
-	log_msg(LVL_DEBUG, "tcp_sock_send()");
-	socket_id = SOCKET_GET_SOCKET_ID(call);
-	fragments = SOCKET_GET_DATA_FRAGMENTS(call);
-	SOCKET_GET_FLAGS(call);
-
-	sock_core = socket_cores_find(&client->sockets, socket_id);
-	if (sock_core == NULL) {
-		async_answer_0(callid, ENOTSOCK);
-		return;
-	}
-
-	socket = (tcp_sockdata_t *)sock_core->specific_data;
-	fibril_mutex_lock(&socket->lock);
-
-	if (socket->conn == NULL) {
-		fibril_mutex_unlock(&socket->lock);
-		async_answer_0(callid, ENOTCONN);
-		return;
-	}
-
-	for (index = 0; index < fragments; index++) {
-		if (!async_data_write_receive(&wcallid, &length)) {
-			fibril_mutex_unlock(&socket->lock);
-			async_answer_0(callid, EINVAL);
-			return;
-		}
-
-		if (length > FRAGMENT_SIZE)
-			length = FRAGMENT_SIZE;
-
-		rc = async_data_write_finalize(wcallid, buffer, length);
-		if (rc != EOK) {
-			fibril_mutex_unlock(&socket->lock);
-			async_answer_0(callid, rc);
-			return;
-		}
-
-		trc = tcp_uc_send(socket->conn, buffer, length, 0);
-
-		switch (trc) {
-		case TCP_EOK:
-			rc = EOK;
-			break;
-		case TCP_ENOTEXIST:
-			rc = ENOTCONN;
-			break;
-		case TCP_ECLOSING:
-			rc = ENOTCONN;
-			break;
-		case TCP_ERESET:
-			rc = ECONNABORTED;
-			break;
-		default:
-			assert(false);
-		}
-
-		if (rc != EOK) {
-			fibril_mutex_unlock(&socket->lock);
-			async_answer_0(callid, rc);
-			return;
-		}
-	}
-
-	refresh_answer(&answer, NULL);
-	SOCKET_SET_DATA_FRAGMENT_SIZE(answer, FRAGMENT_SIZE);
-	answer_call(callid, EOK, &answer, 2);
-	fibril_mutex_unlock(&socket->lock);
-}
-
-static void tcp_sock_sendto(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
-{
-	log_msg(LVL_DEBUG, "tcp_sock_sendto()");
-	async_answer_0(callid, ENOTSUP);
-}
-
-static void tcp_sock_recvfrom(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
-{
-	int socket_id;
-	int flags;
-	size_t addr_length, length;
-	socket_core_t *sock_core;
-	tcp_sockdata_t *socket;
-	ipc_call_t answer;
-	ipc_callid_t rcallid;
-	uint8_t buffer[FRAGMENT_SIZE];
-	size_t data_len;
-	xflags_t xflags;
-	tcp_error_t trc;
-	struct sockaddr_in addr;
-	tcp_sock_t *rsock;
-	int rc;
-
-	log_msg(LVL_DEBUG, "%p: tcp_sock_recv[from]()", client);
-
-	socket_id = SOCKET_GET_SOCKET_ID(call);
-	flags = SOCKET_GET_FLAGS(call);
-
-	sock_core = socket_cores_find(&client->sockets, socket_id);
-	if (sock_core == NULL) {
-		async_answer_0(callid, ENOTSOCK);
-		return;
-	}
-
-	socket = (tcp_sockdata_t *)sock_core->specific_data;
-	fibril_mutex_lock(&socket->lock);
-
-	if (socket->conn == NULL) {
-		fibril_mutex_unlock(&socket->lock);
-		async_answer_0(callid, ENOTCONN);
-		return;
-	}
-
-	(void)flags;
-
-	trc = tcp_uc_receive(socket->conn, buffer, FRAGMENT_SIZE, &data_len,
-	    &xflags);
-	log_msg(LVL_DEBUG, "**** tcp_uc_receive done");
-
-	switch (trc) {
-	case TCP_EOK:
-		rc = EOK;
-		break;
-	case TCP_ENOTEXIST:
-	case TCP_ECLOSING:
-		rc = ENOTCONN;
-		break;
-	case TCP_ERESET:
-		rc = ECONNABORTED;
-		break;
-	default:
-		assert(false);
-	}
-
-	log_msg(LVL_DEBUG, "**** tcp_uc_receive -> %d", rc);
-	if (rc != EOK) {
-		fibril_mutex_unlock(&socket->lock);
-		async_answer_0(callid, rc);
-		return;
-	}
-
-	if (IPC_GET_IMETHOD(call) == NET_SOCKET_RECVFROM) {
-		/* Fill addr */
-		rsock = &socket->conn->ident.foreign;
-		addr.sin_family = AF_INET;
-		addr.sin_addr.s_addr = host2uint32_t_be(rsock->addr.ipv4);
-		addr.sin_port = host2uint16_t_be(rsock->port);
-
-		log_msg(LVL_DEBUG, "addr read receive");
-		if (!async_data_read_receive(&rcallid, &addr_length)) {
-			fibril_mutex_unlock(&socket->lock);
-			async_answer_0(callid, EINVAL);
-			return;
-		}
-
-		if (addr_length > sizeof(addr))
-			addr_length = sizeof(addr);
-
-		log_msg(LVL_DEBUG, "addr read finalize");
-		rc = async_data_read_finalize(rcallid, &addr, addr_length);
-		if (rc != EOK) {
-			fibril_mutex_unlock(&socket->lock);
-			async_answer_0(callid, EINVAL);
-			return;
-		}
-	}
-
-	log_msg(LVL_DEBUG, "data read receive");
-	if (!async_data_read_receive(&rcallid, &length)) {
-		fibril_mutex_unlock(&socket->lock);
-		async_answer_0(callid, EINVAL);
-		return;
-	}
-
-	if (length > data_len)
-		length = data_len;
-
-	log_msg(LVL_DEBUG, "data read finalize");
-	rc = async_data_read_finalize(rcallid, buffer, length);
-
-	if (length < data_len && rc == EOK)
-		rc = EOVERFLOW;
-
-	SOCKET_SET_READ_DATA_LENGTH(answer, length);
-	answer_call(callid, EOK, &answer, 1);
-
-	/* Push one fragment notification to client's queue */
-	tcp_sock_notify_data(sock_core);
-	fibril_mutex_unlock(&socket->lock);
-}
-
-static void tcp_sock_close(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
-{
-	int socket_id;
-	socket_core_t *sock_core;
-	tcp_sockdata_t *socket;
-	tcp_error_t trc;
-	int rc;
-	uint8_t buffer[FRAGMENT_SIZE];
-	size_t data_len;
-	xflags_t xflags;
-
-	log_msg(LVL_DEBUG, "tcp_sock_close()");
-	socket_id = SOCKET_GET_SOCKET_ID(call);
-
-	sock_core = socket_cores_find(&client->sockets, socket_id);
-	if (sock_core == NULL) {
-		async_answer_0(callid, ENOTSOCK);
-		return;
-	}
-
-	socket = (tcp_sockdata_t *)sock_core->specific_data;
-	fibril_mutex_lock(&socket->lock);
-
-	if (socket->conn != NULL) {
-		trc = tcp_uc_close(socket->conn);
-		if (trc != TCP_EOK && trc != TCP_ENOTEXIST) {
-			fibril_mutex_unlock(&socket->lock);
-			async_answer_0(callid, EBADF);
-			return;
-		}
-
-		/* Drain incoming data. This should really be done in the background. */
-		do {
-			trc = tcp_uc_receive(socket->conn, buffer,
-			    FRAGMENT_SIZE, &data_len, &xflags);
-		} while (trc == TCP_EOK);
-
-		tcp_uc_delete(socket->conn);
-	}
-
-	rc = socket_destroy(NULL, socket_id, &client->sockets, &gsock,
-	    tcp_free_sock_data);
-	if (rc != EOK) {
-		fibril_mutex_unlock(&socket->lock);
-		async_answer_0(callid, rc);
-		return;
-	}
-
-	fibril_mutex_unlock(&socket->lock);
-	async_answer_0(callid, EOK);
-}
-
-static void tcp_sock_getsockopt(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
-{
-	log_msg(LVL_DEBUG, "tcp_sock_getsockopt()");
-	async_answer_0(callid, ENOTSUP);
-}
-
-static void tcp_sock_setsockopt(tcp_client_t *client, ipc_callid_t callid, ipc_call_t call)
-{
-	log_msg(LVL_DEBUG, "tcp_sock_setsockopt()");
-	async_answer_0(callid, ENOTSUP);
-}
-
-/** Called when connection state changes. */
-static void tcp_sock_cstate_cb(tcp_conn_t *conn, void *arg)
-{
-	tcp_conn_status_t cstatus;
-	tcp_sock_lconn_t *lconn = (tcp_sock_lconn_t *)arg;
-	tcp_sockdata_t *socket = lconn->socket;
-
-	log_msg(LVL_DEBUG, "tcp_sock_cstate_cb()");
-	fibril_mutex_lock(&socket->lock);
-	assert(conn == lconn->conn);
-
-	tcp_uc_status(conn, &cstatus);
-	if (cstatus.cstate != st_established) {
-		fibril_mutex_unlock(&socket->lock);
-		return;
-	}
-
-	assert_link_not_used(&lconn->ready_list);
-	list_append(&lconn->ready_list, &socket->ready);
-
-	log_msg(LVL_DEBUG, "tcp_sock_cstate_cb(): notify accept");
-
-	/* Push one accept notification to client's queue */
-	tcp_sock_notify_aconn(socket->sock_core);
-	fibril_mutex_unlock(&socket->lock);
-}
-
-static void tcp_sock_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
-{
-	ipc_callid_t callid;
-	ipc_call_t call;
-	tcp_client_t client;
-
-	/* Accept the connection */
-	async_answer_0(iid, EOK);
-
-	client.sess = async_callback_receive(EXCHANGE_SERIALIZE);
-	socket_cores_initialize(&client.sockets);
-
-	while (true) {
-		callid = async_get_call(&call);
-		if (!IPC_GET_IMETHOD(call))
-			break;
-
-		log_msg(LVL_DEBUG, "tcp_sock_connection: METHOD=%d\n",
-		    (int)IPC_GET_IMETHOD(call));
-
-		switch (IPC_GET_IMETHOD(call)) {
-		case NET_SOCKET:
-			tcp_sock_socket(&client, callid, call);
-			break;
-		case NET_SOCKET_BIND:
-			tcp_sock_bind(&client, callid, call);
-			break;
-		case NET_SOCKET_LISTEN:
-			tcp_sock_listen(&client, callid, call);
-			break;
-		case NET_SOCKET_CONNECT:
-			tcp_sock_connect(&client, callid, call);
-			break;
-		case NET_SOCKET_ACCEPT:
-			tcp_sock_accept(&client, callid, call);
-			break;
-		case NET_SOCKET_SEND:
-			tcp_sock_send(&client, callid, call);
-			break;
-		case NET_SOCKET_SENDTO:
-			tcp_sock_sendto(&client, callid, call);
-			break;
-		case NET_SOCKET_RECV:
-		case NET_SOCKET_RECVFROM:
-			tcp_sock_recvfrom(&client, callid, call);
-			break;
-		case NET_SOCKET_CLOSE:
-			tcp_sock_close(&client, callid, call);
-			break;
-		case NET_SOCKET_GETSOCKOPT:
-			tcp_sock_getsockopt(&client, callid, call);
-			break;
-		case NET_SOCKET_SETSOCKOPT:
-			tcp_sock_setsockopt(&client, callid, call);
-			break;
-		default:
-			async_answer_0(callid, ENOTSUP);
-			break;
-		}
-	}
-}
-
-/**
- * @}
- */
Index: uspace/srv/tcp/sock.h
===================================================================
--- uspace/srv/tcp/sock.h	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(revision )
@@ -1,45 +1,0 @@
-/*
- * Copyright (c) 2011 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup tcp
- * @{
- */
-/** @file Socket provider
- */
-
-#ifndef SOCK_H
-#define SOCK_H
-
-#include <async.h>
-
-extern int tcp_sock_init(void);
-
-#endif
-
-/** @}
- */
Index: uspace/srv/tcp/std.h
===================================================================
--- uspace/srv/tcp/std.h	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(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: uspace/srv/tcp/tcp.c
===================================================================
--- uspace/srv/tcp/tcp.c	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(revision )
@@ -1,230 +1,0 @@
-/*
- * Copyright (c) 2012 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup tcp
- * @{
- */
-
-/**
- * @file TCP (Transmission Control Protocol) network module
- */
-
-#include <async.h>
-#include <bitops.h>
-#include <byteorder.h>
-#include <errno.h>
-#include <inet/inet.h>
-#include <io/log.h>
-#include <stdio.h>
-#include <task.h>
-
-#include "ncsim.h"
-#include "pdu.h"
-#include "rqueue.h"
-#include "sock.h"
-#include "std.h"
-#include "tcp.h"
-#include "test.h"
-
-#define NAME       "tcp"
-
-#define IP_PROTO_TCP 6
-
-static int tcp_inet_ev_recv(inet_dgram_t *dgram);
-static void tcp_received_pdu(tcp_pdu_t *pdu);
-
-static inet_ev_ops_t tcp_inet_ev_ops = {
-	.recv = tcp_inet_ev_recv
-};
-
-/** Received datagram callback */
-static int tcp_inet_ev_recv(inet_dgram_t *dgram)
-{
-	uint8_t *pdu_raw;
-	size_t pdu_raw_size;
-
-	log_msg(LVL_DEBUG, "tcp_inet_ev_recv()");
-
-	pdu_raw = dgram->data;
-	pdu_raw_size = dgram->size;
-
-	/* Split into header and payload. */
-
-	log_msg(LVL_DEBUG, "tcp_inet_ev_recv() - split header/payload");
-
-	tcp_pdu_t *pdu;
-	size_t hdr_size;
-	tcp_header_t *hdr;
-	uint32_t data_offset;
-
-	if (pdu_raw_size < sizeof(tcp_header_t)) {
-		log_msg(LVL_WARN, "pdu_raw_size = %zu < sizeof(tcp_header_t) = %zu",
-		    pdu_raw_size, sizeof(tcp_header_t));
-		return EINVAL;
-	}
-
-	hdr = (tcp_header_t *)pdu_raw;
-	data_offset = BIT_RANGE_EXTRACT(uint32_t, DF_DATA_OFFSET_h, DF_DATA_OFFSET_l,
-	    uint16_t_be2host(hdr->doff_flags));
-
-	hdr_size = sizeof(uint32_t) * data_offset;
-
-	if (pdu_raw_size < hdr_size) {
-		log_msg(LVL_WARN, "pdu_raw_size = %zu < hdr_size = %zu",
-		    pdu_raw_size, hdr_size);
-		return EINVAL;
-	}
-
-	if (hdr_size < sizeof(tcp_header_t)) {
-		log_msg(LVL_WARN, "hdr_size = %zu < sizeof(tcp_header_t) = %zu",
-		    hdr_size, sizeof(tcp_header_t));		return EINVAL;
-	}
-
-	log_msg(LVL_DEBUG, "pdu_raw_size=%zu, hdr_size=%zu",
-	    pdu_raw_size, hdr_size);
-	pdu = tcp_pdu_create(pdu_raw, hdr_size, pdu_raw + hdr_size,
-	    pdu_raw_size - hdr_size);
-	if (pdu == NULL) {
-		log_msg(LVL_WARN, "Failed creating PDU. Dropped.");
-		return ENOMEM;
-	}
-
-	pdu->src_addr.ipv4 = dgram->src.ipv4;
-	pdu->dest_addr.ipv4 = dgram->dest.ipv4;
-	log_msg(LVL_DEBUG, "src: 0x%08x, dest: 0x%08x",
-	    pdu->src_addr.ipv4, pdu->dest_addr.ipv4);
-
-	tcp_received_pdu(pdu);
-	tcp_pdu_delete(pdu);
-
-	return EOK;
-}
-
-/** Transmit PDU over network layer. */
-void tcp_transmit_pdu(tcp_pdu_t *pdu)
-{
-	int rc;
-	uint8_t *pdu_raw;
-	size_t pdu_raw_size;
-	inet_dgram_t dgram;
-
-	pdu_raw_size = pdu->header_size + pdu->text_size;
-	pdu_raw = malloc(pdu_raw_size);
-	if (pdu_raw == NULL) {
-		log_msg(LVL_ERROR, "Failed to transmit PDU. Out of memory.");
-		return;
-	}
-
-	memcpy(pdu_raw, pdu->header, pdu->header_size);
-	memcpy(pdu_raw + pdu->header_size, pdu->text,
-	    pdu->text_size);
-
-	dgram.src.ipv4 = pdu->src_addr.ipv4;
-	dgram.dest.ipv4 = pdu->dest_addr.ipv4;
-	dgram.tos = 0;
-	dgram.data = pdu_raw;
-	dgram.size = pdu_raw_size;
-
-	rc = inet_send(&dgram, INET_TTL_MAX, 0);
-	if (rc != EOK)
-		log_msg(LVL_ERROR, "Failed to transmit PDU.");
-}
-
-/** Process received PDU. */
-static void tcp_received_pdu(tcp_pdu_t *pdu)
-{
-	tcp_segment_t *dseg;
-	tcp_sockpair_t rident;
-
-	log_msg(LVL_DEBUG, "tcp_received_pdu()");
-
-	if (tcp_pdu_decode(pdu, &rident, &dseg) != EOK) {
-		log_msg(LVL_WARN, "Not enough memory. PDU dropped.");
-		return;
-	}
-
-	/* Insert decoded segment into rqueue */
-	tcp_rqueue_insert_seg(&rident, dseg);
-}
-
-static int tcp_init(void)
-{
-	int rc;
-
-	log_msg(LVL_DEBUG, "tcp_init()");
-
-	tcp_rqueue_init();
-	tcp_rqueue_thread_start();
-
-	tcp_ncsim_init();
-	tcp_ncsim_thread_start();
-
-	if (0) tcp_test();
-
-	rc = inet_init(IP_PROTO_TCP, &tcp_inet_ev_ops);
-	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed connecting to internet service.");
-		return ENOENT;
-	}
-
-	rc = tcp_sock_init();
-	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed initializing socket service.");
-		return ENOENT;
-	}
-
-	return EOK;
-}
-
-int main(int argc, char **argv)
-{
-	int rc;
-
-	printf(NAME ": TCP (Transmission Control Protocol) network module\n");
-
-	rc = log_init(NAME, LVL_DEBUG);
-	if (rc != EOK) {
-		printf(NAME ": Failed to initialize log.\n");
-		return 1;
-	}
-
-	rc = tcp_init();
-	if (rc != EOK)
-		return 1;
-
-	printf(NAME ": Accepting connections.\n");
-	task_retval(0);
-	async_manager();
-
-	/* Not reached */
-	return 0;
-}
-
-/**
- * @}
- */
Index: uspace/srv/tcp/tcp.h
===================================================================
--- uspace/srv/tcp/tcp.h	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(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 TCP (Transmission Control Protocol) network module
- */
-
-#ifndef TCP_H
-#define TCP_H
-
-#include <async.h>
-#include "tcp_type.h"
-
-extern void tcp_transmit_pdu(tcp_pdu_t *);
-
-#endif
-
-/** @}
- */
Index: uspace/srv/tcp/tcp_type.h
===================================================================
--- uspace/srv/tcp/tcp_type.h	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(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: uspace/srv/tcp/test.c
===================================================================
--- uspace/srv/tcp/test.c	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(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: uspace/srv/tcp/test.h
===================================================================
--- uspace/srv/tcp/test.h	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(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: uspace/srv/tcp/tqueue.c
===================================================================
--- uspace/srv/tcp/tqueue.c	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(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: uspace/srv/tcp/tqueue.h
===================================================================
--- uspace/srv/tcp/tqueue.h	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(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: uspace/srv/tcp/ucall.c
===================================================================
--- uspace/srv/tcp/ucall.c	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(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: uspace/srv/tcp/ucall.h
===================================================================
--- uspace/srv/tcp/ucall.h	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(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: uspace/srv/udp/Makefile
===================================================================
--- uspace/srv/udp/Makefile	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(revision )
@@ -1,43 +1,0 @@
-#
-# Copyright (c) 2012 Jiri Svoboda
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# - Redistributions of source code must retain the above copyright
-#   notice, this list of conditions and the following disclaimer.
-# - Redistributions in binary form must reproduce the above copyright
-#   notice, this list of conditions and the following disclaimer in the
-#   documentation and/or other materials provided with the distribution.
-# - The name of the author may not be used to endorse or promote products
-#   derived from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-
-USPACE_PREFIX = ../..
-LIBS = $(LIBNET_PREFIX)/libnet.a
-EXTRA_CFLAGS = -I$(LIBNET_PREFIX)/include
-BINARY = udp
-
-SOURCES = \
-	assoc.c \
-	msg.c \
-	sock.c \
-	pdu.c \
-	ucall.c \
-	udp.c \
-	udp_inet.c
-
-include $(USPACE_PREFIX)/Makefile.common
Index: uspace/srv/udp/assoc.c
===================================================================
--- uspace/srv/udp/assoc.c	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(revision )
@@ -1,411 +1,0 @@
-/*
- * Copyright (c) 2012 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup udp
- * @{
- */
-
-/**
- * @file UDP associations
- */
-
-#include <adt/list.h>
-#include <bool.h>
-#include <fibril_synch.h>
-#include <io/log.h>
-#include <stdlib.h>
-
-#include "assoc.h"
-#include "msg.h"
-#include "pdu.h"
-#include "ucall.h"
-#include "udp_inet.h"
-#include "udp_type.h"
-
-LIST_INITIALIZE(assoc_list);
-FIBRIL_MUTEX_INITIALIZE(assoc_list_lock);
-
-static udp_assoc_t *udp_assoc_find_ref(udp_sockpair_t *);
-static int udp_assoc_queue_msg(udp_assoc_t *, udp_sockpair_t *, udp_msg_t *);
-static bool udp_socket_match(udp_sock_t *, udp_sock_t *);
-static bool udp_sockpair_match(udp_sockpair_t *, udp_sockpair_t *);
-
-/** Create new association structure.
- *
- * @param lsock		Local socket (will be deeply copied)
- * @param fsock		Foreign socket (will be deeply copied)
- * @return		New association or NULL
- */
-udp_assoc_t *udp_assoc_new(udp_sock_t *lsock, udp_sock_t *fsock)
-{
-	udp_assoc_t *assoc = NULL;
-
-	/* Allocate association structure */
-	assoc = calloc(1, sizeof(udp_assoc_t));
-	if (assoc == NULL)
-		goto error;
-
-	fibril_mutex_initialize(&assoc->lock);
-
-	/* One for the user */
-	atomic_set(&assoc->refcnt, 1);
-
-	/* Initialize receive queue */
-	list_initialize(&assoc->rcv_queue);
-	fibril_condvar_initialize(&assoc->rcv_queue_cv);
-
-	if (lsock != NULL)
-		assoc->ident.local = *lsock;
-	if (fsock != NULL)
-		assoc->ident.foreign = *fsock;
-
-	return assoc;
-error:
-	return NULL;
-}
-
-/** Destroy association structure.
- *
- * Association structure should be destroyed when the folowing conditions
- * are met:
- * (1) user has deleted the association
- * (2) nobody is holding references to the association
- *
- * This happens when @a assoc->refcnt is zero as we count (1)
- * as an extra reference.
- *
- * @param assoc		Association
- */
-static void udp_assoc_free(udp_assoc_t *assoc)
-{
-	log_msg(LVL_DEBUG, "%s: udp_assoc_free(%p)", assoc->name, assoc);
-
-	while (!list_empty(&assoc->rcv_queue)) {
-		link_t *link = list_first(&assoc->rcv_queue);
-		udp_rcv_queue_entry_t *rqe = list_get_instance(link,
-		    udp_rcv_queue_entry_t, link);
-		list_remove(link);
-
-		udp_msg_delete(rqe->msg);
-		free(rqe);
-	}
-
-	free(assoc);
-}
-
-/** Add reference to association.
- *
- * Increase association reference count by one.
- *
- * @param assoc		Association
- */
-void udp_assoc_addref(udp_assoc_t *assoc)
-{
-	log_msg(LVL_DEBUG, "%s: upd_assoc_addref(%p)", assoc->name, assoc);
-	atomic_inc(&assoc->refcnt);
-}
-
-/** Remove reference from association.
- *
- * Decrease association reference count by one.
- *
- * @param assoc		Association
- */
-void udp_assoc_delref(udp_assoc_t *assoc)
-{
-	log_msg(LVL_DEBUG, "%s: udp_assoc_delref(%p)", assoc->name, assoc);
-
-	if (atomic_predec(&assoc->refcnt) == 0)
-		udp_assoc_free(assoc);
-}
-
-/** Delete association.
- *
- * The caller promises not make no further references to @a assoc.
- * UDP will free @a assoc eventually.
- *
- * @param assoc		Association
- */
-void udp_assoc_delete(udp_assoc_t *assoc)
-{
-	log_msg(LVL_DEBUG, "%s: udp_assoc_delete(%p)", assoc->name, assoc);
-
-	assert(assoc->deleted == false);
-	udp_assoc_delref(assoc);
-	assoc->deleted = true;
-}
-
-/** Enlist association.
- *
- * Add association to the association map.
- */
-void udp_assoc_add(udp_assoc_t *assoc)
-{
-	udp_assoc_addref(assoc);
-	fibril_mutex_lock(&assoc_list_lock);
-	list_append(&assoc->link, &assoc_list);
-	fibril_mutex_unlock(&assoc_list_lock);
-}
-
-/** Delist association.
- *
- * Remove association from the association map.
- */
-void udp_assoc_remove(udp_assoc_t *assoc)
-{
-	fibril_mutex_lock(&assoc_list_lock);
-	list_remove(&assoc->link);
-	fibril_mutex_unlock(&assoc_list_lock);
-	udp_assoc_delref(assoc);
-}
-
-/** Set foreign socket in association.
- *
- * @param assoc		Association
- * @param fsock		Foreign socket (deeply copied)
- */
-void udp_assoc_set_foreign(udp_assoc_t *assoc, udp_sock_t *fsock)
-{
-	log_msg(LVL_DEBUG, "udp_assoc_set_foreign(%p, %p)", assoc, fsock);
-	fibril_mutex_lock(&assoc->lock);
-	assoc->ident.foreign = *fsock;
-	fibril_mutex_unlock(&assoc->lock);
-}
-
-/** Set local socket in association.
- *
- * @param assoc		Association
- * @param fsock		Foreign socket (deeply copied)
- */
-void udp_assoc_set_local(udp_assoc_t *assoc, udp_sock_t *lsock)
-{
-	log_msg(LVL_DEBUG, "udp_assoc_set_local(%p, %p)", assoc, lsock);
-	fibril_mutex_lock(&assoc->lock);
-	assoc->ident.local = *lsock;
-	fibril_mutex_unlock(&assoc->lock);
-}
-
-/** Send message to association.
- *
- * @param assoc		Association
- * @param fsock		Foreign socket or NULL not to override @a assoc
- * @param msg		Message
- *
- * @return		EOK on success
- *			EINVAL if foreign socket is not set
- *			ENOMEM if out of resources
- *			EIO if no route to destination exists
- */
-int udp_assoc_send(udp_assoc_t *assoc, udp_sock_t *fsock, udp_msg_t *msg)
-{
-	udp_pdu_t *pdu;
-	udp_sockpair_t sp;
-	int rc;
-
-	log_msg(LVL_DEBUG, "udp_assoc_send(%p, %p, %p)",
-	    assoc, fsock, msg);
-
-	/* @a fsock can be used to override the foreign socket */
-	sp = assoc->ident;
-	if (fsock != NULL)
-		sp.foreign = *fsock;
-
-	if (sp.foreign.addr.ipv4 == 0 || sp.foreign.port == 0)
-		return EINVAL;
-
-	rc = udp_pdu_encode(&sp, msg, &pdu);
-	if (rc != EOK)
-		return ENOMEM;
-
-	rc = udp_transmit_pdu(pdu);
-	if (rc != EOK)
-		return EIO;
-
-	udp_pdu_delete(pdu);
-
-	return EOK;
-}
-
-/** Get a received message.
- *
- * Pull one message from the association's receive queue.
- */
-int udp_assoc_recv(udp_assoc_t *assoc, udp_msg_t **msg, udp_sock_t *fsock)
-{
-	link_t *link;
-	udp_rcv_queue_entry_t *rqe;
-
-	log_msg(LVL_DEBUG, "udp_assoc_recv()");
-
-	fibril_mutex_lock(&assoc->lock);
-	while (list_empty(&assoc->rcv_queue)) {
-		log_msg(LVL_DEBUG, "udp_assoc_recv() - waiting");
-		fibril_condvar_wait(&assoc->rcv_queue_cv, &assoc->lock);
-	}
-
-	log_msg(LVL_DEBUG, "udp_assoc_recv() - got a message");
-	link = list_first(&assoc->rcv_queue);
-	rqe = list_get_instance(link, udp_rcv_queue_entry_t, link);
-	list_remove(link);
-	fibril_mutex_unlock(&assoc->lock);
-
-	*msg = rqe->msg;
-	*fsock = rqe->sp.foreign;
-	free(rqe);
-
-	return EOK;
-}
-
-/** Message received.
- *
- * Find the association to which the message belongs and queue it.
- */
-void udp_assoc_received(udp_sockpair_t *rsp, udp_msg_t *msg)
-{
-	udp_assoc_t *assoc;
-	int rc;
-
-	log_msg(LVL_DEBUG, "udp_assoc_received(%p, %p)", rsp, msg);
-
-	assoc = udp_assoc_find_ref(rsp);
-	if (assoc == NULL) {
-		log_msg(LVL_DEBUG, "No association found. Message dropped.");
-		/* XXX Generate ICMP error. */
-		/* XXX Might propagate error directly by error return. */
-		return;
-	}
-
-	rc = udp_assoc_queue_msg(assoc, rsp, msg);
-	if (rc != EOK) {
-		log_msg(LVL_DEBUG, "Out of memory. Message dropped.");
-		/* XXX Generate ICMP error? */
-	}
-}
-
-static int udp_assoc_queue_msg(udp_assoc_t *assoc, udp_sockpair_t *sp,
-    udp_msg_t *msg)
-{
-	udp_rcv_queue_entry_t *rqe;
-
-	log_msg(LVL_DEBUG, "udp_assoc_queue_msg(%p, %p, %p)",
-	    assoc, sp, msg);
-
-	rqe = calloc(1, sizeof(udp_rcv_queue_entry_t));
-	if (rqe == NULL)
-		return ENOMEM;
-
-	link_initialize(&rqe->link);
-	rqe->sp = *sp;
-	rqe->msg = msg;
-
-	fibril_mutex_lock(&assoc->lock);
-	list_append(&rqe->link, &assoc->rcv_queue);
-	fibril_mutex_unlock(&assoc->lock);
-
-	fibril_condvar_broadcast(&assoc->rcv_queue_cv);
-
-	return EOK;
-}
-
-/** Match socket with pattern. */
-static bool udp_socket_match(udp_sock_t *sock, udp_sock_t *patt)
-{
-	log_msg(LVL_DEBUG, "udp_socket_match(sock=(%x,%u), pat=(%x,%u))",
-	    sock->addr.ipv4, sock->port, patt->addr.ipv4, patt->port);
-
-	if (patt->addr.ipv4 != UDP_IPV4_ANY &&
-	    patt->addr.ipv4 != sock->addr.ipv4)
-		return false;
-
-	if (patt->port != UDP_PORT_ANY &&
-	    patt->port != sock->port)
-		return false;
-
-	log_msg(LVL_DEBUG, " -> match");
-
-	return true;
-}
-
-/** Match socket pair with pattern. */
-static bool udp_sockpair_match(udp_sockpair_t *sp, udp_sockpair_t *pattern)
-{
-	log_msg(LVL_DEBUG, "udp_sockpair_match(%p, %p)", sp, pattern);
-
-	if (!udp_socket_match(&sp->local, &pattern->local))
-		return false;
-
-	if (!udp_socket_match(&sp->foreign, &pattern->foreign))
-		return false;
-
-	log_msg(LVL_DEBUG, "Socket pair matched.");
-	return true;
-}
-
-
-/** Find association structure for specified socket pair.
- *
- * An association is uniquely identified by a socket pair. Look up our
- * association map and return association structure based on socket pair.
- * The association reference count is bumped by one.
- *
- * @param sp	Socket pair
- * @return	Association structure or NULL if not found.
- */
-static udp_assoc_t *udp_assoc_find_ref(udp_sockpair_t *sp)
-{
-	log_msg(LVL_DEBUG, "udp_assoc_find_ref(%p)", sp);
-
-	fibril_mutex_lock(&assoc_list_lock);
-
-	list_foreach(assoc_list, link) {
-		udp_assoc_t *assoc = list_get_instance(link, udp_assoc_t, link);
-		udp_sockpair_t *asp = &assoc->ident;
-		log_msg(LVL_DEBUG, "compare with assoc (f:(%x,%u), l:(%x,%u))",
-		    asp->foreign.addr.ipv4, asp->foreign.port,
-		    asp->local.addr.ipv4, asp->local.port);
-
-		/* Skip unbound associations */
-		if (asp->local.port == UDP_PORT_ANY)
-			continue;
-
-		if (udp_sockpair_match(sp, asp)) {
-			log_msg(LVL_DEBUG, "Returning assoc %p", assoc);
-			udp_assoc_addref(assoc);
-			fibril_mutex_unlock(&assoc_list_lock);
-			return assoc;
-		}
-	}
-
-	fibril_mutex_unlock(&assoc_list_lock);
-	return NULL;
-}
-
-
-/**
- * @}
- */
Index: uspace/srv/udp/assoc.h
===================================================================
--- uspace/srv/udp/assoc.h	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(revision )
@@ -1,57 +1,0 @@
-/*
- * Copyright (c) 2012 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup udp
- * @{
- */
-/** @file UDP associations
- */
-
-#ifndef ASSOC_H
-#define ASSOC_H
-
-#include <sys/types.h>
-#include "udp_type.h"
-
-extern udp_assoc_t *udp_assoc_new(udp_sock_t *, udp_sock_t *);
-extern void udp_assoc_delete(udp_assoc_t *);
-extern void udp_assoc_add(udp_assoc_t *);
-extern void udp_assoc_remove(udp_assoc_t *);
-extern void udp_assoc_addref(udp_assoc_t *);
-extern void udp_assoc_delref(udp_assoc_t *);
-extern void udp_assoc_set_foreign(udp_assoc_t *, udp_sock_t *);
-extern void udp_assoc_set_local(udp_assoc_t *, udp_sock_t *);
-extern int udp_assoc_send(udp_assoc_t *, udp_sock_t *, udp_msg_t *);
-extern int udp_assoc_recv(udp_assoc_t *, udp_msg_t **, udp_sock_t *);
-extern void udp_assoc_received(udp_sockpair_t *, udp_msg_t *);
-
-
-#endif
-
-/** @}
- */
Index: uspace/srv/udp/msg.c
===================================================================
--- uspace/srv/udp/msg.c	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(revision )
@@ -1,57 +1,0 @@
-/*
- * Copyright (c) 2012 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup udp
- * @{
- */
-
-/**
- * @file UDP message
- */
-
-#include <io/log.h>
-#include <stdlib.h>
-
-#include "msg.h"
-#include "udp_type.h"
-
-/** Alocate new segment structure. */
-udp_msg_t *udp_msg_new(void)
-{
-	return calloc(1, sizeof(udp_msg_t));
-}
-
-/** Delete segment. */
-void udp_msg_delete(udp_msg_t *msg)
-{
-	free(msg);
-}
-
-/**
- * @}
- */
Index: uspace/srv/udp/msg.h
===================================================================
--- uspace/srv/udp/msg.h	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(revision )
@@ -1,46 +1,0 @@
-/*
- * Copyright (c) 2012 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup udp
- * @{
- */
-/** @file UDP message
- */
-
-#ifndef MSG_H
-#define MSG_H
-
-#include "udp_type.h"
-
-extern udp_msg_t *udp_msg_new(void);
-extern void udp_msg_delete(udp_msg_t *);
-
-#endif
-
-/** @}
- */
Index: uspace/srv/udp/pdu.c
===================================================================
--- uspace/srv/udp/pdu.c	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(revision )
@@ -1,210 +1,0 @@
-/*
- * Copyright (c) 2012 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup udp
- * @{
- */
-
-/**
- * @file UDP PDU encoding and decoding
- */
-
-#include <bitops.h>
-#include <byteorder.h>
-#include <errno.h>
-#include <mem.h>
-#include <stdlib.h>
-
-#include "msg.h"
-#include "pdu.h"
-#include "std.h"
-#include "udp_type.h"
-
-#define UDP_CHECKSUM_INIT 0xffff
-
-/** One's complement addition.
- *
- * Result is a + b + carry.
- */
-static uint16_t udp_ocadd16(uint16_t a, uint16_t b)
-{
-	uint32_t s;
-
-	s = (uint32_t)a + (uint32_t)b;
-	return (s & 0xffff) + (s >> 16);
-}
-
-static uint16_t udp_checksum_calc(uint16_t ivalue, void *data, size_t size)
-{
-	uint16_t sum;
-	uint16_t w;
-	size_t words, i;
-	uint8_t *bdata;
-
-	sum = ~ivalue;
-	words = size / 2;
-	bdata = (uint8_t *)data;
-
-	for (i = 0; i < words; i++) {
-		w = ((uint16_t)bdata[2*i] << 8) | bdata[2*i + 1];
-		sum = udp_ocadd16(sum, w);
-	}
-
-	if (size % 2 != 0) {
-		w = ((uint16_t)bdata[2*words] << 8);
-		sum = udp_ocadd16(sum, w);
-	}
-
-	return ~sum;
-}
-
-static void udp_phdr_setup(udp_pdu_t *pdu, udp_phdr_t *phdr)
-{
-	phdr->src_addr = host2uint32_t_be(pdu->src.ipv4);
-	phdr->dest_addr = host2uint32_t_be(pdu->dest.ipv4);
-	phdr->zero = 0;
-	phdr->protocol = IP_PROTO_UDP;
-	phdr->udp_length = host2uint16_t_be(pdu->data_size);
-}
-
-udp_pdu_t *udp_pdu_new(void)
-{
-	return calloc(1, sizeof(udp_pdu_t));
-}
-
-void udp_pdu_delete(udp_pdu_t *pdu)
-{
-	free(pdu->data);
-	free(pdu);
-}
-
-static uint16_t udp_pdu_checksum_calc(udp_pdu_t *pdu)
-{
-	uint16_t cs_phdr;
-	uint16_t cs_all;
-	udp_phdr_t phdr;
-
-	udp_phdr_setup(pdu, &phdr);
-	cs_phdr = udp_checksum_calc(UDP_CHECKSUM_INIT, (void *)&phdr,
-	    sizeof(udp_phdr_t));
-	cs_all = udp_checksum_calc(cs_phdr, pdu->data, pdu->data_size);
-
-	return cs_all;
-}
-
-static void udp_pdu_set_checksum(udp_pdu_t *pdu, uint16_t checksum)
-{
-	udp_header_t *hdr;
-
-	hdr = (udp_header_t *)pdu->data;
-	hdr->checksum = host2uint16_t_be(checksum);
-}
-
-/** Decode incoming PDU */
-int udp_pdu_decode(udp_pdu_t *pdu, udp_sockpair_t *sp, udp_msg_t **msg)
-{
-	udp_msg_t *nmsg;
-	udp_header_t *hdr;
-	void *text;
-	size_t text_size;
-	uint16_t length;
-	uint16_t checksum;
-
-	if (pdu->data_size < sizeof(udp_header_t))
-		return EINVAL;
-
-	text = pdu->data + sizeof(udp_header_t);
-	text_size = pdu->data_size - sizeof(udp_header_t);
-
-	hdr = (udp_header_t *)pdu->data;
-
-	sp->foreign.port = uint16_t_be2host(hdr->src_port);
-	sp->foreign.addr = pdu->src;
-	sp->local.port = uint16_t_be2host(hdr->dest_port);
-	sp->local.addr = pdu->dest;
-
-	length = uint16_t_be2host(hdr->length);
-	checksum = uint16_t_be2host(hdr->checksum);
-	(void) checksum;
-
-	if (length < sizeof(udp_header_t) ||
-	    length > sizeof(udp_header_t) + text_size)
-		return EINVAL;
-
-	nmsg = udp_msg_new();
-	if (nmsg == NULL)
-		return ENOMEM;
-
-	nmsg->data = text;
-	nmsg->data_size = length - sizeof(udp_header_t);
-
-	*msg = nmsg;
-	return EOK;
-}
-
-/** Encode outgoing PDU */
-int udp_pdu_encode(udp_sockpair_t *sp, udp_msg_t *msg, udp_pdu_t **pdu)
-{
-	udp_pdu_t *npdu;
-	udp_header_t *hdr;
-	uint16_t checksum;
-
-	npdu = udp_pdu_new();
-	if (npdu == NULL)
-		return ENOMEM;
-
-	npdu->src = sp->local.addr;
-	npdu->dest = sp->foreign.addr;
-
-	npdu->data_size = sizeof(udp_header_t) + msg->data_size;
-	npdu->data = calloc(1, npdu->data_size);
-	if (npdu->data == NULL) {
-		udp_pdu_delete(npdu);
-		return ENOMEM;
-	}
-
-	hdr = (udp_header_t *)npdu->data;
-	hdr->src_port = host2uint16_t_be(sp->local.port);
-	hdr->dest_port = host2uint16_t_be(sp->foreign.port);
-	hdr->length = host2uint16_t_be(npdu->data_size);
-	hdr->checksum = 0;
-
-	memcpy((uint8_t *)npdu->data + sizeof(udp_header_t), msg->data,
-	    msg->data_size);
-
-	/* Checksum calculation */
-	checksum = udp_pdu_checksum_calc(npdu);
-	udp_pdu_set_checksum(npdu, checksum);
-
-	*pdu = npdu;
-	return EOK;
-}
-
-/**
- * @}
- */
Index: uspace/srv/udp/pdu.h
===================================================================
--- uspace/srv/udp/pdu.h	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(revision )
@@ -1,50 +1,0 @@
-/*
- * Copyright (c) 2012 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup udp
- * @{
- */
-/** @file UDP PDU (encoded Protocol Data Unit) handling
- */
-
-#ifndef PDU_H
-#define PDU_H
-
-#include <sys/types.h>
-#include "std.h"
-#include "udp_type.h"
-
-extern udp_pdu_t *udp_pdu_new(void);
-extern void udp_pdu_delete(udp_pdu_t *);
-extern int udp_pdu_decode(udp_pdu_t *, udp_sockpair_t *, udp_msg_t **);
-extern int udp_pdu_encode(udp_sockpair_t *, udp_msg_t *, udp_pdu_t **);
-
-#endif
-
-/** @}
- */
Index: uspace/srv/udp/sock.c
===================================================================
--- uspace/srv/udp/sock.c	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(revision )
@@ -1,605 +1,0 @@
-/*
- * Copyright (c) 2008 Lukas Mejdrech
- * Copyright (c) 2012 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup udp
- * @{
- */
-
-/**
- * @file Socket provider
- */
-
-#include <async.h>
-#include <byteorder.h>
-#include <errno.h>
-#include <inet/inet.h>
-#include <io/log.h>
-#include <ipc/services.h>
-#include <ipc/socket.h>
-#include <net/modules.h>
-#include <net/socket.h>
-#include <ns.h>
-
-#include "sock.h"
-#include "std.h"
-#include "udp_type.h"
-#include "ucall.h"
-
-#define FRAGMENT_SIZE 1024
-
-/** Free ports pool start. */
-#define UDP_FREE_PORTS_START		1025
-
-/** Free ports pool end. */
-#define UDP_FREE_PORTS_END		65535
-
-static int last_used_port = UDP_FREE_PORTS_START - 1;
-static socket_ports_t gsock;
-
-static void udp_sock_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg);
-
-int udp_sock_init(void)
-{
-	int rc;
-
-	socket_ports_initialize(&gsock);
-
-	async_set_client_connection(udp_sock_connection);
-
-	rc = service_register(SERVICE_UDP);
-	if (rc != EOK)
-		return EEXIST;
-
-	return EOK;
-}
-
-static void udp_free_sock_data(socket_core_t *sock_core)
-{
-	udp_sockdata_t *socket;
-
-	socket = (udp_sockdata_t *)sock_core->specific_data;
-	(void)socket;
-}
-
-static void udp_sock_notify_data(socket_core_t *sock_core)
-{
-	log_msg(LVL_DEBUG, "udp_sock_notify_data(%d)", sock_core->socket_id);
-	async_exch_t *exch = async_exchange_begin(sock_core->sess);
-	async_msg_5(exch, NET_SOCKET_RECEIVED, (sysarg_t)sock_core->socket_id,
-	    FRAGMENT_SIZE, 0, 0, 1);
-	async_exchange_end(exch);
-}
-
-static void udp_sock_socket(udp_client_t *client, ipc_callid_t callid, ipc_call_t call)
-{
-	udp_sockdata_t *sock;
-	socket_core_t *sock_core;
-	int sock_id;
-	int rc;
-	ipc_call_t answer;
-
-	log_msg(LVL_DEBUG, "udp_sock_socket()");
-	sock = calloc(sizeof(udp_sockdata_t), 1);
-	if (sock == NULL) {
-		async_answer_0(callid, ENOMEM);
-		return;
-	}
-
-	fibril_mutex_initialize(&sock->lock);
-	sock->client = client;
-
-	rc = udp_uc_create(&sock->assoc);
-	if (rc != EOK) {
-		udp_uc_destroy(sock->assoc);
-		free(sock);
-		async_answer_0(callid, rc);
-		return;
-	}
-
-	sock_id = SOCKET_GET_SOCKET_ID(call);
-	rc = socket_create(&client->sockets, client->sess, sock, &sock_id);
-	if (rc != EOK) {
-		async_answer_0(callid, rc);
-		return;
-	}
-
-	sock_core = socket_cores_find(&client->sockets, sock_id);
-	assert(sock_core != NULL);
-	sock->sock_core = sock_core;
-
-
-	refresh_answer(&answer, NULL);
-	SOCKET_SET_SOCKET_ID(answer, sock_id);
-
-	SOCKET_SET_DATA_FRAGMENT_SIZE(answer, FRAGMENT_SIZE);
-	SOCKET_SET_HEADER_SIZE(answer, sizeof(udp_header_t));
-	answer_call(callid, EOK, &answer, 3);
-}
-
-static void udp_sock_bind(udp_client_t *client, ipc_callid_t callid, ipc_call_t call)
-{
-	int rc;
-	struct sockaddr_in *addr;
-	size_t addr_size;
-	socket_core_t *sock_core;
-	udp_sockdata_t *socket;
-	udp_sock_t fsock;
-	udp_error_t urc;
-
-	log_msg(LVL_DEBUG, "udp_sock_bind()");
-	log_msg(LVL_DEBUG, " - async_data_write_accept");
-
-	addr = NULL;
-
-	rc = async_data_write_accept((void **) &addr, false, 0, 0, 0, &addr_size);
-	if (rc != EOK) {
-		async_answer_0(callid, rc);
-		goto out;
-	}
-
-	log_msg(LVL_DEBUG, " - call socket_bind");
-	rc = socket_bind(&client->sockets, &gsock, SOCKET_GET_SOCKET_ID(call),
-	    addr, addr_size, UDP_FREE_PORTS_START, UDP_FREE_PORTS_END,
-	    last_used_port);
-	if (rc != EOK) {
-		async_answer_0(callid, rc);
-		goto out;
-	}
-
-	if (addr_size != sizeof(struct sockaddr_in)) {
-		async_answer_0(callid, EINVAL);
-		goto out;
-	}
-
-	log_msg(LVL_DEBUG, " - call socket_cores_find");
-	sock_core = socket_cores_find(&client->sockets, SOCKET_GET_SOCKET_ID(call));
-	if (sock_core == NULL) {
-		async_answer_0(callid, ENOENT);
-		goto out;
-	}
-
-	socket = (udp_sockdata_t *)sock_core->specific_data;
-
-	fsock.addr.ipv4 = uint32_t_be2host(addr->sin_addr.s_addr);
-	fsock.port = sock_core->port;
-	urc = udp_uc_set_local(socket->assoc, &fsock);
-
-	switch (urc) {
-	case UDP_EOK:
-		rc = EOK;
-		break;
-/*	case TCP_ENOTEXIST:
-		rc = ENOTCONN;
-		break;
-	case TCP_ECLOSING:
-		rc = ENOTCONN;
-		break;
-	case TCP_ERESET:
-		rc = ECONNABORTED;
-		break;*/
-	default:
-		assert(false);
-	}
-
-	udp_sock_notify_data(sock_core);
-
-	log_msg(LVL_DEBUG, " - success");
-	async_answer_0(callid, rc);
-out:
-	if (addr != NULL)
-		free(addr);
-}
-
-static void udp_sock_listen(udp_client_t *client, ipc_callid_t callid, ipc_call_t call)
-{
-	log_msg(LVL_DEBUG, "udp_sock_listen()");
-	async_answer_0(callid, ENOTSUP);
-}
-
-static void udp_sock_connect(udp_client_t *client, ipc_callid_t callid, ipc_call_t call)
-{
-	log_msg(LVL_DEBUG, "udp_sock_connect()");
-	async_answer_0(callid, ENOTSUP);
-}
-
-static void udp_sock_accept(udp_client_t *client, ipc_callid_t callid, ipc_call_t call)
-{
-	log_msg(LVL_DEBUG, "udp_sock_accept()");
-	async_answer_0(callid, ENOTSUP);
-}
-
-static void udp_sock_sendto(udp_client_t *client, ipc_callid_t callid, ipc_call_t call)
-{
-	int socket_id;
-	int fragments;
-	int index;
-	struct sockaddr_in *addr;
-	size_t addr_size;
-	socket_core_t *sock_core;
-	udp_sockdata_t *socket;
-	udp_sock_t fsock, *fsockp;
-	ipc_call_t answer;
-	ipc_callid_t wcallid;
-	size_t length;
-	uint8_t buffer[FRAGMENT_SIZE];
-	udp_error_t urc;
-	int rc;
-
-	log_msg(LVL_DEBUG, "udp_sock_send()");
-
-	addr = NULL;
-
-	if (IPC_GET_IMETHOD(call) == NET_SOCKET_SENDTO) {
-		rc = async_data_write_accept((void **) &addr, false,
-		    0, 0, 0, &addr_size);
-		if (rc != EOK) {
-			async_answer_0(callid, rc);
-			goto out;
-		}
-
-		if (addr_size != sizeof(struct sockaddr_in)) {
-			async_answer_0(callid, EINVAL);
-			goto out;
-		}
-
-		fsock.addr.ipv4 = uint32_t_be2host(addr->sin_addr.s_addr);
-		fsock.port = uint16_t_be2host(addr->sin_port);
-		fsockp = &fsock;
-	} else {
-		fsockp = NULL;
-	}
-
-	socket_id = SOCKET_GET_SOCKET_ID(call);
-	fragments = SOCKET_GET_DATA_FRAGMENTS(call);
-	SOCKET_GET_FLAGS(call);
-
-	sock_core = socket_cores_find(&client->sockets, socket_id);
-	if (sock_core == NULL) {
-		async_answer_0(callid, ENOTSOCK);
-		goto out;
-	}
-
-	if (sock_core->port == 0) {
-		/* Implicitly bind socket to port */
-		rc = socket_bind(&client->sockets, &gsock, SOCKET_GET_SOCKET_ID(call),
-		    addr, addr_size, UDP_FREE_PORTS_START, UDP_FREE_PORTS_END,
-		    last_used_port);
-		if (rc != EOK) {
-			async_answer_0(callid, rc);
-			goto out;
-		}
-
-		udp_sock_notify_data(sock_core);
-	}
-
-	socket = (udp_sockdata_t *)sock_core->specific_data;
-	fibril_mutex_lock(&socket->lock);
-
-	if (socket->assoc->ident.local.addr.ipv4 == UDP_IPV4_ANY) {
-		/* Determine local IP address */
-		inet_addr_t loc_addr, rem_addr;
-
-		rem_addr.ipv4 = fsockp ? fsock.addr.ipv4 :
-		    socket->assoc->ident.foreign.addr.ipv4;
-
-		rc = inet_get_srcaddr(&rem_addr, 0, &loc_addr);
-		if (rc != EOK) {
-			fibril_mutex_unlock(&socket->lock);
-			async_answer_0(callid, rc);
-			log_msg(LVL_DEBUG, "udp_sock_sendto: Failed to "
-			    "determine local address.");
-			return;
-		}
-
-		socket->assoc->ident.local.addr.ipv4 = loc_addr.ipv4;
-		log_msg(LVL_DEBUG, "Local IP address is %x",
-		    socket->assoc->ident.local.addr.ipv4);
-	}
-
-
-	assert(socket->assoc != NULL);
-
-	for (index = 0; index < fragments; index++) {
-		if (!async_data_write_receive(&wcallid, &length)) {
-			fibril_mutex_unlock(&socket->lock);
-			async_answer_0(callid, EINVAL);
-			goto out;
-		}
-
-		if (length > FRAGMENT_SIZE)
-			length = FRAGMENT_SIZE;
-
-		rc = async_data_write_finalize(wcallid, buffer, length);
-		if (rc != EOK) {
-			fibril_mutex_unlock(&socket->lock);
-			async_answer_0(callid, rc);
-			goto out;
-		}
-
-		urc = udp_uc_send(socket->assoc, fsockp, buffer, length, 0);
-
-		switch (urc) {
-		case UDP_EOK:
-			rc = EOK;
-			break;
-/*		case TCP_ENOTEXIST:
-			rc = ENOTCONN;
-			break;
-		case TCP_ECLOSING:
-			rc = ENOTCONN;
-			break;
-		case TCP_ERESET:
-			rc = ECONNABORTED;
-			break;*/
-		default:
-			assert(false);
-		}
-
-		if (rc != EOK) {
-			fibril_mutex_unlock(&socket->lock);
-			async_answer_0(callid, rc);
-			goto out;
-		}
-	}
-
-	refresh_answer(&answer, NULL);
-	SOCKET_SET_DATA_FRAGMENT_SIZE(answer, FRAGMENT_SIZE);
-	answer_call(callid, EOK, &answer, 2);
-	fibril_mutex_unlock(&socket->lock);
-out:
-	if (addr != NULL)
-		free(addr);
-}
-
-static void udp_sock_recvfrom(udp_client_t *client, ipc_callid_t callid, ipc_call_t call)
-{
-	int socket_id;
-	int flags;
-	size_t addr_length, length;
-	socket_core_t *sock_core;
-	udp_sockdata_t *socket;
-	ipc_call_t answer;
-	ipc_callid_t rcallid;
-	uint8_t buffer[FRAGMENT_SIZE];
-	size_t data_len;
-	xflags_t xflags;
-	udp_error_t urc;
-	struct sockaddr_in addr;
-	udp_sock_t rsock;
-	int rc;
-
-	log_msg(LVL_DEBUG, "%p: udp_sock_recv[from]()", client);
-
-	socket_id = SOCKET_GET_SOCKET_ID(call);
-	flags = SOCKET_GET_FLAGS(call);
-
-	sock_core = socket_cores_find(&client->sockets, socket_id);
-	if (sock_core == NULL) {
-		async_answer_0(callid, ENOTSOCK);
-		return;
-	}
-
-	socket = (udp_sockdata_t *)sock_core->specific_data;
-	fibril_mutex_lock(&socket->lock);
-
-	if (socket->assoc == NULL) {
-		fibril_mutex_unlock(&socket->lock);
-		async_answer_0(callid, ENOTCONN);
-		return;
-	}
-
-	(void)flags;
-
-	urc = udp_uc_receive(socket->assoc, buffer, FRAGMENT_SIZE, &data_len,
-	    &xflags, &rsock);
-	log_msg(LVL_DEBUG, "**** udp_uc_receive done, data_len=%zu", data_len);
-
-	switch (urc) {
-	case UDP_EOK:
-		rc = EOK;
-		break;
-/*	case TCP_ENOTEXIST:
-	case TCP_ECLOSING:
-		rc = ENOTCONN;
-		break;
-	case TCP_ERESET:
-		rc = ECONNABORTED;
-		break;*/
-	default:
-		assert(false);
-	}
-
-	log_msg(LVL_DEBUG, "**** udp_uc_receive -> %d", rc);
-	if (rc != EOK) {
-		fibril_mutex_unlock(&socket->lock);
-		async_answer_0(callid, rc);
-		return;
-	}
-
-	if (IPC_GET_IMETHOD(call) == NET_SOCKET_RECVFROM) {
-		/* Fill addr */
-		addr.sin_family = AF_INET;
-		addr.sin_addr.s_addr = host2uint32_t_be(rsock.addr.ipv4);
-		addr.sin_port = host2uint16_t_be(rsock.port);
-
-		log_msg(LVL_DEBUG, "addr read receive");
-		if (!async_data_read_receive(&rcallid, &addr_length)) {
-			fibril_mutex_unlock(&socket->lock);
-			async_answer_0(callid, EINVAL);
-			return;
-		}
-
-		if (addr_length > sizeof(addr))
-			addr_length = sizeof(addr);
-
-		log_msg(LVL_DEBUG, "addr read finalize");
-		rc = async_data_read_finalize(rcallid, &addr, addr_length);
-		if (rc != EOK) {
-			fibril_mutex_unlock(&socket->lock);
-			async_answer_0(callid, EINVAL);
-			return;
-		}
-	}
-
-	log_msg(LVL_DEBUG, "data read receive");
-	if (!async_data_read_receive(&rcallid, &length)) {
-		fibril_mutex_unlock(&socket->lock);
-		async_answer_0(callid, EINVAL);
-		return;
-	}
-
-	if (length > data_len)
-		length = data_len;
-
-	log_msg(LVL_DEBUG, "data read finalize");
-	rc = async_data_read_finalize(rcallid, buffer, length);
-
-	if (length < data_len && rc == EOK)
-		rc = EOVERFLOW;
-
-	log_msg(LVL_DEBUG, "read_data_length <- %zu", length);
-	SOCKET_SET_READ_DATA_LENGTH(answer, length);
-	SOCKET_SET_ADDRESS_LENGTH(answer, sizeof(addr));
-	answer_call(callid, EOK, &answer, 3);
-
-	/* Push one fragment notification to client's queue */
-	udp_sock_notify_data(sock_core);
-	fibril_mutex_unlock(&socket->lock);
-}
-
-static void udp_sock_close(udp_client_t *client, ipc_callid_t callid, ipc_call_t call)
-{
-	int socket_id;
-	socket_core_t *sock_core;
-	udp_sockdata_t *socket;
-	int rc;
-
-	log_msg(LVL_DEBUG, "tcp_sock_close()");
-	socket_id = SOCKET_GET_SOCKET_ID(call);
-
-	sock_core = socket_cores_find(&client->sockets, socket_id);
-	if (sock_core == NULL) {
-		async_answer_0(callid, ENOTSOCK);
-		return;
-	}
-
-	socket = (udp_sockdata_t *)sock_core->specific_data;
-	fibril_mutex_lock(&socket->lock);
-
-	assert(socket->assoc != NULL);
-	udp_uc_destroy(socket->assoc);
-
-	rc = socket_destroy(NULL, socket_id, &client->sockets, &gsock,
-	    udp_free_sock_data);
-	if (rc != EOK) {
-		fibril_mutex_unlock(&socket->lock);
-		async_answer_0(callid, rc);
-		return;
-	}
-
-	fibril_mutex_unlock(&socket->lock);
-	async_answer_0(callid, EOK);
-}
-
-static void udp_sock_getsockopt(udp_client_t *client, ipc_callid_t callid, ipc_call_t call)
-{
-	log_msg(LVL_DEBUG, "udp_sock_getsockopt()");
-	async_answer_0(callid, ENOTSUP);
-}
-
-static void udp_sock_setsockopt(udp_client_t *client, ipc_callid_t callid, ipc_call_t call)
-{
-	log_msg(LVL_DEBUG, "udp_sock_setsockopt()");
-	async_answer_0(callid, ENOTSUP);
-}
-
-static void udp_sock_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg)
-{
-	ipc_callid_t callid;
-	ipc_call_t call;
-	udp_client_t client;
-
-	/* Accept the connection */
-	async_answer_0(iid, EOK);
-
-	client.sess = async_callback_receive(EXCHANGE_SERIALIZE);
-	socket_cores_initialize(&client.sockets);
-
-	while (true) {
-		log_msg(LVL_DEBUG, "udp_sock_connection: wait");
-		callid = async_get_call(&call);
-		if (!IPC_GET_IMETHOD(call))
-			break;
-
-		log_msg(LVL_DEBUG, "udp_sock_connection: METHOD=%d",
-		    (int)IPC_GET_IMETHOD(call));
-
-		switch (IPC_GET_IMETHOD(call)) {
-		case NET_SOCKET:
-			udp_sock_socket(&client, callid, call);
-			break;
-		case NET_SOCKET_BIND:
-			udp_sock_bind(&client, callid, call);
-			break;
-		case NET_SOCKET_LISTEN:
-			udp_sock_listen(&client, callid, call);
-			break;
-		case NET_SOCKET_CONNECT:
-			udp_sock_connect(&client, callid, call);
-			break;
-		case NET_SOCKET_ACCEPT:
-			udp_sock_accept(&client, callid, call);
-			break;
-		case NET_SOCKET_SEND:
-		case NET_SOCKET_SENDTO:
-			udp_sock_sendto(&client, callid, call);
-			break;
-		case NET_SOCKET_RECV:
-		case NET_SOCKET_RECVFROM:
-			udp_sock_recvfrom(&client, callid, call);
-			break;
-		case NET_SOCKET_CLOSE:
-			udp_sock_close(&client, callid, call);
-			break;
-		case NET_SOCKET_GETSOCKOPT:
-			udp_sock_getsockopt(&client, callid, call);
-			break;
-		case NET_SOCKET_SETSOCKOPT:
-			udp_sock_setsockopt(&client, callid, call);
-			break;
-		default:
-			async_answer_0(callid, ENOTSUP);
-			break;
-		}
-	}
-}
-
-/**
- * @}
- */
Index: uspace/srv/udp/sock.h
===================================================================
--- uspace/srv/udp/sock.h	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(revision )
@@ -1,45 +1,0 @@
-/*
- * Copyright (c) 2012 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup udp
- * @{
- */
-/** @file Socket provider
- */
-
-#ifndef SOCK_H
-#define SOCK_H
-
-#include <async.h>
-
-extern int udp_sock_init(void);
-
-#endif
-
-/** @}
- */
Index: uspace/srv/udp/std.h
===================================================================
--- uspace/srv/udp/std.h	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(revision )
@@ -1,73 +1,0 @@
-/*
- * Copyright (c) 2012 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup udp
- * @{
- */
-/** @file UDP standard definitions
- *
- * Based on IETF RFC 768
- */
-
-#ifndef STD_H
-#define STD_H
-
-#include <sys/types.h>
-
-#define IP_PROTO_UDP 17
-
-/** UDP Header */
-typedef struct {
-	/** Source port */
-	uint16_t src_port;
-	/** Destination port */
-	uint16_t dest_port;
-	/** Length (header + data) */
-	uint16_t length;
-	/* Checksum */
-	uint16_t checksum;
-} udp_header_t;
-
-/** UDP pseudo header */
-typedef struct {
-	/** Source address */
-	uint32_t src_addr;
-	/** Destination address */
-	uint32_t dest_addr;
-	/** Zero */
-	uint8_t zero;
-	/** Protocol */
-	uint8_t protocol;
-	/** TCP length */
-	uint16_t udp_length;
-} udp_phdr_t;
-
-#endif
-
-/** @}
- */
Index: uspace/srv/udp/ucall.c
===================================================================
--- uspace/srv/udp/ucall.c	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(revision )
@@ -1,133 +1,0 @@
-/*
- * Copyright (c) 2012 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup tcp
- * @{
- */
-
-/**
- * @file UDP user calls
- */
-
-#include <io/log.h>
-#include <macros.h>
-
-#include "assoc.h"
-#include "msg.h"
-#include "udp_type.h"
-#include "ucall.h"
-
-udp_error_t udp_uc_create(udp_assoc_t **assoc)
-{
-	udp_assoc_t *nassoc;
-
-	log_msg(LVL_DEBUG, "udp_uc_create()");
-	nassoc = udp_assoc_new(NULL, NULL);
-	if (nassoc == NULL)
-		return UDP_ENORES;
-
-	udp_assoc_add(nassoc);
-	*assoc = nassoc;
-	return UDP_EOK;
-}
-
-udp_error_t udp_uc_set_foreign(udp_assoc_t *assoc, udp_sock_t *fsock)
-{
-	log_msg(LVL_DEBUG, "udp_uc_set_foreign(%p, %p)", assoc, fsock);
-
-	udp_assoc_set_foreign(assoc, fsock);
-	return UDP_EOK;
-}
-
-udp_error_t udp_uc_set_local(udp_assoc_t *assoc, udp_sock_t *lsock)
-{
-	log_msg(LVL_DEBUG, "udp_uc_set_local(%p, %p)", assoc, lsock);
-
-	udp_assoc_set_local(assoc, lsock);
-	return UDP_EOK;
-}
-
-udp_error_t udp_uc_send(udp_assoc_t *assoc, udp_sock_t *fsock, void *data,
-    size_t size, xflags_t flags)
-{
-	int rc;
-	udp_msg_t msg;
-
-	log_msg(LVL_DEBUG, "%s: udp_uc_send()", assoc->name);
-
-	msg.data = data;
-	msg.data_size = size;
-
-	rc = udp_assoc_send(assoc, fsock, &msg);
-	switch (rc) {
-	case ENOMEM:
-		return UDP_ENORES;
-	case EINVAL:
-		return UDP_EUNSPEC;
-	case EIO:
-		return UDP_ENOROUTE;
-	}
-	return UDP_EOK;
-}
-
-udp_error_t udp_uc_receive(udp_assoc_t *assoc, void *buf, size_t size,
-    size_t *rcvd, xflags_t *xflags, udp_sock_t *fsock)
-{
-	size_t xfer_size;
-	udp_msg_t *msg;
-	int rc;
-
-	log_msg(LVL_DEBUG, "%s: udp_uc_receive()", assoc->name);
-	rc = udp_assoc_recv(assoc, &msg, fsock);
-	switch (rc) {
-	}
-
-	xfer_size = min(size, msg->data_size);
-	memcpy(buf, msg->data, xfer_size);
-	*rcvd = xfer_size;
-	udp_msg_delete(msg);
-
-	return UDP_EOK;
-}
-
-void udp_uc_status(udp_assoc_t *assoc, udp_assoc_status_t *astatus)
-{
-	log_msg(LVL_DEBUG, "udp_uc_status()");
-//	cstatus->cstate = conn->cstate;
-}
-
-void udp_uc_destroy(udp_assoc_t *assoc)
-{
-	log_msg(LVL_DEBUG, "udp_uc_destroy()");
-	udp_assoc_remove(assoc);
-	udp_assoc_delete(assoc);
-}
-
-/**
- * @}
- */
Index: uspace/srv/udp/ucall.h
===================================================================
--- uspace/srv/udp/ucall.h	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(revision )
@@ -1,54 +1,0 @@
-/*
- * Copyright (c) 2012 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup udp
- * @{
- */
-/** @file UDP user calls
- */
-
-#ifndef UCALL_H
-#define UCALL_H
-
-#include <sys/types.h>
-#include "udp_type.h"
-
-extern udp_error_t udp_uc_create(udp_assoc_t **);
-extern udp_error_t udp_uc_set_foreign(udp_assoc_t *, udp_sock_t *);
-extern udp_error_t udp_uc_set_local(udp_assoc_t *, udp_sock_t *);
-extern udp_error_t udp_uc_send(udp_assoc_t *, udp_sock_t *, void *, size_t,
-    xflags_t);
-extern udp_error_t udp_uc_receive(udp_assoc_t *, void *, size_t, size_t *,
-    xflags_t *, udp_sock_t *);
-extern void udp_uc_status(udp_assoc_t *, udp_assoc_status_t *);
-extern void udp_uc_destroy(udp_assoc_t *);
-
-#endif
-
-/** @}
- */
Index: uspace/srv/udp/udp.c
===================================================================
--- uspace/srv/udp/udp.c	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(revision )
@@ -1,95 +1,0 @@
-/*
- * Copyright (c) 2012 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup udp
- * @{
- */
-
-/**
- * @file UDP (User Datagram Protocol) service
- */
-
-#include <async.h>
-#include <errno.h>
-#include <io/log.h>
-#include <stdio.h>
-#include <task.h>
-
-#include "udp_inet.h"
-#include "sock.h"
-
-#define NAME       "udp"
-
-static int udp_init(void)
-{
-	int rc;
-
-	log_msg(LVL_DEBUG, "udp_init()");
-
-	rc = udp_inet_init();
-	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed connecting to internet service.");
-		return ENOENT;
-	}
-
-	rc = udp_sock_init();
-	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed initializing socket service.");
-		return ENOENT;
-	}
-
-	return EOK;
-}
-
-int main(int argc, char **argv)
-{
-	int rc;
-
-	printf(NAME ": UDP (User Datagram Protocol) service\n");
-
-	rc = log_init(NAME, LVL_DEBUG);
-	if (rc != EOK) {
-		printf(NAME ": Failed to initialize log.\n");
-		return 1;
-	}
-
-	rc = udp_init();
-	if (rc != EOK)
-		return 1;
-
-	printf(NAME ": Accepting connections.\n");
-	task_retval(0);
-	async_manager();
-
-	/* Not reached */
-	return 0;
-}
-
-/**
- * @}
- */
Index: uspace/srv/udp/udp_inet.c
===================================================================
--- uspace/srv/udp/udp_inet.c	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(revision )
@@ -1,139 +1,0 @@
-/*
- * Copyright (c) 2012 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup udp
- * @{
- */
-
-/**
- * @file
- */
-
-#include <bitops.h>
-#include <byteorder.h>
-#include <errno.h>
-#include <inet/inet.h>
-#include <io/log.h>
-#include <stdio.h>
-#include <task.h>
-
-#include "assoc.h"
-#include "pdu.h"
-#include "std.h"
-#include "udp_inet.h"
-#include "udp_type.h"
-
-static int udp_inet_ev_recv(inet_dgram_t *dgram);
-static void udp_received_pdu(udp_pdu_t *pdu);
-
-static inet_ev_ops_t udp_inet_ev_ops = {
-	.recv = udp_inet_ev_recv
-};
-
-/** Received datagram callback */
-static int udp_inet_ev_recv(inet_dgram_t *dgram)
-{
-	udp_pdu_t *pdu;
-
-	log_msg(LVL_DEBUG, "udp_inet_ev_recv()");
-
-	pdu = udp_pdu_new();
-	pdu->data = dgram->data;
-	pdu->data_size = dgram->size;
-
-	pdu->src.ipv4 = dgram->src.ipv4;
-	pdu->dest.ipv4 = dgram->dest.ipv4;
-	log_msg(LVL_DEBUG, "src: 0x%08x, dest: 0x%08x",
-	    pdu->src.ipv4, pdu->dest.ipv4);
-
-	udp_received_pdu(pdu);
-	udp_pdu_delete(pdu);
-
-	return EOK;
-}
-
-/** Transmit PDU over network layer. */
-int udp_transmit_pdu(udp_pdu_t *pdu)
-{
-	int rc;
-	inet_dgram_t dgram;
-
-	log_msg(LVL_DEBUG, "udp_transmit_pdu()");
-
-	dgram.src.ipv4 = pdu->src.ipv4;
-	dgram.dest.ipv4 = pdu->dest.ipv4;
-	dgram.tos = 0;
-	dgram.data = pdu->data;
-	dgram.size = pdu->data_size;
-
-	rc = inet_send(&dgram, INET_TTL_MAX, 0);
-	if (rc != EOK)
-		log_msg(LVL_ERROR, "Failed to transmit PDU.");
-
-	return rc;
-}
-
-/** Process received PDU. */
-static void udp_received_pdu(udp_pdu_t *pdu)
-{
-	udp_msg_t *dmsg;
-	udp_sockpair_t rident;
-
-	log_msg(LVL_DEBUG, "udp_received_pdu()");
-
-	if (udp_pdu_decode(pdu, &rident, &dmsg) != EOK) {
-		log_msg(LVL_WARN, "Not enough memory. PDU dropped.");
-		return;
-	}
-
-	/*
-	 * Insert decoded message into appropriate receive queue.
-	 * This transfers ownership of dmsg to the callee, we do not
-	 * free it.
-	 */
-	udp_assoc_received(&rident, dmsg);
-}
-
-int udp_inet_init(void)
-{
-	int rc;
-
-	log_msg(LVL_DEBUG, "udp_inet_init()");
-
-	rc = inet_init(IP_PROTO_UDP, &udp_inet_ev_ops);
-	if (rc != EOK) {
-		log_msg(LVL_ERROR, "Failed connecting to internet service.");
-		return ENOENT;
-	}
-
-	return EOK;
-}
-
-/**
- * @}
- */
Index: uspace/srv/udp/udp_inet.h
===================================================================
--- uspace/srv/udp/udp_inet.h	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(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 udp
- * @{
- */
-/** @file
- */
-
-#ifndef UDP_INET_H
-#define UDP_INET_H
-
-#include "udp_type.h"
-
-extern int udp_inet_init(void);
-extern int udp_transmit_pdu(udp_pdu_t *);
-
-#endif
-
-/** @}
- */
Index: uspace/srv/udp/udp_type.h
===================================================================
--- uspace/srv/udp/udp_type.h	(revision 7fda2e083e83e11956b6f1c016bf5aa164c3e1b1)
+++ 	(revision )
@@ -1,157 +1,0 @@
-/*
- * Copyright (c) 2012 Jiri Svoboda
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup udp
- * @{
- */
-/** @file UDP type definitions
- */
-
-#ifndef UDP_TYPE_H
-#define UDP_TYPE_H
-
-#include <fibril_synch.h>
-#include <socket_core.h>
-#include <sys/types.h>
-
-typedef enum {
-	UDP_EOK,
-	/* Insufficient resources */
-	UDP_ENORES,
-	/* Foreign socket unspecified */
-	UDP_EUNSPEC,
-	/* No route to destination */
-	UDP_ENOROUTE
-} udp_error_t;
-
-typedef enum {
-	XF_DUMMY	= 0x1
-} xflags_t;
-
-typedef struct {
-	uint32_t ipv4;
-} netaddr_t;
-
-enum netaddr {
-	UDP_IPV4_ANY = 0
-};
-
-enum tcp_port {
-	UDP_PORT_ANY = 0
-};
-
-typedef struct {
-	netaddr_t addr;
-	uint16_t port;
-} udp_sock_t;
-
-typedef struct {
-	udp_sock_t local;
-	udp_sock_t foreign;
-} udp_sockpair_t;
-
-/** Unencoded UDP message (datagram) */
-typedef struct {
-	/** Message data */
-	void *data;
-	/** Message data size */
-	size_t data_size;
-} udp_msg_t;
-
-/** Encoded PDU */
-typedef struct {
-	/** Source address */
-	netaddr_t src;
-	/** Destination address */
-	netaddr_t dest;
-
-	/** Encoded PDU data including header */
-	void *data;
-	/** Encoded PDU data size */
-	size_t data_size;
-} udp_pdu_t;
-
-typedef struct {
-	async_sess_t *sess;
-	socket_cores_t sockets;
-} udp_client_t;
-
-/** UDP association
- *
- * This is a rough equivalent of a TCP connection endpoint. It allows
- * sending and receiving UDP datagrams and it is uniquely identified
- * by a socket pair.
- */
-typedef struct {
-	char *name;
-	link_t link;
-
-	/** Association identification (local and foreign socket) */
-	udp_sockpair_t ident;
-
-	/** True if association was deleted by user */
-	bool deleted;
-
-	/** Protects access to association structure */
-	fibril_mutex_t lock;
-	/** Reference count */
-	atomic_t refcnt;
-
-	/** Receive queue */
-	list_t rcv_queue;
-	/** Receive queue CV. Broadcast when new datagram is inserted */
-	fibril_condvar_t rcv_queue_cv;
-} udp_assoc_t;
-
-typedef struct {
-} udp_assoc_status_t;
-
-typedef struct udp_sockdata {
-	/** Lock */
-	fibril_mutex_t lock;
-	/** Socket core */
-	socket_core_t *sock_core;
-	/** Client */
-	udp_client_t *client;
-	/** Connection */
-	udp_assoc_t *assoc;
-} udp_sockdata_t;
-
-typedef struct {
-	/** Link to receive queue */
-	link_t link;
-	/** Socket pair */
-	udp_sockpair_t sp;
-	/** Message */
-	udp_msg_t *msg;
-} udp_rcv_queue_entry_t;
-
-#endif
-
-/** @}
- */
