Index: uspace/srv/net/socket/socket_client.c
===================================================================
--- uspace/srv/net/socket/socket_client.c	(revision 1a0fb3f8aa71e3bb907eb17703615fc685752ca1)
+++ uspace/srv/net/socket/socket_client.c	(revision ede63e47763744e7b1eba0111fb300543d072dc9)
@@ -40,4 +40,6 @@
 #include <async.h>
 #include <fibril_synch.h>
+#include <limits.h>
+#include <stdlib.h>
 
 #include <ipc/services.h>
@@ -74,4 +76,8 @@
  */
 #define SOCKET_CONNECT_TIMEOUT	( 1 * 1000 * 1000 )
+
+/** Maximum number of random attempts to find a new socket identifier before switching to the sequence.
+ */
+#define SOCKET_ID_TRIES					100
 
 /** Type definition of the socket specific data.
@@ -155,4 +161,7 @@
 	 */
 	int	udp_phone;
+//	/** The last socket identifier.
+//	 */
+//	int last_id;
 	/** Active sockets.
 	 */
@@ -168,4 +177,5 @@
 	.tcp_phone = -1,
 	.udp_phone = -1,
+//	.last_id = 0,
 	.sockets = NULL,
 	.lock = {
@@ -199,4 +209,10 @@
  */
 static sockets_ref	socket_get_sockets( void );
+
+/** Tries to find a new free socket identifier.
+ *	@returns The new socket identifier.
+ *  @returns ELIMIT if there is no socket identifier available.
+ */
+static int	socket_generate_new_id( void );
 
 /** Default thread for new connections.
@@ -288,6 +304,38 @@
 			socket_globals.sockets = NULL;
 		}
+		srand( task_get_id());
 	}
 	return socket_globals.sockets;
+}
+
+static int socket_generate_new_id( void ){
+	sockets_ref	sockets;
+	int			socket_id;
+	int			count;
+
+	sockets = socket_get_sockets();
+	count = 0;
+//	socket_id = socket_globals.last_id;
+	do{
+		if( count < SOCKET_ID_TRIES ){
+			socket_id = rand() % INT_MAX;
+			++ count;
+		}else if( count == SOCKET_ID_TRIES ){
+			socket_id = 1;
+			++ count;
+		// only this branch for last_id
+		}else{
+			if( socket_id < INT_MAX ){
+				++ socket_id;
+/*			}else if( socket_globals.last_id ){
+*				socket_globals.last_id = 0;
+*				socket_id = 1;
+*/			}else{
+				return ELIMIT;
+			}
+		}
+	}while( sockets_find( sockets, socket_id ));
+//	last_id = socket_id
+	return socket_id;
 }
 
@@ -311,5 +359,4 @@
 	ipc_call_t		call;
 	socket_ref		socket;
-	socket_ref		new_socket;
 
 	while( true ){
@@ -318,53 +365,5 @@
 		switch( IPC_GET_METHOD( call )){
 			case NET_SOCKET_RECEIVED:
-				fibril_rwlock_read_lock( & socket_globals.lock );
-				// find the socket
-				socket = sockets_find( socket_get_sockets(), SOCKET_GET_SOCKET_ID( call ));
-				if( ! socket ){
-					ERROR_CODE = ENOTSOCK;
-				}else{
-					fibril_mutex_lock( & socket->receive_lock );
-					// push the number of received packet fragments
-					if( ! ERROR_OCCURRED( dyn_fifo_push( & socket->received, SOCKET_GET_DATA_FRAGMENTS( call ), SOCKET_MAX_RECEIVED_SIZE ))){
-						// signal the received packet
-						fibril_condvar_signal( & socket->receive_signal );
-					}
-					fibril_mutex_unlock( & socket->receive_lock );
-				}
-				fibril_rwlock_read_unlock( & socket_globals.lock );
-				break;
 			case NET_SOCKET_ACCEPTED:
-				fibril_rwlock_read_lock( & socket_globals.lock );
-				// find the socket
-				socket = sockets_find( socket_get_sockets(), SOCKET_GET_SOCKET_ID( call ));
-				if( ! socket ){
-					ERROR_CODE = ENOTSOCK;
-				}else{
-					// create a new scoket
-					new_socket = ( socket_ref ) malloc( sizeof( socket_t ));
-					if( ! new_socket ){
-						ERROR_CODE = ENOMEM;
-					}else{
-						bzero( new_socket, sizeof( * new_socket ));
-						socket_initialize( new_socket, SOCKET_GET_NEW_SOCKET_ID( call ), socket->phone, socket->service );
-						ERROR_CODE = sockets_add( socket_get_sockets(), new_socket->socket_id, new_socket );
-						if( ERROR_CODE < 0 ){
-							free( new_socket );
-						}else{
-							// push the new socket identifier
-							fibril_mutex_lock( & socket->accept_lock );
-							if( ERROR_OCCURRED( dyn_fifo_push( & socket->accepted, new_socket->socket_id, SOCKET_MAX_ACCEPTED_SIZE ))){
-								sockets_exclude( socket_get_sockets(), new_socket->socket_id );
-							}else{
-								// signal the accepted socket
-								fibril_condvar_signal( & socket->accept_signal );
-							}
-							fibril_mutex_unlock( & socket->accept_lock );
-							ERROR_CODE = EOK;
-						}
-					}
-				}
-				fibril_rwlock_read_unlock( & socket_globals.lock );
-				break;
 			case NET_SOCKET_DATA_FRAGMENT_SIZE:
 				fibril_rwlock_read_lock( & socket_globals.lock );
@@ -374,12 +373,37 @@
 					ERROR_CODE = ENOTSOCK;
 				}else{
-					fibril_rwlock_write_lock( & socket->sending_lock );
-					// set the data fragment size
-					socket->data_fragment_size = SOCKET_GET_DATA_FRAGMENT_SIZE( call );
-					fibril_rwlock_write_unlock( & socket->sending_lock );
-					ERROR_CODE = EOK;
+					switch( IPC_GET_METHOD( call )){
+						case NET_SOCKET_RECEIVED:
+							fibril_mutex_lock( & socket->receive_lock );
+							// push the number of received packet fragments
+							if( ! ERROR_OCCURRED( dyn_fifo_push( & socket->received, SOCKET_GET_DATA_FRAGMENTS( call ), SOCKET_MAX_RECEIVED_SIZE ))){
+								// signal the received packet
+								fibril_condvar_signal( & socket->receive_signal );
+							}
+							fibril_mutex_unlock( & socket->receive_lock );
+							break;
+						case NET_SOCKET_ACCEPTED:
+							// push the new socket identifier
+							fibril_mutex_lock( & socket->accept_lock );
+							if( ERROR_OCCURRED( dyn_fifo_push( & socket->accepted, SOCKET_GET_NEW_SOCKET_ID( call ), SOCKET_MAX_ACCEPTED_SIZE ))){
+								sockets_exclude( socket_get_sockets(), SOCKET_GET_NEW_SOCKET_ID( call ));
+							}else{
+								// signal the accepted socket
+								fibril_condvar_signal( & socket->accept_signal );
+							}
+							fibril_mutex_unlock( & socket->accept_lock );
+							break;
+						default:
+							ERROR_CODE = ENOTSUP;
+					}
+					if(( SOCKET_GET_DATA_FRAGMENT_SIZE( call ) > 0 )
+					&& ( SOCKET_GET_DATA_FRAGMENT_SIZE( call ) != socket->data_fragment_size )){
+						fibril_rwlock_write_lock( & socket->sending_lock );
+						// set the data fragment size
+						socket->data_fragment_size = SOCKET_GET_DATA_FRAGMENT_SIZE( call );
+						fibril_rwlock_write_unlock( & socket->sending_lock );
+					}
 				}
 				fibril_rwlock_read_unlock( & socket_globals.lock );
-				break;
 			default:
 				ERROR_CODE = ENOTSUP;
@@ -396,4 +420,5 @@
 	int			socket_id;
 	services_t	service;
+	int			count;
 
 	// find the appropriate service
@@ -437,6 +462,15 @@
 	if( ! socket ) return ENOMEM;
 	bzero( socket, sizeof( * socket ));
+	count = 0;
+	fibril_rwlock_write_lock( & socket_globals.lock );
 	// request a new socket
-	if( ERROR_OCCURRED(( int ) async_req_3_3( phone, NET_SOCKET, 0, 0, service, ( ipcarg_t * ) & socket_id, ( ipcarg_t * ) & socket->data_fragment_size, ( ipcarg_t * ) & socket->header_size ))){
+	socket_id = socket_generate_new_id();
+	if( socket_id <= 0 ){
+		fibril_rwlock_write_unlock( & socket_globals.lock );
+		free( socket );
+		return socket_id;
+	}
+	if( ERROR_OCCURRED(( int ) async_req_3_3( phone, NET_SOCKET, socket_id, 0, service, NULL, ( ipcarg_t * ) & socket->data_fragment_size, ( ipcarg_t * ) & socket->header_size ))){
+		fibril_rwlock_write_unlock( & socket_globals.lock );
 		free( socket );
 		return ERROR_CODE;
@@ -445,5 +479,4 @@
 	socket_initialize( socket, socket_id, phone, service );
 	// store the new socket
-	fibril_rwlock_write_lock( & socket_globals.lock );
 	ERROR_CODE = sockets_add( socket_get_sockets(), socket_id, socket );
 	fibril_rwlock_write_unlock( & socket_globals.lock );
@@ -509,4 +542,5 @@
 int accept( int socket_id, struct sockaddr * cliaddr, socklen_t * addrlen ){
 	socket_ref		socket;
+	socket_ref		new_socket;
 	aid_t			message_id;
 	int				result;
@@ -515,9 +549,9 @@
 	if(( ! cliaddr ) || ( ! addrlen )) return EBADMEM;
 
-	fibril_rwlock_read_lock( & socket_globals.lock );
+	fibril_rwlock_write_lock( & socket_globals.lock );
 	// find the socket
 	socket = sockets_find( socket_get_sockets(), socket_id );
 	if( ! socket ){
-		fibril_rwlock_read_unlock( & socket_globals.lock );
+		fibril_rwlock_write_unlock( & socket_globals.lock );
 		return ENOTSOCK;
 	}
@@ -526,20 +560,49 @@
 	++ socket->blocked;
 	while( dyn_fifo_value( & socket->accepted ) <= 0 ){
-		fibril_rwlock_read_unlock( & socket_globals.lock );
+		fibril_rwlock_write_unlock( & socket_globals.lock );
 		fibril_condvar_wait( & socket->accept_signal, & socket->accept_lock );
-		fibril_rwlock_read_lock( & socket_globals.lock );
+		fibril_rwlock_write_lock( & socket_globals.lock );
 	}
 	-- socket->blocked;
+
+	// create a new scoket
+	new_socket = ( socket_ref ) malloc( sizeof( socket_t ));
+	if( ! new_socket ){
+		fibril_mutex_unlock( & socket->accept_lock );
+		fibril_rwlock_write_unlock( & socket_globals.lock );
+		return ENOMEM;
+	}
+	bzero( new_socket, sizeof( * new_socket ));
+	socket_id = socket_generate_new_id();
+	if( socket_id <= 0 ){
+		fibril_mutex_unlock( & socket->accept_lock );
+		fibril_rwlock_write_unlock( & socket_globals.lock );
+		free( new_socket );
+		return socket_id;
+	}
+	socket_initialize( new_socket, socket_id, socket->phone, socket->service );
+	result = sockets_add( socket_get_sockets(), new_socket->socket_id, new_socket );
+	if( result < 0 ){
+		fibril_mutex_unlock( & socket->accept_lock );
+		fibril_rwlock_write_unlock( & socket_globals.lock );
+		free( new_socket );
+		return result;
+	}
+
 	// request accept
-	message_id = async_send_3( socket->phone, NET_SOCKET_ACCEPT, ( ipcarg_t ) socket->socket_id, 0, socket->service, & answer );
+	message_id = async_send_5( socket->phone, NET_SOCKET_ACCEPT, ( ipcarg_t ) socket->socket_id, 0, socket->service, 0, new_socket->socket_id, & answer );
 	// read address
-	async_data_read_start( socket->phone, cliaddr, * addrlen );
-	fibril_rwlock_read_unlock( & socket_globals.lock );
+	ipc_data_read_start( socket->phone, cliaddr, * addrlen );
+	fibril_rwlock_write_unlock( & socket_globals.lock );
 	async_wait_for( message_id, ( ipcarg_t * ) & result );
 	if( result > 0 ){
+		if( result != socket_id ){
+			result = EINVAL;
+		}
 		// dequeue the accepted socket if successful
 		dyn_fifo_pop( & socket->accepted );
 		// set address length
 		* addrlen = SOCKET_GET_ADDRESS_LENGTH( answer );
+		new_socket->data_fragment_size = SOCKET_GET_DATA_FRAGMENT_SIZE( answer );
 	}else if( result == ENOTSOCK ){
 		// empty the queue if no accepted sockets
@@ -609,4 +672,5 @@
 	ipcarg_t		result;
 	size_t			fragments;
+	ipc_call_t		answer;
 
 	if( ! data ) return EBADMEM;
@@ -621,8 +685,12 @@
 	fibril_rwlock_read_lock( & socket->sending_lock );
 	// compute data fragment count
-	fragments = ( datalength + socket->header_size ) / socket->data_fragment_size;
-	if(( datalength + socket->header_size ) % socket->data_fragment_size ) ++ fragments;
+	if( socket->data_fragment_size > 0 ){
+		fragments = ( datalength + socket->header_size ) / socket->data_fragment_size;
+		if(( datalength + socket->header_size ) % socket->data_fragment_size ) ++ fragments;
+	}else{
+		fragments = 1;
+	}
 	// request send
-	message_id = async_send_5( socket->phone, message, ( ipcarg_t ) socket->socket_id, socket->data_fragment_size, socket->service, ( ipcarg_t ) flags, fragments, NULL );
+	message_id = async_send_5( socket->phone, message, ( ipcarg_t ) socket->socket_id, ( fragments == 1 ? datalength : socket->data_fragment_size ), socket->service, ( ipcarg_t ) flags, fragments, & answer );
 	// send the address if given
 	if(( ! toaddr ) || ( async_data_write_start( socket->phone, toaddr, addrlen ) == EOK )){
@@ -643,7 +711,12 @@
 		}
 	}
+	async_wait_for( message_id, & result );
+	if(( SOCKET_GET_DATA_FRAGMENT_SIZE( answer ) > 0 )
+	&& ( SOCKET_GET_DATA_FRAGMENT_SIZE( answer ) != socket->data_fragment_size )){
+		// set the data fragment size
+		socket->data_fragment_size = SOCKET_GET_DATA_FRAGMENT_SIZE( answer );
+	}
 	fibril_rwlock_read_unlock( & socket->sending_lock );
 	fibril_rwlock_read_unlock( & socket_globals.lock );
-	async_wait_for( message_id, & result );
 	return ( int ) result;
 }
Index: uspace/srv/net/socket/socket_core.c
===================================================================
--- uspace/srv/net/socket/socket_core.c	(revision 1a0fb3f8aa71e3bb907eb17703615fc685752ca1)
+++ uspace/srv/net/socket/socket_core.c	(revision ede63e47763744e7b1eba0111fb300543d072dc9)
@@ -35,4 +35,7 @@
  */
 
+#include <limits.h>
+#include <stdlib.h>
+
 #include "../err.h"
 
@@ -51,4 +54,8 @@
 
 #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.
@@ -94,4 +101,12 @@
  */
 int	socket_port_add_core( socket_port_ref socket_port, socket_core_ref socket, const char * key, size_t key_length );
+
+/** Tries to find a new free socket identifier.
+ *  @param[in] local_sockets The local sockets to be searched.
+ *  @param[in] positive A value indicating whether a positive identifier is requested. A negative identifier is requested if set to false.
+ *	@returns The new socket identifier.
+ *  @returns ELIMIT if there is no socket identifier available.
+ */
+static int	socket_generate_new_id( socket_cores_ref local_sockets, int positive );
 
 INT_MAP_IMPLEMENT( socket_cores, socket_core_t );
@@ -230,4 +245,34 @@
 }
 
+
+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;
@@ -235,6 +280,20 @@
 	socket_core_ref	socket;
 	int				res;
-
-	if( ! socket_id ) return EBADMEM;
+	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;
@@ -254,7 +313,5 @@
 		return ERROR_CODE;
 	}
-	// get a next free socket number
-	socket->socket_id = socket_cores_count( local_sockets ) + 1;
-	// store the socket
+	socket->socket_id = * socket_id;
 	res = socket_cores_add( local_sockets, socket->socket_id, socket );
 	if( res < 0 ){
@@ -264,6 +321,4 @@
 		return res;
 	}
-	// return the socket identifier
-	* socket_id = socket->socket_id;
 	return EOK;
 }
Index: uspace/srv/net/socket/socket_core.h
===================================================================
--- uspace/srv/net/socket/socket_core.h	(revision 1a0fb3f8aa71e3bb907eb17703615fc685752ca1)
+++ uspace/srv/net/socket/socket_core.h	(revision ede63e47763744e7b1eba0111fb300543d072dc9)
@@ -177,7 +177,7 @@
  *  @param[in] app_phone The application phone.
  *  @param[in] specific_data The socket specific data.
- *  @param[out] socket_id The new socket identifier.
- *  @returns EOK on success.
- *  @returns EBADMEM if the socket_id parameter is NULL.
+ *  @param[in,out] socket_id The new socket identifier. A new identifier is chosen if set to zero (0) or negative. A negative identifier is chosen if set to negative.
+ *  @returns EOK on success.
+ *  @returns EINVAL if the socket_id parameter is NULL.
  *  @returns ENOMEM if there is not enough memory left.
  */
Index: uspace/srv/net/socket/socket_messages.h
===================================================================
--- uspace/srv/net/socket/socket_messages.h	(revision 1a0fb3f8aa71e3bb907eb17703615fc685752ca1)
+++ uspace/srv/net/socket/socket_messages.h	(revision ede63e47763744e7b1eba0111fb300543d072dc9)
@@ -142,14 +142,4 @@
 #define SOCKET_GET_OPT_LEVEL( call )			( int ) IPC_GET_ARG2( call )
 
-/** Sets the address length in the message answer.
- *  @param[out] answer The message answer structure.
- */
-#define SOCKET_SET_ADDRESS_LENGTH( answer )		( socklen_t * ) & IPC_GET_ARG2( answer )
-
-/** Returns the address length message parameter.
- *  @param[in] call The message call structure.
- */
-#define SOCKET_GET_ADDRESS_LENGTH( call )		( socklen_t ) IPC_GET_ARG2( call )
-
 /** Returns the data fragment size message parameter.
  *  @param[in] call The message call structure.
@@ -161,4 +151,14 @@
  */
 #define SOCKET_SET_DATA_FRAGMENT_SIZE( answer )	( size_t * ) & IPC_GET_ARG2( answer )
+
+/** Sets the address length in the message answer.
+ *  @param[out] answer The message answer structure.
+ */
+#define SOCKET_SET_ADDRESS_LENGTH( answer )		( socklen_t * ) & IPC_GET_ARG3( answer )
+
+/** Returns the address length message parameter.
+ *  @param[in] call The message call structure.
+ */
+#define SOCKET_GET_ADDRESS_LENGTH( call )		( socklen_t ) IPC_GET_ARG3( call )
 
 /** Sets the header size in the message answer.
Index: uspace/srv/net/structures/int_map.h
===================================================================
--- uspace/srv/net/structures/int_map.h	(revision 1a0fb3f8aa71e3bb907eb17703615fc685752ca1)
+++ uspace/srv/net/structures/int_map.h	(revision ede63e47763744e7b1eba0111fb300543d072dc9)
@@ -82,4 +82,5 @@
 void	name##_exclude_index( name##_ref map, int index );						\
 type *	name##_find( name##_ref map, int key );									\
+int		name##_update( name##_ref map, int key, int new_key );					\
 type *	name##_get_index( name##_ref map, int index );							\
 int		name##_initialize( name##_ref map );									\
@@ -178,4 +179,22 @@
 	}																			\
 	return NULL;																\
+}																				\
+																				\
+int name##_update( name##_ref map, int key, int new_key ){						\
+	if( name##_is_valid( map )){												\
+		int	index;																\
+																				\
+		for( index = 0; index < map->next; ++ index ){							\
+			if( name##_item_is_valid( &( map->items[ index ] ))){				\
+				if( map->items[ index ].key == new_key ){						\
+					return EEXIST;												\
+				}else if( map->items[ index ].key == key ){						\
+					map->items[ index ].key = new_key;							\
+					return EOK;													\
+				}																\
+			}																	\
+		}																		\
+	}																			\
+	return ENOENT;																\
 }																				\
 																				\
Index: uspace/srv/net/tl/icmp/icmp.c
===================================================================
--- uspace/srv/net/tl/icmp/icmp.c	(revision 1a0fb3f8aa71e3bb907eb17703615fc685752ca1)
+++ uspace/srv/net/tl/icmp/icmp.c	(revision ede63e47763744e7b1eba0111fb300543d072dc9)
@@ -350,5 +350,5 @@
 	// TODO do not ask all the time
 	ERROR_PROPAGATE( ip_packet_size_req( icmp_globals.ip_phone, -1, & icmp_globals.addr_len, & icmp_globals.prefix, & icmp_globals.content, & icmp_globals.suffix ));
-	packet = packet_get_4( icmp_globals.net_phone, size, icmp_globals.addr_len, sizeof( icmp_header_t ) + icmp_globals.prefix, icmp_globals.suffix );
+	packet = packet_get_4( icmp_globals.net_phone, size, icmp_globals.addr_len, ICMP_HEADER_SIZE + icmp_globals.prefix, icmp_globals.suffix );
 	if( ! packet ) return ENOMEM;
 
@@ -548,6 +548,6 @@
 	}
 	ERROR_PROPAGATE( ip_packet_size_req( icmp_globals.ip_phone, -1, & icmp_globals.addr_len, & icmp_globals.prefix, & icmp_globals.content, & icmp_globals.suffix ));
-	icmp_globals.prefix += sizeof( icmp_header_t );
-	icmp_globals.content -= sizeof( icmp_header_t );
+	icmp_globals.prefix += ICMP_HEADER_SIZE;
+	icmp_globals.content -= ICMP_HEADER_SIZE;
 	// get configuration
 	icmp_globals.error_reporting = NET_DEFAULT_ICMP_ERROR_REPORTING;
@@ -610,5 +610,5 @@
 	length = packet_get_data_length( packet );
 	if( length <= 0 ) return EINVAL;
-	if( length < sizeof( icmp_header_t )) return EINVAL;
+	if( length < ICMP_HEADER_SIZE) return EINVAL;
 	data = packet_get_data( packet );
 	if( ! data ) return EINVAL;
Index: uspace/srv/net/tl/icmp/icmp_header.h
===================================================================
--- uspace/srv/net/tl/icmp/icmp_header.h	(revision 1a0fb3f8aa71e3bb907eb17703615fc685752ca1)
+++ uspace/srv/net/tl/icmp/icmp_header.h	(revision ede63e47763744e7b1eba0111fb300543d072dc9)
@@ -43,4 +43,8 @@
 #include "../../include/in.h"
 #include "../../include/icmp_codes.h"
+
+/** ICMP header size in bytes.
+ */
+#define ICMP_HEADER_SIZE			sizeof( icmp_header_t )
 
 /** Type definition of the echo specific data.
Index: uspace/srv/net/tl/tcp/tcp.c
===================================================================
--- uspace/srv/net/tl/tcp/tcp.c	(revision 1a0fb3f8aa71e3bb907eb17703615fc685752ca1)
+++ uspace/srv/net/tl/tcp/tcp.c	(revision ede63e47763744e7b1eba0111fb300543d072dc9)
@@ -205,6 +205,6 @@
 int	tcp_connect_message( socket_cores_ref local_sockets, int socket_id, struct sockaddr * addr, socklen_t addrlen );
 int	tcp_recvfrom_message( socket_cores_ref local_sockets, int socket_id, int flags, size_t * addrlen );
-int	tcp_send_message( socket_cores_ref local_sockets, int socket_id, int fragments, size_t data_fragment_size, int flags );
-int	tcp_accept_message( socket_cores_ref local_sockets, int socket_id, size_t * addrlen );
+int	tcp_send_message( socket_cores_ref local_sockets, int socket_id, int fragments, size_t * data_fragment_size, int flags );
+int	tcp_accept_message( socket_cores_ref local_sockets, int socket_id, int new_socket_id, size_t * data_fragment_size, size_t * addrlen );
 int tcp_close_message( socket_cores_ref local_sockets, int socket_id );
 
@@ -298,5 +298,5 @@
 		return tcp_release_and_return( packet, EINVAL );
 	}
-	if( length < sizeof( tcp_header_t ) + offset ){
+	if( length < TCP_HEADER_SIZE + offset ){
 		return tcp_release_and_return( packet, NO_DATA );
 	}
@@ -668,4 +668,6 @@
 	ERROR_DECLARE;
 
+	packet_dimension_ref	packet_dimension;
+
 	assert( socket );
 	assert( socket_data );
@@ -676,5 +678,6 @@
 
 	// queue the received packet
-	if( ERROR_OCCURRED( dyn_fifo_push( & socket->received, packet_get_id( packet ), SOCKET_MAX_RECEIVED_SIZE ))){
+	if( ERROR_OCCURRED( dyn_fifo_push( & socket->received, packet_get_id( packet ), SOCKET_MAX_RECEIVED_SIZE ))
+	|| ERROR_OCCURRED( tl_get_ip_packet_dimension( tcp_globals.ip_phone, & tcp_globals.dimensions, socket_data->device_id, & packet_dimension ))){
 		return tcp_release_and_return( packet, ERROR_CODE );
 	}
@@ -684,5 +687,5 @@
 
 	// notify the destination socket
-	async_msg_5( socket->phone, NET_SOCKET_RECEIVED, ( ipcarg_t ) socket->socket_id, 0, 0, 0, ( ipcarg_t ) fragments );
+	async_msg_5( socket->phone, NET_SOCKET_RECEIVED, ( ipcarg_t ) socket->socket_id, (( packet_dimension->content < socket_data->data_fragment_size ) ? packet_dimension->content : socket_data->data_fragment_size ), 0, 0, ( ipcarg_t ) fragments );
 	return EOK;
 }
@@ -783,4 +786,5 @@
 //			printf( "addr %p\n", socket_data->addr, socket_data->addrlen );
 			// create a socket
+			socket_id = -1;
 			if( ERROR_OCCURRED( socket_create( socket_data->local_sockets, listening_socket->phone, socket_data, & socket_id ))){
 				free( socket_data->addr );
@@ -789,4 +793,5 @@
 			}
 
+			socket_id *= -1;
 			printf("new_sock %d\n", socket_id);
 			socket_data->pseudo_header = listening_socket_data->pseudo_header;
@@ -901,5 +906,5 @@
 			if( ! ERROR_OCCURRED( dyn_fifo_push( & listening_socket->accepted, socket->socket_id, listening_socket_data->backlog ))){
 				// notify the destination socket
-				async_msg_5( socket->phone, NET_SOCKET_ACCEPTED, ( ipcarg_t ) listening_socket->socket_id, 0, 0, 0, ( ipcarg_t ) socket->socket_id );
+				async_msg_5( socket->phone, NET_SOCKET_ACCEPTED, ( ipcarg_t ) listening_socket->socket_id, socket_data->data_fragment_size, TCP_HEADER_SIZE, 0, ( ipcarg_t ) socket->socket_id );
 				fibril_rwlock_write_unlock( socket_data->local_lock );
 				return EOK;
@@ -1035,5 +1040,5 @@
 	bzero( socket_data, sizeof( * socket_data ));
 	socket_data->state = TCP_SOCKET_INITIAL;
-	socket_data->device_id = -1;
+	socket_data->device_id = DEVICE_INVALID_ID;
 	socket_data->window = NET_DEFAULT_TCP_WINDOW;
 	socket_data->treshold = socket_data->window;
@@ -1051,4 +1056,5 @@
 	fibril_mutex_initialize( & socket_data->operation.mutex );
 	fibril_condvar_initialize( & socket_data->operation.condvar );
+	socket_data->data_fragment_size = MAX_TCP_FRAGMENT_SIZE;
 }
 
@@ -1065,4 +1071,5 @@
 	tcp_socket_data_ref		socket_data;
 	socket_core_ref			socket;
+	packet_dimension_ref	packet_dimension;
 
 	/*
@@ -1096,9 +1103,13 @@
 					socket_data->local_sockets = & local_sockets;
 					fibril_rwlock_write_lock( & lock );
+					* SOCKET_SET_SOCKET_ID( answer ) = SOCKET_GET_SOCKET_ID( call );
 					res = socket_create( & local_sockets, app_phone, socket_data, SOCKET_SET_SOCKET_ID( answer ));
 					fibril_rwlock_write_unlock( & lock );
 					if( res == EOK ){
-						* SOCKET_SET_HEADER_SIZE( answer ) = sizeof( tcp_header_t );
-						* SOCKET_SET_DATA_FRAGMENT_SIZE( answer ) = MAX_TCP_FRAGMENT_SIZE;
+						if( tl_get_ip_packet_dimension( tcp_globals.ip_phone, & tcp_globals.dimensions, DEVICE_INVALID_ID, & packet_dimension ) == EOK ){
+							* SOCKET_SET_DATA_FRAGMENT_SIZE( answer ) = (( packet_dimension->content < socket_data->data_fragment_size ) ? packet_dimension->content : socket_data->data_fragment_size );
+						}
+//						* SOCKET_SET_DATA_FRAGMENT_SIZE( answer ) = MAX_TCP_FRAGMENT_SIZE;
+						* SOCKET_SET_HEADER_SIZE( answer ) = TCP_HEADER_SIZE;
 						answer_count = 3;
 					}else{
@@ -1138,5 +1149,5 @@
 				res = data_receive(( void ** ) & addr, & addrlen );
 				if( res == EOK ){
-					// the global lock may released in the tcp_connect_message() function
+					// the global lock may be released in the tcp_connect_message() function
 					fibril_rwlock_write_lock( & tcp_globals.lock );
 					fibril_rwlock_write_lock( & lock );
@@ -1152,5 +1163,5 @@
 				fibril_rwlock_read_lock( & tcp_globals.lock );
 				fibril_rwlock_write_lock( & lock );
-				res = tcp_accept_message( & local_sockets, SOCKET_GET_SOCKET_ID( call ), & addrlen );
+				res = tcp_accept_message( & local_sockets, SOCKET_GET_SOCKET_ID( call ), SOCKET_GET_NEW_SOCKET_ID( call ), SOCKET_SET_DATA_FRAGMENT_SIZE( answer ), & addrlen );
 				fibril_rwlock_write_unlock( & lock );
 				fibril_rwlock_read_unlock( & tcp_globals.lock );
@@ -1158,5 +1169,5 @@
 					* SOCKET_SET_SOCKET_ID( answer ) = res;
 					* SOCKET_SET_ADDRESS_LENGTH( answer ) = addrlen;
-					answer_count = 2;
+					answer_count = 3;
 				}
 				break;
@@ -1164,8 +1175,10 @@
 				fibril_rwlock_read_lock( & tcp_globals.lock );
 				fibril_rwlock_write_lock( & lock );
-				res = tcp_send_message( & local_sockets, SOCKET_GET_SOCKET_ID( call ), SOCKET_GET_DATA_FRAGMENTS( call ), SOCKET_GET_DATA_FRAGMENT_SIZE( call ), SOCKET_GET_FLAGS( call ));
+				res = tcp_send_message( & local_sockets, SOCKET_GET_SOCKET_ID( call ), SOCKET_GET_DATA_FRAGMENTS( call ), SOCKET_SET_DATA_FRAGMENT_SIZE( answer ), SOCKET_GET_FLAGS( call ));
 				if( res != EOK ){
 					fibril_rwlock_write_unlock( & lock );
 					fibril_rwlock_read_unlock( & tcp_globals.lock );
+				}else{
+					answer_count = 2;
 				}
 				break;
@@ -1175,8 +1188,10 @@
 					fibril_rwlock_read_lock( & tcp_globals.lock );
 					fibril_rwlock_write_lock( & lock );
-					res = tcp_send_message( & local_sockets, SOCKET_GET_SOCKET_ID( call ), SOCKET_GET_DATA_FRAGMENTS( call ), SOCKET_GET_DATA_FRAGMENT_SIZE( call ), SOCKET_GET_FLAGS( call ));
+					res = tcp_send_message( & local_sockets, SOCKET_GET_SOCKET_ID( call ), SOCKET_GET_DATA_FRAGMENTS( call ), SOCKET_SET_DATA_FRAGMENT_SIZE( answer ), SOCKET_GET_FLAGS( call ));
 					if( res != EOK ){
 						fibril_rwlock_write_unlock( & lock );
 						fibril_rwlock_read_unlock( & tcp_globals.lock );
+					}else{
+						answer_count = 2;
 					}
 					free( addr );
@@ -1204,5 +1219,5 @@
 					* SOCKET_SET_READ_DATA_LENGTH( answer ) = res;
 					* SOCKET_SET_ADDRESS_LENGTH( answer ) = addrlen;
-					answer_count = 2;
+					answer_count = 3;
 					res = EOK;
 				}
@@ -1725,5 +1740,5 @@
 }
 
-int tcp_send_message( socket_cores_ref local_sockets, int socket_id, int fragments, size_t data_fragment_size, int flags ){
+int tcp_send_message( socket_cores_ref local_sockets, int socket_id, int fragments, size_t * data_fragment_size, int flags ){
 	ERROR_DECLARE;
 
@@ -1738,4 +1753,5 @@
 
 	assert( local_sockets );
+	assert( data_fragment_size );
 
 	// find the socket
@@ -1753,10 +1769,9 @@
 	ERROR_PROPAGATE( tl_get_ip_packet_dimension( tcp_globals.ip_phone, & tcp_globals.dimensions, socket_data->device_id, & packet_dimension ));
 
-	// TODO return the device_id + data_fragment_size if different - the client should send it again
-	// ( two messages are better than ip fragmentation )
+	* data_fragment_size = (( packet_dimension->content < socket_data->data_fragment_size ) ? packet_dimension->content : socket_data->data_fragment_size );
 
 	for( index = 0; index < fragments; ++ index ){
 		// read the data fragment
-		result = tl_socket_read_packet_data( tcp_globals.net_phone, & packet, sizeof( tcp_header_t ), packet_dimension, socket_data->addr, socket_data->addrlen );
+		result = tl_socket_read_packet_data( tcp_globals.net_phone, & packet, TCP_HEADER_SIZE, packet_dimension, socket_data->addr, socket_data->addrlen );
 		if( result < 0 ) return result;
 		total_length = ( size_t ) result;
@@ -1844,5 +1859,5 @@
 	ERROR_PROPAGATE( tl_get_ip_packet_dimension( tcp_globals.ip_phone, & tcp_globals.dimensions, socket_data->device_id, & packet_dimension ));
 	// get a new packet
-	* packet = packet_get_4( tcp_globals.net_phone, sizeof( tcp_header_t ), packet_dimension->addr_len, packet_dimension->prefix, packet_dimension->suffix );
+	* packet = packet_get_4( tcp_globals.net_phone, TCP_HEADER_SIZE, packet_dimension->addr_len, packet_dimension->prefix, packet_dimension->suffix );
 	if( ! * packet ) return ENOMEM;
 	// allocate space in the packet
@@ -1856,5 +1871,5 @@
 }
 
-int tcp_accept_message( socket_cores_ref local_sockets, int socket_id, size_t * addrlen ){
+int tcp_accept_message( socket_cores_ref local_sockets, int socket_id, int new_socket_id, size_t * data_fragment_size, size_t * addrlen ){
 	ERROR_DECLARE;
 
@@ -1862,6 +1877,8 @@
 	socket_core_ref		socket;
 	tcp_socket_data_ref	socket_data;
+	packet_dimension_ref	packet_dimension;
 
 	assert( local_sockets );
+	assert( data_fragment_size );
 	assert( addrlen );
 
@@ -1887,7 +1904,14 @@
 		socket_data = ( tcp_socket_data_ref ) accepted->specific_data;
 		assert( socket_data );
+		// TODO can it be in another state?
 		if( socket_data->state == TCP_SOCKET_ESTABLISHED ){
 			ERROR_PROPAGATE( data_reply( socket_data->addr, socket_data->addrlen ));
+			ERROR_PROPAGATE( tl_get_ip_packet_dimension( tcp_globals.ip_phone, & tcp_globals.dimensions, socket_data->device_id, & packet_dimension ));
 			* addrlen = socket_data->addrlen;
+			* data_fragment_size = (( packet_dimension->content < socket_data->data_fragment_size ) ? packet_dimension->content : socket_data->data_fragment_size );
+			if( new_socket_id > 0 ){
+				ERROR_PROPAGATE( socket_cores_update( local_sockets, accepted->socket_id, new_socket_id ));
+				accepted->socket_id = new_socket_id;
+			}
 		}
 		dyn_fifo_pop( & socket->accepted );
Index: uspace/srv/net/tl/tcp/tcp_header.h
===================================================================
--- uspace/srv/net/tl/tcp/tcp_header.h	(revision 1a0fb3f8aa71e3bb907eb17703615fc685752ca1)
+++ uspace/srv/net/tl/tcp/tcp_header.h	(revision ede63e47763744e7b1eba0111fb300543d072dc9)
@@ -41,4 +41,8 @@
 #include <sys/types.h>
 
+/** TCP header size in bytes.
+ */
+#define TCP_HEADER_SIZE			sizeof( tcp_header_t )
+
 /** Returns the actual TCP header length in bytes.
  *  @param[in] header The TCP packet header.
Index: uspace/srv/net/tl/udp/udp.c
===================================================================
--- uspace/srv/net/tl/udp/udp.c	(revision 1a0fb3f8aa71e3bb907eb17703615fc685752ca1)
+++ uspace/srv/net/tl/udp/udp.c	(revision ede63e47763744e7b1eba0111fb300543d072dc9)
@@ -97,5 +97,5 @@
  *  Is used as an entry point from the underlying IP module.
  *  Locks the global lock and calls udp_process_packet() function.
- *  @param device_id The device identifier. Ignored parameter.
+ *  @param[in] device_id The receiving device identifier.
  *  @param[in,out] packet The received packet queue.
  *  @param receiver The target service. Ignored parameter.
@@ -109,4 +109,5 @@
  *  Notifies the destination socket application.
  *  Releases the packet on error or sends an ICMP error notification..
+ *  @param[in] device_id The receiving device identifier.
  *  @param[in,out] packet The received packet queue.
  *  @param[in] error The packet error reporting service. Prefixes the received packet.
@@ -120,5 +121,5 @@
  *  @returns Other error codes as defined for the ip_client_process_packet() function.
  */
-int udp_process_packet( packet_t packet, services_t error );
+int udp_process_packet( device_id_t device_id, packet_t packet, services_t error );
 
 /** Releases the packet and returns the result.
@@ -151,5 +152,5 @@
  *  @param[in] addrlen The address length.
  *  @param[in] fragments The number of data fragments.
- *  @param[in] data_fragment_size The data fragment size in bytes.
+ *  @param[out] data_fragment_size The data fragment size in bytes.
  *  @param[in] flags Various send flags.
  *  @returns EOK on success.
@@ -163,5 +164,5 @@
  *  @returns Other error codes as defined for the ip_send_msg() function.
  */
-int udp_sendto_message( socket_cores_ref local_sockets, int socket_id, const struct sockaddr * addr, socklen_t addrlen, int fragments, size_t data_fragment_size, int flags );
+int udp_sendto_message( socket_cores_ref local_sockets, int socket_id, const struct sockaddr * addr, socklen_t addrlen, int fragments, size_t * data_fragment_size, int flags );
 
 /** Receives data to the socket.
@@ -235,5 +236,5 @@
 
 	fibril_rwlock_write_lock( & udp_globals.lock );
-	result = udp_process_packet( packet, error );
+	result = udp_process_packet( device_id, packet, error );
 	if( result != EOK ){
 		fibril_rwlock_write_unlock( & udp_globals.lock );
@@ -243,5 +244,5 @@
 }
 
-int udp_process_packet( packet_t packet, services_t error ){
+int udp_process_packet( device_id_t device_id, packet_t packet, services_t error ){
 	ERROR_DECLARE;
 
@@ -261,4 +262,5 @@
 	struct sockaddr *		src;
 	struct sockaddr *		dest;
+	packet_dimension_ref	packet_dimension;
 
 	if( error ){
@@ -292,5 +294,5 @@
 		return udp_release_and_return( packet, EINVAL );
 	}
-	if( length < sizeof( udp_header_t ) + offset ){
+	if( length < UDP_HEADER_SIZE + offset ){
 		return udp_release_and_return( packet, NO_DATA );
 	}
@@ -380,5 +382,6 @@
 
 	// queue the received packet
-	if( ERROR_OCCURRED( dyn_fifo_push( & socket->received, packet_get_id( packet ), SOCKET_MAX_RECEIVED_SIZE ))){
+	if( ERROR_OCCURRED( dyn_fifo_push( & socket->received, packet_get_id( packet ), SOCKET_MAX_RECEIVED_SIZE ))
+	|| ERROR_OCCURRED( tl_get_ip_packet_dimension( udp_globals.ip_phone, & udp_globals.dimensions, device_id, & packet_dimension ))){
 		return udp_release_and_return( packet, ERROR_CODE );
 	}
@@ -386,6 +389,8 @@
 	// notify the destination socket
 	fibril_rwlock_write_unlock( & udp_globals.lock );
+	async_msg_5( socket->phone, NET_SOCKET_RECEIVED, ( ipcarg_t ) socket->socket_id, packet_dimension->content, 0, 0, ( ipcarg_t ) fragments );
+/*	fibril_rwlock_write_unlock( & udp_globals.lock );
 	async_msg_5( socket->phone, NET_SOCKET_RECEIVED, ( ipcarg_t ) socket->socket_id, 0, 0, 0, ( ipcarg_t ) fragments );
-	return EOK;
+*/	return EOK;
 }
 
@@ -418,4 +423,5 @@
 	ipc_call_t				answer;
 	int						answer_count;
+	packet_dimension_ref	packet_dimension;
 
 	/*
@@ -444,10 +450,15 @@
 			case NET_SOCKET:
 				fibril_rwlock_write_lock( & lock );
+				* SOCKET_SET_SOCKET_ID( answer ) = SOCKET_GET_SOCKET_ID( call );
 				res = socket_create( & local_sockets, app_phone, NULL, SOCKET_SET_SOCKET_ID( answer ));
 				fibril_rwlock_write_unlock( & lock );
-				// TODO max fragment size
-				* SOCKET_SET_DATA_FRAGMENT_SIZE( answer ) = MAX_UDP_FRAGMENT_SIZE;
-				* SOCKET_SET_HEADER_SIZE( answer ) = sizeof( udp_header_t );
-				answer_count = 3;
+				if( res == EOK ){
+					if( tl_get_ip_packet_dimension( udp_globals.ip_phone, & udp_globals.dimensions, DEVICE_INVALID_ID, & packet_dimension ) == EOK ){
+						* SOCKET_SET_DATA_FRAGMENT_SIZE( answer ) = packet_dimension->content;
+					}
+//					* SOCKET_SET_DATA_FRAGMENT_SIZE( answer ) = MAX_UDP_FRAGMENT_SIZE;
+					* SOCKET_SET_HEADER_SIZE( answer ) = UDP_HEADER_SIZE;
+					answer_count = 3;
+				}
 				break;
 			case NET_SOCKET_BIND:
@@ -467,7 +478,9 @@
 					fibril_rwlock_read_lock( & lock );
 					fibril_rwlock_write_lock( & udp_globals.lock );
-					res = udp_sendto_message( & local_sockets, SOCKET_GET_SOCKET_ID( call ), addr, addrlen, SOCKET_GET_DATA_FRAGMENTS( call ), SOCKET_GET_DATA_FRAGMENT_SIZE( call ), SOCKET_GET_FLAGS( call ));
+					res = udp_sendto_message( & local_sockets, SOCKET_GET_SOCKET_ID( call ), addr, addrlen, SOCKET_GET_DATA_FRAGMENTS( call ), SOCKET_SET_DATA_FRAGMENT_SIZE( answer ), SOCKET_GET_FLAGS( call ));
 					if( res != EOK ){
 						fibril_rwlock_write_unlock( & udp_globals.lock );
+					}else{
+						answer_count = 2;
 					}
 					fibril_rwlock_read_unlock( & lock );
@@ -484,5 +497,5 @@
 					* SOCKET_SET_READ_DATA_LENGTH( answer ) = res;
 					* SOCKET_SET_ADDRESS_LENGTH( answer ) = addrlen;
-					answer_count = 2;
+					answer_count = 3;
 					res = EOK;
 				}
@@ -513,5 +526,5 @@
 }
 
-int udp_sendto_message( socket_cores_ref local_sockets, int socket_id, const struct sockaddr * addr, socklen_t addrlen, int fragments, size_t data_fragment_size, int flags ){
+int udp_sendto_message( socket_cores_ref local_sockets, int socket_id, const struct sockaddr * addr, socklen_t addrlen, int fragments, size_t * data_fragment_size, int flags ){
 	ERROR_DECLARE;
 
@@ -571,5 +584,5 @@
 
 	// read the first packet fragment
-	result = tl_socket_read_packet_data( udp_globals.net_phone, & packet, sizeof( udp_header_t ), packet_dimension, addr, addrlen );
+	result = tl_socket_read_packet_data( udp_globals.net_phone, & packet, UDP_HEADER_SIZE, packet_dimension, addr, addrlen );
 	if( result < 0 ) return result;
 	total_length = ( size_t ) result;
@@ -606,5 +619,5 @@
 //			return udp_release_and_return( packet, ERROR_CODE );
 //		}
-		if( ERROR_OCCURRED( ip_client_set_pseudo_header_data_length( ip_header, headerlen, total_length + sizeof( udp_header_t )))){
+		if( ERROR_OCCURRED( ip_client_set_pseudo_header_data_length( ip_header, headerlen, total_length + UDP_HEADER_SIZE))){
 			free( ip_header );
 			return udp_release_and_return( packet, ERROR_CODE );
@@ -615,5 +628,5 @@
 		free( ip_header );
 	}else{
-		device_id = -1;
+		device_id = DEVICE_INVALID_ID;
 	}
 	// prepare the first packet fragment
@@ -665,5 +678,5 @@
 
 	// trim the header
-	ERROR_PROPAGATE( packet_trim( packet, sizeof( udp_header_t ), 0 ));
+	ERROR_PROPAGATE( packet_trim( packet, UDP_HEADER_SIZE, 0 ));
 
 	// reply the packets
Index: uspace/srv/net/tl/udp/udp_header.h
===================================================================
--- uspace/srv/net/tl/udp/udp_header.h	(revision 1a0fb3f8aa71e3bb907eb17703615fc685752ca1)
+++ uspace/srv/net/tl/udp/udp_header.h	(revision ede63e47763744e7b1eba0111fb300543d072dc9)
@@ -41,4 +41,8 @@
 #include <sys/types.h>
 
+/** UDP header size in bytes.
+ */
+#define UDP_HEADER_SIZE			sizeof( udp_header_t )
+
 /** Type definition of the user datagram header.
  *  @see udp_header
