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{ |