Rev 4582 | Rev 4695 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 4582 | Rev 4589 | ||
|---|---|---|---|
| Line 108... | Line 108... | ||
| 108 | 108 | ||
| 109 | packet_t ip_split_packet( packet_t packet, size_t prefix, size_t content, size_t suffix, size_t addr_len ); |
109 | packet_t ip_split_packet( packet_t packet, size_t prefix, size_t content, size_t suffix, size_t addr_len ); |
| 110 | int ip_fragment_packet( packet_t packet, size_t length, size_t prefix, size_t suffix, size_t addr_len ); |
110 | int ip_fragment_packet( packet_t packet, size_t length, size_t prefix, size_t suffix, size_t addr_len ); |
| 111 | int ip_fragment_packet_data( packet_t packet, packet_t new_packet, ip_header_ref header, ip_header_ref new_header, size_t length, void * src, void * dest, size_t address_length ); |
111 | int ip_fragment_packet_data( packet_t packet, packet_t new_packet, ip_header_ref header, ip_header_ref new_header, size_t length, void * src, void * dest, size_t address_length ); |
| 112 | ip_header_ref ip_create_middle_header( packet_t packet, ip_header_ref last ); |
112 | ip_header_ref ip_create_middle_header( packet_t packet, ip_header_ref last ); |
| 113 | ip_header_ref ip_create_last_header( packet_t packet, ip_header_ref first ); |
113 | void ip_create_last_header( ip_header_ref last, ip_header_ref first ); |
| 114 | 114 | ||
| 115 | in_addr_t * ip_netif_addr( ip_netif_ref netif ); |
115 | in_addr_t * ip_netif_addr( ip_netif_ref netif ); |
| 116 | ip_route_ref ip_find_route( in_addr_t destination ); |
116 | ip_route_ref ip_find_route( in_addr_t destination ); |
| 117 | ip_route_ref ip_netif_find_route( ip_netif_ref netif, in_addr_t destination ); |
117 | ip_route_ref ip_netif_find_route( ip_netif_ref netif, in_addr_t destination ); |
| 118 | 118 | ||
| Line 483... | Line 483... | ||
| 483 | } |
483 | } |
| 484 | 484 | ||
| 485 | int ip_send_route( packet_t packet, ip_netif_ref netif, ip_route_ref route, in_addr_t * src, in_addr_t dest ){ |
485 | int ip_send_route( packet_t packet, ip_netif_ref netif, ip_route_ref route, in_addr_t * src, in_addr_t dest ){ |
| 486 | ERROR_DECLARE; |
486 | ERROR_DECLARE; |
| 487 | 487 | ||
| 488 | packet_t next; |
- | |
| 489 | packet_t tmp; |
- | |
| 490 | measured_string_t destination; |
488 | measured_string_t destination; |
| 491 | measured_string_ref translation; |
489 | measured_string_ref translation; |
| 492 | char * data; |
490 | char * data; |
| 493 | 491 | ||
| 494 | // get destination hardware address |
492 | // get destination hardware address |
| Line 506... | Line 504... | ||
| 506 | free( translation ); |
504 | free( translation ); |
| 507 | free( data ); |
505 | free( data ); |
| 508 | return EINVAL; |
506 | return EINVAL; |
| 509 | } |
507 | } |
| 510 | }else translation = NULL; |
508 | }else translation = NULL; |
| 511 | // process packet queue |
- | |
| 512 | next = packet; |
- | |
| 513 | do{ |
- | |
| 514 | if( ERROR_OCCURRED( ip_prepare_packet( src, dest, next, translation ))){ |
509 | if( ERROR_OCCURRED( ip_prepare_packet( src, dest, packet, translation ))){ |
| 515 | // release invalid packet |
- | |
| 516 | tmp = pq_detach( next ); |
- | |
| 517 | if( next == packet ) packet = tmp; |
- | |
| 518 | pq_release( ip_globals.net_phone, packet_get_id( next )); |
510 | pq_release( ip_globals.net_phone, packet_get_id( packet )); |
| 519 | next = tmp; |
- | |
| 520 | }else{ |
511 | }else{ |
| 521 | next = pq_next( next ); |
- | |
| 522 | } |
- | |
| 523 | }while( next ); |
- | |
| 524 | if( translation ){ |
- | |
| 525 | free( translation ); |
- | |
| 526 | free( data ); |
- | |
| 527 | } |
- | |
| 528 | // send packet queue |
- | |
| 529 | if( packet ){ |
- | |
| 530 | packet = ip_split_packet( packet, netif->prefix, netif->content, netif->suffix, netif->addr_len ); |
512 | packet = ip_split_packet( packet, netif->prefix, netif->content, netif->suffix, netif->addr_len ); |
| 531 | if( packet ){ |
513 | if( packet ){ |
| 532 | nil_send_msg( netif->phone, netif->device_id, packet, SERVICE_IP ); |
514 | nil_send_msg( netif->phone, netif->device_id, packet, SERVICE_IP ); |
| 533 | } |
515 | } |
| 534 | } |
516 | } |
| - | 517 | if( translation ){ |
|
| - | 518 | free( translation ); |
|
| - | 519 | free( data ); |
|
| - | 520 | } |
|
| 535 | return EOK; |
521 | return ERROR_CODE; |
| 536 | } |
522 | } |
| 537 | 523 | ||
| 538 | int ip_prepare_packet( in_addr_t * source, in_addr_t dest, packet_t packet, measured_string_ref destination ){ |
524 | int ip_prepare_packet( in_addr_t * source, in_addr_t dest, packet_t packet, measured_string_ref destination ){ |
| 539 | ERROR_DECLARE; |
525 | ERROR_DECLARE; |
| 540 | 526 | ||
| 541 | size_t length; |
527 | size_t length; |
| 542 | ip_header_ref header; |
528 | ip_header_ref header; |
| - | 529 | ip_header_ref last_header; |
|
| - | 530 | ip_header_ref middle_header; |
|
| - | 531 | packet_t next; |
|
| 543 | 532 | ||
| 544 | length = packet_get_data_length( packet ); |
533 | length = packet_get_data_length( packet ); |
| 545 | if(( length < sizeof( ip_header_t )) || ( length > IP_MAX_CONTENT )) return EINVAL; |
534 | if(( length < sizeof( ip_header_t )) || ( length > IP_MAX_CONTENT )) return EINVAL; |
| 546 | header = ( ip_header_ref ) packet_get_data( packet ); |
535 | header = ( ip_header_ref ) packet_get_data( packet ); |
| 547 | if( destination ){ |
536 | if( destination ){ |
| 548 | ERROR_PROPAGATE( packet_set_addr( packet, NULL, ( uint8_t * ) destination->value, CONVERT_SIZE( char, uint8_t, destination->length ))); |
537 | ERROR_PROPAGATE( packet_set_addr( packet, NULL, ( uint8_t * ) destination->value, CONVERT_SIZE( char, uint8_t, destination->length ))); |
| 549 | } |
538 | } |
| 550 | header->version = 4; |
539 | header->version = 4; |
| 551 | header->total_length = htons( length ); |
- | |
| 552 | header->fragment_offset = 0; |
540 | header->fragment_offset = 0; |
| - | 541 | header->header_checksum = 0; |
|
| 553 | if( source ) header->source_address = source->s_addr; |
542 | if( source ) header->source_address = source->s_addr; |
| 554 | header->destination_address = dest.s_addr; |
543 | header->destination_address = dest.s_addr; |
| 555 | fibril_rwlock_write_lock( & ip_globals.lock ); |
544 | fibril_rwlock_write_lock( & ip_globals.lock ); |
| 556 | ++ ip_globals.packet_counter; |
545 | ++ ip_globals.packet_counter; |
| 557 | header->identification = htons( ip_globals.packet_counter ); |
546 | header->identification = htons( ip_globals.packet_counter ); |
| 558 | fibril_rwlock_write_unlock( & ip_globals.lock ); |
547 | fibril_rwlock_write_unlock( & ip_globals.lock ); |
| - | 548 | length = packet_get_data_length( packet ); |
|
| - | 549 | if( pq_next( packet )){ |
|
| - | 550 | last_header = ( ip_header_ref ) malloc( IP_HEADER_LENGTH( header )); |
|
| - | 551 | if( ! last_header ) return ENOMEM; |
|
| - | 552 | ip_create_last_header( last_header, header ); |
|
| - | 553 | next = pq_next( packet ); |
|
| - | 554 | while( pq_next( next )){ |
|
| - | 555 | middle_header = ( ip_header_ref ) packet_prefix( next, IP_HEADER_LENGTH( last_header )); |
|
| - | 556 | if( ! middle_header ) return ENOMEM; |
|
| - | 557 | memcpy( middle_header, last_header, IP_HEADER_LENGTH( last_header )); |
|
| - | 558 | header->flags |= IPFLAG_MORE_FRAGMENTS; |
|
| - | 559 | middle_header->total_length = htons( packet_get_data_length( next )); |
|
| - | 560 | middle_header->fragment_offset = length / 8; |
|
| - | 561 | middle_header->header_checksum = IP_HEADER_CHECKSUM( middle_header ); |
|
| - | 562 | if( destination ){ |
|
| - | 563 | ERROR_PROPAGATE( packet_set_addr( next, NULL, ( uint8_t * ) destination->value, CONVERT_SIZE( char, uint8_t, destination->length ))); |
|
| - | 564 | } |
|
| - | 565 | length += packet_get_data_length( next ); |
|
| - | 566 | next = pq_next( next ); |
|
| - | 567 | } |
|
| - | 568 | middle_header = ( ip_header_ref ) packet_prefix( next, IP_HEADER_LENGTH( last_header )); |
|
| - | 569 | if( ! middle_header ) return ENOMEM; |
|
| - | 570 | memcpy( middle_header, last_header, IP_HEADER_LENGTH( last_header )); |
|
| - | 571 | middle_header->total_length = htons( packet_get_data_length( next )); |
|
| - | 572 | middle_header->fragment_offset = length / 8; |
|
| - | 573 | middle_header->header_checksum = IP_HEADER_CHECKSUM( middle_header ); |
|
| - | 574 | if( destination ){ |
|
| - | 575 | ERROR_PROPAGATE( packet_set_addr( next, NULL, ( uint8_t * ) destination->value, CONVERT_SIZE( char, uint8_t, destination->length ))); |
|
| - | 576 | } |
|
| - | 577 | length += packet_get_data_length( next ); |
|
| - | 578 | free( last_header ); |
|
| - | 579 | header->flags |= IPFLAG_MORE_FRAGMENTS; |
|
| - | 580 | } |
|
| 559 | header->header_checksum = 0; |
581 | header->total_length = htons( length ); |
| 560 | // unnecessary for all protocols |
582 | // unnecessary for all protocols |
| 561 | header->header_checksum = IP_HEADER_CHECKSUM( header ); |
583 | header->header_checksum = IP_HEADER_CHECKSUM( header ); |
| 562 | return EOK; |
584 | return EOK; |
| 563 | } |
585 | } |
| 564 | 586 | ||
| - | 587 | ||
| - | 588 | ||
| 565 | int ip_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){ |
589 | int ip_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){ |
| 566 | ERROR_DECLARE; |
590 | ERROR_DECLARE; |
| 567 | 591 | ||
| 568 | packet_t packet; |
592 | packet_t packet; |
| 569 | 593 | ||
| Line 758... | Line 782... | ||
| 758 | return EPERM; |
782 | return EPERM; |
| 759 | } |
783 | } |
| 760 | // create the last fragment |
784 | // create the last fragment |
| 761 | new_packet = packet_get_4( ip_globals.net_phone, prefix, length, suffix, ((( size_t ) address_length > addr_len ) ? ( size_t ) address_length : addr_len )); |
785 | new_packet = packet_get_4( ip_globals.net_phone, prefix, length, suffix, ((( size_t ) address_length > addr_len ) ? ( size_t ) address_length : addr_len )); |
| 762 | if( ! new_packet ) return ENOMEM; |
786 | if( ! new_packet ) return ENOMEM; |
| - | 787 | // allocate as much as originally |
|
| 763 | last_header = ip_create_last_header( new_packet, header ); |
788 | last_header = ( ip_header_ref ) packet_suffix( new_packet, IP_HEADER_LENGTH( header )); |
| 764 | if( ! last_header ){ |
789 | if( ! last_header ){ |
| 765 | pq_release( ip_globals.net_phone, packet_get_id( new_packet )); |
790 | pq_release( ip_globals.net_phone, packet_get_id( new_packet )); |
| 766 | return ENOMEM; |
791 | return ENOMEM; |
| 767 | } |
792 | } |
| - | 793 | ip_create_last_header( last_header, header ); |
|
| - | 794 | // trim the unused space |
|
| - | 795 | if( ERROR_OCCURRED( packet_trim( new_packet, 0, IP_HEADER_LENGTH( header ) - IP_HEADER_LENGTH( last_header )))){ |
|
| - | 796 | pq_release( ip_globals.net_phone, packet_get_id( new_packet )); |
|
| - | 797 | return ERROR_CODE; |
|
| - | 798 | } |
|
| 768 | // biggest multiple of 8 lower than content |
799 | // biggest multiple of 8 lower than content |
| 769 | // TODO even fragmentation? |
800 | // TODO even fragmentation? |
| 770 | length = length & ( ~ 0x7 );// ( content / 8 ) * 8 |
801 | length = length & ( ~ 0x7 );// ( content / 8 ) * 8 |
| 771 | if( ERROR_OCCURRED( ip_fragment_packet_data( packet, new_packet, header, last_header, (( IP_TOTAL_LENGTH( header ) - length ) % ( length - IP_HEADER_LENGTH( last_header ))), src, dest, address_length ))){ |
802 | if( ERROR_OCCURRED( ip_fragment_packet_data( packet, new_packet, header, last_header, (( IP_TOTAL_LENGTH( header ) - length ) % ( length - IP_HEADER_LENGTH( last_header ))), src, dest, address_length ))){ |
| 772 | pq_release( ip_globals.net_phone, packet_get_id( new_packet )); |
803 | pq_release( ip_globals.net_phone, packet_get_id( new_packet )); |
| Line 819... | Line 850... | ||
| 819 | memcpy( middle, last, IP_HEADER_LENGTH( last )); |
850 | memcpy( middle, last, IP_HEADER_LENGTH( last )); |
| 820 | middle->flags |= IPFLAG_MORE_FRAGMENTS; |
851 | middle->flags |= IPFLAG_MORE_FRAGMENTS; |
| 821 | return middle; |
852 | return middle; |
| 822 | } |
853 | } |
| 823 | 854 | ||
| 824 | ip_header_ref ip_create_last_header( packet_t packet, ip_header_ref first ){ |
855 | void ip_create_last_header( ip_header_ref last, ip_header_ref first ){ |
| 825 | ip_header_ref last; |
- | |
| 826 | ip_option_ref option; |
856 | ip_option_ref option; |
| 827 | size_t next; |
857 | size_t next; |
| 828 | size_t length; |
858 | size_t length; |
| 829 | 859 | ||
| 830 | // allocate as much as originally |
- | |
| 831 | last = ( ip_header_ref ) packet_suffix( packet, IP_HEADER_LENGTH( first )); |
- | |
| 832 | if( ! last ) return NULL; |
- | |
| 833 | // copy first itself |
860 | // copy first itself |
| 834 | memcpy( last, first, sizeof( ip_header_t )); |
861 | memcpy( last, first, sizeof( ip_header_t )); |
| 835 | length = sizeof( ip_header_t ); |
862 | length = sizeof( ip_header_t ); |
| 836 | next = sizeof( ip_header_t ); |
863 | next = sizeof( ip_header_t ); |
| 837 | // process all ip options |
864 | // process all ip options |
| Line 855... | Line 882... | ||
| 855 | bzero((( void * ) last ) + length, 4 - ( length % 4 )); |
882 | bzero((( void * ) last ) + length, 4 - ( length % 4 )); |
| 856 | last->ihl = length / 4 + 1; |
883 | last->ihl = length / 4 + 1; |
| 857 | }else{ |
884 | }else{ |
| 858 | last->ihl = length / 4; |
885 | last->ihl = length / 4; |
| 859 | } |
886 | } |
| 860 | // trim the unused space |
887 | last->header_checksum = 0; |
| 861 | if( packet_trim( packet, 0, IP_HEADER_LENGTH( first ) - IP_HEADER_LENGTH( last )) != EOK ) return NULL; |
- | |
| 862 | return last; |
- | |
| 863 | } |
888 | } |
| 864 | 889 | ||
| 865 | int ip_received_msg( device_id_t device_id, packet_t packet ){ |
890 | int ip_received_msg( device_id_t device_id, packet_t packet ){ |
| 866 | packet_t next; |
891 | packet_t next; |
| 867 | 892 | ||