/branches/network/uspace/srv/net/tl/icmp/icmp.c |
---|
228,10 → 228,18 |
* Sets the message type and code and computes the checksum. |
* Error messages are sent only if allowed in the configuration. |
* Releases the packet on errors. |
* @param type The message type. Input parameter. |
* @param code The message code. Input parameter. |
* @param packet The message packet to be sent. Input parameter. |
* @param header The ICMP header. Input parameter. |
* @param error The error service to be announced. Should be SERVICE_ICMP or zero (0). Input parametr. |
* @param ttl The time to live. Input parameter. |
* @param tos The type of service. Input parameter. |
* @param dont_fragment The value indicating whether the datagram must not be fragmented. Is used as a MTU discovery. Input parameter. |
* @returns EOK on success. |
* @returns EPERM if the error message is not allowed. |
*/ |
int icmp_send_packet( icmp_type_t type, icmp_code_t code, packet_t packet, icmp_header_ref header, services_t error ); |
int icmp_send_packet( icmp_type_t type, icmp_code_t code, packet_t packet, icmp_header_ref header, services_t error, ip_ttl_t ttl, ip_tos_t tos, int dont_fragment ); |
/** Tries to set the pending reply result as the received message type. |
* If the reply data are still present, the reply timeouted and the parent fibril is awaken. |
404,7 → 412,7 |
fibril_rwlock_write_unlock( & icmp_globals.lock ); |
// send the request |
icmp_send_packet( ICMP_ECHO, 0, packet, header, 0 ); |
icmp_send_packet( ICMP_ECHO, 0, packet, header, 0, ttl, tos, dont_fragment ); |
// wait for a reply |
fibril_condvar_wait( & reply->condvar, & reply->mutex ); |
428,7 → 436,7 |
if( mtu ){ |
header->un.frag.mtu = mtu; |
} |
return icmp_send_packet( ICMP_DEST_UNREACH, code, packet, header, SERVICE_ICMP ); |
return icmp_send_packet( ICMP_DEST_UNREACH, code, packet, header, SERVICE_ICMP, 0, 0, 0 ); |
} |
int icmp_source_quench_msg( int icmp_phone, packet_t packet ){ |
438,7 → 446,7 |
if( ! header ){ |
return icmp_release_and_return( packet, ENOMEM ); |
} |
return icmp_send_packet( ICMP_SOURCE_QUENCH, 0, packet, header, SERVICE_ICMP ); |
return icmp_send_packet( ICMP_SOURCE_QUENCH, 0, packet, header, SERVICE_ICMP, 0, 0, 0 ); |
} |
int icmp_time_exceeded_msg( int icmp_phone, icmp_code_t code, packet_t packet ){ |
448,7 → 456,7 |
if( ! header ){ |
return icmp_release_and_return( packet, ENOMEM ); |
} |
return icmp_send_packet( ICMP_TIME_EXCEEDED, code, packet, header, SERVICE_ICMP ); |
return icmp_send_packet( ICMP_TIME_EXCEEDED, code, packet, header, SERVICE_ICMP, 0, 0, 0 ); |
} |
int icmp_parameter_problem_msg( int icmp_phone, icmp_code_t code, icmp_param_t pointer, packet_t packet ){ |
459,7 → 467,7 |
return icmp_release_and_return( packet, ENOMEM ); |
} |
header->un.param.pointer = pointer; |
return icmp_send_packet( ICMP_PARAMETERPROB, code, packet, header, SERVICE_ICMP ); |
return icmp_send_packet( ICMP_PARAMETERPROB, code, packet, header, SERVICE_ICMP, 0, 0, 0 ); |
} |
icmp_header_ref icmp_prepare_packet( packet_t packet ){ |
482,7 → 490,7 |
return header; |
} |
int icmp_send_packet( icmp_type_t type, icmp_code_t code, packet_t packet, icmp_header_ref header, services_t error ){ |
int icmp_send_packet( icmp_type_t type, icmp_code_t code, packet_t packet, icmp_header_ref header, services_t error, ip_ttl_t ttl, ip_tos_t tos, int dont_fragment ){ |
ERROR_DECLARE; |
// do not send an error if disabled |
493,7 → 501,7 |
header->code = code; |
header->checksum = 0; |
header->checksum = ICMP_CHECKSUM( header, packet_get_data_length( packet )); |
if( ERROR_OCCURRED( ip_client_prepare_packet( packet, IPPROTO_ICMP, 0, 0, 0, 0 ))){ |
if( ERROR_OCCURRED( ip_client_prepare_packet( packet, IPPROTO_ICMP, ttl, tos, dont_fragment, 0 ))){ |
return icmp_release_and_return( packet, ERROR_CODE ); |
} |
return ip_send_msg( icmp_globals.ip_phone, -1, packet, SERVICE_ICMP, error ); |
587,8 → 595,6 |
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; |
639,7 → 645,7 |
// set both addresses to the source one (avoids the source address deletion before setting the destination one) |
&& ( packet_set_addr( packet, src, src, ( size_t ) addrlen ) == EOK )){ |
// send the reply |
icmp_send_packet( ICMP_ECHOREPLY, 0, packet, header, 0 ); |
icmp_send_packet( ICMP_ECHOREPLY, 0, packet, header, 0, 0, 0, 0 ); |
return EOK; |
}else{ |
return EINVAL; |
/branches/network/uspace/srv/net/tl/tl_common.c |
---|
99,7 → 99,7 |
} |
} |
void tl_send_icmp_port_unreachable( int packet_phone, int icmp_phone, packet_t packet, services_t error ){ |
int tl_prepare_icmp_packet( int packet_phone, int icmp_phone, packet_t packet, services_t error ){ |
packet_t next; |
uint8_t * src; |
int length; |
115,10 → 115,11 |
&& ( icmp_phone >= 0 ) |
// set both addresses to the source one (avoids the source address deletion before setting the destination one) |
&& ( packet_set_addr( packet, src, src, ( size_t ) length ) == EOK )){ |
icmp_destination_unreachable_msg( icmp_phone, ICMP_PORT_UNREACH, 0, packet ); |
return EOK; |
}else{ |
pq_release( packet_phone, packet_get_id( packet )); |
} |
return ENOENT; |
} |
int tl_socket_read_packet_data( int packet_phone, packet_ref packet, size_t prefix, const packet_dimension_ref dimension, const struct sockaddr * addr, socklen_t addrlen ){ |
/branches/network/uspace/srv/net/tl/udp/udp.c |
---|
243,7 → 243,6 |
size_t length; |
size_t offset; |
int result; |
uint8_t * data; |
udp_header_ref header; |
socket_core_ref * socket; |
packet_t next_packet; |
260,14 → 259,13 |
if( error ){ |
switch( error ){ |
case SERVICE_ICMP: |
// ignore error |
// length = icmp_client_header_length( packet ); |
// 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 udp_release_and_return( packet, result ); |
} |
printf( "ICMP error %d (%d) in packet %d\n", type, code, packet_get_id( packet ) ); |
length = ( size_t ) result; |
if( ERROR_OCCURRED( packet_trim( packet, length, 0 ))){ |
return udp_release_and_return( packet, ERROR_CODE ); |
291,22 → 289,26 |
if( length < sizeof( udp_header_t ) + offset ){ |
return udp_release_and_return( packet, NO_DATA ); |
} |
data = packet_get_data( packet ); |
if( ! data ){ |
// trim all but UDP header |
if( ERROR_OCCURRED( packet_trim( packet, offset, 0 ))){ |
return udp_release_and_return( packet, ERROR_CODE ); |
} |
// get udp header |
header = ( udp_header_ref ) packet_get_data( packet ); |
if( ! header ){ |
return udp_release_and_return( packet, NO_DATA ); |
} |
// get udp header |
header = ( udp_header_ref )( data + offset ); |
// find the destination socket |
socket = socket_ports_find( & udp_globals.sockets, ntohs( header->destination_port )); |
if( ! socket ){ |
tl_send_icmp_port_unreachable( udp_globals.net_phone, udp_globals.icmp_phone, packet, error ); |
if( tl_prepare_icmp_packet( udp_globals.net_phone, udp_globals.icmp_phone, packet, error ) == EOK ){ |
icmp_destination_unreachable_msg( udp_globals.icmp_phone, ICMP_PORT_UNREACH, 0, packet ); |
} |
return EADDRNOTAVAIL; |
} |
// trim after successful processing to be able to send an ICMP error message! |
ERROR_PROPAGATE( packet_trim( packet, offset, 0 )); |
// count the received packet fragments |
next_packet = packet; |
fragments = 0; |
363,12 → 365,13 |
// check checksum |
if( header->checksum ){ |
if( flip_checksum( compact_checksum( checksum ))){ |
// TODO checksum error ICMP? |
// TODO remove debug dump |
printf("udp check failed %x => %x\n", header->checksum, flip_checksum( compact_checksum( checksum ))); |
return udp_release_and_return( packet, EINVAL ); |
if( tl_prepare_icmp_packet( udp_globals.net_phone, udp_globals.icmp_phone, packet, error ) == EOK ){ |
// checksum error ICMP |
icmp_parameter_problem_msg( udp_globals.icmp_phone, ICMP_PARAM_POINTER, (( size_t ) (( void * ) & header->checksum )) - (( size_t ) (( void * ) header )), packet ); |
} |
return EINVAL; |
} |
} |
// queue the received packet |
if( ERROR_OCCURRED( dyn_fifo_push( &( ** socket ).received, packet_get_id( packet ), SOCKET_MAX_RECEIVED_SIZE ))){ |
436,6 → 439,7 |
// fibril_rwlock_write_lock( & lock ); |
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; |
582,11 → 586,7 |
free( ip_header ); |
return udp_release_and_return( packet, ERROR_CODE ); |
} |
/*// TODO remove debug dump: |
uint8_t * data; |
data = ip_header; |
printf( "ip_header:\tlength\t= %d\n\tdata\t= %.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX:%.2hhX %.2hhX %.2hhX %.2hhX\n", headerlen, data[ 0 ], data[ 1 ], data[ 2 ], data[ 3 ], data[ 4 ], data[ 5 ], data[ 6 ], data[ 7 ], data[ 8 ], data[ 9 ], data[ 10 ], data[ 11 ] ); |
*/ checksum = compute_checksum( checksum, ip_header, headerlen ); |
checksum = compute_checksum( checksum, ip_header, headerlen ); |
checksum = compute_checksum( checksum, ( uint8_t * ) header, sizeof( * header )); |
header->checksum = htons( flip_checksum( compact_checksum( checksum ))); |
free( ip_header ); |
/branches/network/uspace/srv/net/tl/tl_common.h |
---|
91,15 → 91,17 |
*/ |
int tl_set_address_port( struct sockaddr * addr, int addrlen, uint16_t port ); |
/** Sends the port unreachable ICMP notification. |
* Sends the first packet and releases all the others. |
* Releases the packet queu on error. |
/** Prepares the packet for ICMP error notification. |
* Keeps the first packet and releases all the others. |
* Releases all the packets on error. |
* @param packet_phone The packet server module phone. Input parameter. |
* @param icmp_phone The ICMP module phone. Input parameter. |
* @param packet The packet to be send. Input parameter. |
* @param error The packet error reporting service. Prefixes the received packet. Input parameter. |
* @returns EOK on success. |
* @returns ENOENT if no packet may be sent. |
*/ |
void tl_send_icmp_port_unreachable( int packet_phone, int icmp_phone, packet_t packet, services_t error ); |
int tl_prepare_icmp_packet( int packet_phone, int icmp_phone, packet_t packet, services_t error ); |
/** Receives data from the socket into a packet. |
* @param packet_phone The packet server module phone. Input parameter. |