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