Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/net/tl/icmp/icmp.c

    r91478aa rb48ebd19  
    4141#include <fibril_synch.h>
    4242#include <stdint.h>
     43#include <string.h>
    4344
    4445#include <ipc/ipc.h>
     
    102103 *  @returns The computed checksum.
    103104 */
    104 #define ICMP_CHECKSUM( header, length )         htons( ip_checksum(( uint8_t * ) ( header ), ( length )))
     105#define ICMP_CHECKSUM(header, length)           htons(ip_checksum((uint8_t *) (header), (length)))
    105106
    106107/** An echo request datagrams pattern.
     
    113114 *  @returns The computed ICMP reply data key.
    114115 */
    115 #define ICMP_GET_REPLY_KEY( id, sequence )      ((( id ) << 16 ) | ( sequence & 0xFFFF ))
     116#define ICMP_GET_REPLY_KEY(id, sequence)        (((id) << 16) | (sequence &0xFFFF))
    116117
    117118/** Processes the received ICMP packet.
     
    125126 *  @returns Other error codes as defined for the icmp_process_packet() function.
    126127 */
    127 int     icmp_received_msg( device_id_t device_id, packet_t packet, services_t receiver, services_t error );
     128int icmp_received_msg(device_id_t device_id, packet_t packet, services_t receiver, services_t error);
    128129
    129130/** Processes the received ICMP packet.
     
    140141 *  @returns Other error codes as defined for the ip_client_process_packet() function.
    141142 */
    142 int     icmp_process_packet( packet_t packet, services_t error );
     143int icmp_process_packet(packet_t packet, services_t error);
    143144
    144145/** Processes the client messages.
     
    151152 *  @see icmp_api.h
    152153 */
    153 int icmp_process_client_messages( ipc_callid_t callid, ipc_call_t call );
     154int icmp_process_client_messages(ipc_callid_t callid, ipc_call_t call);
    154155
    155156/** Processes the generic client messages.
     
    164165 *  @see icmp_interface.h
    165166 */
    166 int     icmp_process_message( ipc_call_t * call );
     167int icmp_process_message(ipc_call_t * call);
    167168
    168169/** Releases the packet and returns the result.
     
    171172 *  @returns The result parameter.
    172173 */
    173 int     icmp_release_and_return( packet_t packet, int result );
     174int icmp_release_and_return(packet_t packet, int result);
    174175
    175176/** Requests an echo message.
    176177 *  Sends a packet with specified parameters to the target host and waits for the reply upto the given timeout.
    177  *  Blocks the caller until the reply or the timeout occurres.
     178 *  Blocks the caller until the reply or the timeout occurs.
    178179 *  @param[in] id The message identifier.
    179180 *  @param[in] sequence The message sequence parameter.
     
    192193 *  @returns EPARTY if there was an internal error.
    193194 */
    194 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 );
     195int 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);
    195196
    196197/** Prepares the ICMP error packet.
     
    201202 *  @returns NULL on errors.
    202203 */
    203 icmp_header_ref icmp_prepare_packet( packet_t packet );
     204icmp_header_ref icmp_prepare_packet(packet_t packet);
    204205
    205206/** Sends the ICMP message.
     
    218219 *  @returns EPERM if the error message is not allowed.
    219220 */
    220 int     icmp_send_packet( icmp_type_t type, icmp_code_t code, packet_t packet, icmp_header_ref header, services_t error, ip_ttl_t ttl, ip_tos_t tos, int dont_fragment );
     221int icmp_send_packet(icmp_type_t type, icmp_code_t code, packet_t packet, icmp_header_ref header, services_t error, ip_ttl_t ttl, ip_tos_t tos, int dont_fragment);
    221222
    222223/** Tries to set the pending reply result as the received message type.
    223  *  If the reply data are still present, the reply timeouted and the parent fibril is awaken.
    224  *  The global lock is not released in this case to be reused by the parent fibril.
     224 *  If the reply data is not present, the reply timed out and the other fibril
     225 *  is already awake.
    225226 *  Releases the packet.
    226227 *  @param[in] packet The received reply message.
     
    230231 *  @returns EOK.
    231232 */
    232 int     icmp_process_echo_reply( packet_t packet, icmp_header_ref header, icmp_type_t type, icmp_code_t code );
     233int icmp_process_echo_reply(packet_t packet, icmp_header_ref header, icmp_type_t type, icmp_code_t code);
    233234
    234235/** Assigns a new identifier for the connection.
     
    239240 *  @returns ENOTCONN if no free identifier have been found.
    240241 */
    241 int     icmp_bind_free_id( icmp_echo_ref echo_data );
     242int icmp_bind_free_id(icmp_echo_ref echo_data);
    242243
    243244/** ICMP global data.
     
    245246icmp_globals_t  icmp_globals;
    246247
    247 INT_MAP_IMPLEMENT( icmp_replies, icmp_reply_t );
    248 
    249 INT_MAP_IMPLEMENT( icmp_echo_data, icmp_echo_t );
    250 
    251 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 ){
    252         icmp_echo_ref   echo_data;
    253         int                             res;
    254 
    255         fibril_rwlock_write_lock( & icmp_globals.lock );
     248INT_MAP_IMPLEMENT(icmp_replies, icmp_reply_t);
     249
     250INT_MAP_IMPLEMENT(icmp_echo_data, icmp_echo_t);
     251
     252int 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){
     253        icmp_echo_ref echo_data;
     254        int res;
     255
     256        fibril_rwlock_write_lock(&icmp_globals.lock);
    256257        // use the phone as the echo data index
    257         echo_data = icmp_echo_data_find( & icmp_globals.echo_data, icmp_phone );
    258         if( ! echo_data ){
     258        echo_data = icmp_echo_data_find(&icmp_globals.echo_data, icmp_phone);
     259        if(! echo_data){
    259260                res = ENOENT;
    260261        }else{
    261                 res = icmp_echo( echo_data->identifier, echo_data->sequence_number, size, timeout, ttl, tos, dont_fragment, addr, addrlen );
    262                 if( echo_data->sequence_number < MAX_UINT16 ){
     262                res = icmp_echo(echo_data->identifier, echo_data->sequence_number, size, timeout, ttl, tos, dont_fragment, addr, addrlen);
     263                if(echo_data->sequence_number < MAX_UINT16){
    263264                        ++ echo_data->sequence_number;
    264265                }else{
     
    266267                }
    267268        }
    268         fibril_rwlock_write_unlock( & icmp_globals.lock );
     269        fibril_rwlock_write_unlock(&icmp_globals.lock);
    269270        return res;
    270271}
    271272
    272 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 ){
     273int 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){
    273274        ERROR_DECLARE;
    274275
    275         icmp_header_ref header;
    276         packet_t                packet;
    277         size_t                  length;
    278         uint8_t *               data;
    279         icmp_reply_ref                  reply;
    280         int                             reply_key;
    281         int                             result;
    282         int                             index;
    283 
    284         if( addrlen <= 0 ){
     276        icmp_header_ref header;
     277        packet_t packet;
     278        size_t length;
     279        uint8_t * data;
     280        icmp_reply_ref reply;
     281        int reply_key;
     282        int result;
     283        int index;
     284
     285        if(addrlen <= 0){
    285286                return EINVAL;
    286287        }
    287         length = ( size_t ) addrlen;
     288        length = (size_t) addrlen;
    288289        // TODO do not ask all the time
    289         ERROR_PROPAGATE( ip_packet_size_req( icmp_globals.ip_phone, -1, & icmp_globals.packet_dimension ));
    290         packet = packet_get_4( icmp_globals.net_phone, size, icmp_globals.packet_dimension.addr_len, ICMP_HEADER_SIZE + icmp_globals.packet_dimension.prefix, icmp_globals.packet_dimension.suffix );
    291         if( ! packet ) return ENOMEM;
     290        ERROR_PROPAGATE(ip_packet_size_req(icmp_globals.ip_phone, -1, &icmp_globals.packet_dimension));
     291        packet = packet_get_4(icmp_globals.net_phone, size, icmp_globals.packet_dimension.addr_len, ICMP_HEADER_SIZE + icmp_globals.packet_dimension.prefix, icmp_globals.packet_dimension.suffix);
     292        if(! packet){
     293                return ENOMEM;
     294        }
    292295
    293296        // prepare the requesting packet
    294297        // set the destination address
    295         if( ERROR_OCCURRED( packet_set_addr( packet, NULL, ( const uint8_t * ) addr, length ))){
    296                 return icmp_release_and_return( packet, ERROR_CODE );
     298        if(ERROR_OCCURRED(packet_set_addr(packet, NULL, (const uint8_t *) addr, length))){
     299                return icmp_release_and_return(packet, ERROR_CODE);
    297300        }
    298301        // allocate space in the packet
    299         data = ( uint8_t * ) packet_suffix( packet, size );
    300         if( ! data ){
    301                 return icmp_release_and_return( packet, ENOMEM );
     302        data = (uint8_t *) packet_suffix(packet, size);
     303        if(! data){
     304                return icmp_release_and_return(packet, ENOMEM);
    302305        }
    303306        // fill the data
    304307        length = 0;
    305         while( size > length + sizeof( ICMP_ECHO_TEXT )){
    306                 memcpy( data + length, ICMP_ECHO_TEXT, sizeof( ICMP_ECHO_TEXT ));
    307                 length += sizeof( ICMP_ECHO_TEXT );
    308         }
    309         memcpy( data + length, ICMP_ECHO_TEXT, size - length );
     308        while(size > length + sizeof(ICMP_ECHO_TEXT)){
     309                memcpy(data + length, ICMP_ECHO_TEXT, sizeof(ICMP_ECHO_TEXT));
     310                length += sizeof(ICMP_ECHO_TEXT);
     311        }
     312        memcpy(data + length, ICMP_ECHO_TEXT, size - length);
    310313        // prefix the header
    311         header = PACKET_PREFIX( packet, icmp_header_t );
    312         if( ! header ){
    313                 return icmp_release_and_return( packet, ENOMEM );
    314         }
    315         bzero( header, sizeof( * header ));
     314        header = PACKET_PREFIX(packet, icmp_header_t);
     315        if(! header){
     316                return icmp_release_and_return(packet, ENOMEM);
     317        }
     318        bzero(header, sizeof(*header));
    316319        header->un.echo.identifier = id;
    317320        header->un.echo.sequence_number = sequence;
    318321
    319322        // prepare the reply structure
    320         reply = malloc( sizeof( * reply ));
    321         if( ! reply ){
    322                 return icmp_release_and_return( packet, ENOMEM );
    323         }
    324         fibril_mutex_initialize( & reply->mutex );
    325         fibril_mutex_lock( & reply->mutex );
    326         fibril_condvar_initialize( & reply->condvar );
    327         reply_key = ICMP_GET_REPLY_KEY( header->un.echo.identifier, header->un.echo.sequence_number );
    328         index = icmp_replies_add( & icmp_globals.replies, reply_key, reply );
    329         if( index < 0 ){
    330                 free( reply );
    331                 return icmp_release_and_return( packet, index );
    332         }
    333 
    334         // unlock the globals and wait for a reply
    335         fibril_rwlock_write_unlock( & icmp_globals.lock );
     323        reply = malloc(sizeof(*reply));
     324        if(! reply){
     325                return icmp_release_and_return(packet, ENOMEM);
     326        }
     327        fibril_mutex_initialize(&reply->mutex);
     328        fibril_mutex_lock(&reply->mutex);
     329        fibril_condvar_initialize(&reply->condvar);
     330        reply_key = ICMP_GET_REPLY_KEY(header->un.echo.identifier, header->un.echo.sequence_number);
     331        index = icmp_replies_add(&icmp_globals.replies, reply_key, reply);
     332        if(index < 0){
     333                free(reply);
     334                return icmp_release_and_return(packet, index);
     335        }
     336
     337        // unlock the globals so that we can wait for the reply
     338        fibril_rwlock_write_unlock(&icmp_globals.lock);
    336339
    337340        // send the request
    338         icmp_send_packet( ICMP_ECHO, 0, packet, header, 0, ttl, tos, dont_fragment );
    339 
    340         // wait for a reply
     341        icmp_send_packet(ICMP_ECHO, 0, packet, header, 0, ttl, tos, dont_fragment);
     342
     343        // wait for the reply
    341344        // timeout in microseconds
    342         if( ERROR_OCCURRED( fibril_condvar_wait_timeout( & reply->condvar, & reply->mutex, timeout * 1000 ))){
     345        if(ERROR_OCCURRED(fibril_condvar_wait_timeout(&reply->condvar, &reply->mutex, timeout * 1000))){
    343346                result = ERROR_CODE;
    344 
    345                 // lock the globals again and clean up
    346                 fibril_rwlock_write_lock( & icmp_globals.lock );
    347347        }else{
    348348                // read the result
    349349                result = reply->result;
    350 
    351                 // release the reply structure
    352                 fibril_mutex_unlock( & reply->mutex );
    353         }
     350        }
     351
     352        // drop the reply mutex before locking the globals again
     353        fibril_mutex_unlock(&reply->mutex);
     354        fibril_rwlock_write_lock(&icmp_globals.lock);
    354355
    355356        // destroy the reply structure
    356         icmp_replies_exclude_index( & icmp_globals.replies, index );
     357        icmp_replies_exclude_index(&icmp_globals.replies, index);
    357358        return result;
    358359}
    359360
    360 int icmp_destination_unreachable_msg( int icmp_phone, icmp_code_t code, icmp_param_t mtu, packet_t packet ){
    361         icmp_header_ref header;
    362 
    363         header = icmp_prepare_packet( packet );
    364         if( ! header ){
    365                 return icmp_release_and_return( packet, ENOMEM );
    366         }
    367         if( mtu ){
     361int icmp_destination_unreachable_msg(int icmp_phone, icmp_code_t code, icmp_param_t mtu, packet_t packet){
     362        icmp_header_ref header;
     363
     364        header = icmp_prepare_packet(packet);
     365        if(! header){
     366                return icmp_release_and_return(packet, ENOMEM);
     367        }
     368        if(mtu){
    368369                header->un.frag.mtu = mtu;
    369370        }
    370         return icmp_send_packet( ICMP_DEST_UNREACH, code, packet, header, SERVICE_ICMP, 0, 0, 0 );
    371 }
    372 
    373 int icmp_source_quench_msg( int icmp_phone, packet_t packet ){
    374         icmp_header_ref header;
    375 
    376         header = icmp_prepare_packet( packet );
    377         if( ! header ){
    378                 return icmp_release_and_return( packet, ENOMEM );
    379         }
    380         return icmp_send_packet( ICMP_SOURCE_QUENCH, 0, packet, header, SERVICE_ICMP, 0, 0, 0 );
    381 }
    382 
    383 int icmp_time_exceeded_msg( int icmp_phone, icmp_code_t code, packet_t packet ){
    384         icmp_header_ref header;
    385 
    386         header = icmp_prepare_packet( packet );
    387         if( ! header ){
    388                 return icmp_release_and_return( packet, ENOMEM );
    389         }
    390         return icmp_send_packet( ICMP_TIME_EXCEEDED, code, packet, header, SERVICE_ICMP, 0, 0, 0 );
    391 }
    392 
    393 int icmp_parameter_problem_msg( int icmp_phone, icmp_code_t code, icmp_param_t pointer, packet_t packet ){
    394         icmp_header_ref header;
    395 
    396         header = icmp_prepare_packet( packet );
    397         if( ! header ){
    398                 return icmp_release_and_return( packet, ENOMEM );
     371        return icmp_send_packet(ICMP_DEST_UNREACH, code, packet, header, SERVICE_ICMP, 0, 0, 0);
     372}
     373
     374int icmp_source_quench_msg(int icmp_phone, packet_t packet){
     375        icmp_header_ref header;
     376
     377        header = icmp_prepare_packet(packet);
     378        if(! header){
     379                return icmp_release_and_return(packet, ENOMEM);
     380        }
     381        return icmp_send_packet(ICMP_SOURCE_QUENCH, 0, packet, header, SERVICE_ICMP, 0, 0, 0);
     382}
     383
     384int icmp_time_exceeded_msg(int icmp_phone, icmp_code_t code, packet_t packet){
     385        icmp_header_ref header;
     386
     387        header = icmp_prepare_packet(packet);
     388        if(! header){
     389                return icmp_release_and_return(packet, ENOMEM);
     390        }
     391        return icmp_send_packet(ICMP_TIME_EXCEEDED, code, packet, header, SERVICE_ICMP, 0, 0, 0);
     392}
     393
     394int icmp_parameter_problem_msg(int icmp_phone, icmp_code_t code, icmp_param_t pointer, packet_t packet){
     395        icmp_header_ref header;
     396
     397        header = icmp_prepare_packet(packet);
     398        if(! header){
     399                return icmp_release_and_return(packet, ENOMEM);
    399400        }
    400401        header->un.param.pointer = pointer;
    401         return icmp_send_packet( ICMP_PARAMETERPROB, code, packet, header, SERVICE_ICMP, 0, 0, 0 );
    402 }
    403 
    404 icmp_header_ref icmp_prepare_packet( packet_t packet ){
    405         icmp_header_ref header;
    406         size_t                  header_length;
    407         size_t                  total_length;
    408 
    409         total_length = packet_get_data_length( packet );
    410         if( total_length <= 0 ) return NULL;
    411         header_length = ip_client_header_length( packet );
    412         if( header_length <= 0 ) return NULL;
     402        return icmp_send_packet(ICMP_PARAMETERPROB, code, packet, header, SERVICE_ICMP, 0, 0, 0);
     403}
     404
     405icmp_header_ref icmp_prepare_packet(packet_t packet){
     406        icmp_header_ref header;
     407        size_t header_length;
     408        size_t total_length;
     409
     410        total_length = packet_get_data_length(packet);
     411        if(total_length <= 0){
     412                return NULL;
     413        }
     414        header_length = ip_client_header_length(packet);
     415        if(header_length <= 0){
     416                return NULL;
     417        }
    413418        // truncate if longer than 64 bits (without the IP header)
    414         if(( total_length > header_length + ICMP_KEEP_LENGTH )
    415         && ( packet_trim( packet, 0, total_length - header_length - ICMP_KEEP_LENGTH ) != EOK )){
     419        if((total_length > header_length + ICMP_KEEP_LENGTH)
     420                && (packet_trim(packet, 0, total_length - header_length - ICMP_KEEP_LENGTH) != EOK)){
    416421                return NULL;
    417422        }
    418         header = PACKET_PREFIX( packet, icmp_header_t );
    419         if( ! header ) return NULL;
    420         bzero( header, sizeof( * header ));
     423        header = PACKET_PREFIX(packet, icmp_header_t);
     424        if(! header){
     425                return NULL;
     426        }
     427        bzero(header, sizeof(*header));
    421428        return header;
    422429}
    423430
    424 int icmp_send_packet( icmp_type_t type, icmp_code_t code, packet_t packet, icmp_header_ref header, services_t error, ip_ttl_t ttl, ip_tos_t tos, int dont_fragment ){
     431int icmp_send_packet(icmp_type_t type, icmp_code_t code, packet_t packet, icmp_header_ref header, services_t error, ip_ttl_t ttl, ip_tos_t tos, int dont_fragment){
    425432        ERROR_DECLARE;
    426433
    427434        // do not send an error if disabled
    428         if( error && ( ! icmp_globals.error_reporting )){
    429                 return icmp_release_and_return( packet, EPERM );
     435        if(error && (! icmp_globals.error_reporting)){
     436                return icmp_release_and_return(packet, EPERM);
    430437        }
    431438        header->type = type;
    432439        header->code = code;
    433440        header->checksum = 0;
    434         header->checksum = ICMP_CHECKSUM( header, packet_get_data_length( packet ));
    435         if( ERROR_OCCURRED( ip_client_prepare_packet( packet, IPPROTO_ICMP, ttl, tos, dont_fragment, 0 ))){
    436                 return icmp_release_and_return( packet, ERROR_CODE );
    437         }
    438         return ip_send_msg( icmp_globals.ip_phone, -1, packet, SERVICE_ICMP, error );
    439 }
    440 
    441 int icmp_connect_module( services_t service, suseconds_t timeout ){
    442         icmp_echo_ref   echo_data;
    443         icmp_param_t    id;
    444         int                             index;
    445 
    446         echo_data = ( icmp_echo_ref ) malloc( sizeof( * echo_data ));
    447         if( ! echo_data ) return ENOMEM;
     441        header->checksum = ICMP_CHECKSUM(header, packet_get_data_length(packet));
     442        if(ERROR_OCCURRED(ip_client_prepare_packet(packet, IPPROTO_ICMP, ttl, tos, dont_fragment, 0))){
     443                return icmp_release_and_return(packet, ERROR_CODE);
     444        }
     445        return ip_send_msg(icmp_globals.ip_phone, -1, packet, SERVICE_ICMP, error);
     446}
     447
     448int icmp_connect_module(services_t service, suseconds_t timeout){
     449        icmp_echo_ref echo_data;
     450        icmp_param_t id;
     451        int index;
     452
     453        echo_data = (icmp_echo_ref) malloc(sizeof(*echo_data));
     454        if(! echo_data){
     455                return ENOMEM;
     456        }
    448457        // assign a new identifier
    449         fibril_rwlock_write_lock( & icmp_globals.lock );
    450         index = icmp_bind_free_id( echo_data );
    451         if( index < 0 ){
    452                 free( echo_data );
    453                 fibril_rwlock_write_unlock( & icmp_globals.lock );
     458        fibril_rwlock_write_lock(&icmp_globals.lock);
     459        index = icmp_bind_free_id(echo_data);
     460        if(index < 0){
     461                free(echo_data);
     462                fibril_rwlock_write_unlock(&icmp_globals.lock);
    454463                return index;
    455464        }else{
    456465                id = echo_data->identifier;
    457                 fibril_rwlock_write_unlock( & icmp_globals.lock );
     466                fibril_rwlock_write_unlock(&icmp_globals.lock);
    458467                // return the echo data identifier as the ICMP phone
    459468                return id;
     
    461470}
    462471
    463 int icmp_initialize( async_client_conn_t client_connection ){
     472int icmp_initialize(async_client_conn_t client_connection){
    464473        ERROR_DECLARE;
    465474
    466         measured_string_t       names[] = {{ "ICMP_ERROR_REPORTING", 20 }, { "ICMP_ECHO_REPLYING", 18 }};
    467         measured_string_ref     configuration;
    468         size_t                          count = sizeof( names ) / sizeof( measured_string_t );
    469         char *                          data;
    470 
    471         fibril_rwlock_initialize( & icmp_globals.lock );
    472         fibril_rwlock_write_lock( & icmp_globals.lock );
    473         icmp_replies_initialize( & icmp_globals.replies );
    474         icmp_echo_data_initialize( & icmp_globals.echo_data );
    475         icmp_globals.ip_phone = ip_bind_service( SERVICE_IP, IPPROTO_ICMP, SERVICE_ICMP, client_connection, icmp_received_msg );
    476         if( icmp_globals.ip_phone < 0 ){
     475        measured_string_t names[] = {{str_dup("ICMP_ERROR_REPORTING"), 20}, {str_dup("ICMP_ECHO_REPLYING"), 18}};
     476        measured_string_ref configuration;
     477        size_t count = sizeof(names) / sizeof(measured_string_t);
     478        char * data;
     479
     480        fibril_rwlock_initialize(&icmp_globals.lock);
     481        fibril_rwlock_write_lock(&icmp_globals.lock);
     482        icmp_replies_initialize(&icmp_globals.replies);
     483        icmp_echo_data_initialize(&icmp_globals.echo_data);
     484        icmp_globals.ip_phone = ip_bind_service(SERVICE_IP, IPPROTO_ICMP, SERVICE_ICMP, client_connection, icmp_received_msg);
     485        if(icmp_globals.ip_phone < 0){
    477486                return icmp_globals.ip_phone;
    478487        }
    479         ERROR_PROPAGATE( ip_packet_size_req( icmp_globals.ip_phone, -1, & icmp_globals.packet_dimension ));
     488        ERROR_PROPAGATE(ip_packet_size_req(icmp_globals.ip_phone, -1, &icmp_globals.packet_dimension));
    480489        icmp_globals.packet_dimension.prefix += ICMP_HEADER_SIZE;
    481490        icmp_globals.packet_dimension.content -= ICMP_HEADER_SIZE;
     
    483492        icmp_globals.error_reporting = NET_DEFAULT_ICMP_ERROR_REPORTING;
    484493        icmp_globals.echo_replying = NET_DEFAULT_ICMP_ECHO_REPLYING;
    485         configuration = & names[ 0 ];
    486         ERROR_PROPAGATE( net_get_conf_req( icmp_globals.net_phone, & configuration, count, & data ));
    487         if( configuration ){
    488                 if( configuration[ 0 ].value ){
    489                         icmp_globals.error_reporting = ( configuration[ 0 ].value[ 0 ] == 'y' );
     494        configuration = &names[0];
     495        ERROR_PROPAGATE(net_get_conf_req(icmp_globals.net_phone, &configuration, count, &data));
     496        if(configuration){
     497                if(configuration[0].value){
     498                        icmp_globals.error_reporting = (configuration[0].value[0] == 'y');
    490499                }
    491                 if( configuration[ 1 ].value ){
    492                         icmp_globals.echo_replying = ( configuration[ 1 ].value[ 0 ] == 'y' );
     500                if(configuration[1].value){
     501                        icmp_globals.echo_replying = (configuration[1].value[0] == 'y');
    493502                }
    494                 net_free_settings( configuration, data );
    495         }
    496         fibril_rwlock_write_unlock( & icmp_globals.lock );
     503                net_free_settings(configuration, data);
     504        }
     505        fibril_rwlock_write_unlock(&icmp_globals.lock);
    497506        return EOK;
    498507}
    499508
    500 int     icmp_received_msg( device_id_t device_id, packet_t packet, services_t receiver, services_t error ){
     509int icmp_received_msg(device_id_t device_id, packet_t packet, services_t receiver, services_t error){
    501510        ERROR_DECLARE;
    502511
    503         if( ERROR_OCCURRED( icmp_process_packet( packet, error ))){
    504                 return icmp_release_and_return( packet, ERROR_CODE );
     512        if(ERROR_OCCURRED(icmp_process_packet(packet, error))){
     513                return icmp_release_and_return(packet, ERROR_CODE);
    505514        }
    506515
     
    508517}
    509518
    510 int icmp_process_packet( packet_t packet, services_t error ){
     519int icmp_process_packet(packet_t packet, services_t error){
    511520        ERROR_DECLARE;
    512521
    513         size_t                  length;
    514         uint8_t *               src;
    515         int                             addrlen;
    516         int                             result;
    517         void *                  data;
    518         icmp_header_ref header;
    519         icmp_type_t             type;
    520         icmp_code_t             code;
    521 
    522         if( error ){
    523                 switch( error ){
     522        size_t length;
     523        uint8_t * src;
     524        int addrlen;
     525        int result;
     526        void * data;
     527        icmp_header_ref header;
     528        icmp_type_t type;
     529        icmp_code_t code;
     530
     531        if(error){
     532                switch(error){
    524533                        case SERVICE_ICMP:
    525534                                // process error
    526                                 result = icmp_client_process_packet( packet, & type, & code, NULL, NULL );
    527                                 if( result < 0 ) return result;
    528                                 length = ( size_t ) result;
     535                                result = icmp_client_process_packet(packet, &type, &code, NULL, NULL);
     536                                if(result < 0){
     537                                        return result;
     538                                }
     539                                length = (size_t) result;
    529540                                // remove the error header
    530                                 ERROR_PROPAGATE( packet_trim( packet, length, 0 ));
     541                                ERROR_PROPAGATE(packet_trim(packet, length, 0));
    531542                                break;
    532543                        default:
     
    535546        }
    536547        // get rid of the ip header
    537         length = ip_client_header_length( packet );
    538         ERROR_PROPAGATE( packet_trim( packet, length, 0 ));
    539 
    540         length = packet_get_data_length( packet );
    541         if( length <= 0 ) return EINVAL;
    542         if( length < ICMP_HEADER_SIZE) return EINVAL;
    543         data = packet_get_data( packet );
    544         if( ! data ) return EINVAL;
     548        length = ip_client_header_length(packet);
     549        ERROR_PROPAGATE(packet_trim(packet, length, 0));
     550
     551        length = packet_get_data_length(packet);
     552        if(length <= 0){
     553                return EINVAL;
     554        }
     555        if(length < ICMP_HEADER_SIZE){
     556                return EINVAL;
     557        }
     558        data = packet_get_data(packet);
     559        if(! data){
     560                return EINVAL;
     561        }
    545562        // get icmp header
    546         header = ( icmp_header_ref ) data;
     563        header = (icmp_header_ref) data;
    547564        // checksum
    548         if( header->checksum ){
    549                 while( ICMP_CHECKSUM( header, length ) != IP_CHECKSUM_ZERO ){
     565        if(header->checksum){
     566                while(ICMP_CHECKSUM(header, length) != IP_CHECKSUM_ZERO){
    550567                        // set the original message type on error notification
    551568                        // type swap observed in Qemu
    552                         if( error ){
    553                                 switch( header->type ){
     569                        if(error){
     570                                switch(header->type){
    554571                                        case ICMP_ECHOREPLY:
    555572                                                header->type = ICMP_ECHO;
     
    560577                }
    561578        }
    562         switch( header->type ){
     579        switch(header->type){
    563580                case ICMP_ECHOREPLY:
    564                         if( error ){
    565                                 return icmp_process_echo_reply( packet, header, type, code );
     581                        if(error){
     582                                return icmp_process_echo_reply(packet, header, type, code);
    566583                        }else{
    567                                 return icmp_process_echo_reply( packet, header, ICMP_ECHO, 0 );
     584                                return icmp_process_echo_reply(packet, header, ICMP_ECHO, 0);
    568585                        }
    569586                case ICMP_ECHO:
    570                         if( error ){
    571                                 return icmp_process_echo_reply( packet, header, type, code );
     587                        if(error){
     588                                return icmp_process_echo_reply(packet, header, type, code);
    572589                        // do not send a reply if disabled
    573                         }else if( icmp_globals.echo_replying ){
    574                                 addrlen = packet_get_addr( packet, & src, NULL );
    575                                 if(( addrlen > 0 )
     590                        }else if(icmp_globals.echo_replying){
     591                                addrlen = packet_get_addr(packet, &src, NULL);
     592                                if((addrlen > 0)
    576593                                // set both addresses to the source one (avoids the source address deletion before setting the destination one)
    577                                 && ( packet_set_addr( packet, src, src, ( size_t ) addrlen ) == EOK )){
     594                                        && (packet_set_addr(packet, src, src, (size_t) addrlen) == EOK)){
    578595                                        // send the reply
    579                                         icmp_send_packet( ICMP_ECHOREPLY, 0, packet, header, 0, 0, 0, 0 );
     596                                        icmp_send_packet(ICMP_ECHOREPLY, 0, packet, header, 0, 0, 0, 0);
    580597                                        return EOK;
    581598                                }else{
     
    597614                case ICMP_SKIP:
    598615                case ICMP_PHOTURIS:
    599                         ip_received_error_msg( icmp_globals.ip_phone, -1, packet, SERVICE_IP, SERVICE_ICMP );
     616                        ip_received_error_msg(icmp_globals.ip_phone, -1, packet, SERVICE_IP, SERVICE_ICMP);
    600617                        return EOK;
    601618                default:
     
    604621}
    605622
    606 int icmp_process_echo_reply( packet_t packet, icmp_header_ref header, icmp_type_t type, icmp_code_t code ){
    607         int                             reply_key;
    608         icmp_reply_ref  reply;
     623int icmp_process_echo_reply(packet_t packet, icmp_header_ref header, icmp_type_t type, icmp_code_t code){
     624        int reply_key;
     625        icmp_reply_ref reply;
    609626
    610627        // compute the reply key
    611         reply_key = ICMP_GET_REPLY_KEY( header->un.echo.identifier, header->un.echo.sequence_number );
    612         pq_release( icmp_globals.net_phone, packet_get_id( packet ));
     628        reply_key = ICMP_GET_REPLY_KEY(header->un.echo.identifier, header->un.echo.sequence_number);
     629        pq_release(icmp_globals.net_phone, packet_get_id(packet));
    613630        // lock the globals
    614         fibril_rwlock_write_lock( & icmp_globals.lock );
     631        fibril_rwlock_write_lock(&icmp_globals.lock);
    615632        // find the pending reply
    616         reply = icmp_replies_find( & icmp_globals.replies, reply_key );
    617         if( reply ){
     633        reply = icmp_replies_find(&icmp_globals.replies, reply_key);
     634        if(reply){
    618635                // set the result
    619636                reply->result = type;
    620                 // notify the main fibril
    621                 fibril_condvar_signal( & reply->condvar );
    622         }else{
    623                 // unlock only if no reply
    624                 fibril_rwlock_write_unlock( & icmp_globals.lock );
    625         }
     637                // notify the waiting fibril
     638                fibril_condvar_signal(&reply->condvar);
     639        }
     640        fibril_rwlock_write_unlock(&icmp_globals.lock);
    626641        return EOK;
    627642}
    628643
    629 int icmp_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){
     644int icmp_message(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count){
    630645        ERROR_DECLARE;
    631646
    632         packet_t                        packet;
    633 
    634         * answer_count = 0;
    635         switch( IPC_GET_METHOD( * call )){
     647        packet_t packet;
     648
     649        *answer_count = 0;
     650        switch(IPC_GET_METHOD(*call)){
    636651                case NET_TL_RECEIVED:
    637                         if( ! ERROR_OCCURRED( packet_translate( icmp_globals.net_phone, & packet, IPC_GET_PACKET( call )))){
    638                                 ERROR_CODE = icmp_received_msg( IPC_GET_DEVICE( call ), packet, SERVICE_ICMP, IPC_GET_ERROR( call ));
     652                        if(! ERROR_OCCURRED(packet_translate(icmp_globals.net_phone, &packet, IPC_GET_PACKET(call)))){
     653                                ERROR_CODE = icmp_received_msg(IPC_GET_DEVICE(call), packet, SERVICE_ICMP, IPC_GET_ERROR(call));
    639654                        }
    640655                        return ERROR_CODE;
    641656                case NET_ICMP_INIT:
    642                         return icmp_process_client_messages( callid, * call );
     657                        return icmp_process_client_messages(callid, * call);
    643658                default:
    644                         return icmp_process_message( call );
     659                        return icmp_process_message(call);
    645660        }
    646661        return ENOTSUP;
    647662}
    648663
    649 int icmp_process_client_messages( ipc_callid_t callid, ipc_call_t call ){
     664int icmp_process_client_messages(ipc_callid_t callid, ipc_call_t call){
    650665        ERROR_DECLARE;
    651666
    652         bool                                    keep_on_going = true;
     667        bool keep_on_going = true;
    653668//      fibril_rwlock_t                 lock;
    654         ipc_call_t                              answer;
    655         int                                             answer_count;
    656         size_t                                  length;
    657         struct sockaddr *               addr;
    658         ipc_callid_t                    data_callid;
    659         icmp_echo_ref                   echo_data;
     669        ipc_call_t answer;
     670        int answer_count;
     671        size_t length;
     672        struct sockaddr * addr;
     673        ipc_callid_t data_callid;
     674        icmp_echo_ref echo_data;
     675        int res;
    660676
    661677        /*
     
    663679         *  - Answer the first NET_ICMP_INIT call.
    664680         */
    665         ipc_answer_0( callid, EOK );
    666 
    667 //      fibril_rwlock_initialize( & lock );
    668 
    669         echo_data = ( icmp_echo_ref ) malloc( sizeof( * echo_data ));
    670         if( ! echo_data ) return ENOMEM;
     681        res = EOK;
     682        answer_count = 0;
     683
     684//      fibril_rwlock_initialize(&lock);
     685
     686        echo_data = (icmp_echo_ref) malloc(sizeof(*echo_data));
     687        if(! echo_data){
     688                return ENOMEM;
     689        }
     690
    671691        // assign a new identifier
    672         fibril_rwlock_write_lock( & icmp_globals.lock );
    673         ERROR_CODE = icmp_bind_free_id( echo_data );
    674         fibril_rwlock_write_unlock( & icmp_globals.lock );
    675         if( ERROR_CODE < 0 ){
    676                 free( echo_data );
    677                 return ERROR_CODE;
    678         }
    679 
    680         while( keep_on_going ){
    681                 refresh_answer( & answer, & answer_count );
    682 
    683                 callid = async_get_call( & call );
    684 
    685                 switch( IPC_GET_METHOD( call )){
     692        fibril_rwlock_write_lock(&icmp_globals.lock);
     693        res = icmp_bind_free_id(echo_data);
     694        fibril_rwlock_write_unlock(&icmp_globals.lock);
     695        if(res < 0){
     696                free(echo_data);
     697                return res;
     698        }
     699
     700        while(keep_on_going){
     701
     702                // answer the call
     703                answer_call(callid, res, &answer, answer_count);
     704
     705                // refresh data
     706                refresh_answer(&answer, &answer_count);
     707
     708                // get the next call
     709                callid = async_get_call(&call);
     710
     711                // process the call
     712                switch(IPC_GET_METHOD(call)){
    686713                        case IPC_M_PHONE_HUNGUP:
    687714                                keep_on_going = false;
    688                                 ERROR_CODE = EOK;
     715                                res = EHANGUP;
    689716                                break;
    690717                        case NET_ICMP_ECHO:
    691 //                              fibril_rwlock_write_lock( & lock );
    692                                 if( ! async_data_write_receive( & data_callid, & length )){
    693                                         ERROR_CODE = EINVAL;
     718//                              fibril_rwlock_write_lock(&lock);
     719                                if(! async_data_write_receive(&data_callid, &length)){
     720                                        res = EINVAL;
    694721                                }else{
    695                                         addr = malloc( length );
    696                                         if( ! addr ){
    697                                                 ERROR_CODE = ENOMEM;
     722                                        addr = malloc(length);
     723                                        if(! addr){
     724                                                res = ENOMEM;
    698725                                        }else{
    699                                                 if( ! ERROR_OCCURRED( async_data_write_finalize( data_callid, addr, length ))){
    700                                                         fibril_rwlock_write_lock( & icmp_globals.lock );
    701                                                         ERROR_CODE = icmp_echo( echo_data->identifier, echo_data->sequence_number, 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 );
    702                                                         fibril_rwlock_write_unlock( & icmp_globals.lock );
    703                                                         free( addr );
    704                                                         if( echo_data->sequence_number < MAX_UINT16 ){
     726                                                if(! ERROR_OCCURRED(async_data_write_finalize(data_callid, addr, length))){
     727                                                        fibril_rwlock_write_lock(&icmp_globals.lock);
     728                                                        res = icmp_echo(echo_data->identifier, echo_data->sequence_number, 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);
     729                                                        fibril_rwlock_write_unlock(&icmp_globals.lock);
     730                                                        free(addr);
     731                                                        if(echo_data->sequence_number < MAX_UINT16){
    705732                                                                ++ echo_data->sequence_number;
    706733                                                        }else{
    707734                                                                echo_data->sequence_number = 0;
    708735                                                        }
     736                                                }else{
     737                                                        res = ERROR_CODE;
    709738                                                }
    710739                                        }
    711740                                }
    712 //                              fibril_rwlock_write_unlock( & lock );
     741//                              fibril_rwlock_write_unlock(&lock);
    713742                                break;
    714743                        default:
    715                                 ERROR_CODE = icmp_process_message( & call );
     744                                res = icmp_process_message(&call);
    716745                }
    717 
    718                 answer_call( callid, ERROR_CODE, & answer, answer_count );
    719746        }
    720747
    721748        // release the identifier
    722         fibril_rwlock_write_lock( & icmp_globals.lock );
    723         icmp_echo_data_exclude( & icmp_globals.echo_data, echo_data->identifier );
    724         fibril_rwlock_write_unlock( & icmp_globals.lock );
    725         return EOK;
    726 }
    727 
    728 int icmp_process_message( ipc_call_t * call ){
     749        fibril_rwlock_write_lock(&icmp_globals.lock);
     750        icmp_echo_data_exclude(&icmp_globals.echo_data, echo_data->identifier);
     751        fibril_rwlock_write_unlock(&icmp_globals.lock);
     752        return res;
     753}
     754
     755int icmp_process_message(ipc_call_t * call){
    729756        ERROR_DECLARE;
    730757
    731         packet_t        packet;
    732 
    733         switch( IPC_GET_METHOD( * call )){
     758        packet_t packet;
     759
     760        switch(IPC_GET_METHOD(*call)){
    734761                case NET_ICMP_DEST_UNREACH:
    735                         if( ! ERROR_OCCURRED( packet_translate( icmp_globals.net_phone, & packet, IPC_GET_PACKET( call )))){
    736                                 ERROR_CODE = icmp_destination_unreachable_msg( 0, ICMP_GET_CODE( call ), ICMP_GET_MTU( call ), packet );
     762                        if(! ERROR_OCCURRED(packet_translate(icmp_globals.net_phone, &packet, IPC_GET_PACKET(call)))){
     763                                ERROR_CODE = icmp_destination_unreachable_msg(0, ICMP_GET_CODE(call), ICMP_GET_MTU(call), packet);
    737764                        }
    738765                        return ERROR_CODE;
    739766                case NET_ICMP_SOURCE_QUENCH:
    740                         if( ! ERROR_OCCURRED( packet_translate( icmp_globals.net_phone, & packet, IPC_GET_PACKET( call )))){
    741                                 ERROR_CODE = icmp_source_quench_msg( 0, packet );
     767                        if(! ERROR_OCCURRED(packet_translate(icmp_globals.net_phone, &packet, IPC_GET_PACKET(call)))){
     768                                ERROR_CODE = icmp_source_quench_msg(0, packet);
    742769                        }
    743770                        return ERROR_CODE;
    744771                case NET_ICMP_TIME_EXCEEDED:
    745                         if( ! ERROR_OCCURRED( packet_translate( icmp_globals.net_phone, & packet, IPC_GET_PACKET( call )))){
    746                                 ERROR_CODE = icmp_time_exceeded_msg( 0, ICMP_GET_CODE( call ), packet );
     772                        if(! ERROR_OCCURRED(packet_translate(icmp_globals.net_phone, &packet, IPC_GET_PACKET(call)))){
     773                                ERROR_CODE = icmp_time_exceeded_msg(0, ICMP_GET_CODE(call), packet);
    747774                        }
    748775                        return ERROR_CODE;
    749776                case NET_ICMP_PARAMETERPROB:
    750                         if( ! ERROR_OCCURRED( packet_translate( icmp_globals.net_phone, & packet, IPC_GET_PACKET( call )))){
    751                                 ERROR_CODE = icmp_parameter_problem_msg( 0, ICMP_GET_CODE( call ), ICMP_GET_POINTER( call ), packet );
     777                        if(! ERROR_OCCURRED(packet_translate(icmp_globals.net_phone, &packet, IPC_GET_PACKET(call)))){
     778                                ERROR_CODE = icmp_parameter_problem_msg(0, ICMP_GET_CODE(call), ICMP_GET_POINTER(call), packet);
    752779                        }
    753780                        return ERROR_CODE;
     
    757784}
    758785
    759 int     icmp_release_and_return( packet_t packet, int result ){
    760         pq_release( icmp_globals.net_phone, packet_get_id( packet ));
     786int icmp_release_and_return(packet_t packet, int result){
     787        pq_release(icmp_globals.net_phone, packet_get_id(packet));
    761788        return result;
    762789}
    763790
    764 int icmp_bind_free_id( icmp_echo_ref echo_data ){
    765         icmp_param_t    index;
    766 
    767         if( ! echo_data ) return EBADMEM;
     791int icmp_bind_free_id(icmp_echo_ref echo_data){
     792        icmp_param_t index;
     793
     794        if(! echo_data){
     795                return EBADMEM;
     796        }
    768797        // from the last used one
    769798        index = icmp_globals.last_used_id;
     
    771800                ++ index;
    772801                // til the range end
    773                 if( index >= ICMP_FREE_IDS_END ){
     802                if(index >= ICMP_FREE_IDS_END){
    774803                        // start from the range beginning
    775804                        index = ICMP_FREE_IDS_START - 1;
     
    777806                                ++ index;
    778807                                // til the last used one
    779                                 if( index >= icmp_globals.last_used_id ){
     808                                if(index >= icmp_globals.last_used_id){
    780809                                        // none found
    781810                                        return ENOTCONN;
    782811                                }
    783                         }while( icmp_echo_data_find( & icmp_globals.echo_data, index ) != NULL );
     812                        }while(icmp_echo_data_find(&icmp_globals.echo_data, index) != NULL);
    784813                        // found, break immediately
    785814                        break;
    786815                }
    787         }while( icmp_echo_data_find( & icmp_globals.echo_data, index ) != NULL );
     816        }while(icmp_echo_data_find(&icmp_globals.echo_data, index) != NULL);
    788817        echo_data->identifier = index;
    789818        echo_data->sequence_number = 0;
    790         return icmp_echo_data_add( & icmp_globals.echo_data, index, echo_data );
     819        return icmp_echo_data_add(&icmp_globals.echo_data, index, echo_data);
    791820}
    792821
Note: See TracChangeset for help on using the changeset viewer.