Ignore:
File:
1 edited

Legend:

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

    rb5cbff4 raadf01e  
    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.
    176176 *  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 occurs.
     177 *  Blocks the caller until the reply or the timeout occurres.
    178178 *  @param[in] id The message identifier.
    179179 *  @param[in] sequence The message sequence parameter.
     
    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.
    223  *  If the reply data is not present, the reply timed out and the other fibril
    224  *  is already awake.
     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.
    225225 *  Releases the packet.
    226226 *  @param[in] packet The received reply message.
     
    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 );
    332         }
    333 
    334         // unlock the globals so that we can wait for the reply
    335         fibril_rwlock_write_unlock( & icmp_globals.lock );
     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);
     334        }
     335
     336        // unlock the globals and wait for a reply
     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 );
    339 
    340         // wait for the reply
     340        icmp_send_packet(ICMP_ECHO, 0, packet, header, 0, ttl, tos, dont_fragment);
     341
     342        // wait for a 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;
     346
     347                // lock the globals again and clean up
     348                fibril_rwlock_write_lock(&icmp_globals.lock);
    344349        }else{
    345350                // read the result
    346351                result = reply->result;
    347         }
    348 
    349         // drop the reply mutex before locking the globals again
    350         fibril_mutex_unlock( & reply->mutex );
    351         fibril_rwlock_write_lock( & icmp_globals.lock );
     352
     353                // release the reply structure
     354                fibril_mutex_unlock(&reply->mutex);
     355        }
    352356
    353357        // destroy the reply structure
    354         icmp_replies_exclude_index( & icmp_globals.replies, index );
     358        icmp_replies_exclude_index(&icmp_globals.replies, index);
    355359        return result;
    356360}
    357361
    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 ){
     362int 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){
    366370                header->un.frag.mtu = mtu;
    367371        }
    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 );
     372        return icmp_send_packet(ICMP_DEST_UNREACH, code, packet, header, SERVICE_ICMP, 0, 0, 0);
     373}
     374
     375int 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
     385int 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
     395int 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);
    397401        }
    398402        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;
     403        return icmp_send_packet(ICMP_PARAMETERPROB, code, packet, header, SERVICE_ICMP, 0, 0, 0);
     404}
     405
     406icmp_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){
     413                return NULL;
     414        }
     415        header_length = ip_client_header_length(packet);
     416        if(header_length <= 0){
     417                return NULL;
     418        }
    411419        // 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 )){
     420        if((total_length > header_length + ICMP_KEEP_LENGTH)
     421                && (packet_trim(packet, 0, total_length - header_length - ICMP_KEEP_LENGTH) != EOK)){
    414422                return NULL;
    415423        }
    416         header = PACKET_PREFIX( packet, icmp_header_t );
    417         if( ! header ) return NULL;
    418         bzero( header, sizeof( * header ));
     424        header = PACKET_PREFIX(packet, icmp_header_t);
     425        if(! header){
     426                return NULL;
     427        }
     428        bzero(header, sizeof(*header));
    419429        return header;
    420430}
    421431
    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 ){
     432int 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){
    423433        ERROR_DECLARE;
    424434
    425435        // do not send an error if disabled
    426         if( error && ( ! icmp_globals.error_reporting )){
    427                 return icmp_release_and_return( packet, EPERM );
     436        if(error && (! icmp_globals.error_reporting)){
     437                return icmp_release_and_return(packet, EPERM);
    428438        }
    429439        header->type = type;
    430440        header->code = code;
    431441        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;
     442        header->checksum = ICMP_CHECKSUM(header, packet_get_data_length(packet));
     443        if(ERROR_OCCURRED(ip_client_prepare_packet(packet, IPPROTO_ICMP, ttl, tos, dont_fragment, 0))){
     444                return icmp_release_and_return(packet, ERROR_CODE);
     445        }
     446        return ip_send_msg(icmp_globals.ip_phone, -1, packet, SERVICE_ICMP, error);
     447}
     448
     449int icmp_connect_module(services_t service, suseconds_t timeout){
     450        icmp_echo_ref echo_data;
     451        icmp_param_t id;
     452        int index;
     453
     454        echo_data = (icmp_echo_ref) malloc(sizeof(*echo_data));
     455        if(! echo_data){
     456                return ENOMEM;
     457        }
    446458        // 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 );
     459        fibril_rwlock_write_lock(&icmp_globals.lock);
     460        index = icmp_bind_free_id(echo_data);
     461        if(index < 0){
     462                free(echo_data);
     463                fibril_rwlock_write_unlock(&icmp_globals.lock);
    452464                return index;
    453465        }else{
    454466                id = echo_data->identifier;
    455                 fibril_rwlock_write_unlock( & icmp_globals.lock );
     467                fibril_rwlock_write_unlock(&icmp_globals.lock);
    456468                // return the echo data identifier as the ICMP phone
    457469                return id;
     
    459471}
    460472
    461 int icmp_initialize( async_client_conn_t client_connection ){
     473int icmp_initialize(async_client_conn_t client_connection){
    462474        ERROR_DECLARE;
    463475
    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 ){
     476        measured_string_t names[] = {{str_dup("ICMP_ERROR_REPORTING"), 20}, {str_dup("ICMP_ECHO_REPLYING"), 18}};
     477        measured_string_ref configuration;
     478        size_t count = sizeof(names) / sizeof(measured_string_t);
     479        char * data;
     480
     481        fibril_rwlock_initialize(&icmp_globals.lock);
     482        fibril_rwlock_write_lock(&icmp_globals.lock);
     483        icmp_replies_initialize(&icmp_globals.replies);
     484        icmp_echo_data_initialize(&icmp_globals.echo_data);
     485        icmp_globals.ip_phone = ip_bind_service(SERVICE_IP, IPPROTO_ICMP, SERVICE_ICMP, client_connection, icmp_received_msg);
     486        if(icmp_globals.ip_phone < 0){
    475487                return icmp_globals.ip_phone;
    476488        }
    477         ERROR_PROPAGATE( ip_packet_size_req( icmp_globals.ip_phone, -1, & icmp_globals.packet_dimension ));
     489        ERROR_PROPAGATE(ip_packet_size_req(icmp_globals.ip_phone, -1, &icmp_globals.packet_dimension));
    478490        icmp_globals.packet_dimension.prefix += ICMP_HEADER_SIZE;
    479491        icmp_globals.packet_dimension.content -= ICMP_HEADER_SIZE;
     
    481493        icmp_globals.error_reporting = NET_DEFAULT_ICMP_ERROR_REPORTING;
    482494        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' );
     495        configuration = &names[0];
     496        ERROR_PROPAGATE(net_get_conf_req(icmp_globals.net_phone, &configuration, count, &data));
     497        if(configuration){
     498                if(configuration[0].value){
     499                        icmp_globals.error_reporting = (configuration[0].value[0] == 'y');
    488500                }
    489                 if( configuration[ 1 ].value ){
    490                         icmp_globals.echo_replying = ( configuration[ 1 ].value[ 0 ] == 'y' );
     501                if(configuration[1].value){
     502                        icmp_globals.echo_replying = (configuration[1].value[0] == 'y');
    491503                }
    492                 net_free_settings( configuration, data );
    493         }
    494         fibril_rwlock_write_unlock( & icmp_globals.lock );
     504                net_free_settings(configuration, data);
     505        }
     506        fibril_rwlock_write_unlock(&icmp_globals.lock);
    495507        return EOK;
    496508}
    497509
    498 int     icmp_received_msg( device_id_t device_id, packet_t packet, services_t receiver, services_t error ){
     510int icmp_received_msg(device_id_t device_id, packet_t packet, services_t receiver, services_t error){
    499511        ERROR_DECLARE;
    500512
    501         if( ERROR_OCCURRED( icmp_process_packet( packet, error ))){
    502                 return icmp_release_and_return( packet, ERROR_CODE );
     513        if(ERROR_OCCURRED(icmp_process_packet(packet, error))){
     514                return icmp_release_and_return(packet, ERROR_CODE);
    503515        }
    504516
     
    506518}
    507519
    508 int icmp_process_packet( packet_t packet, services_t error ){
     520int icmp_process_packet(packet_t packet, services_t error){
    509521        ERROR_DECLARE;
    510522
    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 ){
     523        size_t length;
     524        uint8_t * src;
     525        int addrlen;
     526        int result;
     527        void * data;
     528        icmp_header_ref header;
     529        icmp_type_t type;
     530        icmp_code_t code;
     531
     532        if(error){
     533                switch(error){
    522534                        case SERVICE_ICMP:
    523535                                // process error
    524                                 result = icmp_client_process_packet( packet, & type, & code, NULL, NULL );
    525                                 if( result < 0 ) return result;
    526                                 length = ( size_t ) result;
     536                                result = icmp_client_process_packet(packet, &type, &code, NULL, NULL);
     537                                if(result < 0){
     538                                        return result;
     539                                }
     540                                length = (size_t) result;
    527541                                // remove the error header
    528                                 ERROR_PROPAGATE( packet_trim( packet, length, 0 ));
     542                                ERROR_PROPAGATE(packet_trim(packet, length, 0));
    529543                                break;
    530544                        default:
     
    533547        }
    534548        // 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;
     549        length = ip_client_header_length(packet);
     550        ERROR_PROPAGATE(packet_trim(packet, length, 0));
     551
     552        length = packet_get_data_length(packet);
     553        if(length <= 0){
     554                return EINVAL;
     555        }
     556        if(length < ICMP_HEADER_SIZE){
     557                return EINVAL;
     558        }
     559        data = packet_get_data(packet);
     560        if(! data){
     561                return EINVAL;
     562        }
    543563        // get icmp header
    544         header = ( icmp_header_ref ) data;
     564        header = (icmp_header_ref) data;
    545565        // checksum
    546         if( header->checksum ){
    547                 while( ICMP_CHECKSUM( header, length ) != IP_CHECKSUM_ZERO ){
     566        if(header->checksum){
     567                while(ICMP_CHECKSUM(header, length) != IP_CHECKSUM_ZERO){
    548568                        // set the original message type on error notification
    549569                        // type swap observed in Qemu
    550                         if( error ){
    551                                 switch( header->type ){
     570                        if(error){
     571                                switch(header->type){
    552572                                        case ICMP_ECHOREPLY:
    553573                                                header->type = ICMP_ECHO;
     
    558578                }
    559579        }
    560         switch( header->type ){
     580        switch(header->type){
    561581                case ICMP_ECHOREPLY:
    562                         if( error ){
    563                                 return icmp_process_echo_reply( packet, header, type, code );
     582                        if(error){
     583                                return icmp_process_echo_reply(packet, header, type, code);
    564584                        }else{
    565                                 return icmp_process_echo_reply( packet, header, ICMP_ECHO, 0 );
     585                                return icmp_process_echo_reply(packet, header, ICMP_ECHO, 0);
    566586                        }
    567587                case ICMP_ECHO:
    568                         if( error ){
    569                                 return icmp_process_echo_reply( packet, header, type, code );
     588                        if(error){
     589                                return icmp_process_echo_reply(packet, header, type, code);
    570590                        // 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 )
     591                        }else if(icmp_globals.echo_replying){
     592                                addrlen = packet_get_addr(packet, &src, NULL);
     593                                if((addrlen > 0)
    574594                                // 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 )){
     595                                        && (packet_set_addr(packet, src, src, (size_t) addrlen) == EOK)){
    576596                                        // send the reply
    577                                         icmp_send_packet( ICMP_ECHOREPLY, 0, packet, header, 0, 0, 0, 0 );
     597                                        icmp_send_packet(ICMP_ECHOREPLY, 0, packet, header, 0, 0, 0, 0);
    578598                                        return EOK;
    579599                                }else{
     
    595615                case ICMP_SKIP:
    596616                case ICMP_PHOTURIS:
    597                         ip_received_error_msg( icmp_globals.ip_phone, -1, packet, SERVICE_IP, SERVICE_ICMP );
     617                        ip_received_error_msg(icmp_globals.ip_phone, -1, packet, SERVICE_IP, SERVICE_ICMP);
    598618                        return EOK;
    599619                default:
     
    602622}
    603623
    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;
     624int icmp_process_echo_reply(packet_t packet, icmp_header_ref header, icmp_type_t type, icmp_code_t code){
     625        int reply_key;
     626        icmp_reply_ref reply;
    607627
    608628        // 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 ));
     629        reply_key = ICMP_GET_REPLY_KEY(header->un.echo.identifier, header->un.echo.sequence_number);
     630        pq_release(icmp_globals.net_phone, packet_get_id(packet));
    611631        // lock the globals
    612         fibril_rwlock_write_lock( & icmp_globals.lock );
     632        fibril_rwlock_write_lock(&icmp_globals.lock);
    613633        // find the pending reply
    614         reply = icmp_replies_find( & icmp_globals.replies, reply_key );
    615         if( reply ){
     634        reply = icmp_replies_find(&icmp_globals.replies, reply_key);
     635        if(reply){
    616636                // set the result
    617637                reply->result = type;
    618                 // notify the waiting fibril
    619                 fibril_condvar_signal( & reply->condvar );
    620         }
    621         fibril_rwlock_write_unlock( & icmp_globals.lock );
     638                // notify the main fibril
     639                fibril_condvar_signal(&reply->condvar);
     640        }else{
     641                // unlock only if no reply
     642                fibril_rwlock_write_unlock(&icmp_globals.lock);
     643        }
    622644        return EOK;
    623645}
    624646
    625 int icmp_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){
     647int icmp_message(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count){
    626648        ERROR_DECLARE;
    627649
    628         packet_t                        packet;
    629 
    630         * answer_count = 0;
    631         switch( IPC_GET_METHOD( * call )){
     650        packet_t packet;
     651
     652        *answer_count = 0;
     653        switch(IPC_GET_METHOD(*call)){
    632654                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 ));
     655                        if(! ERROR_OCCURRED(packet_translate(icmp_globals.net_phone, &packet, IPC_GET_PACKET(call)))){
     656                                ERROR_CODE = icmp_received_msg(IPC_GET_DEVICE(call), packet, SERVICE_ICMP, IPC_GET_ERROR(call));
    635657                        }
    636658                        return ERROR_CODE;
    637659                case NET_ICMP_INIT:
    638                         return icmp_process_client_messages( callid, * call );
     660                        return icmp_process_client_messages(callid, * call);
    639661                default:
    640                         return icmp_process_message( call );
     662                        return icmp_process_message(call);
    641663        }
    642664        return ENOTSUP;
    643665}
    644666
    645 int icmp_process_client_messages( ipc_callid_t callid, ipc_call_t call ){
     667int icmp_process_client_messages(ipc_callid_t callid, ipc_call_t call){
    646668        ERROR_DECLARE;
    647669
    648         bool                                    keep_on_going = true;
     670        bool keep_on_going = true;
    649671//      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;
     672        ipc_call_t answer;
     673        int answer_count;
     674        size_t length;
     675        struct sockaddr * addr;
     676        ipc_callid_t data_callid;
     677        icmp_echo_ref echo_data;
     678        int res;
    656679
    657680        /*
     
    659682         *  - Answer the first NET_ICMP_INIT call.
    660683         */
    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;
     684        res = EOK;
     685        answer_count = 0;
     686
     687//      fibril_rwlock_initialize(&lock);
     688
     689        echo_data = (icmp_echo_ref) malloc(sizeof(*echo_data));
     690        if(! echo_data){
     691                return ENOMEM;
     692        }
     693
    667694        // 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 )){
     695        fibril_rwlock_write_lock(&icmp_globals.lock);
     696        res = icmp_bind_free_id(echo_data);
     697        fibril_rwlock_write_unlock(&icmp_globals.lock);
     698        if(res < 0){
     699                free(echo_data);
     700                return res;
     701        }
     702
     703        while(keep_on_going){
     704
     705                // answer the call
     706                answer_call(callid, res, &answer, answer_count);
     707
     708                // refresh data
     709                refresh_answer(&answer, &answer_count);
     710
     711                // get the next call
     712                callid = async_get_call(&call);
     713
     714                // process the call
     715                switch(IPC_GET_METHOD(call)){
    682716                        case IPC_M_PHONE_HUNGUP:
    683717                                keep_on_going = false;
    684                                 ERROR_CODE = EOK;
     718                                res = EHANGUP;
    685719                                break;
    686720                        case NET_ICMP_ECHO:
    687 //                              fibril_rwlock_write_lock( & lock );
    688                                 if( ! async_data_write_receive( & data_callid, & length )){
    689                                         ERROR_CODE = EINVAL;
     721//                              fibril_rwlock_write_lock(&lock);
     722                                if(! async_data_write_receive(&data_callid, &length)){
     723                                        res = EINVAL;
    690724                                }else{
    691                                         addr = malloc( length );
    692                                         if( ! addr ){
    693                                                 ERROR_CODE = ENOMEM;
     725                                        addr = malloc(length);
     726                                        if(! addr){
     727                                                res = ENOMEM;
    694728                                        }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 ){
     729                                                if(! ERROR_OCCURRED(async_data_write_finalize(data_callid, addr, length))){
     730                                                        fibril_rwlock_write_lock(&icmp_globals.lock);
     731                                                        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);
     732                                                        fibril_rwlock_write_unlock(&icmp_globals.lock);
     733                                                        free(addr);
     734                                                        if(echo_data->sequence_number < MAX_UINT16){
    701735                                                                ++ echo_data->sequence_number;
    702736                                                        }else{
    703737                                                                echo_data->sequence_number = 0;
    704738                                                        }
     739                                                }else{
     740                                                        res = ERROR_CODE;
    705741                                                }
    706742                                        }
    707743                                }
    708 //                              fibril_rwlock_write_unlock( & lock );
     744//                              fibril_rwlock_write_unlock(&lock);
    709745                                break;
    710746                        default:
    711                                 ERROR_CODE = icmp_process_message( & call );
     747                                res = icmp_process_message(&call);
    712748                }
    713 
    714                 answer_call( callid, ERROR_CODE, & answer, answer_count );
    715749        }
    716750
    717751        // 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 ){
     752        fibril_rwlock_write_lock(&icmp_globals.lock);
     753        icmp_echo_data_exclude(&icmp_globals.echo_data, echo_data->identifier);
     754        fibril_rwlock_write_unlock(&icmp_globals.lock);
     755        return res;
     756}
     757
     758int icmp_process_message(ipc_call_t * call){
    725759        ERROR_DECLARE;
    726760
    727         packet_t        packet;
    728 
    729         switch( IPC_GET_METHOD( * call )){
     761        packet_t packet;
     762
     763        switch(IPC_GET_METHOD(*call)){
    730764                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 );
     765                        if(! ERROR_OCCURRED(packet_translate(icmp_globals.net_phone, &packet, IPC_GET_PACKET(call)))){
     766                                ERROR_CODE = icmp_destination_unreachable_msg(0, ICMP_GET_CODE(call), ICMP_GET_MTU(call), packet);
    733767                        }
    734768                        return ERROR_CODE;
    735769                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 );
     770                        if(! ERROR_OCCURRED(packet_translate(icmp_globals.net_phone, &packet, IPC_GET_PACKET(call)))){
     771                                ERROR_CODE = icmp_source_quench_msg(0, packet);
    738772                        }
    739773                        return ERROR_CODE;
    740774                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 );
     775                        if(! ERROR_OCCURRED(packet_translate(icmp_globals.net_phone, &packet, IPC_GET_PACKET(call)))){
     776                                ERROR_CODE = icmp_time_exceeded_msg(0, ICMP_GET_CODE(call), packet);
    743777                        }
    744778                        return ERROR_CODE;
    745779                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 );
     780                        if(! ERROR_OCCURRED(packet_translate(icmp_globals.net_phone, &packet, IPC_GET_PACKET(call)))){
     781                                ERROR_CODE = icmp_parameter_problem_msg(0, ICMP_GET_CODE(call), ICMP_GET_POINTER(call), packet);
    748782                        }
    749783                        return ERROR_CODE;
     
    753787}
    754788
    755 int     icmp_release_and_return( packet_t packet, int result ){
    756         pq_release( icmp_globals.net_phone, packet_get_id( packet ));
     789int icmp_release_and_return(packet_t packet, int result){
     790        pq_release(icmp_globals.net_phone, packet_get_id(packet));
    757791        return result;
    758792}
    759793
    760 int icmp_bind_free_id( icmp_echo_ref echo_data ){
    761         icmp_param_t    index;
    762 
    763         if( ! echo_data ) return EBADMEM;
     794int icmp_bind_free_id(icmp_echo_ref echo_data){
     795        icmp_param_t index;
     796
     797        if(! echo_data){
     798                return EBADMEM;
     799        }
    764800        // from the last used one
    765801        index = icmp_globals.last_used_id;
     
    767803                ++ index;
    768804                // til the range end
    769                 if( index >= ICMP_FREE_IDS_END ){
     805                if(index >= ICMP_FREE_IDS_END){
    770806                        // start from the range beginning
    771807                        index = ICMP_FREE_IDS_START - 1;
     
    773809                                ++ index;
    774810                                // til the last used one
    775                                 if( index >= icmp_globals.last_used_id ){
     811                                if(index >= icmp_globals.last_used_id){
    776812                                        // none found
    777813                                        return ENOTCONN;
    778814                                }
    779                         }while( icmp_echo_data_find( & icmp_globals.echo_data, index ) != NULL );
     815                        }while(icmp_echo_data_find(&icmp_globals.echo_data, index) != NULL);
    780816                        // found, break immediately
    781817                        break;
    782818                }
    783         }while( icmp_echo_data_find( & icmp_globals.echo_data, index ) != NULL );
     819        }while(icmp_echo_data_find(&icmp_globals.echo_data, index) != NULL);
    784820        echo_data->identifier = index;
    785821        echo_data->sequence_number = 0;
    786         return icmp_echo_data_add( & icmp_globals.echo_data, index, echo_data );
     822        return icmp_echo_data_add(&icmp_globals.echo_data, index, echo_data);
    787823}
    788824
Note: See TracChangeset for help on using the changeset viewer.