/branches/network/uspace/srv/net/tl/icmp/icmp_common.c |
---|
38,7 → 38,6 |
#include <async.h> |
#include <ipc/services.h> |
#include "../../err.h" |
#include "../../modules.h" |
#include "../../include/icmp_common.h" |
/branches/network/uspace/srv/net/tl/icmp/icmp_api.c |
---|
51,13 → 51,16 |
#include "icmp_messages.h" |
int icmp_echo_msg( int icmp_phone, size_t size, suseconds_t timeout, ip_ttl_t ttl, ip_tos_t tos, int dont_fragment, const struct sockaddr * addr, socklen_t addrlen ){ |
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 ){ |
aid_t message_id; |
ipcarg_t result; |
if( addrlen <= 0 ){ |
return EINVAL; |
} |
message_id = async_send_5( icmp_phone, NET_ICMP_ECHO, size, timeout, ttl, tos, ( ipcarg_t ) dont_fragment, NULL ); |
// send the address |
ipc_data_write_start( icmp_phone, addr, addrlen ); |
ipc_data_write_start( icmp_phone, addr, ( size_t ) addrlen ); |
// timeout version may cause inconsistency - there is also an inner timer |
// return async_wait_timeout( message_id, & result, timeout ); |
async_wait_for( message_id, & result ); |
/branches/network/uspace/srv/net/tl/icmp/icmp_messages.h |
---|
85,17 → 85,17 |
/** Returns the ICMP code message parameter. |
* @param call The message call structure. Input parameter. |
*/ |
#define ICMP_GET_CODE( call ) ( icmp_param_t ) IPC_GET_ARG1( call ) |
#define ICMP_GET_CODE( call ) ( icmp_code_t ) IPC_GET_ARG1( * call ) |
/** Returns the ICMP link MTU message parameter. |
* @param call The message call structure. Input parameter. |
*/ |
#define ICMP_GET_MTU( call ) ( icmp_param_t ) IPC_GET_ARG3( call ) |
#define ICMP_GET_MTU( call ) ( icmp_param_t ) IPC_GET_ARG3( * call ) |
/** Returns the pointer message parameter. |
* @param call The message call structure. Input parameter. |
*/ |
#define ICMP_GET_POINTER( call ) ( icmp_param_t ) IPC_GET_ARG3( call ) |
#define ICMP_GET_POINTER( call ) ( icmp_param_t ) IPC_GET_ARG3( * call ) |
/** Returns the size message parameter. |
* @param call The message call structure. Input parameter. |
105,7 → 105,7 |
/** Returns the timeout message parameter. |
* @param call The message call structure. Input parameter. |
*/ |
#define ICMP_GET_TIMEOUT( call ) ((( suseconds_t ) IPC_GET_ARG2( call )) * 1000 ) |
#define ICMP_GET_TIMEOUT( call ) (( suseconds_t ) IPC_GET_ARG2( call )) |
/** Returns the time to live message parameter. |
* @param call The message call structure. Input parameter. |
/branches/network/uspace/srv/net/tl/icmp/icmp.c |
---|
63,6 → 63,7 |
#include "../../include/ip_client.h" |
#include "../../include/ip_interface.h" |
#include "../../include/ip_protocols.h" |
#include "../../include/net_interface.h" |
#include "../../include/socket_codes.h" |
#include "../../include/socket_errno.h" |
73,14 → 74,38 |
#include "icmp_messages.h" |
#include "icmp_module.h" |
/** Original datagram length in bytes transfered to the error notification message. |
*/ |
#define ICMP_KEEP_LENGTH 8 |
/** Computes the ICMP datagram checksum. |
* @param header The ICMP datagram header. Input/output parameter. |
* @param length The total datagram length. Input parameter. |
* @returns The computed checksum. |
*/ |
#define ICMP_CHECKSUM( header, length ) htons( ip_checksum(( uint8_t * ) ( header ), ( length ))) |
/** An echo request datagrams pattern. |
*/ |
#define ICMP_ECHO_TEXT "Hello from HelenOS." |
#define ICMP_GET_LOCK_KEY( id, sequence ) ((( id ) << 16 ) | ( sequence & 0xFFFF )) |
/** Computes an ICMP reply data key. |
* @param id The message identifier. Input parameter. |
* @param sequence The message sequence number. Input parameter. |
* @returns The computed ICMP reply data key. |
*/ |
#define ICMP_GET_REPLY_KEY( id, sequence ) ((( id ) << 16 ) | ( sequence & 0xFFFF )) |
/** Type definition of the ICMP reply timeout. |
* @see icmp_reply_timeout |
*/ |
typedef struct icmp_reply_timeout icmp_reply_timeout_t; |
/** Type definition of the ICMP reply timeout pointer. |
* @see icmp_reply_timeout |
*/ |
typedef icmp_reply_timeout_t * icmp_reply_timeout_ref; |
/** Processes the received ICMP packet. |
* Is used as an entry point from the underlying IP module. |
* Releases the packet on error. |
109,42 → 134,126 |
int icmp_process_packet( packet_t packet, services_t error ); |
/** Processes the client messages. |
* Remenbers the assigned identifier and sequence numbers. |
* Remembers the assigned identifier and sequence numbers. |
* Runs until the client module disconnects. |
* @param callid The message identifier. Input parameter. |
* @param call The message parameters. Input parameter. |
* @returns EOK on success. |
* @returns EOK. |
* @see icmp_interface.h |
* @see icmp_api.h |
*/ |
int icmp_process_client_messages( ipc_callid_t callid, ipc_call_t call ); |
/** Processes the generic client messages. |
* @param call The message parameters. Input parameter. |
* @returns EOK on success. |
* @returns ENOTSUP if the message is not known. |
* @returns Other error codes as defined for the packet_translate() function. |
* @returns Other error codes as defined for the icmp_destination_unreachable_msg() function. |
* @returns Other error codes as defined for the icmp_source_quench_msg() function. |
* @returns Other error codes as defined for the icmp_time_exceeded_msg() function. |
* @returns Other error codes as defined for the icmp_parameter_problem_msg() function. |
* @see icmp_interface.h |
*/ |
int icmp_process_message( ipc_call_t * call ); |
/** Releases the packet and returns the result. |
* @param packet The packet queue to be released. Input parameter. |
* @param result The result to be returned. Input parameter. |
* @return The result parameter. |
* @returns The result parameter. |
*/ |
int icmp_release_and_return( packet_t packet, int result ); |
int icmp_echo( icmp_param_t id, icmp_param_t sequence, size_t size, suseconds_t timeout, ip_ttl_t ttl, ip_tos_t tos, int dont_fragment, const struct sockaddr * addr, socklen_t addrlen ); |
/** Requests an echo message. |
* Sends a packet with specified parameters to the target host and waits for the reply upto the given timeout. |
* Blocks the caller until the reply or the timeout occurres. |
* @param id The message identifier. Input parameter. |
* @param sequence The message sequence parameter. Input parameter. |
* @param size The message data length in bytes. Input parameter. |
* @param timeout The timeout in miliseconds. Input parameter. |
* @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. |
* @param addr The target host address. Input parameter. |
* @param addrlen The torget host address length. Input parameter. |
* @returns ICMP_ECHO on success. |
* @returns ETIMEOUT if the reply has not arrived before the timeout. |
* @returns ICMP type of the received error notification. |
* @returns EINVAL if the addrlen parameter is less or equal to zero (<=0). |
* @returns ENOMEM if there is not enough memory left. |
* @returns EPARTY if there was an internal error. |
*/ |
int icmp_echo( icmp_param_t id, icmp_param_t sequence, size_t size, mseconds_t timeout, ip_ttl_t ttl, ip_tos_t tos, int dont_fragment, const struct sockaddr * addr, socklen_t addrlen ); |
/** Prepares the ICMP error packet. |
* Truncates the original packet if longer than ICMP_KEEP_LENGTH bytes. |
* Prefixes and returns the ICMP header. |
* @param packet The original packet. Input/output parameter. |
* @returns The prefixed ICMP header. |
* @returns NULL on errors. |
*/ |
icmp_header_ref icmp_prepare_packet( packet_t packet ); |
/** Sends the ICMP message. |
* 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. |
* @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 process_echo_reply( packet_t packet, icmp_header_ref header, icmp_type_t type, icmp_code_t code ); |
/** 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. |
* The global lock is not released in this case to be reused by the parent fibril. |
* Releases the packet. |
* @param packet The received reply message. Input parameter. |
* @param header The ICMP message header. Input parameter. |
* @param type The received reply message type. Input parameter. |
* @param code The received reply message code. Input parameter. |
* @returns EOK. |
*/ |
int icmp_process_echo_reply( packet_t packet, icmp_header_ref header, icmp_type_t type, icmp_code_t code ); |
/** Tries to set the pending reply result as timeouted. |
* Sleeps the timeout period of time and then tries to obtain and set the pending reply result as timeouted and signals the reply result. |
* If the reply data are still present, the reply timeouted and the parent fibril is awaken. |
* The global lock is not released in this case to be reused by the parent fibril. |
* Should run in a searate fibril. |
* @param data The icmp_reply_timeout structure. Input parameter. |
* @returns EOK on success. |
* @returns EINVAL if the data parameter is NULL. |
*/ |
int icmp_timeout_for_reply( void * data ); |
/** ICMP reply timeout data. |
* Used as a timeouting fibril argument. |
* @see icmp_timeout_for_reply() |
*/ |
struct icmp_reply_timeout{ |
/** Reply data key. |
*/ |
int reply_key; |
/** Timeout in microseconds. |
*/ |
suseconds_t timeout; |
}; |
/** ICMP global data. |
*/ |
icmp_globals_t icmp_globals; |
INT_MAP_IMPLEMENT( time_locks, atomic_t ); |
INT_MAP_IMPLEMENT( icmp_replies, icmp_reply_t ); |
GENERIC_FIELD_IMPLEMENT( echo_data, icmp_echo_t ); |
GENERIC_FIELD_IMPLEMENT( icmp_echo_data, icmp_echo_t ); |
int icmp_echo_msg( int icmp_phone, size_t size, suseconds_t timeout, ip_ttl_t ttl, ip_tos_t tos, int dont_fragment, const struct sockaddr * addr, socklen_t addrlen ){ |
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; |
int res; |
fibril_rwlock_write_lock( & icmp_globals.lock ); |
// use the phone as the echo data index |
echo_data = echo_data_get_index( & icmp_globals.echo_data, icmp_phone ); |
echo_data = icmp_echo_data_get_index( & icmp_globals.echo_data, icmp_phone ); |
if( ! echo_data ){ |
res = ENOENT; |
}else{ |
155,96 → 264,124 |
return res; |
} |
int icmp_echo( icmp_param_t id, icmp_param_t sequence, size_t size, suseconds_t timeout, ip_ttl_t ttl, ip_tos_t tos, int dont_fragment, const struct sockaddr * addr, socklen_t addrlen ){ |
int icmp_timeout_for_reply( void * data ){ |
icmp_reply_ref reply; |
icmp_reply_timeout_ref timeout = data; |
if( ! timeout ){ |
return EINVAL; |
} |
// sleep the given timeout |
async_usleep( timeout->timeout ); |
// lock the globals |
fibril_rwlock_write_lock( & icmp_globals.lock ); |
// find the pending reply |
reply = icmp_replies_find( & icmp_globals.replies, timeout->reply_key ); |
if( reply ){ |
// set the timeout result |
reply->result = ETIMEOUT; |
// notify the main fibril |
fibril_condvar_signal( & reply->condvar ); |
}else{ |
// unlock only if no reply |
fibril_rwlock_write_unlock( & icmp_globals.lock ); |
} |
// release the timeout structure |
free( timeout ); |
return EOK; |
} |
int icmp_echo( icmp_param_t id, icmp_param_t sequence, size_t size, mseconds_t timeout, ip_ttl_t ttl, ip_tos_t tos, int dont_fragment, const struct sockaddr * addr, socklen_t addrlen ){ |
ERROR_DECLARE; |
icmp_header_ref header; |
packet_t packet; |
size_t offset; |
size_t length; |
uint8_t * data; |
atomic_t * lock; |
icmp_reply_ref reply; |
icmp_reply_timeout_ref reply_timeout; |
int result; |
int index; |
int lock_key; |
struct sockaddr_in * address_in; |
struct timeval time_before; |
struct timeval time_after; |
fid_t fibril; |
if( addrlen <= 0 ){ |
return EINVAL; |
} |
length = ( size_t ) addrlen; |
// 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 ); |
if( ! packet ) return ENOMEM; |
// prepare the requesting packet |
// set the destination address |
if( addrlen < sizeof( struct sockaddr )){ |
return icmp_release_and_return( packet, EINVAL ); |
} |
switch( addr->sa_family ){ |
case AF_INET: |
if( addrlen != sizeof( struct sockaddr_in )){ |
return icmp_release_and_return( packet, EINVAL ); |
} |
address_in = ( struct sockaddr_in * ) addr; |
if( ERROR_OCCURRED( packet_set_addr( packet, NULL, ( uint8_t * ) & address_in->sin_addr.s_addr, sizeof( address_in->sin_addr.s_addr )))){ |
if( ERROR_OCCURRED( packet_set_addr( packet, NULL, ( const uint8_t * ) addr, length ))){ |
return icmp_release_and_return( packet, ERROR_CODE ); |
} |
break; |
default: |
return icmp_release_and_return( packet, EAFNOSUPPORT ); |
} |
// allocate space in the packet |
data = ( uint8_t * ) packet_suffix( packet, size ); |
if( ! data ){ |
return icmp_release_and_return( packet, ENOMEM ); |
} |
offset = 0; |
while( size > offset + sizeof( ICMP_ECHO_TEXT )){ |
memcpy( data + offset, ICMP_ECHO_TEXT, sizeof( ICMP_ECHO_TEXT )); |
offset += sizeof( ICMP_ECHO_TEXT ); |
// fill the data |
length = 0; |
while( size > length + sizeof( ICMP_ECHO_TEXT )){ |
memcpy( data + length, ICMP_ECHO_TEXT, sizeof( ICMP_ECHO_TEXT )); |
length += sizeof( ICMP_ECHO_TEXT ); |
} |
memcpy( data + offset, ICMP_ECHO_TEXT, size - offset ); |
header = icmp_prepare_packet( packet ); |
memcpy( data + length, ICMP_ECHO_TEXT, size - length ); |
// prefix the header |
header = PACKET_PREFIX( packet, icmp_header_t ); |
if( ! header ){ |
return icmp_release_and_return( packet, ENOMEM ); |
} |
bzero( header, sizeof( * header )); |
header->un.echo.id = id; |
header->un.echo.sequence = sequence; |
lock_key = ICMP_GET_LOCK_KEY( header->un.echo.id, header->un.echo.sequence ); |
// create a locked fuxed |
lock = malloc( sizeof( * lock )); |
if( ! lock ){ |
// prepare the reply and the reply timeout structures |
reply_timeout = malloc( sizeof( * reply_timeout )); |
if( ! reply_timeout ){ |
return icmp_release_and_return( packet, ENOMEM ); |
} |
atomic_set( lock, 0 ); |
index = time_locks_add( & icmp_globals.time_locks, lock_key, lock ); |
reply = malloc( sizeof( * reply )); |
if( ! reply ){ |
free( reply_timeout ); |
return icmp_release_and_return( packet, ENOMEM ); |
} |
reply_timeout->reply_key = ICMP_GET_REPLY_KEY( header->un.echo.id, header->un.echo.sequence ); |
// timeout in microseconds |
reply_timeout->timeout = timeout * 1000; |
fibril_mutex_initialize( & reply->mutex ); |
fibril_mutex_lock( & reply->mutex ); |
fibril_condvar_initialize( & reply->condvar ); |
index = icmp_replies_add( & icmp_globals.replies, reply_timeout->reply_key, reply ); |
if( index < 0 ){ |
free( lock ); |
free( reply ); |
free( reply_timeout ); |
return icmp_release_and_return( packet, index ); |
} |
if( ERROR_OCCURRED( icmp_send_packet( ICMP_ECHO, 0, packet, header, 0 ))){ |
free( lock ); |
return icmp_release_and_return( packet, ERROR_CODE ); |
// start the timeouting thread |
fibril = fibril_create( icmp_timeout_for_reply, reply_timeout ); |
if( ! fibril ){ |
return EPARTY; |
} |
// unlock the global to allow unlocking and other fibrils to work |
// try to lock again - may be unlocked by the reply |
ERROR_PROPAGATE( gettimeofday( & time_before, NULL )); |
do{ |
result = atomic_get( lock ); |
if( result ){ |
break; |
}else{ |
fibril_add_ready( fibril ); |
// unlock the globals and wait for a reply |
fibril_rwlock_write_unlock( & icmp_globals.lock ); |
// TODO does not yield? |
//printf( "y %d\n", fibril_yield()); |
fibril_yield(); |
fibril_rwlock_write_lock( & icmp_globals.lock ); |
ERROR_PROPAGATE( gettimeofday( & time_after, NULL )); |
} |
}while( tv_sub( & time_after, & time_before ) <= timeout ); |
if( ! result ){ |
result = ELIMIT; |
} |
// destroy the lock |
time_locks_exclude_index( & icmp_globals.time_locks, index ); |
// send the request |
icmp_send_packet( ICMP_ECHO, 0, packet, header, 0 ); |
// wait for a reply |
fibril_condvar_wait( & reply->condvar, & reply->mutex ); |
// read the result |
result = reply->result; |
// destroy the reply structure |
fibril_mutex_unlock( & reply->mutex ); |
icmp_replies_exclude_index( & icmp_globals.replies, index ); |
return result; |
} |
252,7 → 389,9 |
icmp_header_ref header; |
header = icmp_prepare_packet( packet ); |
if( ! header ) return ENOMEM; |
if( ! header ){ |
return icmp_release_and_return( packet, ENOMEM ); |
} |
if( mtu ){ |
header->un.frag.mtu = mtu; |
} |
263,7 → 402,9 |
icmp_header_ref header; |
header = icmp_prepare_packet( packet ); |
if( ! header ) return ENOMEM; |
if( ! header ){ |
return icmp_release_and_return( packet, ENOMEM ); |
} |
return icmp_send_packet( ICMP_SOURCE_QUENCH, 0, packet, header, SERVICE_ICMP ); |
} |
271,7 → 412,9 |
icmp_header_ref header; |
header = icmp_prepare_packet( packet ); |
if( ! header ) return ENOMEM; |
if( ! header ){ |
return icmp_release_and_return( packet, ENOMEM ); |
} |
return icmp_send_packet( ICMP_TIME_EXCEEDED, code, packet, header, SERVICE_ICMP ); |
} |
279,7 → 422,9 |
icmp_header_ref header; |
header = icmp_prepare_packet( packet ); |
if( ! header ) return ENOMEM; |
if( ! header ){ |
return icmp_release_and_return( packet, ENOMEM ); |
} |
header->un.param.pointer = pointer; |
return icmp_send_packet( ICMP_PARAMETERPROB, code, packet, header, SERVICE_ICMP ); |
} |
294,14 → 439,12 |
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( packet_trim( packet, 0, total_length - header_length - ICMP_KEEP_LENGTH ) != EOK ) return NULL; |
if(( total_length - header_length > ICMP_KEEP_LENGTH ) |
&& ( packet_trim( packet, 0, total_length - header_length - ICMP_KEEP_LENGTH ) != EOK )){ |
return NULL; |
} |
header = PACKET_PREFIX( packet, icmp_header_t ); |
if( ! header ){ |
pq_release( icmp_globals.net_phone, packet_get_id( packet )); |
return NULL; |
} |
if( ! header ) return NULL; |
bzero( header, sizeof( * header )); |
return header; |
} |
309,13 → 452,16 |
int icmp_send_packet( icmp_type_t type, icmp_code_t code, packet_t packet, icmp_header_ref header, services_t error ){ |
ERROR_DECLARE; |
// do not send an error if disabled |
if( error && ( ! icmp_globals.error_reporting )){ |
return icmp_release_and_return( packet, EPERM ); |
} |
header->type = type; |
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 ))){ |
pq_release( icmp_globals.net_phone, packet_get_id( packet )); |
return ERROR_CODE; |
return icmp_release_and_return( packet, ERROR_CODE ); |
} |
return ip_send_msg( icmp_globals.ip_phone, -1, packet, SERVICE_ICMP, error ); |
} |
332,7 → 478,7 |
echo_data->id = icmp_globals.last_used_id; |
echo_data->sequence = 0; |
// remember the assigned echo data |
index = echo_data_add( & icmp_globals.echo_data, echo_data ); |
index = icmp_echo_data_add( & icmp_globals.echo_data, echo_data ); |
if( index < 0 ){ |
free( echo_data ); |
} |
344,10 → 490,15 |
int icmp_initialize( async_client_conn_t client_connection ){ |
ERROR_DECLARE; |
measured_string_t names[] = {{ "ICMP_ERROR_REPORTING", 20 }, { "ICMP_ECHO_REPLYING", 18 }}; |
measured_string_ref configuration; |
size_t count = sizeof( names ) / sizeof( measured_string_t ); |
char * data; |
fibril_rwlock_initialize( & icmp_globals.lock ); |
fibril_rwlock_write_lock( & icmp_globals.lock ); |
time_locks_initialize( & icmp_globals.time_locks ); |
echo_data_initialize( & icmp_globals.echo_data ); |
icmp_replies_initialize( & icmp_globals.replies ); |
icmp_echo_data_initialize( & icmp_globals.echo_data ); |
icmp_globals.ip_phone = ip_bind_service( SERVICE_IP, IPPROTO_ICMP, SERVICE_ICMP, client_connection, icmp_received_msg ); |
if( icmp_globals.ip_phone < 0 ){ |
return icmp_globals.ip_phone; |
355,6 → 506,14 |
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 ); |
configuration = & names[ 0 ]; |
// get configuration |
ERROR_PROPAGATE( net_get_conf_req( icmp_globals.net_phone, & configuration, count, & data )); |
if( configuration ){ |
icmp_globals.error_reporting = configuration[ 0 ].value && ( configuration[ 0 ].value[ 0 ] == 'y' ); |
icmp_globals.echo_replying = configuration[ 1 ].value && ( configuration[ 1 ].value[ 0 ] == 'y' ); |
net_free_settings( configuration, data ); |
} |
fibril_rwlock_write_unlock( & icmp_globals.lock ); |
return EOK; |
} |
363,8 → 522,7 |
ERROR_DECLARE; |
if( ERROR_OCCURRED( icmp_process_packet( packet, error ))){ |
pq_release( icmp_globals.net_phone, packet_get_id( packet )); |
return ERROR_CODE; |
return icmp_release_and_return( packet, ERROR_CODE ); |
} |
return EOK; |
401,7 → 559,7 |
// get rid of the ip header |
result = ip_client_process_packet( packet, NULL, NULL, NULL, NULL, NULL ); |
if( result < 0 ) return result; |
packet_trim( packet, ( size_t ) result, 0 ); |
ERROR_PROPAGATE( packet_trim( packet, ( size_t ) result, 0 )); |
length = packet_get_data_length( packet ); |
if( length <= 0 ) return EINVAL; |
411,25 → 569,58 |
// get icmp header |
header = ( icmp_header_ref ) data; |
// checksum |
if(( header->checksum ) && ( ICMP_CHECKSUM( header, length ))){ |
/* 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 ){ |
while( 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: |
return process_echo_reply( packet, header, ICMP_ECHO, 0 ); |
header->type = ICMP_ECHO; |
continue; |
} |
} |
return EINVAL; |
} |
} |
switch( header->type ){ |
case ICMP_ECHOREPLY: |
if( error ){ |
return icmp_process_echo_reply( packet, header, type, code ); |
}else{ |
return icmp_process_echo_reply( packet, header, ICMP_ECHO, 0 ); |
} |
case ICMP_ECHO: |
if( error ){ |
return process_echo_reply( packet, header, type, code ); |
}else{ |
return icmp_process_echo_reply( packet, header, type, code ); |
// do not send a reply if disabled |
}else if( icmp_globals.echo_replying ){ |
addrlen = packet_get_addr( packet, & src, NULL ); |
if(( addrlen > 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 ) addrlen ) == EOK )){ |
// send the reply |
return icmp_send_packet( ICMP_ECHOREPLY, 0, packet, header, 0 ); |
icmp_send_packet( ICMP_ECHOREPLY, 0, packet, header, 0 ); |
return EOK; |
}else{ |
return icmp_release_and_return( packet, EINVAL ); |
return EINVAL; |
} |
}else{ |
return EPERM; |
} |
case ICMP_DEST_UNREACH: |
case ICMP_SOURCE_QUENCH: |
443,28 → 634,33 |
case ICMP_REDIRECT_MOBILE: |
case ICMP_SKIP: |
case ICMP_PHOTURIS: |
fibril_rwlock_read_lock( & icmp_globals.lock ); |
ip_received_error_msg( icmp_globals.ip_phone, -1, packet, SERVICE_IP, SERVICE_ICMP ); |
fibril_rwlock_read_unlock( & icmp_globals.lock ); |
return EOK; |
default: |
return icmp_release_and_return( packet, ENOTSUP ); |
return ENOTSUP; |
} |
} |
int process_echo_reply( packet_t packet, icmp_header_ref header, icmp_type_t type, icmp_code_t code ){ |
int lock_key; |
atomic_t * lock; |
int icmp_process_echo_reply( packet_t packet, icmp_header_ref header, icmp_type_t type, icmp_code_t code ){ |
int reply_key; |
icmp_reply_ref reply; |
lock_key = ICMP_GET_LOCK_KEY( header->un.echo.id, header->un.echo.sequence ); |
// compute the reply key |
reply_key = ICMP_GET_REPLY_KEY( header->un.echo.id, header->un.echo.sequence ); |
pq_release( icmp_globals.net_phone, packet_get_id( packet )); |
// lock the globals |
fibril_rwlock_write_lock( & icmp_globals.lock ); |
lock = time_locks_find( & icmp_globals.time_locks, lock_key ); |
if( lock ){ |
// unlock the lock for the waiting fibril |
atomic_set( lock, type ); |
// find the pending reply |
reply = icmp_replies_find( & icmp_globals.replies, reply_key ); |
if( reply ){ |
// set the result |
reply->result = type; |
// notify the main fibril |
fibril_condvar_signal( & reply->condvar ); |
}else{ |
// unlock only if no reply |
fibril_rwlock_write_unlock( & icmp_globals.lock ); |
} |
pq_release( icmp_globals.net_phone, packet_get_id( packet )); |
fibril_rwlock_write_unlock( & icmp_globals.lock ); |
return EOK; |
} |
482,6 → 678,8 |
return ERROR_CODE; |
case NET_ICMP_INIT: |
return icmp_process_client_messages( callid, * call ); |
default: |
return icmp_process_message( call ); |
} |
return ENOTSUP; |
} |
493,8 → 691,7 |
fibril_rwlock_t lock; |
ipc_call_t answer; |
int answer_count; |
packet_t packet; |
size_t addrlen; |
size_t length; |
struct sockaddr * addr; |
icmp_param_t id; |
icmp_param_t sequence = 0; |
526,16 → 723,16 |
break; |
case NET_ICMP_ECHO: |
fibril_rwlock_write_lock( & lock ); |
if( ! ipc_data_write_receive( & data_callid, & addrlen )){ |
if( ! ipc_data_write_receive( & data_callid, & length )){ |
ERROR_CODE = EINVAL; |
}else{ |
addr = malloc( addrlen ); |
addr = malloc( length ); |
if( ! addr ){ |
ERROR_CODE = ENOMEM; |
}else{ |
if( ! ERROR_OCCURRED( ipc_data_write_finalize( data_callid, addr, addrlen ))){ |
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, addrlen ); |
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 ); |
fibril_rwlock_write_unlock( & icmp_globals.lock ); |
free( addr ); |
++ sequence; |
544,34 → 741,47 |
} |
fibril_rwlock_write_unlock( & lock ); |
break; |
default: |
ERROR_CODE = icmp_process_message( & call ); |
} |
answer_call( callid, ERROR_CODE, & answer, answer_count ); |
} |
return EOK; |
} |
int icmp_process_message( ipc_call_t * call ){ |
ERROR_DECLARE; |
packet_t packet; |
switch( IPC_GET_METHOD( * call )){ |
case NET_ICMP_DEST_UNREACH: |
if( ! ERROR_OCCURRED( packet_translate( icmp_globals.net_phone, & packet, IPC_GET_PACKET( & call )))){ |
if( ! ERROR_OCCURRED( packet_translate( icmp_globals.net_phone, & packet, IPC_GET_PACKET( call )))){ |
ERROR_CODE = icmp_destination_unreachable_msg( 0, ICMP_GET_CODE( call ), ICMP_GET_MTU( call ), packet ); |
} |
break; |
return ERROR_CODE; |
case NET_ICMP_SOURCE_QUENCH: |
if( ! ERROR_OCCURRED( packet_translate( icmp_globals.net_phone, & packet, IPC_GET_PACKET( & call )))){ |
if( ! ERROR_OCCURRED( packet_translate( icmp_globals.net_phone, & packet, IPC_GET_PACKET( call )))){ |
ERROR_CODE = icmp_source_quench_msg( 0, packet ); |
} |
return ERROR_CODE; |
case NET_ICMP_TIME_EXCEEDED: |
if( ! ERROR_OCCURRED( packet_translate( icmp_globals.net_phone, & packet, IPC_GET_PACKET( & call )))){ |
if( ! ERROR_OCCURRED( packet_translate( icmp_globals.net_phone, & packet, IPC_GET_PACKET( call )))){ |
ERROR_CODE = icmp_time_exceeded_msg( 0, ICMP_GET_CODE( call ), packet ); |
} |
break; |
return ERROR_CODE; |
case NET_ICMP_PARAMETERPROB: |
if( ! ERROR_OCCURRED( packet_translate( icmp_globals.net_phone, & packet, IPC_GET_PACKET( & call )))){ |
if( ! ERROR_OCCURRED( packet_translate( icmp_globals.net_phone, & packet, IPC_GET_PACKET( call )))){ |
ERROR_CODE = icmp_parameter_problem_msg( 0, ICMP_GET_CODE( call ), ICMP_GET_POINTER( call ), packet ); |
} |
return ERROR_CODE; |
default: |
ERROR_CODE = ENOTSUP; |
return ENOTSUP; |
} |
answer_call( callid, ERROR_CODE, & answer, answer_count ); |
} |
return EOK; |
} |
int icmp_release_and_return( packet_t packet, int result ){ |
pq_release( icmp_globals.net_phone, packet_get_id( packet )); |
return result; |
/branches/network/uspace/srv/net/tl/icmp/Makefile |
---|
45,9 → 45,9 |
$(NET_BASE)il/ip/ip_client.c \ |
$(NET_BASE)il/ip/ip_remote.c \ |
$(NET_BASE)net/net_remote.c \ |
$(STRUCTURES)measured_strings.c \ |
$(STRUCTURES)packet/packet.c \ |
$(STRUCTURES)packet/packet_client.c \ |
$(STRUCTURES)packet/packet_remote.c \ |
$(STRUCTURES)measured_strings.c |
$(STRUCTURES)packet/packet_remote.c |
include $(NET_BASE)Makefile.module |
/branches/network/uspace/srv/net/tl/icmp/icmp.h |
---|
37,7 → 37,6 |
#ifndef __NET_ICMP_H__ |
#define __NET_ICMP_H__ |
#include <atomic.h> |
#include <fibril_sync.h> |
#include "../../include/icmp_codes.h" |
47,17 → 46,27 |
#include "icmp_header.h" |
/** Type definition of the ICMP reply data. |
* @see icmp_reply |
*/ |
typedef struct icmp_reply icmp_reply_t; |
/** Type definition of the ICMP reply data pointer. |
* @see icmp_reply |
*/ |
typedef icmp_reply_t * icmp_reply_ref; |
/** Type definition of the ICMP global data. |
* @see icmp_globals |
*/ |
typedef struct icmp_globals icmp_globals_t; |
/** Timeout locks map. |
* Maps message identifiers to timeout implementing atomic variables. |
* Sending fibril waits for its associated atomic variable to be set nonzero. |
* Receiving fibril sets the associated atomic variable with the return value. |
/** Pending replies map. |
* Maps message identifiers to the pending replies. |
* Sending fibril waits for its associated reply event. |
* Receiving fibril sets the associated reply with the return value and signals the event. |
*/ |
INT_MAP_DECLARE( time_locks, atomic_t ); |
INT_MAP_DECLARE( icmp_replies, icmp_reply_t ); |
/** Echo specific data field. |
* Used for bundle modules. |
64,8 → 73,22 |
* 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. |
*/ |
GENERIC_FIELD_DECLARE( echo_data, icmp_echo_t ); |
GENERIC_FIELD_DECLARE( icmp_echo_data, icmp_echo_t ); |
/** ICMP reply data. |
*/ |
struct icmp_reply{ |
/** Reply result. |
*/ |
int result; |
/** Safety lock. |
*/ |
fibril_mutex_t mutex; |
/** Received or timeouted reply signaling. |
*/ |
fibril_condvar_t condvar; |
}; |
/** ICMP global data. |
*/ |
struct icmp_globals{ |
87,15 → 110,21 |
/** Networking module phone. |
*/ |
int net_phone; |
/** Indicates whether ICMP error reporting is enabled. |
*/ |
int error_reporting; |
/** Indicates whether ICMP echo replying (ping) is enabled. |
*/ |
int echo_replying; |
/** The last used identifier number. |
*/ |
icmp_param_t last_used_id; |
/** The budled modules assigned echo specific data. |
*/ |
echo_data_t echo_data; |
icmp_echo_data_t echo_data; |
/** Echo timeout locks. |
*/ |
time_locks_t time_locks; |
icmp_replies_t replies; |
/** Safety lock. |
*/ |
fibril_rwlock_t lock; |
/branches/network/uspace/srv/net/tl/udp/udp.c |
---|
50,6 → 50,7 |
#include "../../structures/packet/packet_client.h" |
#include "../../include/in.h" |
#include "../../include/in6.h" |
#include "../../include/inet.h" |
#include "../../include/ip_client.h" |
#include "../../include/ip_interface.h" |
130,6 → 131,7 |
/** Sends data from the socket to the remote address. |
* Binds the socket to a free port if not already connected/bound. |
* Handles the NET_SOCKET_SENDTO message. |
* Supports AF_INET and AF_INET6 address families. |
* @param local_sockets The application local sockets. Input/output parameter. |
* @param socket_id Socket identifier. Input parameter. |
* @param addr The destination address. Input parameter. |
146,13 → 148,15 |
* @returns Other error codes as defined for the ip_client_prepare_packet() function. |
* @returns Other error codes as defined for the ip_send_msg() function. |
*/ |
int udp_sendto_message( socket_cores_ref local_sockets, int socket_id, void * addr, size_t addrlen, int fragments, int flags ); |
int udp_sendto_message( socket_cores_ref local_sockets, int socket_id, const struct sockaddr * addr, socklen_t addrlen, int fragments, int flags ); |
/** Receives data to the socket. |
* Handles the NET_SOCKET_RECVFROM message. |
* Replies the source address as well. |
* @param local_sockets The application local sockets. Input parameter. |
* @param socket_id Socket identifier. Input parameter. |
* @param flags Various receive flags. Input parameter. |
* @param addrlen The source address length. Output parameter. |
* @returns The number of bytes received. |
* @returns ENOTSOCK if the socket is not found. |
* @returns NO_DATA if there are no received packets or data. |
161,7 → 165,7 |
* @returns Other error codes as defined for the packet_translate() function. |
* @returns Other error codes as defined for the socket_write_data() function. |
*/ |
int udp_recvfrom_message( socket_cores_ref local_sockets, int socket_id, int flags ); |
int udp_recvfrom_message( socket_cores_ref local_sockets, int socket_id, int flags, size_t * addrlen ); |
/*@}*/ |
180,13 → 184,14 |
/** Receives data from the socket into a packet. |
* @param packet The new created packet. Output parameter. |
* @param prefix Reserved packet data prefix length. Input parameter. |
* @param address_in The destination address to be set. Input parameter. |
* @param addr The destination address. Input parameter. |
* @param addrlen The address length. Input parameter. |
* @returns Number of bytes received. |
* @returns EINVAL if the client does not send data. |
* @returns ENOMEM if there is not enough memory left. |
* @returns Other error codes as defined for the ipc_data_read_finalize() function. |
*/ |
int socket_read_packet_data( packet_ref packet, size_t prefix, struct sockaddr_in * address_in ); |
int socket_read_packet_data( packet_ref packet, size_t prefix, const struct sockaddr * addr, socklen_t addrlen ); |
/** Replies the data to the socket. |
* @param data The data buffer to be sent. Input parameter. |
197,6 → 202,17 |
*/ |
int socket_write_data( void * data, size_t data_length ); |
/** Sets the address port. |
* Supports AF_INET and AF_INET6 address families. |
* @param addr The address to be updated. Input/output parameter. |
* @param addrlen The address length. Input parameter. |
* @param port The port to be set. Input parameter. |
* @returns EOK on success. |
* @returns EINVAL if the address length does not match the address family. |
* @returns EAFNOSUPPORT if the address family is not supported. |
*/ |
int udp_set_address_port( struct sockaddr * addr, int addrlen, uint16_t port ); |
/** UDP global data. |
*/ |
udp_globals_t udp_globals; |
352,7 → 368,7 |
bool keep_on_going = true; |
socket_cores_t local_sockets; |
int app_phone = IPC_GET_PHONE( & call ); |
void * addr; |
struct sockaddr * addr; |
size_t addrlen; |
fibril_rwlock_t lock; |
ipc_call_t answer; |
388,7 → 404,7 |
answer_count = 3; |
break; |
case NET_SOCKET_BIND: |
res = socket_read_data( & addr, & addrlen ); |
res = socket_read_data(( void ** ) & addr, & addrlen ); |
if( res == EOK ){ |
fibril_rwlock_write_lock( & lock ); |
fibril_rwlock_write_lock( & udp_globals.lock ); |
399,7 → 415,7 |
} |
break; |
case NET_SOCKET_SENDTO: |
res = socket_read_data( & addr, & addrlen ); |
res = socket_read_data(( void ** ) & addr, & addrlen ); |
if( res == EOK ){ |
fibril_rwlock_read_lock( & lock ); |
fibril_rwlock_read_lock( & udp_globals.lock ); |
412,12 → 428,12 |
case NET_SOCKET_RECVFROM: |
fibril_rwlock_read_lock( & lock ); |
fibril_rwlock_read_lock( & udp_globals.lock ); |
res = udp_recvfrom_message( & local_sockets, SOCKET_GET_SOCKET_ID( call ), SOCKET_GET_FLAGS( call )); |
res = udp_recvfrom_message( & local_sockets, SOCKET_GET_SOCKET_ID( call ), SOCKET_GET_FLAGS( call ), & addrlen ); |
fibril_rwlock_read_unlock( & udp_globals.lock ); |
fibril_rwlock_read_unlock( & lock ); |
if( res > 0 ){ |
* SOCKET_SET_READ_DATA_LENGTH( answer ) = res; |
* SOCKET_SET_ADDRESS_LENGTH( answer ) = sizeof( struct sockaddr_in ); |
* SOCKET_SET_ADDRESS_LENGTH( answer ) = addrlen; |
answer_count = 2; |
res = EOK; |
} |
446,12 → 462,12 |
return EOK; |
} |
int udp_sendto_message( socket_cores_ref local_sockets, int socket_id, void * addr, size_t addrlen, int fragments, int flags ){ |
int udp_sendto_message( socket_cores_ref local_sockets, int socket_id, const struct sockaddr * addr, socklen_t addrlen, int fragments, int flags ){ |
ERROR_DECLARE; |
socket_core_ref socket; |
struct sockaddr * address; |
struct sockaddr_in * address_in; |
struct sockaddr_in6 * address_in6; |
packet_t packet; |
packet_t next_packet; |
udp_header_ref header; |
458,13 → 474,24 |
int index; |
size_t total_length; |
int result; |
uint16_t dest_port; |
if( addrlen < sizeof( struct sockaddr )) return EINVAL; |
address = ( struct sockaddr * ) addr; |
switch( address->sa_family ){ |
switch( addr->sa_family ){ |
case AF_INET: |
if( addrlen != sizeof( struct sockaddr_in )) return EINVAL; |
address_in = ( struct sockaddr_in * ) addr; |
dest_port = address_in->sin_port; |
break; |
case AF_INET6: |
if( addrlen != sizeof( struct sockaddr_in6 )) return EINVAL; |
address_in6 = ( struct sockaddr_in6 * ) addr; |
dest_port = address_in6->sin6_port; |
break; |
default: |
return EAFNOSUPPORT; |
} |
socket = socket_cores_find( local_sockets, socket_id ); |
if( ! socket ) return ENOTSOCK; |
481,11 → 508,12 |
fibril_rwlock_write_unlock( & udp_globals.lock ); |
fibril_rwlock_read_lock( & udp_globals.lock ); |
} |
// TODO do not ask all the time |
ERROR_PROPAGATE( ip_packet_size_req( udp_globals.ip_phone, -1, & udp_globals.addr_len, & udp_globals.prefix, & udp_globals.content, & udp_globals.suffix )); |
// read the first packet fragment |
result = socket_read_packet_data( & packet, sizeof( udp_header_t ), address_in ); |
result = socket_read_packet_data( & packet, sizeof( udp_header_t ), addr, addrlen ); |
if( result < 0 ) return result; |
total_length = ( size_t ) result; |
// prefix the udp header |
496,7 → 524,7 |
} |
// read the rest of the packet fragments |
for( index = 1; index < fragments; ++ index ){ |
result = socket_read_packet_data( & next_packet, 0, address_in ); |
result = socket_read_packet_data( & next_packet, 0, addr, addrlen ); |
if( result < 0 ){ |
return udp_release_and_return( packet, result ); |
} |
505,7 → 533,7 |
} |
// set the udp header |
header->source = htons( socket->port ); |
header->dest = htons( address_in->sin_port ); |
header->dest = htons( dest_port ); |
header->len = htons( total_length + sizeof( udp_header_t )); |
// TODO my ip address for the pseudo header checksum |
header->check = 0; |
516,12 → 544,9 |
} |
// send the packet |
return ip_send_msg( udp_globals.ip_phone, socket->device_id, packet, SERVICE_UDP, 0 ); |
// TODO IPv6 |
} |
return EAFNOSUPPORT; |
} |
int udp_recvfrom_message( socket_cores_ref local_sockets, int socket_id, int flags ){ |
int udp_recvfrom_message( socket_cores_ref local_sockets, int socket_id, int flags, size_t * addrlen ){ |
ERROR_DECLARE; |
socket_core_ref socket; |
528,15 → 553,14 |
int packet_id; |
packet_t packet; |
udp_header_ref header; |
struct sockaddr_in address; |
struct sockaddr * addr; |
size_t length; |
packet_t next_packet; |
uint8_t * data; |
size_t fragments; |
size_t * lengths; |
size_t index; |
int result; |
size_t index; |
uint8_t * addr; |
// find the socket |
socket = socket_cores_find( local_sockets, socket_id ); |
552,18 → 576,17 |
return NO_DATA; |
} |
header = ( udp_header_ref ) data; |
// set the source address |
address.sin_family = PF_INET; |
address.sin_port = ntohs( header->source ); |
result = packet_get_addr( packet, & addr, NULL ); |
if( result != sizeof( address.sin_addr.s_addr )){ |
// set the source address port |
result = packet_get_addr( packet, ( uint8_t ** ) & addr, NULL ); |
if( ERROR_OCCURRED( udp_set_address_port( addr, result, ntohs( header->source )))){ |
pq_release( udp_globals.net_phone, packet_id ); |
return EINVAL; |
return ERROR_CODE; |
} |
address.sin_addr.s_addr = *(( uint32_t * ) addr ); |
bzero( & address.sin_zero, sizeof( address.sin_zero )); |
* addrlen = ( size_t ) result; |
// send the source address |
ERROR_PROPAGATE( socket_write_data( & address, sizeof( address ))); |
ERROR_PROPAGATE( socket_write_data( addr, * addrlen )); |
next_packet = pq_next( packet ); |
if( ! next_packet ){ |
// write all if only one fragment |
636,7 → 659,7 |
return EOK; |
} |
int socket_read_packet_data( packet_ref packet, size_t prefix, struct sockaddr_in * address_in ){ |
int socket_read_packet_data( packet_ref packet, size_t prefix, const struct sockaddr * addr, socklen_t addrlen ){ |
ERROR_DECLARE; |
ipc_callid_t callid; |
657,7 → 680,7 |
// read the data into the packet |
if( ERROR_OCCURRED( ipc_data_write_finalize( callid, data, length )) |
// set the packet destination address |
|| ERROR_OCCURRED( packet_set_addr( * packet, NULL, ( uint8_t * ) & address_in->sin_addr.s_addr, sizeof( address_in->sin_addr.s_addr )))){ |
|| ERROR_OCCURRED( packet_set_addr( * packet, NULL, ( uint8_t * ) addr, addrlen ))){ |
pq_release( udp_globals.net_phone, packet_get_id( * packet )); |
return ERROR_CODE; |
} |
691,5 → 714,29 |
} |
} |
int udp_set_address_port( struct sockaddr * addr, int addrlen, uint16_t port ){ |
struct sockaddr_in * address_in; |
struct sockaddr_in6 * address_in6; |
size_t length; |
if( addrlen < 0 ) return EINVAL; |
length = ( size_t ) addrlen; |
if( length < sizeof( struct sockaddr )) return EINVAL; |
switch( addr->sa_family ){ |
case AF_INET: |
if( length != sizeof( struct sockaddr_in )) return EINVAL; |
address_in = ( struct sockaddr_in * ) addr; |
address_in->sin_port = port; |
return EOK; |
case AF_INET6: |
if( length != sizeof( struct sockaddr_in6 )) return EINVAL; |
address_in6 = ( struct sockaddr_in6 * ) addr; |
address_in6->sin6_port = port; |
return EOK; |
default: |
return EAFNOSUPPORT; |
} |
} |
/** @} |
*/ |
/branches/network/uspace/srv/net/tl/udp/Makefile |
---|
47,10 → 47,10 |
$(NET_BASE)tl/icmp/icmp_client.c \ |
$(NET_BASE)tl/icmp/icmp_common.c \ |
$(NET_BASE)tl/icmp/icmp_remote.c \ |
$(STRUCTURES)dynamic_fifo.c \ |
$(STRUCTURES)measured_strings.c \ |
$(STRUCTURES)packet/packet.c \ |
$(STRUCTURES)packet/packet_client.c \ |
$(STRUCTURES)packet/packet_remote.c \ |
$(STRUCTURES)dynamic_fifo.c \ |
$(STRUCTURES)measured_strings.c |
$(STRUCTURES)packet/packet_remote.c |
include $(NET_BASE)Makefile.module |
/branches/network/uspace/srv/net/app/print_error.c |
---|
0,0 → 1,143 |
/* |
* 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 net_app |
* @{ |
*/ |
/** @file |
* Generic application error printing functions implementation. |
*/ |
#include <stdio.h> |
#include "../include/icmp_codes.h" |
#include "../include/socket_errno.h" |
#include "print_error.h" |
void print_error( FILE * output, int error_code, const char * prefix, const char * suffix ){ |
if( IS_ICMP_ERROR( error_code )){ |
icmp_print_error( output, error_code, prefix, suffix ); |
}else if( IS_SOCKET_ERROR( error_code )){ |
socket_print_error( output, error_code, prefix, suffix ); |
} |
} |
void icmp_print_error( FILE * output, int error_code, const char * prefix, const char * suffix ){ |
if( output ){ |
if( prefix ){ |
fprintf( output, "%s", prefix ); |
} |
switch( error_code ){ |
case ICMP_DEST_UNREACH: |
fprintf( output, "ICMP Destination Unreachable (%d) error", error_code ); |
break; |
case ICMP_SOURCE_QUENCH: |
fprintf( output, "ICMP Source Quench (%d) error", error_code ); |
break; |
case ICMP_REDIRECT: |
fprintf( output, "ICMP Redirect (%d) error", error_code ); |
break; |
case ICMP_ALTERNATE_ADDR: |
fprintf( output, "ICMP Alternate Host Address (%d) error", error_code ); |
break; |
case ICMP_ROUTER_ADV: |
fprintf( output, "ICMP Router Advertisement (%d) error", error_code ); |
break; |
case ICMP_ROUTER_SOL: |
fprintf( output, "ICMP Router Solicitation (%d) error", error_code ); |
break; |
case ICMP_TIME_EXCEEDED: |
fprintf( output, "ICMP Time Exceeded (%d) error", error_code ); |
break; |
case ICMP_PARAMETERPROB: |
fprintf( output, "ICMP Paramenter Problem (%d) error", error_code ); |
break; |
case ICMP_CONVERSION_ERROR: |
fprintf( output, "ICMP Datagram Conversion Error (%d) error", error_code ); |
break; |
case ICMP_REDIRECT_MOBILE: |
fprintf( output, "ICMP Mobile Host Redirect (%d) error", error_code ); |
break; |
case ICMP_SKIP: |
fprintf( output, "ICMP SKIP (%d) error", error_code ); |
break; |
case ICMP_PHOTURIS: |
fprintf( output, "ICMP Photuris (%d) error", error_code ); |
break; |
default: |
fprintf( output, "Other (%d) error", error_code ); |
} |
if( suffix ){ |
fprintf( output, "%s", suffix ); |
} |
} |
} |
void socket_print_error( FILE * output, int error_code, const char * prefix, const char * suffix ){ |
if( output ){ |
if( prefix ){ |
fprintf( output, "%s", prefix ); |
} |
switch( error_code ){ |
case ENOTSOCK: |
fprintf( output, "Not a socket (%d) error", error_code ); |
break; |
case EPROTONOSUPPORT: |
fprintf( output, "Protocol not supported (%d) error", error_code ); |
break; |
case ESOCKTNOSUPPORT: |
fprintf( output, "Socket type not supported (%d) error", error_code ); |
break; |
case EPFNOSUPPORT: |
fprintf( output, "Protocol family not supported (%d) error", error_code ); |
break; |
case EAFNOSUPPORT: |
fprintf( output, "Address family not supported (%d) error", error_code ); |
break; |
case EADDRINUSE: |
fprintf( output, "Address already in use (%d) error", error_code ); |
break; |
case ENOTCONN: |
fprintf( output, "Socket not connected (%d) error", error_code ); |
break; |
case NO_DATA: |
fprintf( output, "No data (%d) error", error_code ); |
break; |
default: |
fprintf( output, "Other (%d) error", error_code ); |
} |
if( suffix ){ |
fprintf( output, "%s", suffix ); |
} |
} |
} |
/** @} |
*/ |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/branches/network/uspace/srv/net/app/print_error.h |
---|
0,0 → 1,80 |
/* |
* 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 net_app |
* @{ |
*/ |
/** @file |
* Generic application error printing functions. |
*/ |
#ifndef __NET_APP_PRINT__ |
#define __NET_APP_PRINT__ |
/** Returns whether the error code may be an ICMP error code. |
* @param error_code The error code. Input parameter. |
* @returns A value indicating whether the error code may be an ICMP error code. |
*/ |
#define IS_ICMP_ERROR( error_code ) (( error_code ) > 0 ) |
/** Returns whether the error code may be socket error code. |
* @param error_code The error code. Input parameter. |
* @returns A value indicating whether the error code may be a socket error code. |
*/ |
#define IS_SOCKET_ERROR( error_code ) (( error_code ) < 0 ) |
/** Prints the error description. |
* Supports ICMP and socket error codes. |
* @param output The description output stream. May be NULL. Input parameter. |
* @param error_code The error code. Input parameter. |
* @param prefix The error description prefix. May be NULL. Input parameter. |
* @param suffix The error description suffix. May be NULL. Input parameter. |
*/ |
void print_error( FILE * output, int error_code, const char * prefix, const char * suffix ); |
/** Prints the specific ICMP error description. |
* @param output The description output stream. May be NULL. Input parameter. |
* @param error_code The ICMP error code. Input parameter. |
* @param prefix The error description prefix. May be NULL. Input parameter. |
* @param suffix The error description suffix. May be NULL. Input parameter. |
*/ |
void icmp_print_error( FILE * output, int error_code, const char * prefix, const char * suffix ); |
/** Prints the specific socket error description. |
* @param output The description output stream. May be NULL. Input parameter. |
* @param error_code The socket error code. Input parameter. |
* @param prefix The error description prefix. May be NULL. Input parameter. |
* @param suffix The error description suffix. May be NULL. Input parameter. |
*/ |
void socket_print_error( FILE * output, int error_code, const char * prefix, const char * suffix ); |
#endif |
/** @} |
*/ |
Property changes: |
Added: svn:eol-style |
+native |
\ No newline at end of property |
/branches/network/uspace/srv/net/app/ping/Makefile |
---|
40,6 → 40,7 |
SOURCES = \ |
$(NAME).c \ |
$(NET_BASE)app/parse.c \ |
$(NET_BASE)app/print_error.c \ |
$(NET_BASE)inet.c \ |
$(NET_BASE)modules.c \ |
$(NET_BASE)tl/icmp/icmp_api.c \ |
/branches/network/uspace/srv/net/app/ping/ping.c |
---|
42,13 → 42,15 |
#include "../../include/icmp_api.h" |
#include "../../include/in.h" |
#include "../../include/in6.h" |
#include "../../include/inet.h" |
#include "../../include/ip_codes.h" |
#include "../../include/socket_codes.h" |
#include "../../include/socket_errno.h" |
#include "../../err.h" |
#include "../parse.h" |
#include "../print_error.h" |
/** Echo module name. |
*/ |
69,6 → 71,7 |
/** Translates the character string to the address family number. |
* @param name The address family name. Input parameter. |
* @returns The corresponding address family number. |
* @returns EAFNOSUPPORTED if the address family is not supported. |
*/ |
int parse_address_family( const char * name ); |
85,7 → 88,7 |
"\tDisable packet fragmentation.\n" |
"\n" \ |
"-f address_family | --family=address_family\n" \ |
"\tThe given address family. Only the AF_INET is supported.\n" |
"\tThe given address family. Only the AF_INET and AF_INET6 are supported.\n" |
"\n" \ |
"-h | --help\n" \ |
"\tShow this application help.\n" |
110,8 → 113,10 |
int parse_address_family( const char * name ){ |
if( str_lcmp( name, "AF_INET", 7 ) == 0 ){ |
return AF_INET; |
}else if( str_lcmp( name, "AF_INET6", 8 ) == 0 ){ |
return AF_INET6; |
} |
return ENOENT; |
return EAFNOSUPPORT; |
} |
int main( int argc, char * argv[] ){ |
124,8 → 129,16 |
ip_tos_t tos = 0; |
int count = 3; |
suseconds_t timeout = 3000; |
struct sockaddr_in address = { .sin_family = AF_INET, .sin_port = 7 }; |
int family = AF_INET; |
socklen_t max_length = sizeof( struct sockaddr_in6 ); |
uint8_t address_data[ max_length ]; |
struct sockaddr * address = ( struct sockaddr * ) address_data; |
struct sockaddr_in * address_in = ( struct sockaddr_in * ) address; |
struct sockaddr_in6 * address_in6 = ( struct sockaddr_in6 * ) address; |
socklen_t addrlen; |
char address_string[ INET6_ADDRSTRLEN ]; |
uint8_t * address_start; |
int icmp_phone; |
struct timeval time_before; |
struct timeval time_after; |
141,8 → 154,7 |
switch( argv[ index ][ 1 ] ){ |
case 'c': ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & count, "count", 0 )); |
break; |
case 'f': ERROR_PROPAGATE( parse_parameter_name_int( argc, argv, & index, & value, "address family", 0, parse_address_family )); |
address.sin_family = ( uint16_t ) value; |
case 'f': ERROR_PROPAGATE( parse_parameter_name_int( argc, argv, & index, & family, "address family", 0, parse_address_family )); |
break; |
case 'h': print_help(); |
return EOK; |
160,8 → 172,7 |
}else if( str_lcmp( argv[ index ] + 2, "dont_fragment", 13 ) == 0 ){ |
dont_fragment = 1; |
}else if( str_lcmp( argv[ index ] + 2, "family=", 7 ) == 0 ){ |
ERROR_PROPAGATE( parse_parameter_name_int( argc, argv, & index, & value, "address family", 9, parse_address_family )); |
address.sin_family = ( uint16_t ) value; |
ERROR_PROPAGATE( parse_parameter_name_int( argc, argv, & index, & family, "address family", 9, parse_address_family )); |
}else if( str_lcmp( argv[ index ] + 2, "help", 5 ) == 0 ){ |
print_help(); |
return EOK; |
197,7 → 208,24 |
} |
} |
if( ERROR_OCCURRED( inet_pton( address.sin_family, argv[ argc - 1 ], ( uint8_t * ) & address.sin_addr ))){ |
bzero( address_data, max_length ); |
switch( family ){ |
case AF_INET: |
address_in->sin_family = AF_INET; |
address_start = ( uint8_t * ) & address_in->sin_addr.s_addr; |
addrlen = sizeof( struct sockaddr_in ); |
break; |
case AF_INET6: |
address_in6->sin6_family = AF_INET6; |
address_start = ( uint8_t * ) & address_in6->sin6_addr.s6_addr; |
addrlen = sizeof( struct sockaddr_in6 ); |
break; |
default: |
fprintf( stderr, "Protocol family is not supported\n" ); |
return EAFNOSUPPORT; |
} |
if( ERROR_OCCURRED( inet_pton( family, argv[ argc - 1 ], address_start ))){ |
fprintf( stderr, "Address parse error %d\n", ERROR_CODE ); |
return ERROR_CODE; |
} |
208,6 → 236,11 |
} |
printf( "PING %d bytes of data\n", size ); |
if( ERROR_OCCURRED( inet_ntop( address->sa_family, address_start, address_string, sizeof( address_string )))){ |
fprintf( stderr, "Address error %d\n", ERROR_CODE ); |
}else{ |
printf( "Address %s:\n", address_string ); |
} |
while( count > 0 ){ |
if( ERROR_OCCURRED( gettimeofday( & time_before, NULL ))){ |
214,7 → 247,7 |
fprintf( stderr, "Get time of day error %d\n", ERROR_CODE ); |
return ERROR_CODE; |
} |
result = icmp_echo_msg( icmp_phone, size, timeout, ttl, tos, dont_fragment, ( struct sockaddr * ) & address, sizeof( address )); |
result = icmp_echo_msg( icmp_phone, size, timeout, ttl, tos, dont_fragment, address, addrlen ); |
if( ERROR_OCCURRED( gettimeofday( & time_after, NULL ))){ |
fprintf( stderr, "Get time of day error %d\n", ERROR_CODE ); |
return ERROR_CODE; |
223,11 → 256,11 |
case ICMP_ECHO: |
printf( "Ping round trip time %d microseconds\n", tv_sub( & time_after, & time_before )); |
break; |
case ELIMIT: |
case ETIMEOUT: |
printf( "Timeouted.\n" ); |
break; |
default: |
printf( "Error %d.\n", result ); |
print_error( stdout, result, NULL, "\n" ); |
} |
-- count; |
} |
/branches/network/uspace/srv/net/app/echo/echo.c |
---|
41,6 → 41,7 |
#include <task.h> |
#include "../../include/in.h" |
#include "../../include/in6.h" |
#include "../../include/inet.h" |
#include "../../include/socket.h" |
47,6 → 48,7 |
#include "../../err.h" |
#include "../parse.h" |
#include "../print_error.h" |
/** Echo module name. |
*/ |
67,6 → 69,7 |
/** Translates the character string to the protocol family number. |
* @param name The protocol family name. Input parameter. |
* @returns The corresponding protocol family number. |
* @returns EPFNOSUPPORTED if the protocol family is not supported. |
*/ |
int parse_protocol_family( const char * name ); |
73,6 → 76,7 |
/** Translates the character string to the socket type number. |
* @param name The socket type name. Input parameter. |
* @returns The corresponding socket type number. |
* @returns ESOCKNOSUPPORTED if the socket type is not supported. |
*/ |
int parse_socket_type( const char * name ); |
85,7 → 89,7 |
"\tThe number of received messages to handle. A negative number means infinity. The default is infinity.\n" \ |
"\n" \ |
"-f protocol_family | --family=protocol_family\n" \ |
"\tThe listenning socket protocol family. Only the PF_INET is supported.\n" |
"\tThe listenning socket protocol family. Only the PF_INET and PF_INET6 are supported.\n" |
"\n" \ |
"-h | --help\n" \ |
"\tShow this application help.\n" |
110,8 → 114,10 |
int parse_protocol_family( const char * name ){ |
if( str_lcmp( name, "PF_INET", 7 ) == 0 ){ |
return PF_INET; |
}else if( str_lcmp( name, "PF_INET6", 8 ) == 0 ){ |
return PF_INET6; |
} |
return ENOENT; |
return EPFNOSUPPORT; |
} |
int parse_socket_type( const char * name ){ |
118,7 → 124,7 |
if( str_lcmp( name, "SOCK_DGRAM", 11 ) == 0 ){ |
return SOCK_DGRAM; |
} |
return ENOENT; |
return ESOCKTNOSUPPORT; |
} |
int main( int argc, char * argv[] ){ |
129,12 → 135,18 |
char * reply = NULL; |
sock_type_t type = SOCK_DGRAM; |
int count = -1; |
struct sockaddr_in address = { .sin_family = AF_INET, .sin_port = 7 }; |
int family = PF_INET; |
uint16_t port = 7; |
socklen_t max_length = sizeof( struct sockaddr_in6 ); |
uint8_t address_data[ max_length ]; |
struct sockaddr * address = ( struct sockaddr * ) address_data; |
struct sockaddr_in * address_in = ( struct sockaddr_in * ) address; |
struct sockaddr_in6 * address_in6 = ( struct sockaddr_in6 * ) address; |
socklen_t addrlen; |
char address_string[ INET6_ADDRSTRLEN ]; |
uint8_t * address_start; |
int socket_id; |
int address_length; |
char address_string[ INET_ADDRSTRLEN ]; |
char * data; |
size_t length; |
int index; |
149,21 → 161,13 |
switch( argv[ index ][ 1 ] ){ |
case 'c': ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & count, "count", 0 )); |
break; |
case 'f': ERROR_PROPAGATE( parse_parameter_name_int( argc, argv, & index, & value, "protocol family", 0, parse_protocol_family )); |
family = value; |
switch( family ){ |
case PF_INET: |
address.sin_family = AF_INET; |
case 'f': ERROR_PROPAGATE( parse_parameter_name_int( argc, argv, & index, & family, "protocol family", 0, parse_protocol_family )); |
break; |
default: |
return ENOENT; |
} |
break; |
case 'h': print_help(); |
return EOK; |
break; |
case 'p': ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & value, "port number", 0 )); |
address.sin_port = ( uint16_t ) value; |
port = ( uint16_t ) value; |
break; |
case 'r': ERROR_PROPAGATE( parse_parameter_string( argc, argv, & index, & reply, "reply string", 0 )); |
break; |
178,22 → 182,13 |
case '-': if( str_lcmp( argv[ index ] + 2, "count=", 6 ) == 0 ){ |
ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & count, "received count", 8 )) |
}else if( str_lcmp( argv[ index ] + 2, "family=", 7 ) == 0 ){ |
ERROR_PROPAGATE( parse_parameter_name_int( argc, argv, & index, & value, "protocol family", 9, parse_protocol_family )); |
family = value; |
switch( family ){ |
case PF_INET: |
address.sin_family = AF_INET; |
break; |
default: |
return ENOENT; |
} |
break; |
ERROR_PROPAGATE( parse_parameter_name_int( argc, argv, & index, & family, "protocol family", 9, parse_protocol_family )); |
}else if( str_lcmp( argv[ index ] + 2, "help", 5 ) == 0 ){ |
print_help(); |
return EOK; |
}else if( str_lcmp( argv[ index ] + 2, "port=", 5 ) == 0 ){ |
ERROR_PROPAGATE( parse_parameter_int( argc, argv, & index, & value, "port number", 7 )); |
address.sin_port = ( uint16_t ) value; |
port = ( uint16_t ) value; |
}else if( str_lcmp( argv[ index ] + 2, "reply=", 6 ) == 0 ){ |
ERROR_PROPAGATE( parse_parameter_string( argc, argv, & index, & reply, "reply string", 8 )); |
}else if( str_lcmp( argv[ index ] + 2, "size=", 5 ) == 0 ){ |
239,33 → 234,64 |
fprintf( stderr, "Socket create error %d\n", socket_id ); |
return socket_id; |
} |
if( ERROR_OCCURRED( bind( socket_id, ( struct sockaddr * ) & address, sizeof( address )))){ |
fprintf( stderr, "Socket bind error %d\n", ERROR_CODE ); |
bzero( address_data, max_length ); |
switch( family ){ |
case PF_INET: |
address_in->sin_family = AF_INET; |
address_in->sin_port = port; |
addrlen = sizeof( struct sockaddr_in ); |
break; |
case PF_INET6: |
address_in6->sin6_family = AF_INET6; |
address_in6->sin6_port = port; |
addrlen = sizeof( struct sockaddr_in6 ); |
break; |
default: |
fprintf( stderr, "Protocol family is not supported\n" ); |
return EAFNOSUPPORT; |
} |
if( ERROR_OCCURRED( bind( socket_id, address, addrlen ))){ |
socket_print_error( stderr, ERROR_CODE, "Socket bind: ", "\n" ); |
return ERROR_CODE; |
} |
if( verbose ) printf( "Listenning at %d\n", address.sin_port ); |
if( verbose ) printf( "Listenning at %d\n", port ); |
while( count ){ |
address_length = sizeof( address ); |
value = recvfrom( socket_id, data, size, 0, ( struct sockaddr * ) & address, & address_length ); |
addrlen = max_length; |
value = recvfrom( socket_id, data, size, 0, address, & addrlen ); |
if( value < 0 ){ |
fprintf( stderr, "Socket receive error %d\n", value ); |
socket_print_error( stderr, value, "Socket receive: ", "\n" ); |
}else{ |
length = ( size_t ) value; |
if( verbose ){ |
if( ERROR_OCCURRED( inet_ntop( address.sin_family, ( uint8_t * ) & address.sin_addr.s_addr, address_string, sizeof( address_string )))){ |
address_start = NULL; |
switch( address->sa_family ){ |
case AF_INET: |
port = address_in->sin_port; |
address_start = ( uint8_t * ) & address_in->sin_addr.s_addr; |
break; |
case AF_INET6: |
port = address_in6->sin6_port; |
address_start = ( uint8_t * ) & address_in6->sin6_addr.s6_addr; |
break; |
default: |
fprintf( stderr, "Address family %d (0x%X) is not supported.\n", address->sa_family ); |
} |
if( address_start ){ |
if( ERROR_OCCURRED( inet_ntop( address->sa_family, address_start, address_string, sizeof( address_string )))){ |
fprintf( stderr, "Received address error %d\n", ERROR_CODE ); |
continue; |
}else{ |
data[ length ] = '\0'; |
printf( "Received from %s:%d\n%s\n", address_string, address.sin_port, data ); |
printf( "Received from %s:%d\n%s\n", address_string, port, data ); |
} |
} |
if( ERROR_OCCURRED( sendto( socket_id, reply ? reply : data, reply ? reply_length : length, 0, ( struct sockaddr * ) & address, sizeof( address )))){ |
fprintf( stderr, "Socket send error %d\n", ERROR_CODE ); |
} |
if( ERROR_OCCURRED( sendto( socket_id, reply ? reply : data, reply ? reply_length : length, 0, address, addrlen ))){ |
socket_print_error( stderr, ERROR_CODE, "Socket send: ", "\n" ); |
} |
} |
if( count > 0 ){ |
-- count; |
if( verbose ) printf( "Waiting for next %d packet(s)\n", count ); |
275,7 → 301,7 |
if( verbose ) printf( "Closing the socket\n" ); |
if( ERROR_OCCURRED( closesocket( socket_id ))){ |
fprintf( stderr, "Close socket error %d\n", ERROR_CODE ); |
socket_print_error( stderr, ERROR_CODE, "Close socket: ", "\n" ); |
return ERROR_CODE; |
} |
/branches/network/uspace/srv/net/app/echo/Makefile |
---|
39,7 → 39,8 |
OUTPUT = $(NAME) |
SOURCES = \ |
$(NAME).c \ |
$(NET_BASE)app/parse.c |
$(NET_BASE)app/parse.c \ |
$(NET_BASE)app/print_error.c |
LIBS += ../../socket/libsocket.a |
/branches/network/uspace/srv/net/nil/eth/Makefile |
---|
42,7 → 42,7 |
$(NET_BASE)netif/netif_remote.c \ |
$(STRUCTURES)measured_strings.c \ |
$(STRUCTURES)packet/packet.c \ |
$(STRUCTURES)/packet/packet_client.c \ |
$(STRUCTURES)packet/packet_client.c \ |
$(STRUCTURES)packet/packet_remote.c |
include $(NET_BASE)Makefile.module |
/branches/network/uspace/srv/net/nil/nildummy/Makefile |
---|
41,7 → 41,7 |
$(NET_BASE)netif/netif_remote.c \ |
$(STRUCTURES)measured_strings.c \ |
$(STRUCTURES)packet/packet.c \ |
$(STRUCTURES)/packet/packet_client.c \ |
$(STRUCTURES)packet/packet_client.c \ |
$(STRUCTURES)packet/packet_remote.c |
include $(NET_BASE)Makefile.module |
/branches/network/uspace/srv/net/include/icmp_common.h |
---|
42,7 → 42,7 |
/** Connects to the ICMP module. |
* @param service The ICMP module service. Ignored parameter. |
* @returns The ICMP module phone on success. |
* @returns 0 if called by the bundle module. |
* @returns The ICMP socket identifier if called by the bundle module. |
*/ |
int icmp_connect_module( services_t service ); |
/branches/network/uspace/srv/net/include/icmp_codes.h |
---|
78,7 → 78,7 |
*/ |
#define ICMP_ECHO 8 |
/** Router advertisement. |
/** Router Advertisement. |
*/ |
#define ICMP_ROUTER_ADV 9 |
/branches/network/uspace/srv/net/include/icmp_interface.h |
---|
59,19 → 59,52 |
*/ |
/*@{*/ |
/** \todo |
/** Sends the Destination Unreachable error notification packet. |
* Beginning of the packet is sent as the notification packet data. |
* The source and the destination addresses should be set in the original packet. |
* @param icmp_phone The ICMP module phone used for (semi)remote calls. Input parameter. |
* @param code The error specific code. Input parameter. |
* @param mtu The error MTU value. Input parameter. |
* @param packet The original packet. |
* @returns EOK on success. |
* @returns EPERM if the ICMP error notifications are disabled. |
* @returns ENOMEM if there is not enough memory left. |
*/ |
int icmp_destination_unreachable_msg( int icmp_phone, icmp_code_t code, icmp_param_t mtu, packet_t packet ); |
/** \todo |
/** Sends the Source Quench error notification packet. |
* Beginning of the packet is sent as the notification packet data. |
* The source and the destination addresses should be set in the original packet. |
* @param icmp_phone The ICMP module phone used for (semi)remote calls. Input parameter. |
* @param packet The original packet. |
* @returns EOK on success. |
* @returns EPERM if the ICMP error notifications are disabled. |
* @returns ENOMEM if there is not enough memory left. |
*/ |
int icmp_source_quench_msg( int icmp_phone, packet_t packet ); |
/** \todo |
/** Sends the Time Exceeded error notification packet. |
* Beginning of the packet is sent as the notification packet data. |
* The source and the destination addresses should be set in the original packet. |
* @param icmp_phone The ICMP module phone used for (semi)remote calls. Input parameter. |
* @param code The error specific code. Input parameter. |
* @param packet The original packet. |
* @returns EOK on success. |
* @returns EPERM if the ICMP error notifications are disabled. |
* @returns ENOMEM if there is not enough memory left. |
*/ |
int icmp_time_exceeded_msg( int icmp_phone, icmp_code_t code, packet_t packet ); |
/** \todo |
/** Sends the Parameter Problem error notification packet. |
* Beginning of the packet is sent as the notification packet data. |
* The source and the destination addresses should be set in the original packet. |
* @param icmp_phone The ICMP module phone used for (semi)remote calls. Input parameter. |
* @param code The error specific code. Input parameter. |
* @param pointer The problematic parameter offset. Input parameter. |
* @param packet The original packet. |
* @returns EOK on success. |
* @returns EPERM if the ICMP error notifications are disabled. |
* @returns ENOMEM if there is not enough memory left. |
*/ |
int icmp_parameter_problem_msg( int icmp_phone, icmp_code_t code, icmp_param_t pointer, packet_t packet ); |
/branches/network/uspace/srv/net/include/icmp_api.h |
---|
51,22 → 51,35 |
#include "icmp_codes.h" |
#include "icmp_common.h" |
/** Miliseconds type definition. |
*/ |
typedef size_t mseconds_t; |
/** @name ICMP module application interface |
* This interface is used by other application modules. |
*/ |
/*@{*/ |
/** \todo |
/** Requests an echo message. |
* Sends a packet with specified parameters to the target host and waits for the reply upto the given timeout. |
* Blocks the caller until the reply or the timeout occurres. |
* @param icmp_phone The ICMP module phone used for (semi)remote calls. Input parameter. |
* @param size The message data length in bytes. Input parameter. |
* @param timeout The timeout in miliseconds. Input parameter. |
* @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. |
* @param addr The target host address. Input parameter. |
* @param addrlen The torget host address length. Input parameter. |
* @returns ICMP_ECHO on success. |
* @returns ETIMEOUT if the reply has not arrived before the timeout. |
* @returns ICMP type of the received error notification. |
* @returns EINVAL if the addrlen parameter is less or equal to zero (<=0). |
* @returns ENOMEM if there is not enough memory left. |
* @returns EPARTY if there was an internal error. |
*/ |
int icmp_echo_msg( int icmp_phone, size_t size, suseconds_t timeout, ip_ttl_t ttl, ip_tos_t tos, int dont_fragment, const struct sockaddr * addr, socklen_t addrlen ); |
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 ); |
/** Connects to the ICMP module. |
* @param service The ICMP module service. Ignored parameter. |
* @returns The ICMP module phone on success. |
* @returns 0 if called by the bundle module. |
*/ |
int icmp_connect_module( services_t service ); |
/*@}*/ |
#endif |
/branches/network/uspace/srv/net/include/icmp_client.h |
---|
40,7 → 40,14 |
#include "icmp_codes.h" |
#include "../structures/packet/packet.h" |
/** \todo |
/** Processes the received packet prefixed with an ICMP header. |
* @param packet The received packet. Input parameter. |
* @param type The ICMP header type. Output parameter. |
* @param code The ICMP header code. Output parameter. |
* @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. |
*/ |
int icmp_client_process_packet( packet_t packet, icmp_type_t * type, icmp_code_t * code, icmp_param_t * pointer, icmp_param_t * mtu ); |
/branches/network/uspace/srv/net/include/ip_interface.h |
---|
98,7 → 98,7 |
* @param device_id The device identifier. Input parameter. |
* @param packet The packet queue. Input parameter. |
* @param sender The sending module service. Input parameter. |
* @param target The target transport layer module service to be delivered to. Input parameter. |
* @param error The packet error reporting service. Prefixes the received packet. Input parameter. |
* @returns EOK on success. |
* @returns Other error codes as defined for the generic_send_msg() function. |
*/ |
/branches/network/uspace/srv/net/include/socket.h |
---|
44,6 → 44,7 |
#include "inet.h" |
#include "socket_codes.h" |
#include "socket_errno.h" |
/** @name Socket application programming interface |
*/ |
/branches/network/uspace/srv/net/net/net_standalone.c |
---|
60,21 → 60,11 |
} |
} |
int net_initialize( async_client_conn_t client_connection ){ |
int net_initialize_build( async_client_conn_t client_connection ){ |
ERROR_DECLARE; |
task_id_t task_id; |
netifs_initialize( & net_globals.netifs ); |
char_map_initialize( & net_globals.netif_names ); |
modules_initialize( & net_globals.modules ); |
measured_strings_initialize( & net_globals.configuration ); |
ERROR_PROPAGATE( add_module( NULL, & net_globals.modules, LO_NAME, LO_FILENAME, SERVICE_LO, 0, connect_to_service )); |
ERROR_PROPAGATE( add_module( NULL, & net_globals.modules, DP8390_NAME, DP8390_FILENAME, SERVICE_DP8390, 0, connect_to_service )); |
ERROR_PROPAGATE( add_module( NULL, & net_globals.modules, ETHERNET_NAME, ETHERNET_FILENAME, SERVICE_ETHERNET, 0, connect_to_service )); |
ERROR_PROPAGATE( add_module( NULL, & net_globals.modules, NILDUMMY_NAME, NILDUMMY_FILENAME, SERVICE_NILDUMMY, 0, connect_to_service )); |
task_id = spawn( "/srv/ip" ); |
if( ! task_id ) return EINVAL; |
ERROR_PROPAGATE( add_module( NULL, & net_globals.modules, IP_NAME, IP_FILENAME, SERVICE_IP, task_id, ip_connect_module )); |
84,39 → 74,13 |
return EOK; |
} |
int read_netif_configuration( char * name, netif_ref netif ){ |
int read_netif_configuration_build( char * name, netif_ref netif ){ |
ERROR_DECLARE; |
if( str_lcmp( name, "lo", 2 ) == 0 ){ |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "NAME", LO_NAME )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "NETIF", LO_NAME )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "NIL", NILDUMMY_NAME )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "IL", IP_NAME )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "IP_CONFIG", "static" )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "IP_ADDR", "127.0.0.1" )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "IP_ROUTING", "yes" )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "NETMASK", "255.0.0.0" )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "MTU", "15535" )); |
}else if( str_lcmp( name, "ne2k", 4 ) == 0 ){ |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "NAME", "eth0" )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "NETIF", DP8390_NAME )); |
// standalone ethernet |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "NIL", ETHERNET_NAME )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "ETH_MODE", "DIX" )); //8023_2_LSAP( not supported ), 8023_2_SNAP |
// ERROR_PROPAGATE( add_configuration( & netif->configuration, "ETH_DUMMY", "yes" )); //anything else not starting with 'y' |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "IL", IP_NAME )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "IRQ", "9" )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "IO", "300" )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "MTU", "576" )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "IP_CONFIG", "static" )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "IP_ADDR", "10.0.2.15" )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "IP_ROUTING", "yes" )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "NETMASK", "255.255.255.240" )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "BROADCAST", "10.0.2.255" )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "GATEWAY", "10.0.2.2" )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "DNS1", "10.0.2.2" )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "DNS2", "10.0.2.2" )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "ARP", "arp" )); |
} |
return EOK; |
} |
/branches/network/uspace/srv/net/net/net_bundle.c |
---|
97,21 → 97,11 |
} |
} |
int net_initialize( async_client_conn_t client_connection ){ |
int net_initialize_build( async_client_conn_t client_connection ){ |
ERROR_DECLARE; |
ipcarg_t phonehash; |
netifs_initialize( & net_globals.netifs ); |
char_map_initialize( & net_globals.netif_names ); |
modules_initialize( & net_globals.modules ); |
measured_strings_initialize( & net_globals.configuration ); |
ERROR_PROPAGATE( add_module( NULL, & net_globals.modules, LO_NAME, LO_FILENAME, SERVICE_LO, 0, connect_to_service )); |
ERROR_PROPAGATE( add_module( NULL, & net_globals.modules, DP8390_NAME, DP8390_FILENAME, SERVICE_DP8390, 0, connect_to_service )); |
ERROR_PROPAGATE( add_module( NULL, & net_globals.modules, ETHERNET_NAME, ETHERNET_FILENAME, SERVICE_ETHERNET, 0, connect_to_service )); |
ERROR_PROPAGATE( add_module( NULL, & net_globals.modules, NILDUMMY_NAME, NILDUMMY_FILENAME, SERVICE_NILDUMMY, 0, connect_to_service )); |
ERROR_PROPAGATE( REGISTER_ME( SERVICE_IP, & phonehash )); |
ERROR_PROPAGATE( add_module( NULL, & net_globals.modules, IP_NAME, IP_FILENAME, SERVICE_IP, task_get_id(), ip_connect_module )); |
ERROR_PROPAGATE( ip_initialize( client_connection )); |
126,38 → 116,13 |
return EOK; |
} |
int read_netif_configuration( char * name, netif_ref netif ){ |
int read_netif_configuration_build( char * name, netif_ref netif ){ |
ERROR_DECLARE; |
if( str_lcmp( name, "lo", 2 ) == 0 ){ |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "NAME", LO_NAME )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "NETIF", LO_NAME )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "NIL", NILDUMMY_NAME )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "IL", IP_NAME )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "IP_CONFIG", "static" )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "IP_ADDR", "127.0.0.1" )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "IP_ROUTING", "yes" )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "NETMASK", "255.0.0.0" )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "MTU", "15535" )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "NIL", LO_NAME )); |
}else if( str_lcmp( name, "ne2k", 4 ) == 0 ){ |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "NAME", "eth0" )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "NETIF", DP8390_NAME )); |
// ethernet bundled in dp8390 |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "NIL", DP8390_NAME )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "ETH_MODE", "DIX" )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "IL", IP_NAME )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "IRQ", "9" )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "IO", "300" )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "MTU", "1492" )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "IP_CONFIG", "static" )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "IP_ADDR", "10.0.2.15" )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "IP_ROUTING", "yes" )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "NETMASK", "255.255.255.240" )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "BROADCAST", "10.0.2.255" )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "GATEWAY", "10.0.2.2" )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "DNS1", "10.0.2.2" )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "DNS2", "10.0.2.2" )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "ARP", "arp" )); |
} |
return EOK; |
} |
/branches/network/uspace/srv/net/net/net.c |
---|
129,6 → 129,21 |
*/ |
int net_get_conf( measured_strings_ref netif_conf, measured_string_ref configuration, size_t count, char ** data ); |
/** Initializes the networking module. |
* @param client_connection The client connection processing function. The module skeleton propagates its own one. Input parameter. |
* @returns EOK on success. |
* @returns ENOMEM if there is not enough memory left. |
*/ |
int net_initialize( async_client_conn_t client_connection ); |
/** Reads the network interface specific configuration. |
* @param name The network interface name. Input parameter. |
* @param netif The network interface structure. Input/output parameter. |
* @returns EOK on success. |
* @returns Other error codes as defined for the add_configuration() function. |
*/ |
int read_netif_configuration( char * name, netif_ref netif ); |
/** Networking module global data. |
*/ |
net_globals_t net_globals; |
160,6 → 175,26 |
return EOK; |
} |
int net_initialize( async_client_conn_t client_connection ){ |
ERROR_DECLARE; |
netifs_initialize( & net_globals.netifs ); |
char_map_initialize( & net_globals.netif_names ); |
modules_initialize( & net_globals.modules ); |
measured_strings_initialize( & net_globals.configuration ); |
// TODO dynamic configuration |
ERROR_PROPAGATE( read_configuration()); |
ERROR_PROPAGATE( add_module( NULL, & net_globals.modules, LO_NAME, LO_FILENAME, SERVICE_LO, 0, connect_to_service )); |
ERROR_PROPAGATE( add_module( NULL, & net_globals.modules, DP8390_NAME, DP8390_FILENAME, SERVICE_DP8390, 0, connect_to_service )); |
ERROR_PROPAGATE( add_module( NULL, & net_globals.modules, ETHERNET_NAME, ETHERNET_FILENAME, SERVICE_ETHERNET, 0, connect_to_service )); |
ERROR_PROPAGATE( add_module( NULL, & net_globals.modules, NILDUMMY_NAME, NILDUMMY_FILENAME, SERVICE_NILDUMMY, 0, connect_to_service )); |
// build specific initialization |
return net_initialize_build( client_connection ); |
} |
int net_get_device_conf_req( int net_phone, device_id_t device_id, measured_string_ref * configuration, size_t count, char ** data ){ |
netif_ref netif; |
313,9 → 348,45 |
// read general configuration |
ERROR_PROPAGATE( add_configuration( & net_globals.configuration, "IPV", "4" )); |
ERROR_PROPAGATE( add_configuration( & net_globals.configuration, "MTU", "1500" )); |
ERROR_PROPAGATE( add_configuration( & net_globals.configuration, "ICMP_ERROR_REPORTING", "yes" )); //anything else not starting with 'y' |
ERROR_PROPAGATE( add_configuration( & net_globals.configuration, "ICMP_ECHO_REPLYING", "yes" )); //anything else not starting with 'y' |
return EOK; |
} |
int read_netif_configuration( char * name, netif_ref netif ){ |
ERROR_DECLARE; |
if( str_lcmp( name, "lo", 2 ) == 0 ){ |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "NAME", LO_NAME )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "NETIF", LO_NAME )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "IL", IP_NAME )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "IP_CONFIG", "static" )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "IP_ADDR", "127.0.0.1" )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "IP_ROUTING", "yes" )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "NETMASK", "255.0.0.0" )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "MTU", "15535" )); |
}else if( str_lcmp( name, "ne2k", 4 ) == 0 ){ |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "NAME", "eth0" )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "NETIF", DP8390_NAME )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "ETH_MODE", "DIX" )); //8023_2_LSAP( not supported ), 8023_2_SNAP |
// ERROR_PROPAGATE( add_configuration( & netif->configuration, "ETH_DUMMY", "yes" )); //anything else not starting with 'y' |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "IL", IP_NAME )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "IRQ", "9" )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "IO", "300" )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "MTU", "576" )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "IP_CONFIG", "static" )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "IP_ADDR", "10.0.2.15" )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "IP_ROUTING", "yes" )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "NETMASK", "255.255.255.240" )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "BROADCAST", "10.0.2.255" )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "GATEWAY", "10.0.2.2" )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "DNS1", "10.0.2.2" )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "DNS2", "10.0.2.2" )); |
ERROR_PROPAGATE( add_configuration( & netif->configuration, "ARP", "arp" )); |
} |
return read_netif_configuration_build( name, netif ); |
} |
int start_device( netif_ref netif ){ |
ERROR_DECLARE; |
389,9 → 460,6 |
int i; |
measured_string_ref setting; |
// TODO dynamic configuration |
ERROR_PROPAGATE( read_configuration()); |
for( i = 0; i < count; ++ i ){ |
netif = ( netif_ref ) malloc( sizeof( netif_t )); |
if( ! netif ) return ENOMEM; |
/branches/network/uspace/srv/net/net/net.h |
---|
215,12 → 215,12 |
*/ |
int net_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ); |
/** Initializes the networking module. |
/** Initializes the networking module for the chosen subsystem build type. |
* @param client_connection The client connection processing function. The module skeleton propagates its own one. Input parameter. |
* @returns EOK on success. |
* @returns ENOMEM if there is not enough memory left. |
*/ |
int net_initialize( async_client_conn_t client_connection ); |
int net_initialize_build( async_client_conn_t client_connection ); |
/** Processes the module message. |
* Distributes the message to the right bundled module. |
234,13 → 234,13 |
*/ |
int module_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ); |
/** Reads the network interface specific configuration. |
/** Reads the network interface specific configuration for the chosen subsystem build type. |
* @param name The network interface name. Input parameter. |
* @param netif The network interface structure. Input/output parameter. |
* @returns EOK on success. |
* @returns Other error codes as defined for the add_configuration() function. |
*/ |
int read_netif_configuration( char * name, netif_ref netif ); |
int read_netif_configuration_build( char * name, netif_ref netif ); |
#endif |
/branches/network/uspace/srv/net/il/ip/ip.c |
---|
51,21 → 51,24 |
#include "../../messages.h" |
#include "../../modules.h" |
#include "../../include/net_interface.h" |
#include "../../include/inet.h" |
#include "../../include/socket_codes.h" |
#include "../../include/arp_interface.h" |
#include "../../include/byteorder.h" |
#include "../../include/crc.h" |
#include "../../include/device.h" |
#include "../../include/arp_interface.h" |
#include "../../include/nil_interface.h" |
#include "../../include/icmp_client.h" |
#include "../../include/icmp_codes.h" |
#include "../../include/icmp_interface.h" |
#include "../../include/il_interface.h" |
#include "../../include/in.h" |
#include "../../include/in6.h" |
#include "../../include/inet.h" |
#include "../../include/ip_client.h" |
#include "../../include/ip_interface.h" |
#include "../../include/net_interface.h" |
#include "../../include/nil_interface.h" |
#include "../../include/tl_interface.h" |
#include "../../include/icmp_codes.h" |
#include "../../include/icmp_interface.h" |
#include "../../include/icmp_client.h" |
#include "../../include/socket_codes.h" |
#include "../../include/socket_errno.h" |
#include "../../structures/measured_strings.h" |
#include "../../structures/module_map.h" |
#include "../../structures/packet/packet_client.h" |
97,7 → 100,7 |
/** IP packet address length. |
*/ |
#define IP_ADDR sizeof( in_addr_t ) |
#define IP_ADDR sizeof( struct sockaddr_in6 ) |
/** IP packet prefix length. |
*/ |
179,9 → 182,9 |
int ip_send_route( packet_t packet, ip_netif_ref netif, ip_route_ref route, in_addr_t * src, in_addr_t dest, services_t error ); |
int ip_prepare_packet( in_addr_t * source, in_addr_t dest, packet_t packet, measured_string_ref destination ); |
packet_t ip_split_packet( packet_t packet, size_t prefix, size_t content, size_t suffix, size_t addr_len, services_t error ); |
int ip_fragment_packet( packet_t packet, size_t length, size_t prefix, size_t suffix, size_t addr_len ); |
int ip_fragment_packet_data( packet_t packet, packet_t new_packet, ip_header_ref header, ip_header_ref new_header, size_t length, void * src, void * dest, size_t address_length ); |
packet_t ip_split_packet( packet_t packet, size_t prefix, size_t content, size_t suffix, socklen_t addr_len, services_t error ); |
int ip_fragment_packet( packet_t packet, size_t length, size_t prefix, size_t suffix, socklen_t addr_len ); |
int ip_fragment_packet_data( packet_t packet, packet_t new_packet, ip_header_ref header, ip_header_ref new_header, size_t length, const struct sockaddr * src, const struct sockaddr * dest, socklen_t addrlen ); |
ip_header_ref ip_create_middle_header( packet_t packet, ip_header_ref last ); |
void ip_create_last_header( ip_header_ref last, ip_header_ref first ); |
507,9 → 510,12 |
int ip_send_msg( int il_phone, device_id_t device_id, packet_t packet, services_t sender, services_t error ){ |
ERROR_DECLARE; |
int length; |
int addrlen; |
ip_netif_ref netif; |
ip_route_ref route; |
struct sockaddr * addr; |
struct sockaddr_in * address_in; |
// struct sockaddr_in6 * address_in6; |
in_addr_t * dest; |
in_addr_t * src; |
int phone; |
516,14 → 522,29 |
// addresses in the host byte order |
// should be the next hop address or the target destination address |
length = packet_get_addr( packet, NULL, ( uint8_t ** ) & dest ); |
if( length < 0 ){ |
return ip_release_and_return( packet, length ); |
addrlen = packet_get_addr( packet, NULL, ( uint8_t ** ) & addr ); |
if( addrlen < 0 ){ |
return ip_release_and_return( packet, addrlen ); |
} |
// TODO IPv6 |
if( length != IP_ADDR ){ |
if( addrlen < sizeof( struct sockaddr )){ |
return ip_release_and_return( packet, EINVAL ); |
} |
switch( addr->sa_family ){ |
case AF_INET: |
if( addrlen != sizeof( struct sockaddr_in )){ |
return ip_release_and_return( packet, EINVAL ); |
} |
address_in = ( struct sockaddr_in * ) addr; |
dest = & address_in->sin_addr; |
break; |
// TODO IPv6 |
/* case AF_INET6: |
if( addrlen != sizeof( struct sockaddr_in6 )) return EINVAL; |
address_in6 = ( struct sockaddr_in6 * ) dest; |
address_in6.sin6_addr.s6_addr; |
*/ default: |
return ip_release_and_return( packet, EAFNOSUPPORT ); |
} |
fibril_rwlock_read_lock( & ip_globals.netifs_lock ); |
// device specified? |
if( device_id > 0 ){ |
530,7 → 551,6 |
netif = ip_netifs_find( & ip_globals.netifs, device_id ); |
route = ip_netif_find_route( netif, * dest ); |
}else{ |
// TODO IPv6 |
route = ip_find_route( * dest ); |
netif = route ? route->netif : NULL; |
} |
552,21 → 572,12 |
return ip_release_and_return( packet, EINVAL ); |
} |
} |
// to me? |
if( route->address.s_addr == dest->s_addr ){ |
// TODO loopback deliver |
fibril_rwlock_read_unlock( & ip_globals.netifs_lock ); |
return ip_deliver_local( -1, packet, ( ip_header_ref ) packet_get_data( packet ), error ); |
} |
src = ip_netif_address( netif ); |
if( ! src ){ |
fibril_rwlock_read_unlock( & ip_globals.netifs_lock ); |
return ip_release_and_return( packet, ENOENT ); |
} |
if( ERROR_OCCURRED( ip_send_route( packet, netif, route, src, * dest, error ))){ |
pq_release( ip_globals.net_phone, packet_get_id( packet )); |
} |
ERROR_CODE = ip_send_route( packet, netif, route, src, * dest, error ); |
fibril_rwlock_read_unlock( & ip_globals.netifs_lock ); |
return ERROR_CODE; |
} |
591,8 → 602,10 |
destination.value = route->gateway.s_addr ? ( char * ) & route->gateway.s_addr : ( char * ) & dest.s_addr; |
destination.length = CONVERT_SIZE( dest.s_addr, char, 1 ); |
if( ERROR_OCCURRED( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & destination, & translation, & data ))){ |
sleep( 1 ); |
ERROR_PROPAGATE( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & destination, & translation, & data )); |
// sleep( 1 ); |
// ERROR_PROPAGATE( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & destination, & translation, & data )); |
pq_release( ip_globals.net_phone, packet_get_id( packet )); |
return ERROR_CODE; |
} |
if( !( translation && translation->value )){ |
if( translation ){ |
835,7 → 848,7 |
return EOK; |
} |
packet_t ip_split_packet( packet_t packet, size_t prefix, size_t content, size_t suffix, size_t addr_len, services_t error ){ |
packet_t ip_split_packet( packet_t packet, size_t prefix, size_t content, size_t suffix, socklen_t addr_len, services_t error ){ |
size_t length; |
packet_t next; |
packet_t new_packet; |
874,7 → 887,7 |
return packet; |
} |
int ip_fragment_packet( packet_t packet, size_t length, size_t prefix, size_t suffix, size_t addr_len ){ |
int ip_fragment_packet( packet_t packet, size_t length, size_t prefix, size_t suffix, socklen_t addr_len ){ |
ERROR_DECLARE; |
packet_t new_packet; |
881,14 → 894,14 |
ip_header_ref header; |
ip_header_ref middle_header; |
ip_header_ref last_header; |
uint8_t * src; |
uint8_t * dest; |
size_t address_length; |
struct sockaddr * src; |
struct sockaddr * dest; |
socklen_t addrlen; |
int result; |
result = packet_get_addr( packet, & src, & dest ); |
result = packet_get_addr( packet, ( uint8_t ** ) & src, ( uint8_t ** ) & dest ); |
if( result <= 0 ) return EINVAL; |
address_length = ( size_t ) result; |
addrlen = ( socklen_t ) result; |
if( packet_get_data_length( packet ) <= sizeof( ip_header_t )) return ENOMEM; |
// get header |
header = ( ip_header_ref ) packet_get_data( packet ); |
898,7 → 911,7 |
return EPERM; |
} |
// create the last fragment |
new_packet = packet_get_4( ip_globals.net_phone, prefix, length, suffix, ((( size_t ) address_length > addr_len ) ? ( size_t ) address_length : addr_len )); |
new_packet = packet_get_4( ip_globals.net_phone, prefix, length, suffix, (( addrlen > addr_len ) ? addrlen : addr_len )); |
if( ! new_packet ) return ENOMEM; |
// allocate as much as originally |
last_header = ( ip_header_ref ) packet_suffix( new_packet, IP_HEADER_LENGTH( header )); |
913,7 → 926,7 |
// biggest multiple of 8 lower than content |
// TODO even fragmentation? |
length = length & ( ~ 0x7 );// ( content / 8 ) * 8 |
if( ERROR_OCCURRED( ip_fragment_packet_data( packet, new_packet, header, last_header, (( IP_TOTAL_LENGTH( header ) - length ) % ( length - IP_HEADER_LENGTH( last_header ))), src, dest, address_length ))){ |
if( ERROR_OCCURRED( ip_fragment_packet_data( packet, new_packet, header, last_header, (( IP_TOTAL_LENGTH( header ) - length ) % ( length - IP_HEADER_LENGTH( last_header ))), src, dest, addrlen ))){ |
return ip_release_and_return( packet, ERROR_CODE ); |
} |
// mark the first as fragmented |
920,13 → 933,13 |
header->flags |= IPFLAG_MORE_FRAGMENTS; |
// create middle framgents |
while( IP_TOTAL_LENGTH( header ) > length ){ |
new_packet = packet_get_4( ip_globals.net_phone, prefix, length, suffix, (( address_length >= addr_len ) ? address_length : addr_len )); |
new_packet = packet_get_4( ip_globals.net_phone, prefix, length, suffix, (( addrlen >= addr_len ) ? addrlen : addr_len )); |
if( ! new_packet ) return ENOMEM; |
middle_header = ip_create_middle_header( new_packet, last_header ); |
if( ! middle_header ){ |
return ip_release_and_return( packet, ENOMEM ); |
} |
if( ERROR_OCCURRED( ip_fragment_packet_data( packet, new_packet, header, middle_header, length - IP_HEADER_LENGTH( middle_header ), src, dest, address_length ))){ |
if( ERROR_OCCURRED( ip_fragment_packet_data( packet, new_packet, header, middle_header, length - IP_HEADER_LENGTH( middle_header ), src, dest, addrlen ))){ |
return ip_release_and_return( packet, ERROR_CODE ); |
} |
} |
935,7 → 948,7 |
return EOK; |
} |
int ip_fragment_packet_data( packet_t packet, packet_t new_packet, ip_header_ref header, ip_header_ref new_header, size_t length, void * src, void * dest, size_t address_length ){ |
int ip_fragment_packet_data( packet_t packet, packet_t new_packet, ip_header_ref header, ip_header_ref new_header, size_t length, const struct sockaddr * src, const struct sockaddr * dest, socklen_t addrlen ){ |
ERROR_DECLARE; |
void * data; |
948,7 → 961,7 |
new_header->total_length = htons( IP_HEADER_LENGTH( new_header ) + length ); |
new_header->fragment_offset = header->fragment_offset + IP_HEADER_DATA_LENGTH( header ) / 8; |
new_header->header_checksum = IP_HEADER_CHECKSUM( new_header ); |
ERROR_PROPAGATE( packet_set_addr( new_packet, src, dest, address_length )); |
ERROR_PROPAGATE( packet_set_addr( new_packet, ( const uint8_t * ) src, ( const uint8_t * ) dest, addrlen )); |
return pq_insert_after( packet, new_packet ); |
} |
1015,6 → 1028,10 |
in_addr_t dest; |
ip_route_ref route; |
int phone; |
struct sockaddr * addr; |
struct sockaddr_in addr_in; |
// struct sockaddr_in addr_in6; |
socklen_t addrlen; |
header = ( ip_header_ref ) packet_get_data( packet ); |
if( ! header ){ |
1035,7 → 1052,26 |
} |
// process ipopt and get destination |
dest = ip_get_destination( header ); |
ERROR_PROPAGATE( packet_set_addr( packet, NULL, ( uint8_t * ) & dest.s_addr, IP_ADDR )); |
// set the addrination address |
switch( header->version ){ |
case IPVERSION: |
addrlen = sizeof( addr_in ); |
bzero( & addr_in, addrlen ); |
addr_in.sin_family = AF_INET; |
memcpy( & addr_in.sin_addr.s_addr, & dest, sizeof( dest )); |
addr = ( struct sockaddr * ) & addr_in; |
break; |
/* case IPv6VERSION: |
addrlen = sizeof( dest_in6 ); |
bzero( & dest_in6, addrlen ); |
dest_in6.sin6_family = AF_INET6; |
memcpy( & dest_in6.sin6_addr.s6_addr, ); |
dest = ( struct sockaddr * ) & dest_in; |
break; |
*/ default: |
return EAFNOSUPPORT; |
} |
ERROR_PROPAGATE( packet_set_addr( packet, NULL, ( uint8_t * ) & addr, addrlen )); |
route = ip_find_route( dest ); |
if( ! route ){ |
phone = ip_prepare_icmp_and_get_phone( 0, packet, header ); |
1081,7 → 1117,7 |
return ip_release_and_return( packet, ENOMEM ); |
} |
data = packet_get_data( packet ); |
header = ( ip_header_ref ) data + offset; |
header = ( ip_header_ref )( data + offset ); |
// destination host unreachable? |
if(( type == ICMP_DEST_UNREACH ) && ( code == ICMP_HOST_UNREACH )){ |
fibril_rwlock_read_lock( & ip_globals.netifs_lock ); |
1110,12 → 1146,45 |
ip_proto_ref proto; |
int phone; |
services_t service; |
tl_received_msg_t received_msg; |
struct sockaddr * src; |
struct sockaddr * dest; |
struct sockaddr_in src_in; |
struct sockaddr_in dest_in; |
// struct sockaddr_in src_in6; |
// struct sockaddr_in dest_in6; |
socklen_t addrlen; |
if(( header->flags & IPFLAG_MORE_FRAGMENTS ) || header->fragment_offset ){ |
// TODO fragmented |
return ENOTSUP; |
}else{ |
ERROR_PROPAGATE( packet_set_addr( packet, ( uint8_t * ) & header->source_address, ( uint8_t * ) & header->destination_address, IP_ADDR )); |
switch( header->version ){ |
case IPVERSION: |
addrlen = sizeof( src_in ); |
bzero( & src_in, addrlen ); |
src_in.sin_family = AF_INET; |
memcpy( & dest_in, & src_in, addrlen ); |
memcpy( & src_in.sin_addr.s_addr, & header->source_address, sizeof( header->source_address )); |
memcpy( & dest_in.sin_addr.s_addr, & header->destination_address, sizeof( header->destination_address )); |
src = ( struct sockaddr * ) & src_in; |
dest = ( struct sockaddr * ) & dest_in; |
break; |
/* case IPv6VERSION: |
addrlen = sizeof( src_in6 ); |
bzero( & src_in6, addrlen ); |
src_in6.sin6_family = AF_INET6; |
memcpy( & dest_in6, & src_in6, addrlen ); |
memcpy( & src_in6.sin6_addr.s6_addr, ); |
memcpy( & dest_in6.sin6_addr.s6_addr, ); |
src = ( struct sockaddr * ) & src_in; |
dest = ( struct sockaddr * ) & dest_in; |
break; |
*/ default: |
return EAFNOSUPPORT; |
} |
ERROR_PROPAGATE( packet_set_addr( packet, ( uint8_t * ) src, ( uint8_t * ) dest, addrlen )); |
fibril_rwlock_read_lock( & ip_globals.protos_lock ); |
proto = ip_protos_find( & ip_globals.protos, header->protocol ); |
if( ! proto ){ |
1128,11 → 1197,14 |
return ENOENT; |
} |
if( proto->received_msg ){ |
ERROR_CODE = proto->received_msg( device_id, packet, proto->service, error ); |
service = proto->service; |
received_msg = proto->received_msg; |
fibril_rwlock_read_unlock( & ip_globals.protos_lock ); |
ERROR_CODE = received_msg( device_id, packet, service, error ); |
}else{ |
ERROR_CODE = tl_received_msg( proto->phone, device_id, packet, proto->service, error ); |
fibril_rwlock_read_unlock( & ip_globals.protos_lock ); |
} |
fibril_rwlock_read_unlock( & ip_globals.protos_lock ); |
return ERROR_CODE; |
} |
} |
1147,6 → 1219,10 |
int ip_prepare_icmp( packet_t packet, ip_header_ref header ){ |
packet_t next; |
struct sockaddr * dest; |
struct sockaddr_in dest_in; |
// struct sockaddr_in dest_in6; |
socklen_t addrlen; |
// detach the first packet and release the others |
next = pq_detach( packet ); |
1162,8 → 1238,26 |
// only for the first fragment |
if( header->fragment_offset ) return EINVAL; |
// set the destination address |
return packet_set_addr( packet, NULL, ( uint8_t * ) & header->source_address, sizeof( header->source_address )); |
switch( header->version ){ |
case IPVERSION: |
addrlen = sizeof( dest_in ); |
bzero( & dest_in, addrlen ); |
dest_in.sin_family = AF_INET; |
memcpy( & dest_in.sin_addr.s_addr, & header->source_address, sizeof( header->source_address )); |
dest = ( struct sockaddr * ) & dest_in; |
break; |
/* case IPv6VERSION: |
addrlen = sizeof( dest_in6 ); |
bzero( & dest_in6, addrlen ); |
dest_in6.sin6_family = AF_INET6; |
memcpy( & dest_in6.sin6_addr.s6_addr, ); |
dest = ( struct sockaddr * ) & dest_in; |
break; |
*/ default: |
return EAFNOSUPPORT; |
} |
return packet_set_addr( packet, NULL, ( uint8_t * ) dest, addrlen ); |
} |
int ip_get_icmp_phone( void ){ |
ip_proto_ref proto; |
/branches/network/uspace/srv/net/il/ip/Makefile |
---|
46,8 → 46,9 |
$(NET_BASE)il/arp/arp_remote.c \ |
$(NET_BASE)nil/nil_remote.c \ |
$(NET_BASE)net/net_remote.c \ |
$(NET_BASE)tl/icmp/icmp_client.c \ |
$(NET_BASE)tl/icmp/icmp_common.c \ |
$(NET_BASE)tl/icmp/icmp_remote.c \ |
$(NET_BASE)tl/icmp/icmp_client.c \ |
$(STRUCTURES)char_map.c \ |
$(STRUCTURES)measured_strings.c \ |
$(STRUCTURES)module_map.c \ |