Subversion Repositories HelenOS

Rev

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