Changeset 71b00dcc in mainline for uspace/srv/net/tl/icmp/icmp.c


Ignore:
Timestamp:
2010-03-07T22:51:38Z (15 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
60ab6c3
Parents:
b5cbff4 (diff), 31c80a5 (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 lp:~lukasmejdrech/helenos/network.

File:
1 edited

Legend:

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

    rb5cbff4 r71b00dcc  
    102102 *  @returns The computed checksum.
    103103 */
    104 #define ICMP_CHECKSUM( header, length )         htons( ip_checksum(( uint8_t * ) ( header ), ( length )))
     104#define ICMP_CHECKSUM(header, length)           htons(ip_checksum((uint8_t *) (header), (length)))
    105105
    106106/** An echo request datagrams pattern.
     
    113113 *  @returns The computed ICMP reply data key.
    114114 */
    115 #define ICMP_GET_REPLY_KEY( id, sequence )      ((( id ) << 16 ) | ( sequence & 0xFFFF ))
     115#define ICMP_GET_REPLY_KEY(id, sequence)        (((id) << 16) | (sequence &0xFFFF))
    116116
    117117/** Processes the received ICMP packet.
     
    125125 *  @returns Other error codes as defined for the icmp_process_packet() function.
    126126 */
    127 int     icmp_received_msg( device_id_t device_id, packet_t packet, services_t receiver, services_t error );
     127int icmp_received_msg(device_id_t device_id, packet_t packet, services_t receiver, services_t error);
    128128
    129129/** Processes the received ICMP packet.
     
    140140 *  @returns Other error codes as defined for the ip_client_process_packet() function.
    141141 */
    142 int     icmp_process_packet( packet_t packet, services_t error );
     142int icmp_process_packet(packet_t packet, services_t error);
    143143
    144144/** Processes the client messages.
     
    151151 *  @see icmp_api.h
    152152 */
    153 int icmp_process_client_messages( ipc_callid_t callid, ipc_call_t call );
     153int icmp_process_client_messages(ipc_callid_t callid, ipc_call_t call);
    154154
    155155/** Processes the generic client messages.
     
    164164 *  @see icmp_interface.h
    165165 */
    166 int     icmp_process_message( ipc_call_t * call );
     166int icmp_process_message(ipc_call_t * call);
    167167
    168168/** Releases the packet and returns the result.
     
    171171 *  @returns The result parameter.
    172172 */
    173 int     icmp_release_and_return( packet_t packet, int result );
     173int icmp_release_and_return(packet_t packet, int result);
    174174
    175175/** Requests an echo message.
     
    192192 *  @returns EPARTY if there was an internal error.
    193193 */
    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 );
     194int 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);
    195195
    196196/** Prepares the ICMP error packet.
     
    201201 *  @returns NULL on errors.
    202202 */
    203 icmp_header_ref icmp_prepare_packet( packet_t packet );
     203icmp_header_ref icmp_prepare_packet(packet_t packet);
    204204
    205205/** Sends the ICMP message.
     
    218218 *  @returns EPERM if the error message is not allowed.
    219219 */
    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 );
     220int 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);
    221221
    222222/** Tries to set the pending reply result as the received message type.
     
    230230 *  @returns EOK.
    231231 */
    232 int     icmp_process_echo_reply( packet_t packet, icmp_header_ref header, icmp_type_t type, icmp_code_t code );
     232int icmp_process_echo_reply(packet_t packet, icmp_header_ref header, icmp_type_t type, icmp_code_t code);
    233233
    234234/** Assigns a new identifier for the connection.
     
    239239 *  @returns ENOTCONN if no free identifier have been found.
    240240 */
    241 int     icmp_bind_free_id( icmp_echo_ref echo_data );
     241int icmp_bind_free_id(icmp_echo_ref echo_data);
    242242
    243243/** ICMP global data.
     
    245245icmp_globals_t  icmp_globals;
    246246
    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 );
     247INT_MAP_IMPLEMENT(icmp_replies, icmp_reply_t);
     248
     249INT_MAP_IMPLEMENT(icmp_echo_data, icmp_echo_t);
     250
     251int 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);
    256256        // 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 ){
     257        echo_data = icmp_echo_data_find(&icmp_globals.echo_data, icmp_phone);
     258        if(! echo_data){
    259259                res = ENOENT;
    260260        }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 ){
     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){
    263263                        ++ echo_data->sequence_number;
    264264                }else{
     
    266266                }
    267267        }
    268         fibril_rwlock_write_unlock( & icmp_globals.lock );
     268        fibril_rwlock_write_unlock(&icmp_globals.lock);
    269269        return res;
    270270}
    271271
    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 ){
     272int 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){
    273273        ERROR_DECLARE;
    274274
    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 ){
     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){
    285285                return EINVAL;
    286286        }
    287         length = ( size_t ) addrlen;
     287        length = (size_t) addrlen;
    288288        // 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;
     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){
     292                return ENOMEM;
     293        }
    292294
    293295        // prepare the requesting packet
    294296        // 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 );
     297        if(ERROR_OCCURRED(packet_set_addr(packet, NULL, (const uint8_t *) addr, length))){
     298                return icmp_release_and_return(packet, ERROR_CODE);
    297299        }
    298300        // allocate space in the packet
    299         data = ( uint8_t * ) packet_suffix( packet, size );
    300         if( ! data ){
    301                 return icmp_release_and_return( packet, ENOMEM );
     301        data = (uint8_t *) packet_suffix(packet, size);
     302        if(! data){
     303                return icmp_release_and_return(packet, ENOMEM);
    302304        }
    303305        // fill the data
    304306        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 );
     307        while(size > length + sizeof(ICMP_ECHO_TEXT)){
     308                memcpy(data + length, ICMP_ECHO_TEXT, sizeof(ICMP_ECHO_TEXT));
     309                length += sizeof(ICMP_ECHO_TEXT);
     310        }
     311        memcpy(data + length, ICMP_ECHO_TEXT, size - length);
    310312        // 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 ));
     313        header = PACKET_PREFIX(packet, icmp_header_t);
     314        if(! header){
     315                return icmp_release_and_return(packet, ENOMEM);
     316        }
     317        bzero(header, sizeof(*header));
    316318        header->un.echo.identifier = id;
    317319        header->un.echo.sequence_number = sequence;
    318320
    319321        // 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 );
     322        reply = malloc(sizeof(*reply));
     323        if(! reply){
     324                return icmp_release_and_return(packet, ENOMEM);
     325        }
     326        fibril_mutex_initialize(&reply->mutex);
     327        fibril_mutex_lock(&reply->mutex);
     328        fibril_condvar_initialize(&reply->condvar);
     329        reply_key = ICMP_GET_REPLY_KEY(header->un.echo.identifier, header->un.echo.sequence_number);
     330        index = icmp_replies_add(&icmp_globals.replies, reply_key, reply);
     331        if(index < 0){
     332                free(reply);
     333                return icmp_release_and_return(packet, index);
    332334        }
    333335
    334336        // unlock the globals so that we can wait for the reply
    335         fibril_rwlock_write_unlock( & icmp_globals.lock );
     337        fibril_rwlock_write_unlock(&icmp_globals.lock);
    336338
    337339        // send the request
    338         icmp_send_packet( ICMP_ECHO, 0, packet, header, 0, ttl, tos, dont_fragment );
     340        icmp_send_packet(ICMP_ECHO, 0, packet, header, 0, ttl, tos, dont_fragment);
    339341
    340342        // wait for the reply
    341343        // timeout in microseconds
    342         if( ERROR_OCCURRED( fibril_condvar_wait_timeout( & reply->condvar, & reply->mutex, timeout * 1000 ))){
     344        if(ERROR_OCCURRED(fibril_condvar_wait_timeout(&reply->condvar, &reply->mutex, timeout * 1000))){
    343345                result = ERROR_CODE;
    344346        }else{
     
    348350
    349351        // drop the reply mutex before locking the globals again
    350         fibril_mutex_unlock( & reply->mutex );
    351         fibril_rwlock_write_lock( & icmp_globals.lock );
     352        fibril_mutex_unlock(&reply->mutex);
     353        fibril_rwlock_write_lock(&icmp_globals.lock);
    352354
    353355        // destroy the reply structure
    354         icmp_replies_exclude_index( & icmp_globals.replies, index );
     356        icmp_replies_exclude_index(&icmp_globals.replies, index);
    355357        return result;
    356358}
    357359
    358 int icmp_destination_unreachable_msg( int icmp_phone, icmp_code_t code, icmp_param_t mtu, packet_t packet ){
    359         icmp_header_ref header;
    360 
    361         header = icmp_prepare_packet( packet );
    362         if( ! header ){
    363                 return icmp_release_and_return( packet, ENOMEM );
    364         }
    365         if( mtu ){
     360int 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){
    366368                header->un.frag.mtu = mtu;
    367369        }
    368         return icmp_send_packet( ICMP_DEST_UNREACH, code, packet, header, SERVICE_ICMP, 0, 0, 0 );
    369 }
    370 
    371 int icmp_source_quench_msg( int icmp_phone, packet_t packet ){
    372         icmp_header_ref header;
    373 
    374         header = icmp_prepare_packet( packet );
    375         if( ! header ){
    376                 return icmp_release_and_return( packet, ENOMEM );
    377         }
    378         return icmp_send_packet( ICMP_SOURCE_QUENCH, 0, packet, header, SERVICE_ICMP, 0, 0, 0 );
    379 }
    380 
    381 int icmp_time_exceeded_msg( int icmp_phone, icmp_code_t code, packet_t packet ){
    382         icmp_header_ref header;
    383 
    384         header = icmp_prepare_packet( packet );
    385         if( ! header ){
    386                 return icmp_release_and_return( packet, ENOMEM );
    387         }
    388         return icmp_send_packet( ICMP_TIME_EXCEEDED, code, packet, header, SERVICE_ICMP, 0, 0, 0 );
    389 }
    390 
    391 int icmp_parameter_problem_msg( int icmp_phone, icmp_code_t code, icmp_param_t pointer, packet_t packet ){
    392         icmp_header_ref header;
    393 
    394         header = icmp_prepare_packet( packet );
    395         if( ! header ){
    396                 return icmp_release_and_return( packet, ENOMEM );
     370        return icmp_send_packet(ICMP_DEST_UNREACH, code, packet, header, SERVICE_ICMP, 0, 0, 0);
     371}
     372
     373int 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
     383int 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
     393int 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);
    397399        }
    398400        header->un.param.pointer = pointer;
    399         return icmp_send_packet( ICMP_PARAMETERPROB, code, packet, header, SERVICE_ICMP, 0, 0, 0 );
    400 }
    401 
    402 icmp_header_ref icmp_prepare_packet( packet_t packet ){
    403         icmp_header_ref header;
    404         size_t                  header_length;
    405         size_t                  total_length;
    406 
    407         total_length = packet_get_data_length( packet );
    408         if( total_length <= 0 ) return NULL;
    409         header_length = ip_client_header_length( packet );
    410         if( header_length <= 0 ) return NULL;
     401        return icmp_send_packet(ICMP_PARAMETERPROB, code, packet, header, SERVICE_ICMP, 0, 0, 0);
     402}
     403
     404icmp_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){
     411                return NULL;
     412        }
     413        header_length = ip_client_header_length(packet);
     414        if(header_length <= 0){
     415                return NULL;
     416        }
    411417        // truncate if longer than 64 bits (without the IP header)
    412         if(( total_length > header_length + ICMP_KEEP_LENGTH )
    413         && ( packet_trim( packet, 0, total_length - header_length - ICMP_KEEP_LENGTH ) != EOK )){
     418        if((total_length > header_length + ICMP_KEEP_LENGTH)
     419                && (packet_trim(packet, 0, total_length - header_length - ICMP_KEEP_LENGTH) != EOK)){
    414420                return NULL;
    415421        }
    416         header = PACKET_PREFIX( packet, icmp_header_t );
    417         if( ! header ) return NULL;
    418         bzero( header, sizeof( * header ));
     422        header = PACKET_PREFIX(packet, icmp_header_t);
     423        if(! header){
     424                return NULL;
     425        }
     426        bzero(header, sizeof(*header));
    419427        return header;
    420428}
    421429
    422 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 ){
     430int 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){
    423431        ERROR_DECLARE;
    424432
    425433        // do not send an error if disabled
    426         if( error && ( ! icmp_globals.error_reporting )){
    427                 return icmp_release_and_return( packet, EPERM );
     434        if(error && (! icmp_globals.error_reporting)){
     435                return icmp_release_and_return(packet, EPERM);
    428436        }
    429437        header->type = type;
    430438        header->code = code;
    431439        header->checksum = 0;
    432         header->checksum = ICMP_CHECKSUM( header, packet_get_data_length( packet ));
    433         if( ERROR_OCCURRED( ip_client_prepare_packet( packet, IPPROTO_ICMP, ttl, tos, dont_fragment, 0 ))){
    434                 return icmp_release_and_return( packet, ERROR_CODE );
    435         }
    436         return ip_send_msg( icmp_globals.ip_phone, -1, packet, SERVICE_ICMP, error );
    437 }
    438 
    439 int icmp_connect_module( services_t service, suseconds_t timeout ){
    440         icmp_echo_ref   echo_data;
    441         icmp_param_t    id;
    442         int                             index;
    443 
    444         echo_data = ( icmp_echo_ref ) malloc( sizeof( * echo_data ));
    445         if( ! echo_data ) return ENOMEM;
     440        header->checksum = ICMP_CHECKSUM(header, packet_get_data_length(packet));
     441        if(ERROR_OCCURRED(ip_client_prepare_packet(packet, IPPROTO_ICMP, ttl, tos, dont_fragment, 0))){
     442                return icmp_release_and_return(packet, ERROR_CODE);
     443        }
     444        return ip_send_msg(icmp_globals.ip_phone, -1, packet, SERVICE_ICMP, error);
     445}
     446
     447int icmp_connect_module(services_t service, suseconds_t timeout){
     448        icmp_echo_ref echo_data;
     449        icmp_param_t id;
     450        int index;
     451
     452        echo_data = (icmp_echo_ref) malloc(sizeof(*echo_data));
     453        if(! echo_data){
     454                return ENOMEM;
     455        }
    446456        // assign a new identifier
    447         fibril_rwlock_write_lock( & icmp_globals.lock );
    448         index = icmp_bind_free_id( echo_data );
    449         if( index < 0 ){
    450                 free( echo_data );
    451                 fibril_rwlock_write_unlock( & icmp_globals.lock );
     457        fibril_rwlock_write_lock(&icmp_globals.lock);
     458        index = icmp_bind_free_id(echo_data);
     459        if(index < 0){
     460                free(echo_data);
     461                fibril_rwlock_write_unlock(&icmp_globals.lock);
    452462                return index;
    453463        }else{
    454464                id = echo_data->identifier;
    455                 fibril_rwlock_write_unlock( & icmp_globals.lock );
     465                fibril_rwlock_write_unlock(&icmp_globals.lock);
    456466                // return the echo data identifier as the ICMP phone
    457467                return id;
     
    459469}
    460470
    461 int icmp_initialize( async_client_conn_t client_connection ){
     471int icmp_initialize(async_client_conn_t client_connection){
    462472        ERROR_DECLARE;
    463473
    464         measured_string_t       names[] = {{ str_dup("ICMP_ERROR_REPORTING"), 20 }, { str_dup("ICMP_ECHO_REPLYING"), 18 }};
    465         measured_string_ref     configuration;
    466         size_t                          count = sizeof( names ) / sizeof( measured_string_t );
    467         char *                          data;
    468 
    469         fibril_rwlock_initialize( & icmp_globals.lock );
    470         fibril_rwlock_write_lock( & icmp_globals.lock );
    471         icmp_replies_initialize( & icmp_globals.replies );
    472         icmp_echo_data_initialize( & icmp_globals.echo_data );
    473         icmp_globals.ip_phone = ip_bind_service( SERVICE_IP, IPPROTO_ICMP, SERVICE_ICMP, client_connection, icmp_received_msg );
    474         if( icmp_globals.ip_phone < 0 ){
     474        measured_string_t names[] = {{str_dup("ICMP_ERROR_REPORTING"), 20}, {str_dup("ICMP_ECHO_REPLYING"), 18}};
     475        measured_string_ref configuration;
     476        size_t count = sizeof(names) / sizeof(measured_string_t);
     477        char * data;
     478
     479        fibril_rwlock_initialize(&icmp_globals.lock);
     480        fibril_rwlock_write_lock(&icmp_globals.lock);
     481        icmp_replies_initialize(&icmp_globals.replies);
     482        icmp_echo_data_initialize(&icmp_globals.echo_data);
     483        icmp_globals.ip_phone = ip_bind_service(SERVICE_IP, IPPROTO_ICMP, SERVICE_ICMP, client_connection, icmp_received_msg);
     484        if(icmp_globals.ip_phone < 0){
    475485                return icmp_globals.ip_phone;
    476486        }
    477         ERROR_PROPAGATE( ip_packet_size_req( icmp_globals.ip_phone, -1, & icmp_globals.packet_dimension ));
     487        ERROR_PROPAGATE(ip_packet_size_req(icmp_globals.ip_phone, -1, &icmp_globals.packet_dimension));
    478488        icmp_globals.packet_dimension.prefix += ICMP_HEADER_SIZE;
    479489        icmp_globals.packet_dimension.content -= ICMP_HEADER_SIZE;
     
    481491        icmp_globals.error_reporting = NET_DEFAULT_ICMP_ERROR_REPORTING;
    482492        icmp_globals.echo_replying = NET_DEFAULT_ICMP_ECHO_REPLYING;
    483         configuration = & names[ 0 ];
    484         ERROR_PROPAGATE( net_get_conf_req( icmp_globals.net_phone, & configuration, count, & data ));
    485         if( configuration ){
    486                 if( configuration[ 0 ].value ){
    487                         icmp_globals.error_reporting = ( configuration[ 0 ].value[ 0 ] == 'y' );
     493        configuration = &names[0];
     494        ERROR_PROPAGATE(net_get_conf_req(icmp_globals.net_phone, &configuration, count, &data));
     495        if(configuration){
     496                if(configuration[0].value){
     497                        icmp_globals.error_reporting = (configuration[0].value[0] == 'y');
    488498                }
    489                 if( configuration[ 1 ].value ){
    490                         icmp_globals.echo_replying = ( configuration[ 1 ].value[ 0 ] == 'y' );
     499                if(configuration[1].value){
     500                        icmp_globals.echo_replying = (configuration[1].value[0] == 'y');
    491501                }
    492                 net_free_settings( configuration, data );
    493         }
    494         fibril_rwlock_write_unlock( & icmp_globals.lock );
     502                net_free_settings(configuration, data);
     503        }
     504        fibril_rwlock_write_unlock(&icmp_globals.lock);
    495505        return EOK;
    496506}
    497507
    498 int     icmp_received_msg( device_id_t device_id, packet_t packet, services_t receiver, services_t error ){
     508int icmp_received_msg(device_id_t device_id, packet_t packet, services_t receiver, services_t error){
    499509        ERROR_DECLARE;
    500510
    501         if( ERROR_OCCURRED( icmp_process_packet( packet, error ))){
    502                 return icmp_release_and_return( packet, ERROR_CODE );
     511        if(ERROR_OCCURRED(icmp_process_packet(packet, error))){
     512                return icmp_release_and_return(packet, ERROR_CODE);
    503513        }
    504514
     
    506516}
    507517
    508 int icmp_process_packet( packet_t packet, services_t error ){
     518int icmp_process_packet(packet_t packet, services_t error){
    509519        ERROR_DECLARE;
    510520
    511         size_t                  length;
    512         uint8_t *               src;
    513         int                             addrlen;
    514         int                             result;
    515         void *                  data;
    516         icmp_header_ref header;
    517         icmp_type_t             type;
    518         icmp_code_t             code;
    519 
    520         if( error ){
    521                 switch( error ){
     521        size_t length;
     522        uint8_t * src;
     523        int addrlen;
     524        int result;
     525        void * data;
     526        icmp_header_ref header;
     527        icmp_type_t type;
     528        icmp_code_t code;
     529
     530        if(error){
     531                switch(error){
    522532                        case SERVICE_ICMP:
    523533                                // process error
    524                                 result = icmp_client_process_packet( packet, & type, & code, NULL, NULL );
    525                                 if( result < 0 ) return result;
    526                                 length = ( size_t ) result;
     534                                result = icmp_client_process_packet(packet, &type, &code, NULL, NULL);
     535                                if(result < 0){
     536                                        return result;
     537                                }
     538                                length = (size_t) result;
    527539                                // remove the error header
    528                                 ERROR_PROPAGATE( packet_trim( packet, length, 0 ));
     540                                ERROR_PROPAGATE(packet_trim(packet, length, 0));
    529541                                break;
    530542                        default:
     
    533545        }
    534546        // get rid of the ip header
    535         length = ip_client_header_length( packet );
    536         ERROR_PROPAGATE( packet_trim( packet, length, 0 ));
    537 
    538         length = packet_get_data_length( packet );
    539         if( length <= 0 ) return EINVAL;
    540         if( length < ICMP_HEADER_SIZE) return EINVAL;
    541         data = packet_get_data( packet );
    542         if( ! data ) return EINVAL;
     547        length = ip_client_header_length(packet);
     548        ERROR_PROPAGATE(packet_trim(packet, length, 0));
     549
     550        length = packet_get_data_length(packet);
     551        if(length <= 0){
     552                return EINVAL;
     553        }
     554        if(length < ICMP_HEADER_SIZE){
     555                return EINVAL;
     556        }
     557        data = packet_get_data(packet);
     558        if(! data){
     559                return EINVAL;
     560        }
    543561        // get icmp header
    544         header = ( icmp_header_ref ) data;
     562        header = (icmp_header_ref) data;
    545563        // checksum
    546         if( header->checksum ){
    547                 while( ICMP_CHECKSUM( header, length ) != IP_CHECKSUM_ZERO ){
     564        if(header->checksum){
     565                while(ICMP_CHECKSUM(header, length) != IP_CHECKSUM_ZERO){
    548566                        // set the original message type on error notification
    549567                        // type swap observed in Qemu
    550                         if( error ){
    551                                 switch( header->type ){
     568                        if(error){
     569                                switch(header->type){
    552570                                        case ICMP_ECHOREPLY:
    553571                                                header->type = ICMP_ECHO;
     
    558576                }
    559577        }
    560         switch( header->type ){
     578        switch(header->type){
    561579                case ICMP_ECHOREPLY:
    562                         if( error ){
    563                                 return icmp_process_echo_reply( packet, header, type, code );
     580                        if(error){
     581                                return icmp_process_echo_reply(packet, header, type, code);
    564582                        }else{
    565                                 return icmp_process_echo_reply( packet, header, ICMP_ECHO, 0 );
     583                                return icmp_process_echo_reply(packet, header, ICMP_ECHO, 0);
    566584                        }
    567585                case ICMP_ECHO:
    568                         if( error ){
    569                                 return icmp_process_echo_reply( packet, header, type, code );
     586                        if(error){
     587                                return icmp_process_echo_reply(packet, header, type, code);
    570588                        // do not send a reply if disabled
    571                         }else if( icmp_globals.echo_replying ){
    572                                 addrlen = packet_get_addr( packet, & src, NULL );
    573                                 if(( addrlen > 0 )
     589                        }else if(icmp_globals.echo_replying){
     590                                addrlen = packet_get_addr(packet, &src, NULL);
     591                                if((addrlen > 0)
    574592                                // set both addresses to the source one (avoids the source address deletion before setting the destination one)
    575                                 && ( packet_set_addr( packet, src, src, ( size_t ) addrlen ) == EOK )){
     593                                        && (packet_set_addr(packet, src, src, (size_t) addrlen) == EOK)){
    576594                                        // send the reply
    577                                         icmp_send_packet( ICMP_ECHOREPLY, 0, packet, header, 0, 0, 0, 0 );
     595                                        icmp_send_packet(ICMP_ECHOREPLY, 0, packet, header, 0, 0, 0, 0);
    578596                                        return EOK;
    579597                                }else{
     
    595613                case ICMP_SKIP:
    596614                case ICMP_PHOTURIS:
    597                         ip_received_error_msg( icmp_globals.ip_phone, -1, packet, SERVICE_IP, SERVICE_ICMP );
     615                        ip_received_error_msg(icmp_globals.ip_phone, -1, packet, SERVICE_IP, SERVICE_ICMP);
    598616                        return EOK;
    599617                default:
     
    602620}
    603621
    604 int icmp_process_echo_reply( packet_t packet, icmp_header_ref header, icmp_type_t type, icmp_code_t code ){
    605         int                             reply_key;
    606         icmp_reply_ref  reply;
     622int icmp_process_echo_reply(packet_t packet, icmp_header_ref header, icmp_type_t type, icmp_code_t code){
     623        int reply_key;
     624        icmp_reply_ref reply;
    607625
    608626        // compute the reply key
    609         reply_key = ICMP_GET_REPLY_KEY( header->un.echo.identifier, header->un.echo.sequence_number );
    610         pq_release( icmp_globals.net_phone, packet_get_id( packet ));
     627        reply_key = ICMP_GET_REPLY_KEY(header->un.echo.identifier, header->un.echo.sequence_number);
     628        pq_release(icmp_globals.net_phone, packet_get_id(packet));
    611629        // lock the globals
    612         fibril_rwlock_write_lock( & icmp_globals.lock );
     630        fibril_rwlock_write_lock(&icmp_globals.lock);
    613631        // find the pending reply
    614         reply = icmp_replies_find( & icmp_globals.replies, reply_key );
    615         if( reply ){
     632        reply = icmp_replies_find(&icmp_globals.replies, reply_key);
     633        if(reply){
    616634                // set the result
    617635                reply->result = type;
    618636                // notify the waiting fibril
    619                 fibril_condvar_signal( & reply->condvar );
    620         }
    621         fibril_rwlock_write_unlock( & icmp_globals.lock );
     637                fibril_condvar_signal(&reply->condvar);
     638        }
     639        fibril_rwlock_write_unlock(&icmp_globals.lock);
    622640        return EOK;
    623641}
    624642
    625 int icmp_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){
     643int icmp_message(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count){
    626644        ERROR_DECLARE;
    627645
    628         packet_t                        packet;
    629 
    630         * answer_count = 0;
    631         switch( IPC_GET_METHOD( * call )){
     646        packet_t packet;
     647
     648        *answer_count = 0;
     649        switch(IPC_GET_METHOD(*call)){
    632650                case NET_TL_RECEIVED:
    633                         if( ! ERROR_OCCURRED( packet_translate( icmp_globals.net_phone, & packet, IPC_GET_PACKET( call )))){
    634                                 ERROR_CODE = icmp_received_msg( IPC_GET_DEVICE( call ), packet, SERVICE_ICMP, IPC_GET_ERROR( call ));
     651                        if(! ERROR_OCCURRED(packet_translate(icmp_globals.net_phone, &packet, IPC_GET_PACKET(call)))){
     652                                ERROR_CODE = icmp_received_msg(IPC_GET_DEVICE(call), packet, SERVICE_ICMP, IPC_GET_ERROR(call));
    635653                        }
    636654                        return ERROR_CODE;
    637655                case NET_ICMP_INIT:
    638                         return icmp_process_client_messages( callid, * call );
     656                        return icmp_process_client_messages(callid, * call);
    639657                default:
    640                         return icmp_process_message( call );
     658                        return icmp_process_message(call);
    641659        }
    642660        return ENOTSUP;
    643661}
    644662
    645 int icmp_process_client_messages( ipc_callid_t callid, ipc_call_t call ){
     663int icmp_process_client_messages(ipc_callid_t callid, ipc_call_t call){
    646664        ERROR_DECLARE;
    647665
    648         bool                                    keep_on_going = true;
     666        bool keep_on_going = true;
    649667//      fibril_rwlock_t                 lock;
    650         ipc_call_t                              answer;
    651         int                                             answer_count;
    652         size_t                                  length;
    653         struct sockaddr *               addr;
    654         ipc_callid_t                    data_callid;
    655         icmp_echo_ref                   echo_data;
     668        ipc_call_t answer;
     669        int answer_count;
     670        size_t length;
     671        struct sockaddr * addr;
     672        ipc_callid_t data_callid;
     673        icmp_echo_ref echo_data;
     674        int res;
    656675
    657676        /*
     
    659678         *  - Answer the first NET_ICMP_INIT call.
    660679         */
    661         ipc_answer_0( callid, EOK );
    662 
    663 //      fibril_rwlock_initialize( & lock );
    664 
    665         echo_data = ( icmp_echo_ref ) malloc( sizeof( * echo_data ));
    666         if( ! echo_data ) return ENOMEM;
     680        res = EOK;
     681        answer_count = 0;
     682
     683//      fibril_rwlock_initialize(&lock);
     684
     685        echo_data = (icmp_echo_ref) malloc(sizeof(*echo_data));
     686        if(! echo_data){
     687                return ENOMEM;
     688        }
     689
    667690        // assign a new identifier
    668         fibril_rwlock_write_lock( & icmp_globals.lock );
    669         ERROR_CODE = icmp_bind_free_id( echo_data );
    670         fibril_rwlock_write_unlock( & icmp_globals.lock );
    671         if( ERROR_CODE < 0 ){
    672                 free( echo_data );
    673                 return ERROR_CODE;
    674         }
    675 
    676         while( keep_on_going ){
    677                 refresh_answer( & answer, & answer_count );
    678 
    679                 callid = async_get_call( & call );
    680 
    681                 switch( IPC_GET_METHOD( call )){
     691        fibril_rwlock_write_lock(&icmp_globals.lock);
     692        res = icmp_bind_free_id(echo_data);
     693        fibril_rwlock_write_unlock(&icmp_globals.lock);
     694        if(res < 0){
     695                free(echo_data);
     696                return res;
     697        }
     698
     699        while(keep_on_going){
     700
     701                // answer the call
     702                answer_call(callid, res, &answer, answer_count);
     703
     704                // refresh data
     705                refresh_answer(&answer, &answer_count);
     706
     707                // get the next call
     708                callid = async_get_call(&call);
     709
     710                // process the call
     711                switch(IPC_GET_METHOD(call)){
    682712                        case IPC_M_PHONE_HUNGUP:
    683713                                keep_on_going = false;
    684                                 ERROR_CODE = EOK;
     714                                res = EHANGUP;
    685715                                break;
    686716                        case NET_ICMP_ECHO:
    687 //                              fibril_rwlock_write_lock( & lock );
    688                                 if( ! async_data_write_receive( & data_callid, & length )){
    689                                         ERROR_CODE = EINVAL;
     717//                              fibril_rwlock_write_lock(&lock);
     718                                if(! async_data_write_receive(&data_callid, &length)){
     719                                        res = EINVAL;
    690720                                }else{
    691                                         addr = malloc( length );
    692                                         if( ! addr ){
    693                                                 ERROR_CODE = ENOMEM;
     721                                        addr = malloc(length);
     722                                        if(! addr){
     723                                                res = ENOMEM;
    694724                                        }else{
    695                                                 if( ! ERROR_OCCURRED( async_data_write_finalize( data_callid, addr, length ))){
    696                                                         fibril_rwlock_write_lock( & icmp_globals.lock );
    697                                                         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 );
    698                                                         fibril_rwlock_write_unlock( & icmp_globals.lock );
    699                                                         free( addr );
    700                                                         if( echo_data->sequence_number < MAX_UINT16 ){
     725                                                if(! ERROR_OCCURRED(async_data_write_finalize(data_callid, addr, length))){
     726                                                        fibril_rwlock_write_lock(&icmp_globals.lock);
     727                                                        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);
     728                                                        fibril_rwlock_write_unlock(&icmp_globals.lock);
     729                                                        free(addr);
     730                                                        if(echo_data->sequence_number < MAX_UINT16){
    701731                                                                ++ echo_data->sequence_number;
    702732                                                        }else{
    703733                                                                echo_data->sequence_number = 0;
    704734                                                        }
     735                                                }else{
     736                                                        res = ERROR_CODE;
    705737                                                }
    706738                                        }
    707739                                }
    708 //                              fibril_rwlock_write_unlock( & lock );
     740//                              fibril_rwlock_write_unlock(&lock);
    709741                                break;
    710742                        default:
    711                                 ERROR_CODE = icmp_process_message( & call );
     743                                res = icmp_process_message(&call);
    712744                }
    713 
    714                 answer_call( callid, ERROR_CODE, & answer, answer_count );
    715745        }
    716746
    717747        // release the identifier
    718         fibril_rwlock_write_lock( & icmp_globals.lock );
    719         icmp_echo_data_exclude( & icmp_globals.echo_data, echo_data->identifier );
    720         fibril_rwlock_write_unlock( & icmp_globals.lock );
    721         return EOK;
    722 }
    723 
    724 int icmp_process_message( ipc_call_t * call ){
     748        fibril_rwlock_write_lock(&icmp_globals.lock);
     749        icmp_echo_data_exclude(&icmp_globals.echo_data, echo_data->identifier);
     750        fibril_rwlock_write_unlock(&icmp_globals.lock);
     751        return res;
     752}
     753
     754int icmp_process_message(ipc_call_t * call){
    725755        ERROR_DECLARE;
    726756
    727         packet_t        packet;
    728 
    729         switch( IPC_GET_METHOD( * call )){
     757        packet_t packet;
     758
     759        switch(IPC_GET_METHOD(*call)){
    730760                case NET_ICMP_DEST_UNREACH:
    731                         if( ! ERROR_OCCURRED( packet_translate( icmp_globals.net_phone, & packet, IPC_GET_PACKET( call )))){
    732                                 ERROR_CODE = icmp_destination_unreachable_msg( 0, ICMP_GET_CODE( call ), ICMP_GET_MTU( call ), packet );
     761                        if(! ERROR_OCCURRED(packet_translate(icmp_globals.net_phone, &packet, IPC_GET_PACKET(call)))){
     762                                ERROR_CODE = icmp_destination_unreachable_msg(0, ICMP_GET_CODE(call), ICMP_GET_MTU(call), packet);
    733763                        }
    734764                        return ERROR_CODE;
    735765                case NET_ICMP_SOURCE_QUENCH:
    736                         if( ! ERROR_OCCURRED( packet_translate( icmp_globals.net_phone, & packet, IPC_GET_PACKET( call )))){
    737                                 ERROR_CODE = icmp_source_quench_msg( 0, packet );
     766                        if(! ERROR_OCCURRED(packet_translate(icmp_globals.net_phone, &packet, IPC_GET_PACKET(call)))){
     767                                ERROR_CODE = icmp_source_quench_msg(0, packet);
    738768                        }
    739769                        return ERROR_CODE;
    740770                case NET_ICMP_TIME_EXCEEDED:
    741                         if( ! ERROR_OCCURRED( packet_translate( icmp_globals.net_phone, & packet, IPC_GET_PACKET( call )))){
    742                                 ERROR_CODE = icmp_time_exceeded_msg( 0, ICMP_GET_CODE( call ), packet );
     771                        if(! ERROR_OCCURRED(packet_translate(icmp_globals.net_phone, &packet, IPC_GET_PACKET(call)))){
     772                                ERROR_CODE = icmp_time_exceeded_msg(0, ICMP_GET_CODE(call), packet);
    743773                        }
    744774                        return ERROR_CODE;
    745775                case NET_ICMP_PARAMETERPROB:
    746                         if( ! ERROR_OCCURRED( packet_translate( icmp_globals.net_phone, & packet, IPC_GET_PACKET( call )))){
    747                                 ERROR_CODE = icmp_parameter_problem_msg( 0, ICMP_GET_CODE( call ), ICMP_GET_POINTER( call ), packet );
     776                        if(! ERROR_OCCURRED(packet_translate(icmp_globals.net_phone, &packet, IPC_GET_PACKET(call)))){
     777                                ERROR_CODE = icmp_parameter_problem_msg(0, ICMP_GET_CODE(call), ICMP_GET_POINTER(call), packet);
    748778                        }
    749779                        return ERROR_CODE;
     
    753783}
    754784
    755 int     icmp_release_and_return( packet_t packet, int result ){
    756         pq_release( icmp_globals.net_phone, packet_get_id( packet ));
     785int icmp_release_and_return(packet_t packet, int result){
     786        pq_release(icmp_globals.net_phone, packet_get_id(packet));
    757787        return result;
    758788}
    759789
    760 int icmp_bind_free_id( icmp_echo_ref echo_data ){
    761         icmp_param_t    index;
    762 
    763         if( ! echo_data ) return EBADMEM;
     790int icmp_bind_free_id(icmp_echo_ref echo_data){
     791        icmp_param_t index;
     792
     793        if(! echo_data){
     794                return EBADMEM;
     795        }
    764796        // from the last used one
    765797        index = icmp_globals.last_used_id;
     
    767799                ++ index;
    768800                // til the range end
    769                 if( index >= ICMP_FREE_IDS_END ){
     801                if(index >= ICMP_FREE_IDS_END){
    770802                        // start from the range beginning
    771803                        index = ICMP_FREE_IDS_START - 1;
     
    773805                                ++ index;
    774806                                // til the last used one
    775                                 if( index >= icmp_globals.last_used_id ){
     807                                if(index >= icmp_globals.last_used_id){
    776808                                        // none found
    777809                                        return ENOTCONN;
    778810                                }
    779                         }while( icmp_echo_data_find( & icmp_globals.echo_data, index ) != NULL );
     811                        }while(icmp_echo_data_find(&icmp_globals.echo_data, index) != NULL);
    780812                        // found, break immediately
    781813                        break;
    782814                }
    783         }while( icmp_echo_data_find( & icmp_globals.echo_data, index ) != NULL );
     815        }while(icmp_echo_data_find(&icmp_globals.echo_data, index) != NULL);
    784816        echo_data->identifier = index;
    785817        echo_data->sequence_number = 0;
    786         return icmp_echo_data_add( & icmp_globals.echo_data, index, echo_data );
     818        return icmp_echo_data_add(&icmp_globals.echo_data, index, echo_data);
    787819}
    788820
Note: See TracChangeset for help on using the changeset viewer.