Changeset 858fc90 in mainline for uspace/srv/net/tl/icmp/icmp.c


Ignore:
Timestamp:
2010-03-15T19:35:25Z (14 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
6092b56e
Parents:
92307f1 (diff), 4684368 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge from bzr://bzr.helenos.org/head.

File:
1 edited

Legend:

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

    r92307f1 r858fc90  
    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                 // drop the reply mutex
    346                 fibril_mutex_unlock( & reply->mutex );
    347                 // lock the globals again and clean up
    348                 fibril_rwlock_write_lock( & icmp_globals.lock );
    349347        }else{
    350348                // read the result
    351349                result = reply->result;
    352 
    353                 // release the reply structure
    354                 fibril_mutex_unlock( & reply->mutex );
    355         }
     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);
    356355
    357356        // destroy the reply structure
    358         icmp_replies_exclude_index( & icmp_globals.replies, index );
     357        icmp_replies_exclude_index(&icmp_globals.replies, index);
    359358        return result;
    360359}
    361360
    362 int icmp_destination_unreachable_msg( int icmp_phone, icmp_code_t code, icmp_param_t mtu, packet_t packet ){
    363         icmp_header_ref header;
    364 
    365         header = icmp_prepare_packet( packet );
    366         if( ! header ){
    367                 return icmp_release_and_return( packet, ENOMEM );
    368         }
    369         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){
    370369                header->un.frag.mtu = mtu;
    371370        }
    372         return icmp_send_packet( ICMP_DEST_UNREACH, code, packet, header, SERVICE_ICMP, 0, 0, 0 );
    373 }
    374 
    375 int icmp_source_quench_msg( int icmp_phone, packet_t packet ){
    376         icmp_header_ref header;
    377 
    378         header = icmp_prepare_packet( packet );
    379         if( ! header ){
    380                 return icmp_release_and_return( packet, ENOMEM );
    381         }
    382         return icmp_send_packet( ICMP_SOURCE_QUENCH, 0, packet, header, SERVICE_ICMP, 0, 0, 0 );
    383 }
    384 
    385 int icmp_time_exceeded_msg( int icmp_phone, icmp_code_t code, packet_t packet ){
    386         icmp_header_ref header;
    387 
    388         header = icmp_prepare_packet( packet );
    389         if( ! header ){
    390                 return icmp_release_and_return( packet, ENOMEM );
    391         }
    392         return icmp_send_packet( ICMP_TIME_EXCEEDED, code, packet, header, SERVICE_ICMP, 0, 0, 0 );
    393 }
    394 
    395 int icmp_parameter_problem_msg( int icmp_phone, icmp_code_t code, icmp_param_t pointer, packet_t packet ){
    396         icmp_header_ref header;
    397 
    398         header = icmp_prepare_packet( packet );
    399         if( ! header ){
    400                 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);
    401400        }
    402401        header->un.param.pointer = pointer;
    403         return icmp_send_packet( ICMP_PARAMETERPROB, code, packet, header, SERVICE_ICMP, 0, 0, 0 );
    404 }
    405 
    406 icmp_header_ref icmp_prepare_packet( packet_t packet ){
    407         icmp_header_ref header;
    408         size_t                  header_length;
    409         size_t                  total_length;
    410 
    411         total_length = packet_get_data_length( packet );
    412         if( total_length <= 0 ) return NULL;
    413         header_length = ip_client_header_length( packet );
    414         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        }
    415418        // truncate if longer than 64 bits (without the IP header)
    416         if(( total_length > header_length + ICMP_KEEP_LENGTH )
    417         && ( 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)){
    418421                return NULL;
    419422        }
    420         header = PACKET_PREFIX( packet, icmp_header_t );
    421         if( ! header ) return NULL;
    422         bzero( header, sizeof( * header ));
     423        header = PACKET_PREFIX(packet, icmp_header_t);
     424        if(! header){
     425                return NULL;
     426        }
     427        bzero(header, sizeof(*header));
    423428        return header;
    424429}
    425430
    426 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){
    427432        ERROR_DECLARE;
    428433
    429434        // do not send an error if disabled
    430         if( error && ( ! icmp_globals.error_reporting )){
    431                 return icmp_release_and_return( packet, EPERM );
     435        if(error && (! icmp_globals.error_reporting)){
     436                return icmp_release_and_return(packet, EPERM);
    432437        }
    433438        header->type = type;
    434439        header->code = code;
    435440        header->checksum = 0;
    436         header->checksum = ICMP_CHECKSUM( header, packet_get_data_length( packet ));
    437         if( ERROR_OCCURRED( ip_client_prepare_packet( packet, IPPROTO_ICMP, ttl, tos, dont_fragment, 0 ))){
    438                 return icmp_release_and_return( packet, ERROR_CODE );
    439         }
    440         return ip_send_msg( icmp_globals.ip_phone, -1, packet, SERVICE_ICMP, error );
    441 }
    442 
    443 int icmp_connect_module( services_t service, suseconds_t timeout ){
    444         icmp_echo_ref   echo_data;
    445         icmp_param_t    id;
    446         int                             index;
    447 
    448         echo_data = ( icmp_echo_ref ) malloc( sizeof( * echo_data ));
    449         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        }
    450457        // assign a new identifier
    451         fibril_rwlock_write_lock( & icmp_globals.lock );
    452         index = icmp_bind_free_id( echo_data );
    453         if( index < 0 ){
    454                 free( echo_data );
    455                 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);
    456463                return index;
    457464        }else{
    458465                id = echo_data->identifier;
    459                 fibril_rwlock_write_unlock( & icmp_globals.lock );
     466                fibril_rwlock_write_unlock(&icmp_globals.lock);
    460467                // return the echo data identifier as the ICMP phone
    461468                return id;
     
    463470}
    464471
    465 int icmp_initialize( async_client_conn_t client_connection ){
     472int icmp_initialize(async_client_conn_t client_connection){
    466473        ERROR_DECLARE;
    467474
    468         measured_string_t       names[] = {{ str_dup("ICMP_ERROR_REPORTING"), 20 }, { str_dup("ICMP_ECHO_REPLYING"), 18 }};
    469         measured_string_ref     configuration;
    470         size_t                          count = sizeof( names ) / sizeof( measured_string_t );
    471         char *                          data;
    472 
    473         fibril_rwlock_initialize( & icmp_globals.lock );
    474         fibril_rwlock_write_lock( & icmp_globals.lock );
    475         icmp_replies_initialize( & icmp_globals.replies );
    476         icmp_echo_data_initialize( & icmp_globals.echo_data );
    477         icmp_globals.ip_phone = ip_bind_service( SERVICE_IP, IPPROTO_ICMP, SERVICE_ICMP, client_connection, icmp_received_msg );
    478         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){
    479486                return icmp_globals.ip_phone;
    480487        }
    481         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));
    482489        icmp_globals.packet_dimension.prefix += ICMP_HEADER_SIZE;
    483490        icmp_globals.packet_dimension.content -= ICMP_HEADER_SIZE;
     
    485492        icmp_globals.error_reporting = NET_DEFAULT_ICMP_ERROR_REPORTING;
    486493        icmp_globals.echo_replying = NET_DEFAULT_ICMP_ECHO_REPLYING;
    487         configuration = & names[ 0 ];
    488         ERROR_PROPAGATE( net_get_conf_req( icmp_globals.net_phone, & configuration, count, & data ));
    489         if( configuration ){
    490                 if( configuration[ 0 ].value ){
    491                         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');
    492499                }
    493                 if( configuration[ 1 ].value ){
    494                         icmp_globals.echo_replying = ( configuration[ 1 ].value[ 0 ] == 'y' );
     500                if(configuration[1].value){
     501                        icmp_globals.echo_replying = (configuration[1].value[0] == 'y');
    495502                }
    496                 net_free_settings( configuration, data );
    497         }
    498         fibril_rwlock_write_unlock( & icmp_globals.lock );
     503                net_free_settings(configuration, data);
     504        }
     505        fibril_rwlock_write_unlock(&icmp_globals.lock);
    499506        return EOK;
    500507}
    501508
    502 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){
    503510        ERROR_DECLARE;
    504511
    505         if( ERROR_OCCURRED( icmp_process_packet( packet, error ))){
    506                 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);
    507514        }
    508515
     
    510517}
    511518
    512 int icmp_process_packet( packet_t packet, services_t error ){
     519int icmp_process_packet(packet_t packet, services_t error){
    513520        ERROR_DECLARE;
    514521
    515         size_t                  length;
    516         uint8_t *               src;
    517         int                             addrlen;
    518         int                             result;
    519         void *                  data;
    520         icmp_header_ref header;
    521         icmp_type_t             type;
    522         icmp_code_t             code;
    523 
    524         if( error ){
    525                 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){
    526533                        case SERVICE_ICMP:
    527534                                // process error
    528                                 result = icmp_client_process_packet( packet, & type, & code, NULL, NULL );
    529                                 if( result < 0 ) return result;
    530                                 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;
    531540                                // remove the error header
    532                                 ERROR_PROPAGATE( packet_trim( packet, length, 0 ));
     541                                ERROR_PROPAGATE(packet_trim(packet, length, 0));
    533542                                break;
    534543                        default:
     
    537546        }
    538547        // get rid of the ip header
    539         length = ip_client_header_length( packet );
    540         ERROR_PROPAGATE( packet_trim( packet, length, 0 ));
    541 
    542         length = packet_get_data_length( packet );
    543         if( length <= 0 ) return EINVAL;
    544         if( length < ICMP_HEADER_SIZE) return EINVAL;
    545         data = packet_get_data( packet );
    546         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        }
    547562        // get icmp header
    548         header = ( icmp_header_ref ) data;
     563        header = (icmp_header_ref) data;
    549564        // checksum
    550         if( header->checksum ){
    551                 while( ICMP_CHECKSUM( header, length ) != IP_CHECKSUM_ZERO ){
     565        if(header->checksum){
     566                while(ICMP_CHECKSUM(header, length) != IP_CHECKSUM_ZERO){
    552567                        // set the original message type on error notification
    553568                        // type swap observed in Qemu
    554                         if( error ){
    555                                 switch( header->type ){
     569                        if(error){
     570                                switch(header->type){
    556571                                        case ICMP_ECHOREPLY:
    557572                                                header->type = ICMP_ECHO;
     
    562577                }
    563578        }
    564         switch( header->type ){
     579        switch(header->type){
    565580                case ICMP_ECHOREPLY:
    566                         if( error ){
    567                                 return icmp_process_echo_reply( packet, header, type, code );
     581                        if(error){
     582                                return icmp_process_echo_reply(packet, header, type, code);
    568583                        }else{
    569                                 return icmp_process_echo_reply( packet, header, ICMP_ECHO, 0 );
     584                                return icmp_process_echo_reply(packet, header, ICMP_ECHO, 0);
    570585                        }
    571586                case ICMP_ECHO:
    572                         if( error ){
    573                                 return icmp_process_echo_reply( packet, header, type, code );
     587                        if(error){
     588                                return icmp_process_echo_reply(packet, header, type, code);
    574589                        // do not send a reply if disabled
    575                         }else if( icmp_globals.echo_replying ){
    576                                 addrlen = packet_get_addr( packet, & src, NULL );
    577                                 if(( addrlen > 0 )
     590                        }else if(icmp_globals.echo_replying){
     591                                addrlen = packet_get_addr(packet, &src, NULL);
     592                                if((addrlen > 0)
    578593                                // set both addresses to the source one (avoids the source address deletion before setting the destination one)
    579                                 && ( packet_set_addr( packet, src, src, ( size_t ) addrlen ) == EOK )){
     594                                        && (packet_set_addr(packet, src, src, (size_t) addrlen) == EOK)){
    580595                                        // send the reply
    581                                         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);
    582597                                        return EOK;
    583598                                }else{
     
    599614                case ICMP_SKIP:
    600615                case ICMP_PHOTURIS:
    601                         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);
    602617                        return EOK;
    603618                default:
     
    606621}
    607622
    608 int icmp_process_echo_reply( packet_t packet, icmp_header_ref header, icmp_type_t type, icmp_code_t code ){
    609         int                             reply_key;
    610         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;
    611626
    612627        // compute the reply key
    613         reply_key = ICMP_GET_REPLY_KEY( header->un.echo.identifier, header->un.echo.sequence_number );
    614         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));
    615630        // lock the globals
    616         fibril_rwlock_write_lock( & icmp_globals.lock );
     631        fibril_rwlock_write_lock(&icmp_globals.lock);
    617632        // find the pending reply
    618         reply = icmp_replies_find( & icmp_globals.replies, reply_key );
    619         if( reply ){
     633        reply = icmp_replies_find(&icmp_globals.replies, reply_key);
     634        if(reply){
    620635                // set the result
    621636                reply->result = type;
    622                 // notify the main fibril
    623                 fibril_condvar_signal( & reply->condvar );
    624         }else{
    625                 // unlock only if no reply
    626                 fibril_rwlock_write_unlock( & icmp_globals.lock );
    627         }
     637                // notify the waiting fibril
     638                fibril_condvar_signal(&reply->condvar);
     639        }
     640        fibril_rwlock_write_unlock(&icmp_globals.lock);
    628641        return EOK;
    629642}
    630643
    631 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){
    632645        ERROR_DECLARE;
    633646
    634         packet_t                        packet;
    635 
    636         * answer_count = 0;
    637         switch( IPC_GET_METHOD( * call )){
     647        packet_t packet;
     648
     649        *answer_count = 0;
     650        switch(IPC_GET_METHOD(*call)){
    638651                case NET_TL_RECEIVED:
    639                         if( ! ERROR_OCCURRED( packet_translate( icmp_globals.net_phone, & packet, IPC_GET_PACKET( call )))){
    640                                 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));
    641654                        }
    642655                        return ERROR_CODE;
    643656                case NET_ICMP_INIT:
    644                         return icmp_process_client_messages( callid, * call );
     657                        return icmp_process_client_messages(callid, * call);
    645658                default:
    646                         return icmp_process_message( call );
     659                        return icmp_process_message(call);
    647660        }
    648661        return ENOTSUP;
    649662}
    650663
    651 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){
    652665        ERROR_DECLARE;
    653666
    654         bool                                    keep_on_going = true;
     667        bool keep_on_going = true;
    655668//      fibril_rwlock_t                 lock;
    656         ipc_call_t                              answer;
    657         int                                             answer_count;
    658         size_t                                  length;
    659         struct sockaddr *               addr;
    660         ipc_callid_t                    data_callid;
    661         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;
    662676
    663677        /*
     
    665679         *  - Answer the first NET_ICMP_INIT call.
    666680         */
    667         ipc_answer_0( callid, EOK );
    668 
    669 //      fibril_rwlock_initialize( & lock );
    670 
    671         echo_data = ( icmp_echo_ref ) malloc( sizeof( * echo_data ));
    672         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
    673691        // assign a new identifier
    674         fibril_rwlock_write_lock( & icmp_globals.lock );
    675         ERROR_CODE = icmp_bind_free_id( echo_data );
    676         fibril_rwlock_write_unlock( & icmp_globals.lock );
    677         if( ERROR_CODE < 0 ){
    678                 free( echo_data );
    679                 return ERROR_CODE;
    680         }
    681 
    682         while( keep_on_going ){
    683                 refresh_answer( & answer, & answer_count );
    684 
    685                 callid = async_get_call( & call );
    686 
    687                 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)){
    688713                        case IPC_M_PHONE_HUNGUP:
    689714                                keep_on_going = false;
    690                                 ERROR_CODE = EOK;
     715                                res = EHANGUP;
    691716                                break;
    692717                        case NET_ICMP_ECHO:
    693 //                              fibril_rwlock_write_lock( & lock );
    694                                 if( ! async_data_write_receive( & data_callid, & length )){
    695                                         ERROR_CODE = EINVAL;
     718//                              fibril_rwlock_write_lock(&lock);
     719                                if(! async_data_write_receive(&data_callid, &length)){
     720                                        res = EINVAL;
    696721                                }else{
    697                                         addr = malloc( length );
    698                                         if( ! addr ){
    699                                                 ERROR_CODE = ENOMEM;
     722                                        addr = malloc(length);
     723                                        if(! addr){
     724                                                res = ENOMEM;
    700725                                        }else{
    701                                                 if( ! ERROR_OCCURRED( async_data_write_finalize( data_callid, addr, length ))){
    702                                                         fibril_rwlock_write_lock( & icmp_globals.lock );
    703                                                         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 );
    704                                                         fibril_rwlock_write_unlock( & icmp_globals.lock );
    705                                                         free( addr );
    706                                                         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){
    707732                                                                ++ echo_data->sequence_number;
    708733                                                        }else{
    709734                                                                echo_data->sequence_number = 0;
    710735                                                        }
     736                                                }else{
     737                                                        res = ERROR_CODE;
    711738                                                }
    712739                                        }
    713740                                }
    714 //                              fibril_rwlock_write_unlock( & lock );
     741//                              fibril_rwlock_write_unlock(&lock);
    715742                                break;
    716743                        default:
    717                                 ERROR_CODE = icmp_process_message( & call );
     744                                res = icmp_process_message(&call);
    718745                }
    719 
    720                 answer_call( callid, ERROR_CODE, & answer, answer_count );
    721746        }
    722747
    723748        // release the identifier
    724         fibril_rwlock_write_lock( & icmp_globals.lock );
    725         icmp_echo_data_exclude( & icmp_globals.echo_data, echo_data->identifier );
    726         fibril_rwlock_write_unlock( & icmp_globals.lock );
    727         return EOK;
    728 }
    729 
    730 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){
    731756        ERROR_DECLARE;
    732757
    733         packet_t        packet;
    734 
    735         switch( IPC_GET_METHOD( * call )){
     758        packet_t packet;
     759
     760        switch(IPC_GET_METHOD(*call)){
    736761                case NET_ICMP_DEST_UNREACH:
    737                         if( ! ERROR_OCCURRED( packet_translate( icmp_globals.net_phone, & packet, IPC_GET_PACKET( call )))){
    738                                 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);
    739764                        }
    740765                        return ERROR_CODE;
    741766                case NET_ICMP_SOURCE_QUENCH:
    742                         if( ! ERROR_OCCURRED( packet_translate( icmp_globals.net_phone, & packet, IPC_GET_PACKET( call )))){
    743                                 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);
    744769                        }
    745770                        return ERROR_CODE;
    746771                case NET_ICMP_TIME_EXCEEDED:
    747                         if( ! ERROR_OCCURRED( packet_translate( icmp_globals.net_phone, & packet, IPC_GET_PACKET( call )))){
    748                                 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);
    749774                        }
    750775                        return ERROR_CODE;
    751776                case NET_ICMP_PARAMETERPROB:
    752                         if( ! ERROR_OCCURRED( packet_translate( icmp_globals.net_phone, & packet, IPC_GET_PACKET( call )))){
    753                                 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);
    754779                        }
    755780                        return ERROR_CODE;
     
    759784}
    760785
    761 int     icmp_release_and_return( packet_t packet, int result ){
    762         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));
    763788        return result;
    764789}
    765790
    766 int icmp_bind_free_id( icmp_echo_ref echo_data ){
    767         icmp_param_t    index;
    768 
    769         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        }
    770797        // from the last used one
    771798        index = icmp_globals.last_used_id;
     
    773800                ++ index;
    774801                // til the range end
    775                 if( index >= ICMP_FREE_IDS_END ){
     802                if(index >= ICMP_FREE_IDS_END){
    776803                        // start from the range beginning
    777804                        index = ICMP_FREE_IDS_START - 1;
     
    779806                                ++ index;
    780807                                // til the last used one
    781                                 if( index >= icmp_globals.last_used_id ){
     808                                if(index >= icmp_globals.last_used_id){
    782809                                        // none found
    783810                                        return ENOTCONN;
    784811                                }
    785                         }while( icmp_echo_data_find( & icmp_globals.echo_data, index ) != NULL );
     812                        }while(icmp_echo_data_find(&icmp_globals.echo_data, index) != NULL);
    786813                        // found, break immediately
    787814                        break;
    788815                }
    789         }while( icmp_echo_data_find( & icmp_globals.echo_data, index ) != NULL );
     816        }while(icmp_echo_data_find(&icmp_globals.echo_data, index) != NULL);
    790817        echo_data->identifier = index;
    791818        echo_data->sequence_number = 0;
    792         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);
    793820}
    794821
Note: See TracChangeset for help on using the changeset viewer.