Subversion Repositories HelenOS

Rev

Rev 4730 | Rev 4743 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 4730 Rev 4731
Line 226... Line 226...
226
 
226
 
227
/** Sends the ICMP message.
227
/** Sends the ICMP message.
228
 *  Sets the message type and code and computes the checksum.
228
 *  Sets the message type and code and computes the checksum.
229
 *  Error messages are sent only if allowed in the configuration.
229
 *  Error messages are sent only if allowed in the configuration.
230
 *  Releases the packet on errors.
230
 *  Releases the packet on errors.
-
 
231
 *  @param type The message type. Input parameter.
-
 
232
 *  @param code The message code. Input parameter.
-
 
233
 *  @param packet The message packet to be sent. Input parameter.
-
 
234
 *  @param header The ICMP header. Input parameter.
-
 
235
 *  @param error The error service to be announced. Should be SERVICE_ICMP or zero (0). Input parametr.
-
 
236
 *  @param ttl The time to live. Input parameter.
-
 
237
 *  @param tos The type of service. Input parameter.
-
 
238
 *  @param dont_fragment The value indicating whether the datagram must not be fragmented. Is used as a MTU discovery. Input parameter.
231
 *  @returns EOK on success.
239
 *  @returns EOK on success.
232
 *  @returns EPERM if the error message is not allowed.
240
 *  @returns EPERM if the error message is not allowed.
233
 */
241
 */
234
int icmp_send_packet( icmp_type_t type, icmp_code_t code, packet_t packet, icmp_header_ref header, services_t error );
242
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 );
235
 
243
 
236
/** Tries to set the pending reply result as the received message type.
244
/** Tries to set the pending reply result as the received message type.
237
 *  If the reply data are still present, the reply timeouted and the parent fibril is awaken.
245
 *  If the reply data are still present, the reply timeouted and the parent fibril is awaken.
238
 *  The global lock is not released in this case to be reused by the parent fibril.
246
 *  The global lock is not released in this case to be reused by the parent fibril.
239
 *  Releases the packet.
247
 *  Releases the packet.
Line 402... Line 410...
402
 
410
 
403
    // unlock the globals and wait for a reply
411
    // unlock the globals and wait for a reply
404
    fibril_rwlock_write_unlock( & icmp_globals.lock );
412
    fibril_rwlock_write_unlock( & icmp_globals.lock );
405
 
413
 
406
    // send the request
414
    // send the request
407
    icmp_send_packet( ICMP_ECHO, 0, packet, header, 0 );
415
    icmp_send_packet( ICMP_ECHO, 0, packet, header, 0, ttl, tos, dont_fragment );
408
 
416
 
409
    // wait for a reply
417
    // wait for a reply
410
    fibril_condvar_wait( & reply->condvar, & reply->mutex );
418
    fibril_condvar_wait( & reply->condvar, & reply->mutex );
411
 
419
 
412
    // read the result
420
    // read the result
Line 426... Line 434...
426
        return icmp_release_and_return( packet, ENOMEM );
434
        return icmp_release_and_return( packet, ENOMEM );
427
    }
435
    }
428
    if( mtu ){
436
    if( mtu ){
429
        header->un.frag.mtu = mtu;
437
        header->un.frag.mtu = mtu;
430
    }
438
    }
431
    return icmp_send_packet( ICMP_DEST_UNREACH, code, packet, header, SERVICE_ICMP );
439
    return icmp_send_packet( ICMP_DEST_UNREACH, code, packet, header, SERVICE_ICMP, 0, 0, 0 );
432
}
440
}
433
 
441
 
434
int icmp_source_quench_msg( int icmp_phone, packet_t packet ){
442
int icmp_source_quench_msg( int icmp_phone, packet_t packet ){
435
    icmp_header_ref header;
443
    icmp_header_ref header;
436
 
444
 
437
    header = icmp_prepare_packet( packet );
445
    header = icmp_prepare_packet( packet );
438
    if( ! header ){
446
    if( ! header ){
439
        return icmp_release_and_return( packet, ENOMEM );
447
        return icmp_release_and_return( packet, ENOMEM );
440
    }
448
    }
441
    return icmp_send_packet( ICMP_SOURCE_QUENCH, 0, packet, header, SERVICE_ICMP );
449
    return icmp_send_packet( ICMP_SOURCE_QUENCH, 0, packet, header, SERVICE_ICMP, 0, 0, 0 );
442
}
450
}
443
 
451
 
444
int icmp_time_exceeded_msg( int icmp_phone, icmp_code_t code, packet_t packet ){
452
int icmp_time_exceeded_msg( int icmp_phone, icmp_code_t code, packet_t packet ){
445
    icmp_header_ref header;
453
    icmp_header_ref header;
446
 
454
 
447
    header = icmp_prepare_packet( packet );
455
    header = icmp_prepare_packet( packet );
448
    if( ! header ){
456
    if( ! header ){
449
        return icmp_release_and_return( packet, ENOMEM );
457
        return icmp_release_and_return( packet, ENOMEM );
450
    }
458
    }
451
    return icmp_send_packet( ICMP_TIME_EXCEEDED, code, packet, header, SERVICE_ICMP );
459
    return icmp_send_packet( ICMP_TIME_EXCEEDED, code, packet, header, SERVICE_ICMP, 0, 0, 0 );
452
}
460
}
453
 
461
 
454
int icmp_parameter_problem_msg( int icmp_phone, icmp_code_t code, icmp_param_t pointer, packet_t packet ){
462
int icmp_parameter_problem_msg( int icmp_phone, icmp_code_t code, icmp_param_t pointer, packet_t packet ){
455
    icmp_header_ref header;
463
    icmp_header_ref header;
456
 
464
 
457
    header = icmp_prepare_packet( packet );
465
    header = icmp_prepare_packet( packet );
458
    if( ! header ){
466
    if( ! header ){
459
        return icmp_release_and_return( packet, ENOMEM );
467
        return icmp_release_and_return( packet, ENOMEM );
460
    }
468
    }
461
    header->un.param.pointer = pointer;
469
    header->un.param.pointer = pointer;
462
    return icmp_send_packet( ICMP_PARAMETERPROB, code, packet, header, SERVICE_ICMP );
470
    return icmp_send_packet( ICMP_PARAMETERPROB, code, packet, header, SERVICE_ICMP, 0, 0, 0 );
463
}
471
}
464
 
472
 
465
icmp_header_ref icmp_prepare_packet( packet_t packet ){
473
icmp_header_ref icmp_prepare_packet( packet_t packet ){
466
    icmp_header_ref header;
474
    icmp_header_ref header;
467
    size_t          header_length;
475
    size_t          header_length;
Line 480... Line 488...
480
    if( ! header ) return NULL;
488
    if( ! header ) return NULL;
481
    bzero( header, sizeof( * header ));
489
    bzero( header, sizeof( * header ));
482
    return header;
490
    return header;
483
}
491
}
484
 
492
 
485
int icmp_send_packet( icmp_type_t type, icmp_code_t code, packet_t packet, icmp_header_ref header, services_t error ){
493
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 ){
486
    ERROR_DECLARE;
494
    ERROR_DECLARE;
487
 
495
 
488
    // do not send an error if disabled
496
    // do not send an error if disabled
489
    if( error && ( ! icmp_globals.error_reporting )){
497
    if( error && ( ! icmp_globals.error_reporting )){
490
        return icmp_release_and_return( packet, EPERM );
498
        return icmp_release_and_return( packet, EPERM );
491
    }
499
    }
492
    header->type = type;
500
    header->type = type;
493
    header->code = code;
501
    header->code = code;
494
    header->checksum = 0;
502
    header->checksum = 0;
495
    header->checksum = ICMP_CHECKSUM( header, packet_get_data_length( packet ));
503
    header->checksum = ICMP_CHECKSUM( header, packet_get_data_length( packet ));
496
    if( ERROR_OCCURRED( ip_client_prepare_packet( packet, IPPROTO_ICMP, 0, 0, 0, 0 ))){
504
    if( ERROR_OCCURRED( ip_client_prepare_packet( packet, IPPROTO_ICMP, ttl, tos, dont_fragment, 0 ))){
497
        return icmp_release_and_return( packet, ERROR_CODE );
505
        return icmp_release_and_return( packet, ERROR_CODE );
498
    }
506
    }
499
    return ip_send_msg( icmp_globals.ip_phone, -1, packet, SERVICE_ICMP, error );
507
    return ip_send_msg( icmp_globals.ip_phone, -1, packet, SERVICE_ICMP, error );
500
}
508
}
501
 
509
 
Line 585... Line 593...
585
            case SERVICE_ICMP:
593
            case SERVICE_ICMP:
586
                // process error
594
                // process error
587
                result = icmp_client_process_packet( packet, & type, & code, NULL, NULL );
595
                result = icmp_client_process_packet( packet, & type, & code, NULL, NULL );
588
                if( result < 0 ) return result;
596
                if( result < 0 ) return result;
589
                length = ( size_t ) result;
597
                length = ( size_t ) result;
590
                // TODO remove debug dump
-
 
591
                printf( "ICMP error %d (%d) in packet %d\n", type, code, packet_get_id( packet ) );
-
 
592
                // remove the error header
598
                // remove the error header
593
                ERROR_PROPAGATE( packet_trim( packet, length, 0 ));
599
                ERROR_PROPAGATE( packet_trim( packet, length, 0 ));
594
                break;
600
                break;
595
            default:
601
            default:
596
                return ENOTSUP;
602
                return ENOTSUP;
Line 637... Line 643...
637
                addrlen = packet_get_addr( packet, & src, NULL );
643
                addrlen = packet_get_addr( packet, & src, NULL );
638
                if(( addrlen > 0 )
644
                if(( addrlen > 0 )
639
                // set both addresses to the source one (avoids the source address deletion before setting the destination one)
645
                // set both addresses to the source one (avoids the source address deletion before setting the destination one)
640
                && ( packet_set_addr( packet, src, src, ( size_t ) addrlen ) == EOK )){
646
                && ( packet_set_addr( packet, src, src, ( size_t ) addrlen ) == EOK )){
641
                    // send the reply
647
                    // send the reply
642
                    icmp_send_packet( ICMP_ECHOREPLY, 0, packet, header, 0 );
648
                    icmp_send_packet( ICMP_ECHOREPLY, 0, packet, header, 0, 0, 0, 0 );
643
                    return EOK;
649
                    return EOK;
644
                }else{
650
                }else{
645
                    return EINVAL;
651
                    return EINVAL;
646
                }
652
                }
647
            }else{
653
            }else{