Rev 4582 | Rev 4702 | 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 |