Index: uspace/lib/net/Makefile
===================================================================
--- uspace/lib/net/Makefile	(revision d52fbaf59e7bccbf3e5d682f5fafb0146f625e9f)
+++ uspace/lib/net/Makefile	(revision 0a866eebd91749e0380adb6b7af11e95a433af59)
@@ -35,5 +35,7 @@
 	generic/net_remote.c \
 	generic/net_checksum.c \
+	generic/packet_client.c \
 	generic/packet_remote.c \
+	generic/socket_core.c \
 	adt/module_map.c \
 	netif/netif_local.c \
Index: uspace/lib/net/generic/packet_client.c
===================================================================
--- uspace/lib/net/generic/packet_client.c	(revision 0a866eebd91749e0380adb6b7af11e95a433af59)
+++ uspace/lib/net/generic/packet_client.c	(revision 0a866eebd91749e0380adb6b7af11e95a433af59)
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup packet
+ *  @{
+ */
+
+/** @file
+ *  Packet client implementation.
+ */
+
+#include <errno.h>
+#include <mem.h>
+#include <unistd.h>
+
+#include <sys/mman.h>
+
+#include <packet_client.h>
+
+#include <net_messages.h>
+#include <packet/packet.h>
+#include <packet/packet_header.h>
+
+int packet_copy_data(packet_t packet, const void * data, size_t length)
+{
+	if (!packet_is_valid(packet))
+		return EINVAL;
+
+	if (packet->data_start + length >= packet->length)
+		return ENOMEM;
+
+	memcpy((void *) packet + packet->data_start, data, length);
+	if (packet->data_start + length > packet->data_end) 
+		packet->data_end = packet->data_start + length;
+
+	return EOK;
+}
+
+void *packet_prefix(packet_t packet, size_t length)
+{
+	if ((!packet_is_valid(packet)) ||
+	    (packet->data_start - sizeof(struct packet) -
+	    2 * (packet->dest_addr - packet->src_addr) < length)) {
+		return NULL;
+	}
+
+	packet->data_start -= length;
+	return (void *) packet + packet->data_start;
+}
+
+void *packet_suffix(packet_t packet, size_t length)
+{
+	if ((!packet_is_valid(packet)) ||
+	    (packet->data_end + length >= packet->length)) {
+		return NULL;
+	}
+
+	packet->data_end += length;
+	return (void *) packet + packet->data_end - length;
+}
+
+int packet_trim(packet_t packet, size_t prefix, size_t suffix)
+{
+	if (!packet_is_valid(packet))
+		return EINVAL;
+
+	if (prefix + suffix > PACKET_DATA_LENGTH(packet))
+		return ENOMEM;
+
+	packet->data_start += prefix;
+	packet->data_end -= suffix;
+	return EOK;
+}
+
+packet_id_t packet_get_id(const packet_t packet)
+{
+	return packet_is_valid(packet) ? packet->packet_id : 0;
+}
+
+int packet_get_addr(const packet_t packet, uint8_t ** src, uint8_t ** dest)
+{
+	if (!packet_is_valid(packet))
+		return EINVAL;
+	if (!packet->addr_len)
+		return 0;
+	if (src)
+		*src = (void *) packet + packet->src_addr;
+	if (dest)
+		*dest = (void *) packet + packet->dest_addr;
+
+	return packet->addr_len;
+}
+
+size_t packet_get_data_length(const packet_t packet)
+{
+	if (!packet_is_valid(packet))
+		return 0;
+
+	return PACKET_DATA_LENGTH(packet);
+}
+
+void *packet_get_data(const packet_t packet)
+{
+	if (!packet_is_valid(packet))
+		return NULL;
+
+	return (void *) packet + packet->data_start;
+}
+
+int
+packet_set_addr(packet_t packet, const uint8_t * src, const uint8_t * dest,
+    size_t addr_len)
+{
+	size_t padding;
+	size_t allocated;
+
+	if (!packet_is_valid(packet))
+		return EINVAL;
+
+	allocated = PACKET_MAX_ADDRESS_LENGTH(packet);
+	if (allocated < addr_len)
+		return ENOMEM;
+
+	padding = allocated - addr_len;
+	packet->addr_len = addr_len;
+
+	if (src) {
+		memcpy((void *) packet + packet->src_addr, src, addr_len);
+		if (padding)
+			bzero((void *) packet + packet->src_addr + addr_len,
+			    padding);
+	} else {
+		bzero((void *) packet + packet->src_addr, allocated);
+	}
+
+	if (dest) {
+		memcpy((void *) packet + packet->dest_addr, dest, addr_len);
+		if (padding)
+			bzero((void *) packet + packet->dest_addr + addr_len,
+			    padding);
+	} else {
+		bzero((void *) packet + packet->dest_addr, allocated);
+	}
+
+	return EOK;
+}
+
+packet_t packet_get_copy(int phone, packet_t packet)
+{
+	packet_t copy;
+	uint8_t * src = NULL;
+	uint8_t * dest = NULL;
+	size_t addrlen;
+
+	if (!packet_is_valid(packet))
+		return NULL;
+
+	// get a new packet
+	copy = packet_get_4_remote(phone, PACKET_DATA_LENGTH(packet),
+	    PACKET_MAX_ADDRESS_LENGTH(packet), packet->max_prefix,
+	    PACKET_MIN_SUFFIX(packet));
+	if (!copy)
+		return NULL;
+
+	// get addresses
+	addrlen = packet_get_addr(packet, &src, &dest);
+	// copy data
+	if ((packet_copy_data(copy, packet_get_data(packet),
+	    PACKET_DATA_LENGTH(packet)) == EOK) &&
+	    // copy addresses if present
+	    ((addrlen <= 0) ||
+	    (packet_set_addr(copy, src, dest, addrlen) == EOK))) {
+		copy->order = packet->order;
+		copy->metric = packet->metric;
+		return copy;
+	} else {
+		pq_release_remote(phone, copy->packet_id);
+		return NULL;
+	}
+}
+
+/** @}
+ */
Index: uspace/lib/net/generic/packet_remote.c
===================================================================
--- uspace/lib/net/generic/packet_remote.c	(revision d52fbaf59e7bccbf3e5d682f5fafb0146f625e9f)
+++ uspace/lib/net/generic/packet_remote.c	(revision 0a866eebd91749e0380adb6b7af11e95a433af59)
@@ -44,8 +44,9 @@
 
 #include <net_messages.h>
+#include <packet_client.h>
+#include <packet_remote.h>
+
 #include <packet/packet.h>
-#include <packet/packet_client.h>
 #include <packet/packet_header.h>
-#include <packet_remote.h>
 
 /** Obtain the packet from the packet server as the shared memory block.
Index: uspace/lib/net/generic/socket_core.c
===================================================================
--- uspace/lib/net/generic/socket_core.c	(revision 0a866eebd91749e0380adb6b7af11e95a433af59)
+++ uspace/lib/net/generic/socket_core.c	(revision 0a866eebd91749e0380adb6b7af11e95a433af59)
@@ -0,0 +1,478 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup socket
+ *  @{
+ */
+
+/** @file
+ *  Socket common core implementation.
+ */
+
+#include <net/socket_codes.h>
+#include <net/in.h>
+#include <net/inet.h>
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <err.h>
+
+#include <adt/dynamic_fifo.h>
+#include <adt/int_map.h>
+#include <packet/packet.h>
+#include <packet_client.h>
+#include <packet_remote.h>
+#include <net/modules.h>
+#include <socket_core.h>
+
+/** Maximum number of random attempts to find a new socket identifier before switching to the sequence.
+ */
+#define SOCKET_ID_TRIES					100
+
+/** Bound port sockets.
+ */
+struct socket_port{
+	/** The bound sockets map.
+	 */
+	socket_port_map_t map;
+	/** The bound sockets count.
+	 */
+	int count;
+};
+
+INT_MAP_IMPLEMENT(socket_cores, socket_core_t);
+
+GENERIC_CHAR_MAP_IMPLEMENT(socket_port_map, socket_core_ref);
+
+INT_MAP_IMPLEMENT(socket_ports, socket_port_t);
+
+/** Destroys the socket.
+ *  If the socket is bound, the port is released.
+ *  Releases all buffered packets, calls the release function and removes the socket from the local sockets.
+ *  @param[in] packet_phone The packet server phone to release buffered packets.
+ *  @param[in] socket The socket to be destroyed.
+ *  @param[in,out] local_sockets The local sockets to be updated.
+ *  @param[in,out] global_sockets The global sockets to be updated.
+ *  @param[in] socket_release The client release callback function.
+ */
+static void socket_destroy_core(int packet_phone, socket_core_ref socket, socket_cores_ref local_sockets, socket_ports_ref global_sockets, void (*socket_release)(socket_core_ref socket)){
+	int packet_id;
+
+	// if bound
+	if(socket->port){
+		// release the port
+		socket_port_release(global_sockets, socket);
+	}
+	// release all received packets
+	while((packet_id = dyn_fifo_pop(&socket->received)) >= 0){
+		pq_release_remote(packet_phone, packet_id);
+	}
+	dyn_fifo_destroy(&socket->received);
+	dyn_fifo_destroy(&socket->accepted);
+	if(socket_release){
+		socket_release(socket);
+	}
+	socket_cores_exclude(local_sockets, socket->socket_id);
+}
+
+void socket_cores_release(int packet_phone, socket_cores_ref local_sockets, socket_ports_ref global_sockets, void (*socket_release)(socket_core_ref socket)){
+	if(socket_cores_is_valid(local_sockets)){
+		int index;
+
+		local_sockets->magic = 0;
+		for(index = 0; index < local_sockets->next; ++ index){
+			if(socket_cores_item_is_valid(&(local_sockets->items[index]))){
+				local_sockets->items[index].magic = 0;
+				if(local_sockets->items[index].value){
+					socket_destroy_core(packet_phone, local_sockets->items[index].value, local_sockets, global_sockets, socket_release);
+					free(local_sockets->items[index].value);
+					local_sockets->items[index].value = NULL;
+				}
+			}
+		}
+		free(local_sockets->items);
+	}
+}
+
+/** Adds the socket to a socket port.
+ *  @param[in,out] socket_port The socket port structure.
+ *  @param[in] socket The socket to be added.
+ *  @param[in] key The socket key identifier.
+ *  @param[in] key_length The socket key length.
+ *  @returns EOK on success.
+ *  @returns ENOMEM if there is not enough memory left.
+ */
+static int socket_port_add_core(socket_port_ref socket_port, socket_core_ref socket, const char * key, size_t key_length){
+	ERROR_DECLARE;
+
+	socket_core_ref * socket_ref;
+
+	// create a wrapper
+	socket_ref = malloc(sizeof(*socket_ref));
+	if(! socket_ref){
+		return ENOMEM;
+	}
+	*socket_ref = socket;
+	// add the wrapper
+	if(ERROR_OCCURRED(socket_port_map_add(&socket_port->map, key, key_length, socket_ref))){
+		free(socket_ref);
+		return ERROR_CODE;
+	}
+	++ socket_port->count;
+	socket->key = key;
+	socket->key_length = key_length;
+	return EOK;
+}
+
+/** Binds the socket to the port.
+ *  The SOCKET_MAP_KEY_LISTENING key identifier is used.
+ *  @param[in] global_sockets The global sockets to be updated.
+ *  @param[in] socket The socket to be added.
+ *  @param[in] port The port number to be bound to.
+ *  @returns EOK on success.
+ *  @returns ENOMEM if there is not enough memory left.
+ *  @returns Other error codes as defined for the socket_ports_add() function.
+ */
+static int socket_bind_insert(socket_ports_ref global_sockets, socket_core_ref socket, int port){
+	ERROR_DECLARE;
+
+	socket_port_ref socket_port;
+
+	// create a wrapper
+	socket_port = malloc(sizeof(*socket_port));
+	if(! socket_port){
+		return ENOMEM;
+	}
+	socket_port->count = 0;
+	if(ERROR_OCCURRED(socket_port_map_initialize(&socket_port->map))
+		|| ERROR_OCCURRED(socket_port_add_core(socket_port, socket, SOCKET_MAP_KEY_LISTENING, 0))){
+		socket_port_map_destroy(&socket_port->map);
+		free(socket_port);
+		return ERROR_CODE;
+	}
+	// register the incomming port
+	ERROR_CODE = socket_ports_add(global_sockets, port, socket_port);
+	if(ERROR_CODE < 0){
+		socket_port_map_destroy(&socket_port->map);
+		free(socket_port);
+		return ERROR_CODE;
+	}
+	socket->port = port;
+	return EOK;
+}
+
+int socket_bind(socket_cores_ref local_sockets, socket_ports_ref global_sockets, int socket_id, void * addr, size_t addrlen, int free_ports_start, int free_ports_end, int last_used_port){
+	socket_core_ref socket;
+	socket_port_ref socket_port;
+	struct sockaddr * address;
+	struct sockaddr_in * address_in;
+
+	if(addrlen < sizeof(struct sockaddr)){
+		return EINVAL;
+	}
+	address = (struct sockaddr *) addr;
+	switch(address->sa_family){
+		case AF_INET:
+			if(addrlen != sizeof(struct sockaddr_in)){
+				return EINVAL;
+			}
+			address_in = (struct sockaddr_in *) addr;
+			// find the socket
+			socket = socket_cores_find(local_sockets, socket_id);
+			if(! socket){
+				return ENOTSOCK;
+			}
+			// bind a free port?
+			if(address_in->sin_port <= 0){
+				return socket_bind_free_port(global_sockets, socket, free_ports_start, free_ports_end, last_used_port);
+			}
+			// try to find the port
+			socket_port = socket_ports_find(global_sockets, ntohs(address_in->sin_port));
+			if(socket_port){
+				// already used
+				return EADDRINUSE;
+			}
+			// if bound
+			if(socket->port){
+				// release the port
+				socket_port_release(global_sockets, socket);
+			}
+			socket->port = -1;
+			return socket_bind_insert(global_sockets, socket, ntohs(address_in->sin_port));
+			break;
+		// TODO IPv6
+	}
+	return EAFNOSUPPORT;
+}
+
+int socket_bind_free_port(socket_ports_ref global_sockets, socket_core_ref socket, int free_ports_start, int free_ports_end, int last_used_port){
+	int index;
+
+	// from the last used one
+	index = last_used_port;
+	do{
+		++ index;
+		// til the range end
+		if(index >= free_ports_end){
+			// start from the range beginning
+			index = free_ports_start - 1;
+			do{
+				++ index;
+				// til the last used one
+				if(index >= last_used_port){
+					// none found
+					return ENOTCONN;
+				}
+			}while(socket_ports_find(global_sockets, index) != NULL);
+			// found, break immediately
+			break;
+		}
+	}while(socket_ports_find(global_sockets, index) != NULL);
+	return socket_bind_insert(global_sockets, socket, index);
+}
+
+/** Tries to find a new free socket identifier.
+ *  @param[in] local_sockets The local sockets to be searched.
+ *  @param[in] positive A value indicating whether a positive identifier is requested. A negative identifier is requested if set to false.
+ *	@returns The new socket identifier.
+ *  @returns ELIMIT if there is no socket identifier available.
+ */
+static int socket_generate_new_id(socket_cores_ref local_sockets, int positive){
+	int socket_id;
+	int count;
+
+	count = 0;
+//	socket_id = socket_globals.last_id;
+	do{
+		if(count < SOCKET_ID_TRIES){
+			socket_id = rand() % INT_MAX;
+			++ count;
+		}else if(count == SOCKET_ID_TRIES){
+			socket_id = 1;
+			++ count;
+		// only this branch for last_id
+		}else{
+			if(socket_id < INT_MAX){
+				++ socket_id;
+/*			}else if(socket_globals.last_id){
+*				socket_globals.last_id = 0;
+*				socket_id = 1;
+*/			}else{
+				return ELIMIT;
+			}
+		}
+	}while(socket_cores_find(local_sockets, ((positive ? 1 : -1) * socket_id)));
+//	last_id = socket_id
+	return socket_id;
+}
+
+int socket_create(socket_cores_ref local_sockets, int app_phone, void * specific_data, int * socket_id){
+	ERROR_DECLARE;
+
+	socket_core_ref socket;
+	int res;
+	int positive;
+
+	if(! socket_id){
+		return EINVAL;
+	}
+	// store the socket
+	if(*socket_id <= 0){
+		positive = (*socket_id == 0);
+		*socket_id = socket_generate_new_id(local_sockets, positive);
+		if(*socket_id <= 0){
+			return * socket_id;
+		}
+		if(! positive){
+			*socket_id *= -1;
+		}
+	}else if(socket_cores_find(local_sockets, * socket_id)){
+		return EEXIST;
+	}
+	socket = (socket_core_ref) malloc(sizeof(*socket));
+	if(! socket){
+		return ENOMEM;
+	}
+	// initialize
+	socket->phone = app_phone;
+	socket->port = -1;
+	socket->key = NULL;
+	socket->key_length = 0;
+	socket->specific_data = specific_data;
+	if(ERROR_OCCURRED(dyn_fifo_initialize(&socket->received, SOCKET_INITIAL_RECEIVED_SIZE))){
+		free(socket);
+		return ERROR_CODE;
+	}
+	if(ERROR_OCCURRED(dyn_fifo_initialize(&socket->accepted, SOCKET_INITIAL_ACCEPTED_SIZE))){
+		dyn_fifo_destroy(&socket->received);
+		free(socket);
+		return ERROR_CODE;
+	}
+	socket->socket_id = * socket_id;
+	res = socket_cores_add(local_sockets, socket->socket_id, socket);
+	if(res < 0){
+		dyn_fifo_destroy(&socket->received);
+		dyn_fifo_destroy(&socket->accepted);
+		free(socket);
+		return res;
+	}
+	return EOK;
+}
+
+int socket_destroy(int packet_phone, int socket_id, socket_cores_ref local_sockets, socket_ports_ref global_sockets, void (*socket_release)(socket_core_ref socket)){
+	socket_core_ref socket;
+	int accepted_id;
+
+	// find the socket
+	socket = socket_cores_find(local_sockets, socket_id);
+	if(! socket){
+		return ENOTSOCK;
+	}
+	// destroy all accepted sockets
+	while((accepted_id = dyn_fifo_pop(&socket->accepted)) >= 0){
+		socket_destroy(packet_phone, accepted_id, local_sockets, global_sockets, socket_release);
+	}
+	socket_destroy_core(packet_phone, socket, local_sockets, global_sockets, socket_release);
+	return EOK;
+}
+
+int socket_reply_packets(packet_t packet, size_t * length){
+	ERROR_DECLARE;
+
+	packet_t next_packet;
+	size_t fragments;
+	size_t * lengths;
+	size_t index;
+
+	if(! length){
+		return EBADMEM;
+	}
+	next_packet = pq_next(packet);
+	if(! next_packet){
+		// write all if only one fragment
+		ERROR_PROPAGATE(data_reply(packet_get_data(packet), packet_get_data_length(packet)));
+		// store the total length
+		*length = packet_get_data_length(packet);
+	}else{
+		// count the packet fragments
+		fragments = 1;
+		next_packet = pq_next(packet);
+		while((next_packet = pq_next(next_packet))){
+			++ fragments;
+		}
+		// compute and store the fragment lengths
+		lengths = (size_t *) malloc(sizeof(size_t) * fragments + sizeof(size_t));
+		if(! lengths){
+			return ENOMEM;
+		}
+		lengths[0] = packet_get_data_length(packet);
+		lengths[fragments] = lengths[0];
+		next_packet = pq_next(packet);
+		for(index = 1; index < fragments; ++ index){
+			lengths[index] = packet_get_data_length(next_packet);
+			lengths[fragments] += lengths[index];
+			next_packet = pq_next(packet);
+		}while(next_packet);
+		// write the fragment lengths
+		ERROR_PROPAGATE(data_reply(lengths, sizeof(int) * (fragments + 1)));
+		next_packet = packet;
+		// write the fragments
+		for(index = 0; index < fragments; ++ index){
+			ERROR_PROPAGATE(data_reply(packet_get_data(next_packet), lengths[index]));
+			next_packet = pq_next(next_packet);
+		}while(next_packet);
+		// store the total length
+		*length = lengths[fragments];
+		free(lengths);
+	}
+	return EOK;
+}
+
+socket_core_ref socket_port_find(socket_ports_ref global_sockets, int port, const char * key, size_t key_length){
+	socket_port_ref socket_port;
+	socket_core_ref * socket_ref;
+
+	socket_port = socket_ports_find(global_sockets, port);
+	if(socket_port && (socket_port->count > 0)){
+		socket_ref = socket_port_map_find(&socket_port->map, key, key_length);
+		if(socket_ref){
+			return * socket_ref;
+		}
+	}
+	return NULL;
+}
+
+void socket_port_release(socket_ports_ref global_sockets, socket_core_ref socket){
+	socket_port_ref socket_port;
+	socket_core_ref * socket_ref;
+
+	if(socket->port){
+		// find ports
+		socket_port = socket_ports_find(global_sockets, socket->port);
+		if(socket_port){
+			// find the socket
+			socket_ref = socket_port_map_find(&socket_port->map, socket->key, socket->key_length);
+			if(socket_ref){
+				-- socket_port->count;
+				// release if empty
+				if(socket_port->count <= 0){
+					// destroy the map
+					socket_port_map_destroy(&socket_port->map);
+					// release the port
+					socket_ports_exclude(global_sockets, socket->port);
+				}else{
+					// remove
+					socket_port_map_exclude(&socket_port->map, socket->key, socket->key_length);
+				}
+			}
+		}
+		socket->port = 0;
+		socket->key = NULL;
+		socket->key_length = 0;
+	}
+}
+
+int socket_port_add(socket_ports_ref global_sockets, int port, socket_core_ref socket, const char * key, size_t key_length){
+	ERROR_DECLARE;
+
+	socket_port_ref socket_port;
+
+	// find ports
+	socket_port = socket_ports_find(global_sockets, port);
+	if(! socket_port){
+		return ENOENT;
+	}
+	// add the socket
+	ERROR_PROPAGATE(socket_port_add_core(socket_port, socket, key, key_length));
+	socket->port = port;
+	return EOK;
+}
+
+/** @}
+ */
Index: uspace/lib/net/il/ip_client.c
===================================================================
--- uspace/lib/net/il/ip_client.c	(revision d52fbaf59e7bccbf3e5d682f5fafb0146f625e9f)
+++ uspace/lib/net/il/ip_client.c	(revision 0a866eebd91749e0380adb6b7af11e95a433af59)
@@ -40,7 +40,8 @@
 
 #include <ip_client.h>
+#include <packet_client.h>
+#include <ip_header.h>
+
 #include <packet/packet.h>
-#include <packet/packet_client.h>
-#include <ip_header.h>
 
 size_t ip_client_header_length(packet_t packet){
Index: uspace/lib/net/il/ip_remote.c
===================================================================
--- uspace/lib/net/il/ip_remote.c	(revision d52fbaf59e7bccbf3e5d682f5fafb0146f625e9f)
+++ uspace/lib/net/il/ip_remote.c	(revision 0a866eebd91749e0380adb6b7af11e95a433af59)
@@ -47,5 +47,5 @@
 #include <net/inet.h>
 #include <ip_interface.h>
-#include <packet/packet_client.h>
+#include <packet_client.h>
 #include <il_messages.h>
 #include <ip_messages.h>
Index: uspace/lib/net/include/il_interface.h
===================================================================
--- uspace/lib/net/include/il_interface.h	(revision d52fbaf59e7bccbf3e5d682f5fafb0146f625e9f)
+++ uspace/lib/net/include/il_interface.h	(revision 0a866eebd91749e0380adb6b7af11e95a433af59)
@@ -46,5 +46,5 @@
 #include <net_device.h>
 #include <packet/packet.h>
-#include <packet/packet_client.h>
+#include <packet_client.h>
 #include <il_messages.h>
 
Index: uspace/lib/net/include/netif_interface.h
===================================================================
--- uspace/lib/net/include/netif_interface.h	(revision d52fbaf59e7bccbf3e5d682f5fafb0146f625e9f)
+++ uspace/lib/net/include/netif_interface.h	(revision 0a866eebd91749e0380adb6b7af11e95a433af59)
@@ -53,5 +53,5 @@
 
 #include <netif_remote.h>
-#include <packet/packet_client.h>
+#include <packet_client.h>
 
 #define netif_module_message    netif_module_message_standalone
Index: uspace/lib/net/include/packet_client.h
===================================================================
--- uspace/lib/net/include/packet_client.h	(revision 0a866eebd91749e0380adb6b7af11e95a433af59)
+++ uspace/lib/net/include/packet_client.h	(revision 0a866eebd91749e0380adb6b7af11e95a433af59)
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) 2009 Lukas Mejdrech
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup packet
+ *  @{
+ */
+
+/** @file
+ *  Packet client.
+ *  The hosting module has to be compiled with both the packet.c and the packet_client.c source files.
+ *  To function correctly, initialization of the packet map by the pm_init() function has to happen at the first place.
+ *  The module should not send the packet messages to the packet server but use the functions provided.
+ *  The packet map should be released by the pm_destroy() function during the module termination.
+ *  The packets and the packet queues can't be locked at all.
+ *  The processing modules should process them sequentially -&nbsp;by passing the packets to the next module and stopping using the passed ones.
+ *  @see packet.h
+ */
+
+#ifndef __NET_PACKET_CLIENT_H__
+#define __NET_PACKET_CLIENT_H__
+
+#include <packet/packet.h>
+
+/** @name Packet client interface
+ */
+/*@{*/
+
+/** Allocates the specified type right before the actual packet content and returns its pointer.
+ *  The wrapper of the packet_prepend() function.
+ *  @param[in] packet The packet to be used.
+ *  @param[in] type The type to be allocated at the beginning of the packet content.
+ *  @returns The typed pointer to the allocated memory.
+ *  @returns NULL if the packet is not valid.
+ *  @returns NULL if there is not enough memory left.
+ */
+#define PACKET_PREFIX(packet, type)	(type *) packet_prefix((packet), sizeof(type))
+
+/** Allocates the specified type right after the actual packet content and returns its pointer.
+ *  The wrapper of the packet_append() function.
+ *  @param[in] packet The packet to be used.
+ *  @param[in] type The type to be allocated at the end of the packet content.
+ *  @returns The typed pointer to the allocated memory.
+ *  @returns NULL if the packet is not valid.
+ *  @returns NULL if there is not enough memory left.
+ */
+#define PACKET_SUFFIX(packet, type)	(type *) packet_suffix((packet), sizeof(type))
+
+/** Trims the actual packet content by the specified prefix and suffix types.
+ *  The wrapper of the packet_trim() function.
+ *  @param[in] packet The packet to be trimmed.
+ *  @param[in] prefix The type of the prefix to be removed from the beginning of the packet content.
+ *  @param[in] suffix The type of the suffix to be removed from the end of the packet content.
+ *  @returns EOK on success.
+ *  @returns EINVAL if the packet is not valid.
+ *  @returns ENOMEM if there is not enough memory left.
+ */
+#define PACKET_TRIM(packet, prefix, suffix)	packet_trim((packet), sizeof(prefix), sizeof(suffix))
+
+/** Allocates the specified space right before the actual packet content and returns its pointer.
+ *  @param[in] packet The packet to be used.
+ *  @param[in] length The space length to be allocated at the beginning of the packet content.
+ *  @returns The pointer to the allocated memory.
+ *  @returns NULL if there is not enough memory left.
+ */
+extern void * packet_prefix(packet_t packet, size_t length);
+
+/** Allocates the specified space right after the actual packet content and returns its pointer.
+ *  @param[in] packet The packet to be used.
+ *  @param[in] length The space length to be allocated at the end of the packet content.
+ *  @returns The pointer to the allocated memory.
+ *  @returns NULL if there is not enough memory left.
+ */
+extern void * packet_suffix(packet_t packet, size_t length);
+
+/** Trims the actual packet content by the specified prefix and suffix lengths.
+ *  @param[in] packet The packet to be trimmed.
+ *  @param[in] prefix The prefix length to be removed from the beginning of the packet content.
+ *  @param[in] suffix The suffix length to be removed from the end of the packet content.
+ *  @returns EOK on success.
+ *  @returns EINVAL if the packet is not valid.
+ *  @returns ENOMEM if there is not enough memory left.
+ */
+extern int packet_trim(packet_t packet, size_t prefix, size_t suffix);
+
+/** Copies the specified data to the beginning of the actual packet content.
+ *  Pushes the content end if needed.
+ *  @param[in] packet The packet to be filled.
+ *  @param[in] data The data to be copied.
+ *  @param[in] length The length of the copied data.
+ *  @returns EOK on success.
+ *  @returns EINVAL if the packet is not valid.
+ *  @returns ENOMEM if there is not enough memory left.
+ */
+extern int packet_copy_data(packet_t packet, const void * data, size_t length);
+
+/** Returns the packet identifier.
+ *  @param[in] packet The packet.
+ *  @returns The packet identifier.
+ *  @returns Zero (0) if the packet is not valid.
+ */
+extern packet_id_t packet_get_id(const packet_t packet);
+
+/** Returns the packet content length.
+ *  @param[in] packet The packet.
+ *  @returns The packet content length in bytes.
+ *  @returns Zero (0) if the packet is not valid.
+ */
+extern size_t packet_get_data_length(const packet_t packet);
+
+/** Returns the pointer to the beginning of the packet content.
+ *  @param[in] packet The packet.
+ *  @returns The pointer to the beginning of the packet content.
+ *  @returns NULL if the packet is not valid.
+ */
+extern void * packet_get_data(const packet_t packet);
+
+/** Returns the stored packet addresses and their length.
+ *  @param[in] packet The packet.
+ *  @param[out] src The source address. May be NULL if not desired.
+ *  @param[out] dest The destination address. May be NULL if not desired.
+ *  @returns The stored addresses length.
+ *  @returns Zero (0) if the addresses are not present.
+ *  @returns EINVAL if the packet is not valid.
+ */
+extern int packet_get_addr(const packet_t packet, uint8_t ** src, uint8_t ** dest);
+
+/** Sets the packet addresses.
+ *  @param[in] packet The packet.
+ *  @param[in] src The new source address. May be NULL.
+ *  @param[in] dest The new destination address. May be NULL.
+ *  @param[in] addr_len The addresses length.
+ *  @returns EOK on success.
+ *  @returns EINVAL if the packet is not valid.
+ *  @returns ENOMEM if there is not enough memory left.
+ */
+extern int packet_set_addr(packet_t packet, const uint8_t * src, const uint8_t * dest, size_t addr_len);
+
+/** Translates the packet identifier to the packet reference.
+ *  Tries to find mapping first.
+ *  Contacts the packet server to share the packet if the mapping is not present.
+ *  @param[in] phone The packet server module phone.
+ *  @param[out] packet The packet reference.
+ *  @param[in] packet_id The packet identifier.
+ *  @returns EOK on success.
+ *  @returns EINVAL if the packet parameter is NULL.
+ *  @returns Other error codes as defined for the NET_PACKET_GET_SIZE message.
+ *  @returns Other error codes as defined for the packet_return() function.
+ */
+extern int packet_translate_remote(int phone, packet_ref packet, packet_id_t packet_id);
+
+/** Obtains the packet of the given dimensions.
+ *  Contacts the packet server to return the appropriate packet.
+ *  @param[in] phone The packet server module phone.
+ *  @param[in] addr_len The source and destination addresses maximal length in bytes.
+ *  @param[in] max_prefix The maximal prefix length in bytes.
+ *  @param[in] max_content The maximal content length in bytes.
+ *  @param[in] max_suffix The maximal suffix length in bytes.
+ *  @returns The packet reference.
+ *  @returns NULL on error.
+ */
+extern packet_t packet_get_4_remote(int phone, size_t max_content, size_t addr_len, size_t max_prefix, size_t max_suffix);
+
+/** Obtains the packet of the given content size.
+ *  Contacts the packet server to return the appropriate packet.
+ *  @param[in] phone The packet server module phone.
+ *  @param[in] content The maximal content length in bytes.
+ *  @returns The packet reference.
+ *  @returns NULL on error.
+ */
+extern packet_t packet_get_1_remote(int phone, size_t content);
+
+/** Releases the packet queue.
+ *  All packets in the queue are marked as free for use.
+ *  The packet queue may be one packet only.
+ *  The module should not use the packets after this point until they are received or obtained again.
+ *  @param[in] phone The packet server module phone.
+ *  @param[in] packet_id The packet identifier.
+ */
+extern void pq_release_remote(int phone, packet_id_t packet_id);
+
+/** Returns the packet copy.
+ *  Copies the addresses, data, order and metric values.
+ *  Does not copy the queue placement.
+ *  @param[in] phone The packet server module phone.
+ *  @param[in] packet The original packet.
+ *  @returns The packet copy.
+ *  @returns NULL on error.
+ */
+extern packet_t packet_get_copy(int phone, packet_t packet);
+
+/*@}*/
+
+#endif
+
+/** @}
+ */
Index: uspace/lib/net/include/tl_interface.h
===================================================================
--- uspace/lib/net/include/tl_interface.h	(revision d52fbaf59e7bccbf3e5d682f5fafb0146f625e9f)
+++ uspace/lib/net/include/tl_interface.h	(revision 0a866eebd91749e0380adb6b7af11e95a433af59)
@@ -44,5 +44,5 @@
 #include <net_device.h>
 #include <packet/packet.h>
-#include <packet/packet_client.h>
+#include <packet_client.h>
 #include <tl_messages.h>
 
Index: uspace/lib/net/netif/netif_local.c
===================================================================
--- uspace/lib/net/netif/netif_local.c	(revision d52fbaf59e7bccbf3e5d682f5fafb0146f625e9f)
+++ uspace/lib/net/netif/netif_local.c	(revision 0a866eebd91749e0380adb6b7af11e95a433af59)
@@ -47,5 +47,5 @@
 #include <net/modules.h>
 #include <packet/packet.h>
-#include <packet/packet_client.h>
+#include <packet_client.h>
 #include <packet/packet_server.h>
 #include <packet_remote.h>
Index: uspace/lib/net/netif/netif_remote.c
===================================================================
--- uspace/lib/net/netif/netif_remote.c	(revision d52fbaf59e7bccbf3e5d682f5fafb0146f625e9f)
+++ uspace/lib/net/netif/netif_remote.c	(revision 0a866eebd91749e0380adb6b7af11e95a433af59)
@@ -40,5 +40,5 @@
 #include <adt/measured_strings.h>
 #include <packet/packet.h>
-#include <packet/packet_client.h>
+#include <packet_client.h>
 #include <net_device.h>
 #include <netif_remote.h>
Index: uspace/lib/net/nil/nil_remote.c
===================================================================
--- uspace/lib/net/nil/nil_remote.c	(revision d52fbaf59e7bccbf3e5d682f5fafb0146f625e9f)
+++ uspace/lib/net/nil/nil_remote.c	(revision 0a866eebd91749e0380adb6b7af11e95a433af59)
@@ -40,5 +40,5 @@
 #include <nil_interface.h>
 #include <packet/packet.h>
-#include <packet/packet_client.h>
+#include <packet_client.h>
 #include <nil_messages.h>
 #include <nil_remote.h>
Index: uspace/lib/net/tl/icmp_client.c
===================================================================
--- uspace/lib/net/tl/icmp_client.c	(revision d52fbaf59e7bccbf3e5d682f5fafb0146f625e9f)
+++ uspace/lib/net/tl/icmp_client.c	(revision 0a866eebd91749e0380adb6b7af11e95a433af59)
@@ -46,5 +46,5 @@
 #include <icmp_client.h>
 #include <packet/packet.h>
-#include <packet/packet_client.h>
+#include <packet_client.h>
 #include <icmp_header.h>
 
Index: uspace/lib/net/tl/icmp_remote.c
===================================================================
--- uspace/lib/net/tl/icmp_remote.c	(revision d52fbaf59e7bccbf3e5d682f5fafb0146f625e9f)
+++ uspace/lib/net/tl/icmp_remote.c	(revision 0a866eebd91749e0380adb6b7af11e95a433af59)
@@ -45,5 +45,5 @@
 #include <net/modules.h>
 #include <icmp_interface.h>
-#include <packet/packet_client.h>
+#include <packet_client.h>
 #include <icmp_messages.h>
 
Index: uspace/lib/net/tl/tl_common.c
===================================================================
--- uspace/lib/net/tl/tl_common.c	(revision d52fbaf59e7bccbf3e5d682f5fafb0146f625e9f)
+++ uspace/lib/net/tl/tl_common.c	(revision 0a866eebd91749e0380adb6b7af11e95a433af59)
@@ -46,5 +46,5 @@
 
 #include <packet/packet.h>
-#include <packet/packet_client.h>
+#include <packet_client.h>
 #include <packet_remote.h>
 #include <net_device.h>
