Subversion Repositories HelenOS

Compare Revisions

Ignore whitespace Rev 4720 → Rev 4721

/branches/network/uspace/srv/net/tl/icmp/icmp_client.c
51,7 → 51,10
icmp_header_ref header;
 
header = ( icmp_header_ref ) packet_get_data( packet );
if( ! header ) return ENOMEM;
if(( ! header )
|| ( packet_get_data_length( packet ) < sizeof( icmp_header_t ))){
return 0;
}
if( type ) * type = header->type;
if( code ) * code = header->code;
if( pointer ) * pointer = header->un.param.pointer;
59,7 → 62,10
return sizeof( icmp_header_t );
}
 
int icmp_client_header_length( packet_t packet ){
size_t icmp_client_header_length( packet_t packet ){
if( packet_get_data_length( packet ) < sizeof( icmp_header_t )){
return 0;
}
return sizeof( icmp_header_t );
}
 
/branches/network/uspace/srv/net/tl/icmp/icmp.c
39,6 → 39,7
#include <atomic.h>
#include <fibril.h>
#include <fibril_sync.h>
#include <stdint.h>
 
#include <ipc/ipc.h>
#include <ipc/services.h>
78,6 → 79,14
*/
#define ICMP_KEEP_LENGTH 8
 
/** Free identifier numbers pool start.
*/
#define ICMP_FREE_IDS_START 1
 
/** Free identifier numbers pool end.
*/
#define ICMP_FREE_IDS_END MAX_UINT16
 
/** Computes the ICMP datagram checksum.
* @param header The ICMP datagram header. Input/output parameter.
* @param length The total datagram length. Input parameter.
226,6 → 235,15
*/
int icmp_timeout_for_reply( void * data );
 
/** Assigns a new identifier for the connection.
* Fills the echo data parameter with the assigned values.
* @param echo_data The echo data to be bound. Input/output parameter.
* @returns Index of the inserted echo data.
* @returns EBADMEM if the echo_data parameter is NULL.
* @returns ENOTCONN if no free identifier have been found.
*/
int icmp_bind_free_id( icmp_echo_ref echo_data );
 
/** ICMP reply timeout data.
* Used as a timeouting fibril argument.
* @see icmp_timeout_for_reply()
245,7 → 263,7
 
INT_MAP_IMPLEMENT( icmp_replies, icmp_reply_t );
 
GENERIC_FIELD_IMPLEMENT( icmp_echo_data, icmp_echo_t );
INT_MAP_IMPLEMENT( icmp_echo_data, icmp_echo_t );
 
int icmp_echo_msg( int icmp_phone, size_t size, mseconds_t timeout, ip_ttl_t ttl, ip_tos_t tos, int dont_fragment, const struct sockaddr * addr, socklen_t addrlen ){
icmp_echo_ref echo_data;
253,12 → 271,16
 
fibril_rwlock_write_lock( & icmp_globals.lock );
// use the phone as the echo data index
echo_data = icmp_echo_data_get_index( & icmp_globals.echo_data, icmp_phone );
echo_data = icmp_echo_data_find( & icmp_globals.echo_data, icmp_phone );
if( ! echo_data ){
res = ENOENT;
}else{
res = icmp_echo( echo_data->id, echo_data->sequence, size, timeout, ttl, tos, dont_fragment, addr, addrlen );
++ echo_data->sequence;
if( echo_data->sequence < MAX_UINT16 ){
++ echo_data->sequence;
}else{
echo_data->sequence = 0;
}
}
fibril_rwlock_write_unlock( & icmp_globals.lock );
return res;
431,7 → 453,7
 
icmp_header_ref icmp_prepare_packet( packet_t packet ){
icmp_header_ref header;
int header_length;
size_t header_length;
size_t total_length;
 
total_length = packet_get_data_length( packet );
439,7 → 461,7
header_length = ip_client_header_length( packet );
if( header_length <= 0 ) return NULL;
// truncate if longer than 64 bits (without the IP header)
if(( total_length - header_length > ICMP_KEEP_LENGTH )
if(( total_length > header_length + ICMP_KEEP_LENGTH )
&& ( packet_trim( packet, 0, total_length - header_length - ICMP_KEEP_LENGTH ) != EOK )){
return NULL;
}
468,6 → 490,7
 
int icmp_connect_module( services_t service ){
icmp_echo_ref echo_data;
icmp_param_t id;
int index;
 
echo_data = ( icmp_echo_ref ) malloc( sizeof( * echo_data ));
474,17 → 497,15
if( ! echo_data ) return ENOMEM;
// assign a new identifier
fibril_rwlock_write_lock( & icmp_globals.lock );
++ icmp_globals.last_used_id;
echo_data->id = icmp_globals.last_used_id;
echo_data->sequence = 0;
// remember the assigned echo data
index = icmp_echo_data_add( & icmp_globals.echo_data, echo_data );
index = icmp_bind_free_id( echo_data );
if( index < 0 ){
free( echo_data );
}else{
id = echo_data->id;
}
fibril_rwlock_write_unlock( & icmp_globals.lock );
// return the echo data index as the ICMP phone
return index;
// return the echo data identifier as the ICMP phone
return id;
}
 
int icmp_initialize( async_client_conn_t client_connection ){
544,12 → 565,12
switch( error ){
case SERVICE_ICMP:
// process error
// TODO remove debug dump
// length = icmp_client_header_length( packet );
result = icmp_client_process_packet( packet, & type, & code, NULL, NULL );
if( result < 0 ) return result;
length = ( size_t ) result;
// TODO remove debug dump
printf( "ICMP error %d (%d) in packet %d\n", type, code, packet_get_id( packet ) );
// remove the error header
ERROR_PROPAGATE( packet_trim( packet, length, 0 ));
break;
default:
557,9 → 578,8
}
}
// get rid of the ip header
result = ip_client_process_packet( packet, NULL, NULL, NULL, NULL, NULL );
if( result < 0 ) return result;
ERROR_PROPAGATE( packet_trim( packet, ( size_t ) result, 0 ));
length = ip_client_header_length( packet );
ERROR_PROPAGATE( packet_trim( packet, length, 0 ));
 
length = packet_get_data_length( packet );
if( length <= 0 ) return EINVAL;
569,21 → 589,7
// get icmp header
header = ( icmp_header_ref ) data;
// checksum
/* if(( header->checksum ) && ( ICMP_CHECKSUM( header, length ))){
// set the original message type on error notification
// type swap observed in Qemu
if( error ){
switch( header->type ){
case ICMP_ECHOREPLY:
header->type = ICMP_ECHO;
break;
}
}
if( ICMP_CHECKSUM( header, length )){
return EINVAL;
}
}
*/ if( header->checksum ){
if( header->checksum ){
while( ICMP_CHECKSUM( header, length )){
// set the original message type on error notification
// type swap observed in Qemu
693,9 → 699,8
int answer_count;
size_t length;
struct sockaddr * addr;
icmp_param_t id;
icmp_param_t sequence = 0;
ipc_callid_t data_callid;
icmp_echo_ref echo_data;
 
/*
* Accept the connection
705,11 → 710,16
 
fibril_rwlock_initialize( & lock );
 
echo_data = ( icmp_echo_ref ) malloc( sizeof( * echo_data ));
if( ! echo_data ) return ENOMEM;
// assign a new identifier
fibril_rwlock_write_lock( & icmp_globals.lock );
++ icmp_globals.last_used_id;
id = icmp_globals.last_used_id;
ERROR_CODE = icmp_bind_free_id( echo_data );
fibril_rwlock_write_unlock( & icmp_globals.lock );
if( ERROR_CODE < 0 ){
free( echo_data );
return ERROR_CODE;
}
 
while( keep_on_going ){
refresh_answer( & answer, & answer_count );
732,10 → 742,14
}else{
if( ! ERROR_OCCURRED( ipc_data_write_finalize( data_callid, addr, length ))){
fibril_rwlock_write_lock( & icmp_globals.lock );
ERROR_CODE = icmp_echo( id, sequence, ICMP_GET_SIZE( call ), ICMP_GET_TIMEOUT( call ), ICMP_GET_TTL( call ), ICMP_GET_TOS( call ), ICMP_GET_DONT_FRAGMENT( call ), addr, ( socklen_t ) length );
ERROR_CODE = icmp_echo( echo_data->id, echo_data->sequence, ICMP_GET_SIZE( call ), ICMP_GET_TIMEOUT( call ), ICMP_GET_TTL( call ), ICMP_GET_TOS( call ), ICMP_GET_DONT_FRAGMENT( call ), addr, ( socklen_t ) length );
fibril_rwlock_write_unlock( & icmp_globals.lock );
free( addr );
++ sequence;
if( echo_data->sequence < MAX_UINT16 ){
++ echo_data->sequence;
}else{
echo_data->sequence = 0;
}
}
}
}
748,6 → 762,10
answer_call( callid, ERROR_CODE, & answer, answer_count );
}
 
// release the identifier
fibril_rwlock_write_lock( & icmp_globals.lock );
icmp_echo_data_exclude( & icmp_globals.echo_data, echo_data->id );
fibril_rwlock_write_unlock( & icmp_globals.lock );
return EOK;
}
 
787,5 → 805,34
return result;
}
 
int icmp_bind_free_id( icmp_echo_ref echo_data ){
icmp_param_t index;
 
if( ! echo_data ) return EBADMEM;
// from the last used one
index = icmp_globals.last_used_id;
do{
++ index;
// til the range end
if( index >= ICMP_FREE_IDS_END ){
// start from the range beginning
index = ICMP_FREE_IDS_START - 1;
do{
++ index;
// til the last used one
if( index >= icmp_globals.last_used_id ){
// none found
return ENOTCONN;
}
}while( icmp_echo_data_find( & icmp_globals.echo_data, index ) != NULL );
// found, break immediately
break;
}
}while( icmp_echo_data_find( & icmp_globals.echo_data, index ) != NULL );
echo_data->id = index;
echo_data->sequence = 0;
return icmp_echo_data_add( & icmp_globals.echo_data, index, echo_data );
}
 
/** @}
*/
/branches/network/uspace/srv/net/tl/icmp/icmp.h
42,7 → 42,6
#include "../../include/icmp_codes.h"
 
#include "../../structures/int_map.h"
#include "../../structures/generic_field.h"
 
#include "icmp_header.h"
 
68,12 → 67,11
*/
INT_MAP_DECLARE( icmp_replies, icmp_reply_t );
 
/** Echo specific data field.
* Used for bundle modules.
* The bundle module gets an index to the assigned echo specific data while connecting.
* The index is used in the future semi-remote calls instead of the ICMP phone.
/** Echo specific data map.
* The bundle module gets an identifier of the assigned echo specific data while connecting.
* The identifier is used in the future semi-remote calls instead of the ICMP phone.
*/
GENERIC_FIELD_DECLARE( icmp_echo_data, icmp_echo_t );
INT_MAP_DECLARE( icmp_echo_data, icmp_echo_t );
 
/** ICMP reply data.
*/
/branches/network/uspace/srv/net/include/ip_client.h
50,9 → 50,9
/** Returns the IP header length.
* @param packet The packet. Input parameter.
* @returns The IP header length in bytes.
* @returns ENOMEM if there is no IP header.
* @returns Zero (0) if there is no IP header.
*/
int ip_client_header_length( packet_t packet );
size_t ip_client_header_length( packet_t packet );
 
// TODO ipopt manipulation
 
/branches/network/uspace/srv/net/include/icmp_client.h
47,7 → 47,7
* @param pointer The ICMP header pointer. Output parameter.
* @param mtu The ICMP header MTU. Output parameter.
* @returns The ICMP header length.
* @returns ENOMEM if the packet contains no data.
* @returns Zero (0) if the packet contains no data.
*/
int icmp_client_process_packet( packet_t packet, icmp_type_t * type, icmp_code_t * code, icmp_param_t * pointer, icmp_param_t * mtu );
 
54,9 → 54,8
/** Returns the ICMP header length.
* @param packet The packet. Input parameter.
* @returns The ICMP header length in bytes.
* @returns ENOMEM if there is no ICMP header.
*/
int icmp_client_header_length( packet_t packet );
size_t icmp_client_header_length( packet_t packet );
 
#endif
 
/branches/network/uspace/srv/net/il/ip/ip_client.c
72,7 → 72,10
ip_header_ref header;
 
header = ( ip_header_ref ) packet_get_data( packet );
if( ! header ) return ENOMEM;
if(( ! header )
|| ( packet_get_data_length( packet ) < sizeof( ip_header_t ))){
return ENOMEM;
}
if( protocol ) * protocol = header->protocol;
if( ttl ) * ttl = header->ttl;
if( tos ) * tos = header->tos;
85,12 → 88,15
}
}
 
int ip_client_header_length( packet_t packet ){
size_t ip_client_header_length( packet_t packet ){
ip_header_ref header;
 
header = ( ip_header_ref ) packet_get_data( packet );
if( ! header ) return ENOMEM;
return header->ihl * 4;
if(( ! header )
|| ( packet_get_data_length( packet ) < sizeof( ip_header_t ))){
return 0;
}
return header->ihl * 4u;
}
 
/** @}