Rev 4702 | Rev 4708 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 4702 | Rev 4707 | ||
---|---|---|---|
Line 61... | Line 61... | ||
61 | #include "../../include/nil_interface.h" |
61 | #include "../../include/nil_interface.h" |
62 | #include "../../include/il_interface.h" |
62 | #include "../../include/il_interface.h" |
63 | #include "../../include/ip_client.h" |
63 | #include "../../include/ip_client.h" |
64 | #include "../../include/ip_interface.h" |
64 | #include "../../include/ip_interface.h" |
65 | #include "../../include/tl_interface.h" |
65 | #include "../../include/tl_interface.h" |
- | 66 | #include "../../include/icmp_codes.h" |
|
- | 67 | #include "../../include/icmp_interface.h" |
|
- | 68 | #include "../../include/icmp_client.h" |
|
66 | #include "../../structures/measured_strings.h" |
69 | #include "../../structures/measured_strings.h" |
67 | #include "../../structures/module_map.h" |
70 | #include "../../structures/module_map.h" |
68 | #include "../../structures/packet/packet_client.h" |
71 | #include "../../structures/packet/packet_client.h" |
69 | 72 | ||
70 | #include "../../nil/nil_messages.h" |
73 | #include "../../nil/nil_messages.h" |
Line 176... | Line 179... | ||
176 | * @returns Other error codes as defined for the specific arp_device_req() function. |
179 | * @returns Other error codes as defined for the specific arp_device_req() function. |
177 | * @returns Other error codes as defined for the nil_packet_size_req() function. |
180 | * @returns Other error codes as defined for the nil_packet_size_req() function. |
178 | */ |
181 | */ |
179 | int ip_netif_initialize( ip_netif_ref ip_netif ); |
182 | int ip_netif_initialize( ip_netif_ref ip_netif ); |
180 | 183 | ||
181 | int ip_send_route( packet_t packet, ip_netif_ref netif, ip_route_ref route, in_addr_t * src, in_addr_t dest ); |
184 | int ip_send_route( packet_t packet, ip_netif_ref netif, ip_route_ref route, in_addr_t * src, in_addr_t dest, services_t error ); |
182 | int ip_prepare_packet( in_addr_t * source, in_addr_t dest, packet_t packet, measured_string_ref destination ); |
185 | int ip_prepare_packet( in_addr_t * source, in_addr_t dest, packet_t packet, measured_string_ref destination ); |
183 | 186 | ||
184 | packet_t ip_split_packet( packet_t packet, size_t prefix, size_t content, size_t suffix, size_t addr_len ); |
187 | packet_t ip_split_packet( packet_t packet, size_t prefix, size_t content, size_t suffix, size_t addr_len, services_t error ); |
185 | int ip_fragment_packet( packet_t packet, size_t length, size_t prefix, size_t suffix, size_t addr_len ); |
188 | int ip_fragment_packet( packet_t packet, size_t length, size_t prefix, size_t suffix, size_t addr_len ); |
186 | 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 ); |
189 | 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 ); |
187 | ip_header_ref ip_create_middle_header( packet_t packet, ip_header_ref last ); |
190 | ip_header_ref ip_create_middle_header( packet_t packet, ip_header_ref last ); |
188 | void ip_create_last_header( ip_header_ref last, ip_header_ref first ); |
191 | void ip_create_last_header( ip_header_ref last, ip_header_ref first ); |
189 | 192 | ||
190 | in_addr_t * ip_netif_addr( ip_netif_ref netif ); |
193 | in_addr_t * ip_netif_address( ip_netif_ref netif ); |
191 | ip_route_ref ip_find_route( in_addr_t destination ); |
194 | ip_route_ref ip_find_route( in_addr_t destination ); |
192 | ip_route_ref ip_netif_find_route( ip_netif_ref netif, in_addr_t destination ); |
195 | ip_route_ref ip_netif_find_route( ip_netif_ref netif, in_addr_t destination ); |
193 | 196 | ||
194 | /** Processes the received IP packet. |
197 | /** Processes the received IP packet. |
195 | * @param device_id The source device identifier. Input parameter. |
198 | * @param device_id The source device identifier. Input parameter. |
Line 203... | Line 206... | ||
203 | */ |
206 | */ |
204 | int ip_receive_message( device_id_t device_id, packet_t packet ); |
207 | int ip_receive_message( device_id_t device_id, packet_t packet ); |
205 | 208 | ||
206 | int ip_process_packet( device_id_t device_id, packet_t packet ); |
209 | int ip_process_packet( device_id_t device_id, packet_t packet ); |
207 | in_addr_t ip_get_destination( ip_header_ref header ); |
210 | in_addr_t ip_get_destination( ip_header_ref header ); |
208 | int ip_deliver_local( device_id_t device_id, packet_t packet, ip_header_ref header ); |
211 | int ip_deliver_local( device_id_t device_id, packet_t packet, ip_header_ref header, services_t error ); |
209 | 212 | ||
210 | /** Computes the ip header checksum. |
213 | /** Computes the ip header checksum. |
211 | * To compute the checksum of a new packet, the checksum header field must be zero. |
214 | * To compute the checksum of a new packet, the checksum header field must be zero. |
212 | * To check the checksum of a received packet, the checksum may be left set. |
215 | * To check the checksum of a received packet, the checksum may be left set. |
213 | * The zero (0) value will returned in this case if valid. |
216 | * The zero (0) value will returned in this case if valid. |
Line 216... | Line 219... | ||
216 | * @returns The internet protocol header checksum. |
219 | * @returns The internet protocol header checksum. |
217 | * @returns 0xFFFF if the computed checksum is zero. |
220 | * @returns 0xFFFF if the computed checksum is zero. |
218 | */ |
221 | */ |
219 | uint16_t ip_checksum( uint8_t * data, size_t length ); |
222 | uint16_t ip_checksum( uint8_t * data, size_t length ); |
220 | 223 | ||
- | 224 | int ip_prepare_icmp_and_get_phone( services_t error, packet_t packet, ip_header_ref header ); |
|
- | 225 | int ip_get_icmp_phone( void ); |
|
- | 226 | int ip_prepare_icmp( packet_t packet, ip_header_ref header ); |
|
- | 227 | ||
- | 228 | static int release_and_return( packet_t packet, int result ); |
|
- | 229 | ||
221 | uint16_t ip_checksum( uint8_t * data, size_t length ){ |
230 | uint16_t ip_checksum( uint8_t * data, size_t length ){ |
222 | uint16_t checksum; |
231 | uint16_t checksum; |
223 | 232 | ||
224 | checksum = compact_checksum(compute_checksum( 0, data, length )); |
233 | checksum = compact_checksum(compute_checksum( 0, data, length )); |
225 | 234 | ||
Line 516... | Line 525... | ||
516 | printf( "New protocol registered:\n\tprotocol\t= %d\n\tphone\t= %d\n", proto->protocol, proto->phone ); |
525 | printf( "New protocol registered:\n\tprotocol\t= %d\n\tphone\t= %d\n", proto->protocol, proto->phone ); |
517 | fibril_rwlock_write_unlock( & ip_globals.protos_lock ); |
526 | fibril_rwlock_write_unlock( & ip_globals.protos_lock ); |
518 | return EOK; |
527 | return EOK; |
519 | } |
528 | } |
520 | 529 | ||
521 | int ip_send_msg( int il_phone, device_id_t device_id, packet_t packet, services_t sender ){ |
530 | int ip_send_msg( int il_phone, device_id_t device_id, packet_t packet, services_t sender, services_t error ){ |
522 | ERROR_DECLARE; |
531 | ERROR_DECLARE; |
523 | 532 | ||
524 | int length; |
533 | int length; |
525 | ip_netif_ref netif; |
534 | ip_netif_ref netif; |
526 | ip_route_ref route; |
535 | ip_route_ref route; |
527 | in_addr_t * dest; |
536 | in_addr_t * dest; |
528 | in_addr_t * src; |
537 | in_addr_t * src; |
- | 538 | int phone; |
|
529 | 539 | ||
530 | // addresses in the host byte order |
540 | // addresses in the host byte order |
531 | // should be the next hop address or the target destination address |
541 | // should be the next hop address or the target destination address |
532 | length = packet_get_addr( packet, NULL, ( uint8_t ** ) & dest ); |
542 | length = packet_get_addr( packet, NULL, ( uint8_t ** ) & dest ); |
533 | if( length < 0 ){ |
543 | if( length < 0 ){ |
534 | pq_release( ip_globals.net_phone, packet_get_id( packet )); |
544 | return release_and_return( packet, length ); |
535 | return length; |
- | |
536 | } |
545 | } |
537 | // TODO IPv6 |
546 | // TODO IPv6 |
538 | if( length != IP_ADDR ){ |
547 | if( length != IP_ADDR ){ |
539 | pq_release( ip_globals.net_phone, packet_get_id( packet )); |
548 | return release_and_return( packet, EINVAL ); |
540 | return EINVAL; |
- | |
541 | } |
549 | } |
542 | fibril_rwlock_read_lock( & ip_globals.netifs_lock ); |
550 | fibril_rwlock_read_lock( & ip_globals.netifs_lock ); |
543 | // device specified? |
551 | // device specified? |
544 | // dest.s_addr = ntohl( dest.s_addr ); |
- | |
545 | if( device_id > 0 ){ |
552 | if( device_id > 0 ){ |
546 | netif = ip_netifs_find( & ip_globals.netifs, device_id ); |
553 | netif = ip_netifs_find( & ip_globals.netifs, device_id ); |
547 | route = ip_netif_find_route( netif, * dest ); |
554 | route = ip_netif_find_route( netif, * dest ); |
548 | }else{ |
555 | }else{ |
549 | // TODO IPv6 |
556 | // TODO IPv6 |
550 | route = ip_find_route( * dest ); |
557 | route = ip_find_route( * dest ); |
551 | netif = route ? route->netif : NULL; |
558 | netif = route ? route->netif : NULL; |
552 | } |
559 | } |
553 | if( !( netif && route )){ |
560 | if( !( netif && route )){ |
554 | fibril_rwlock_read_unlock( & ip_globals.netifs_lock ); |
561 | fibril_rwlock_read_unlock( & ip_globals.netifs_lock ); |
555 | pq_release( ip_globals.net_phone, packet_get_id( packet )); |
562 | phone = ip_prepare_icmp_and_get_phone( error, packet, NULL ); |
- | 563 | if( phone >= 0 ){ |
|
- | 564 | // unreachable ICMP if no routing |
|
- | 565 | icmp_destination_unreachable_msg( phone, ICMP_HOST_UNREACH, 0, packet ); |
|
- | 566 | } |
|
556 | return ENOENT; |
567 | return ENOENT; |
557 | } |
568 | } |
- | 569 | if( error ){ |
|
- | 570 | // do not send for broadcast, anycast packets or network broadcast |
|
- | 571 | if(( ! dest->s_addr ) |
|
- | 572 | || ( !( ~ dest->s_addr )) |
|
- | 573 | || ( !( ~(( dest->s_addr & ( ~ route->netmask.s_addr )) | route->netmask.s_addr ))) |
|
- | 574 | || ( !( dest->s_addr & ( ~ route->netmask.s_addr )))){ |
|
- | 575 | return release_and_return( packet, EINVAL ); |
|
- | 576 | } |
|
- | 577 | } |
|
558 | // to me? |
578 | // to me? |
559 | if( route->address.s_addr == dest->s_addr ){ |
579 | if( route->address.s_addr == dest->s_addr ){ |
560 | // TODO loopback deliver |
580 | // TODO loopback deliver |
561 | fibril_rwlock_read_unlock( & ip_globals.netifs_lock ); |
581 | fibril_rwlock_read_unlock( & ip_globals.netifs_lock ); |
562 | return ip_deliver_local( -1, packet, ( ip_header_ref ) packet_get_data( packet )); |
582 | return ip_deliver_local( -1, packet, ( ip_header_ref ) packet_get_data( packet ), error ); |
563 | } |
583 | } |
564 | 584 | ||
565 | src = ip_netif_addr( netif ); |
585 | src = ip_netif_address( netif ); |
566 | if( ! src ){ |
586 | if( ! src ){ |
567 | fibril_rwlock_read_unlock( & ip_globals.netifs_lock ); |
587 | fibril_rwlock_read_unlock( & ip_globals.netifs_lock ); |
568 | pq_release( ip_globals.net_phone, packet_get_id( packet )); |
588 | return release_and_return( packet, ENOENT ); |
569 | return ENOENT; |
- | |
570 | } |
589 | } |
571 | if( ERROR_OCCURRED( ip_send_route( packet, netif, route, src, * dest ))){ |
590 | if( ERROR_OCCURRED( ip_send_route( packet, netif, route, src, * dest, error ))){ |
572 | pq_release( ip_globals.net_phone, packet_get_id( packet )); |
591 | pq_release( ip_globals.net_phone, packet_get_id( packet )); |
573 | } |
592 | } |
574 | fibril_rwlock_read_unlock( & ip_globals.netifs_lock ); |
593 | fibril_rwlock_read_unlock( & ip_globals.netifs_lock ); |
575 | return ERROR_CODE; |
594 | return ERROR_CODE; |
576 | } |
595 | } |
577 | 596 | ||
578 | in_addr_t * ip_netif_addr( ip_netif_ref netif ){ |
597 | in_addr_t * ip_netif_address( ip_netif_ref netif ){ |
579 | ip_route_ref route; |
598 | ip_route_ref route; |
580 | 599 | ||
581 | route = ip_routes_get_index( & netif->routes, 0 ); |
600 | route = ip_routes_get_index( & netif->routes, 0 ); |
582 | return route ? & route->address : NULL; |
601 | return route ? & route->address : NULL; |
583 | } |
602 | } |
584 | 603 | ||
585 | int ip_send_route( packet_t packet, ip_netif_ref netif, ip_route_ref route, in_addr_t * src, in_addr_t dest ){ |
604 | int ip_send_route( packet_t packet, ip_netif_ref netif, ip_route_ref route, in_addr_t * src, in_addr_t dest, services_t error ){ |
586 | ERROR_DECLARE; |
605 | ERROR_DECLARE; |
587 | 606 | ||
588 | measured_string_t destination; |
607 | measured_string_t destination; |
589 | measured_string_ref translation; |
608 | measured_string_ref translation; |
590 | char * data; |
609 | char * data; |
- | 610 | int phone; |
|
591 | 611 | ||
592 | // get destination hardware address |
612 | // get destination hardware address |
593 | if( netif->arp ){ |
613 | if( netif->arp ){ |
594 | destination.value = route->gateway.s_addr ? ( char * ) & route->gateway.s_addr : ( char * ) & dest.s_addr; |
614 | destination.value = route->gateway.s_addr ? ( char * ) & route->gateway.s_addr : ( char * ) & dest.s_addr; |
595 | destination.length = CONVERT_SIZE( dest.s_addr, char, 1 ); |
615 | destination.length = CONVERT_SIZE( dest.s_addr, char, 1 ); |
596 | if( ERROR_OCCURRED( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & destination, & translation, & data ))){ |
616 | if( ERROR_OCCURRED( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & destination, & translation, & data ))){ |
597 | sleep( 1 ); |
617 | sleep( 1 ); |
598 | ERROR_PROPAGATE( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & destination, & translation, & data )); |
618 | ERROR_PROPAGATE( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & destination, & translation, & data )); |
599 | } |
619 | } |
600 | // TODO unreachable |
- | |
601 | if( ! translation ) return EINVAL; |
620 | if( !( translation && translation->value )){ |
602 | if( ! translation->value ){ |
621 | if( translation ){ |
603 | // TODO unreachable |
- | |
604 | free( translation ); |
622 | free( translation ); |
605 | free( data ); |
623 | free( data ); |
- | 624 | } |
|
- | 625 | phone = ip_prepare_icmp_and_get_phone( error, packet, NULL ); |
|
- | 626 | if( phone >= 0 ){ |
|
- | 627 | // unreachable ICMP if no routing |
|
- | 628 | icmp_destination_unreachable_msg( phone, ICMP_HOST_UNREACH, 0, packet ); |
|
- | 629 | } |
|
606 | return EINVAL; |
630 | return EINVAL; |
607 | } |
631 | } |
608 | }else translation = NULL; |
632 | }else translation = NULL; |
609 | if( ERROR_OCCURRED( ip_prepare_packet( src, dest, packet, translation ))){ |
633 | if( ERROR_OCCURRED( ip_prepare_packet( src, dest, packet, translation ))){ |
610 | pq_release( ip_globals.net_phone, packet_get_id( packet )); |
634 | pq_release( ip_globals.net_phone, packet_get_id( packet )); |
611 | }else{ |
635 | }else{ |
612 | packet = ip_split_packet( packet, netif->prefix, netif->content, netif->suffix, netif->addr_len ); |
636 | packet = ip_split_packet( packet, netif->prefix, netif->content, netif->suffix, netif->addr_len, error ); |
613 | if( packet ){ |
637 | if( packet ){ |
614 | nil_send_msg( netif->phone, netif->device_id, packet, SERVICE_IP ); |
638 | nil_send_msg( netif->phone, netif->device_id, packet, SERVICE_IP ); |
615 | } |
639 | } |
616 | } |
640 | } |
617 | if( translation ){ |
641 | if( translation ){ |
Line 697... | Line 721... | ||
697 | return ip_device_req( 0, IPC_GET_DEVICE( call ), IPC_GET_SERVICE( call )); |
721 | return ip_device_req( 0, IPC_GET_DEVICE( call ), IPC_GET_SERVICE( call )); |
698 | case IPC_M_CONNECT_TO_ME: |
722 | case IPC_M_CONNECT_TO_ME: |
699 | return ip_register( IL_GET_PROTO( call ), IL_GET_SERVICE( call ), IPC_GET_PHONE( call ), NULL ); |
723 | return ip_register( IL_GET_PROTO( call ), IL_GET_SERVICE( call ), IPC_GET_PHONE( call ), NULL ); |
700 | case NET_IL_SEND: |
724 | case NET_IL_SEND: |
701 | ERROR_PROPAGATE( packet_translate( ip_globals.net_phone, & packet, IPC_GET_PACKET( call ))); |
725 | ERROR_PROPAGATE( packet_translate( ip_globals.net_phone, & packet, IPC_GET_PACKET( call ))); |
702 | return ip_send_msg( 0, IPC_GET_DEVICE( call ), packet, 0 ); |
726 | return ip_send_msg( 0, IPC_GET_DEVICE( call ), packet, 0, IPC_GET_ERROR( call )); |
703 | case NET_IL_DEVICE_STATE: |
727 | case NET_IL_DEVICE_STATE: |
704 | return ip_device_state_message( IPC_GET_DEVICE( call ), IPC_GET_STATE( call )); |
728 | return ip_device_state_message( IPC_GET_DEVICE( call ), IPC_GET_STATE( call )); |
705 | case NET_IL_RECEIVED: |
729 | case NET_IL_RECEIVED: |
706 | ERROR_PROPAGATE( packet_translate( ip_globals.net_phone, & packet, IPC_GET_PACKET( call ))); |
730 | ERROR_PROPAGATE( packet_translate( ip_globals.net_phone, & packet, IPC_GET_PACKET( call ))); |
707 | return ip_receive_message( IPC_GET_DEVICE( call ), packet ); |
731 | return ip_receive_message( IPC_GET_DEVICE( call ), packet ); |
- | 732 | case NET_IP_RECEIVED_ERROR: |
|
- | 733 | ERROR_PROPAGATE( packet_translate( ip_globals.net_phone, & packet, IPC_GET_PACKET( call ))); |
|
- | 734 | return ip_received_error_msg( 0, IPC_GET_DEVICE( call ), packet, IPC_GET_TARGET( call ), IPC_GET_ERROR( call )); |
|
708 | case NET_IP_ADD_ROUTE: |
735 | case NET_IP_ADD_ROUTE: |
709 | return ip_add_route_req( 0, IPC_GET_DEVICE( call ), IP_GET_ADDRESS( call ), IP_GET_NETMASK( call ), IP_GET_GATEWAY( call )); |
736 | return ip_add_route_req( 0, IPC_GET_DEVICE( call ), IP_GET_ADDRESS( call ), IP_GET_NETMASK( call ), IP_GET_GATEWAY( call )); |
710 | case NET_IP_SET_GATEWAY: |
737 | case NET_IP_SET_GATEWAY: |
711 | return ip_set_gateway_req( 0, IPC_GET_DEVICE( call ), IP_GET_GATEWAY( call )); |
738 | return ip_set_gateway_req( 0, IPC_GET_DEVICE( call ), IP_GET_GATEWAY( call )); |
712 | case NET_IL_PACKET_SPACE: |
739 | case NET_IL_PACKET_SPACE: |
Line 829... | Line 856... | ||
829 | ip_globals.gateway.netif = netif; |
856 | ip_globals.gateway.netif = netif; |
830 | fibril_rwlock_write_unlock( & ip_globals.netifs_lock ); |
857 | fibril_rwlock_write_unlock( & ip_globals.netifs_lock ); |
831 | return EOK; |
858 | return EOK; |
832 | } |
859 | } |
833 | 860 | ||
834 | packet_t ip_split_packet( packet_t packet, size_t prefix, size_t content, size_t suffix, size_t addr_len ){ |
861 | packet_t ip_split_packet( packet_t packet, size_t prefix, size_t content, size_t suffix, size_t addr_len, services_t error ){ |
835 | size_t length; |
862 | size_t length; |
836 | packet_t next; |
863 | packet_t next; |
837 | packet_t new_packet; |
864 | packet_t new_packet; |
- | 865 | int result; |
|
- | 866 | int phone; |
|
838 | 867 | ||
839 | next = packet; |
868 | next = packet; |
840 | // check all packets |
869 | // check all packets |
841 | while( next ){ |
870 | while( next ){ |
842 | length = packet_get_data_length( next ); |
871 | length = packet_get_data_length( next ); |
843 | // too long? |
872 | // too long? |
844 | if( length > content ){ |
873 | if( length > content ){ |
845 | if( ip_fragment_packet( next, content, prefix, suffix, addr_len ) != EOK ){ |
874 | result = ip_fragment_packet( next, content, prefix, suffix, addr_len ); |
- | 875 | if( result != EOK ){ |
|
846 | new_packet = pq_detach( next ); |
876 | new_packet = pq_detach( next ); |
847 | if( next == packet ){ |
877 | if( next == packet ){ |
- | 878 | // the new first packet of the queue |
|
848 | packet = new_packet; |
879 | packet = new_packet; |
849 | } |
880 | } |
- | 881 | // fragmentation needed? |
|
- | 882 | if( result == EPERM ){ |
|
- | 883 | phone = ip_prepare_icmp_and_get_phone( error, next, NULL ); |
|
- | 884 | if( phone >= 0 ){ |
|
- | 885 | // fragmentation necessary ICMP |
|
- | 886 | icmp_destination_unreachable_msg( phone, ICMP_FRAG_NEEDED, content, next ); |
|
- | 887 | } |
|
- | 888 | }else{ |
|
850 | pq_release( ip_globals.net_phone, packet_get_id( next )); |
889 | pq_release( ip_globals.net_phone, packet_get_id( next )); |
- | 890 | } |
|
851 | next = new_packet; |
891 | next = new_packet; |
852 | continue; |
892 | continue; |
853 | } |
893 | } |
854 | } |
894 | } |
855 | next = pq_next( next ); |
895 | next = pq_next( next ); |
Line 874... | Line 914... | ||
874 | // get header |
914 | // get header |
875 | header = ( ip_header_ref ) packet_get_data( packet ); |
915 | header = ( ip_header_ref ) packet_get_data( packet ); |
876 | if( ! header ) return EINVAL; |
916 | if( ! header ) return EINVAL; |
877 | // fragmentation forbidden? |
917 | // fragmentation forbidden? |
878 | if( header->flags & IPFLAG_DONT_FRAGMENT ){ |
918 | if( header->flags & IPFLAG_DONT_FRAGMENT ){ |
879 | // TODO fragmentation necessary ICMP |
- | |
880 | return EPERM; |
919 | return EPERM; |
881 | } |
920 | } |
882 | // create the last fragment |
921 | // create the last fragment |
883 | new_packet = packet_get_4( ip_globals.net_phone, prefix, length, suffix, ((( size_t ) address_length > addr_len ) ? ( size_t ) address_length : addr_len )); |
922 | new_packet = packet_get_4( ip_globals.net_phone, prefix, length, suffix, ((( size_t ) address_length > addr_len ) ? ( size_t ) address_length : addr_len )); |
884 | if( ! new_packet ) return ENOMEM; |
923 | if( ! new_packet ) return ENOMEM; |
885 | // allocate as much as originally |
924 | // allocate as much as originally |
886 | last_header = ( ip_header_ref ) packet_suffix( new_packet, IP_HEADER_LENGTH( header )); |
925 | last_header = ( ip_header_ref ) packet_suffix( new_packet, IP_HEADER_LENGTH( header )); |
887 | if( ! last_header ){ |
926 | if( ! last_header ){ |
888 | pq_release( ip_globals.net_phone, packet_get_id( new_packet )); |
927 | return release_and_return( packet, ENOMEM ); |
889 | return ENOMEM; |
- | |
890 | } |
928 | } |
891 | ip_create_last_header( last_header, header ); |
929 | ip_create_last_header( last_header, header ); |
892 | // trim the unused space |
930 | // trim the unused space |
893 | if( ERROR_OCCURRED( packet_trim( new_packet, 0, IP_HEADER_LENGTH( header ) - IP_HEADER_LENGTH( last_header )))){ |
931 | if( ERROR_OCCURRED( packet_trim( new_packet, 0, IP_HEADER_LENGTH( header ) - IP_HEADER_LENGTH( last_header )))){ |
894 | pq_release( ip_globals.net_phone, packet_get_id( new_packet )); |
932 | return release_and_return( packet, ERROR_CODE ); |
895 | return ERROR_CODE; |
- | |
896 | } |
933 | } |
897 | // biggest multiple of 8 lower than content |
934 | // biggest multiple of 8 lower than content |
898 | // TODO even fragmentation? |
935 | // TODO even fragmentation? |
899 | length = length & ( ~ 0x7 );// ( content / 8 ) * 8 |
936 | length = length & ( ~ 0x7 );// ( content / 8 ) * 8 |
900 | 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 ))){ |
937 | 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 ))){ |
901 | pq_release( ip_globals.net_phone, packet_get_id( new_packet )); |
938 | return release_and_return( packet, ERROR_CODE ); |
902 | return ERROR_CODE; |
- | |
903 | } |
939 | } |
904 | // mark the first as fragmented |
940 | // mark the first as fragmented |
905 | header->flags |= IPFLAG_MORE_FRAGMENTS; |
941 | header->flags |= IPFLAG_MORE_FRAGMENTS; |
906 | // create middle framgents |
942 | // create middle framgents |
907 | while( IP_TOTAL_LENGTH( header ) > length ){ |
943 | while( IP_TOTAL_LENGTH( header ) > length ){ |
908 | new_packet = packet_get_4( ip_globals.net_phone, prefix, length, suffix, (( address_length >= addr_len ) ? address_length : addr_len )); |
944 | new_packet = packet_get_4( ip_globals.net_phone, prefix, length, suffix, (( address_length >= addr_len ) ? address_length : addr_len )); |
909 | if( ! new_packet ) return ENOMEM; |
945 | if( ! new_packet ) return ENOMEM; |
910 | middle_header = ip_create_middle_header( new_packet, last_header ); |
946 | middle_header = ip_create_middle_header( new_packet, last_header ); |
911 | if( ! middle_header ){ |
947 | if( ! middle_header ){ |
912 | pq_release( ip_globals.net_phone, packet_get_id( new_packet )); |
948 | return release_and_return( packet, ENOMEM ); |
913 | return ENOMEM; |
- | |
914 | } |
949 | } |
915 | if( ERROR_OCCURRED( ip_fragment_packet_data( packet, new_packet, header, middle_header, length - IP_HEADER_LENGTH( middle_header ), src, dest, address_length ))){ |
950 | if( ERROR_OCCURRED( ip_fragment_packet_data( packet, new_packet, header, middle_header, length - IP_HEADER_LENGTH( middle_header ), src, dest, address_length ))){ |
916 | pq_release( ip_globals.net_phone, packet_get_id( new_packet )); |
951 | return release_and_return( packet, ERROR_CODE ); |
917 | return ERROR_CODE; |
- | |
918 | } |
952 | } |
919 | } |
953 | } |
920 | // finish the first fragment |
954 | // finish the first fragment |
921 | header->header_checksum = IP_HEADER_CHECKSUM( header ); |
955 | header->header_checksum = IP_HEADER_CHECKSUM( header ); |
922 | printf( "ok\n" ); |
- | |
923 | return EOK; |
956 | return EOK; |
924 | } |
957 | } |
925 | 958 | ||
926 | 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 ){ |
959 | 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 ){ |
927 | ERROR_DECLARE; |
960 | ERROR_DECLARE; |
Line 988... | Line 1021... | ||
988 | int ip_receive_message( device_id_t device_id, packet_t packet ){ |
1021 | int ip_receive_message( device_id_t device_id, packet_t packet ){ |
989 | packet_t next; |
1022 | packet_t next; |
990 | 1023 | ||
991 | do{ |
1024 | do{ |
992 | next = pq_detach( packet ); |
1025 | next = pq_detach( packet ); |
993 | if( ip_process_packet( device_id, packet ) != EOK ){ |
1026 | ip_process_packet( device_id, packet ); |
994 | pq_release( ip_globals.net_phone, packet_get_id( packet )); |
- | |
995 | } |
- | |
996 | packet = next; |
1027 | packet = next; |
997 | }while( packet ); |
1028 | }while( packet ); |
998 | return EOK; |
1029 | return EOK; |
999 | } |
1030 | } |
1000 | 1031 | ||
Line 1002... | Line 1033... | ||
1002 | ERROR_DECLARE; |
1033 | ERROR_DECLARE; |
1003 | 1034 | ||
1004 | ip_header_ref header; |
1035 | ip_header_ref header; |
1005 | in_addr_t dest; |
1036 | in_addr_t dest; |
1006 | ip_route_ref route; |
1037 | ip_route_ref route; |
- | 1038 | int phone; |
|
1007 | 1039 | ||
1008 | header = ( ip_header_ref ) packet_get_data( packet ); |
1040 | header = ( ip_header_ref ) packet_get_data( packet ); |
1009 | if( ! header ) return ENOMEM; |
1041 | if( ! header ){ |
- | 1042 | return release_and_return( packet, ENOMEM ); |
|
- | 1043 | } |
|
1010 | // checksum |
1044 | // checksum |
1011 | if(( header->header_checksum ) && ( IP_HEADER_CHECKSUM( header ))){ |
1045 | if(( header->header_checksum ) && ( IP_HEADER_CHECKSUM( header ))){ |
1012 | // TODO checksum error ICMP? |
1046 | // TODO checksum error ICMP? |
- | 1047 | return release_and_return( packet, EINVAL ); |
|
- | 1048 | } |
|
- | 1049 | if( header->ttl <= 1 ){ |
|
- | 1050 | phone = ip_prepare_icmp_and_get_phone( 0, packet, header ); |
|
- | 1051 | if( phone >= 0 ){ |
|
- | 1052 | // ttl oxceeded ICMP |
|
- | 1053 | icmp_time_exceeded_msg( phone, ICMP_EXC_TTL, packet ); |
|
- | 1054 | } |
|
1013 | return EINVAL; |
1055 | return EINVAL; |
1014 | } |
1056 | } |
1015 | // TODO ttl oxceeded ICMP? |
- | |
1016 | if( !( -- header->ttl )) return EINVAL; |
- | |
1017 | // process ipopt and get destination |
1057 | // process ipopt and get destination |
1018 | dest = ip_get_destination( header ); |
1058 | dest = ip_get_destination( header ); |
1019 | ERROR_PROPAGATE( packet_set_addr( packet, NULL, ( uint8_t * ) & dest.s_addr, IP_ADDR )); |
1059 | ERROR_PROPAGATE( packet_set_addr( packet, NULL, ( uint8_t * ) & dest.s_addr, IP_ADDR )); |
1020 | route = ip_find_route( dest ); |
1060 | route = ip_find_route( dest ); |
- | 1061 | if( ! route ){ |
|
- | 1062 | phone = ip_prepare_icmp_and_get_phone( 0, packet, header ); |
|
- | 1063 | if( phone >= 0 ){ |
|
1021 | // TODO unreachable ICMP? |
1064 | // unreachable ICMP |
- | 1065 | icmp_destination_unreachable_msg( phone, ICMP_HOST_UNREACH, 0, packet ); |
|
- | 1066 | } |
|
1022 | if( ! route ) return ENOENT; |
1067 | return ENOENT; |
- | 1068 | } |
|
1023 | if( route->address.s_addr == dest.s_addr ){ |
1069 | if( route->address.s_addr == dest.s_addr ){ |
1024 | // local delivery |
1070 | // local delivery |
1025 | return ip_deliver_local( device_id, packet, header ); |
1071 | return ip_deliver_local( device_id, packet, header, 0 ); |
1026 | }else{ |
1072 | }else{ |
1027 | // only if routing enabled |
1073 | // only if routing enabled |
1028 | if( route->netif->routing ){ |
1074 | if( route->netif->routing ){ |
- | 1075 | -- header->ttl; |
|
1029 | return ip_send_route( packet, route->netif, route, NULL, dest ); |
1076 | return ip_send_route( packet, route->netif, route, NULL, dest, 0 ); |
- | 1077 | }else{ |
|
- | 1078 | phone = ip_prepare_icmp_and_get_phone( 0, packet, header ); |
|
- | 1079 | if( phone >= 0 ){ |
|
- | 1080 | // unreachable ICMP if no routing |
|
- | 1081 | icmp_destination_unreachable_msg( phone, ICMP_HOST_UNREACH, 0, packet ); |
|
1030 | } |
1082 | } |
1031 | else |
- | |
1032 | { |
- | |
1033 | // TODO icmp unreachable? |
- | |
1034 | return ENOENT; |
1083 | return ENOENT; |
1035 | } |
1084 | } |
1036 | } |
1085 | } |
1037 | } |
1086 | } |
1038 | 1087 | ||
- | 1088 | int ip_received_error_msg( int ip_phone, device_id_t device_id, packet_t packet, services_t target, services_t error ){ |
|
- | 1089 | uint8_t * data; |
|
- | 1090 | int offset; |
|
- | 1091 | icmp_type_t type; |
|
- | 1092 | icmp_code_t code; |
|
- | 1093 | ip_netif_ref netif; |
|
- | 1094 | measured_string_t address; |
|
- | 1095 | ip_route_ref route; |
|
- | 1096 | ip_header_ref header; |
|
- | 1097 | ||
- | 1098 | switch( error ){ |
|
- | 1099 | case SERVICE_ICMP: |
|
- | 1100 | offset = icmp_client_process_packet( packet, & type, & code, NULL, NULL ); |
|
- | 1101 | if( offset < 0 ){ |
|
- | 1102 | return release_and_return( packet, ENOMEM ); |
|
- | 1103 | } |
|
- | 1104 | data = packet_get_data( packet ); |
|
- | 1105 | header = ( ip_header_ref ) data + offset; |
|
- | 1106 | // destination host unreachable? |
|
- | 1107 | if(( type == ICMP_DEST_UNREACH ) && ( code == ICMP_HOST_UNREACH )){ |
|
- | 1108 | fibril_rwlock_read_lock( & ip_globals.netifs_lock ); |
|
- | 1109 | netif = ip_netifs_find( & ip_globals.netifs, device_id ); |
|
- | 1110 | if( netif && netif->arp ){ |
|
- | 1111 | route = ip_routes_get_index( & netif->routes, 0 ); |
|
- | 1112 | // from the same network? |
|
- | 1113 | if( route && (( route->address.s_addr & route->netmask.s_addr ) == ( header->destination_address & route->netmask.s_addr ))){ |
|
- | 1114 | // clear the ARP mapping if any |
|
- | 1115 | address.value = ( char * ) & header->destination_address; |
|
- | 1116 | address.length = CONVERT_SIZE( uint8_t, char, sizeof( header->destination_address )); |
|
- | 1117 | arp_clear_address_req( netif->arp->phone, netif->device_id, SERVICE_IP, & address ); |
|
- | 1118 | } |
|
- | 1119 | } |
|
- | 1120 | fibril_rwlock_read_unlock( & ip_globals.netifs_lock ); |
|
- | 1121 | } |
|
- | 1122 | break; |
|
- | 1123 | default: |
|
- | 1124 | return release_and_return( packet, ENOTSUP ); |
|
- | 1125 | } |
|
- | 1126 | return ip_deliver_local( device_id, packet, header, error ); |
|
- | 1127 | } |
|
- | 1128 | ||
1039 | int ip_deliver_local( device_id_t device_id, packet_t packet, ip_header_ref header ){ |
1129 | int ip_deliver_local( device_id_t device_id, packet_t packet, ip_header_ref header, services_t error ){ |
1040 | ERROR_DECLARE; |
1130 | ERROR_DECLARE; |
1041 | 1131 | ||
1042 | ip_proto_ref proto; |
1132 | ip_proto_ref proto; |
- | 1133 | int phone; |
|
1043 | 1134 | ||
1044 | if(( header->flags & IPFLAG_MORE_FRAGMENTS ) || header->fragment_offset ){ |
1135 | if(( header->flags & IPFLAG_MORE_FRAGMENTS ) || header->fragment_offset ){ |
1045 | // TODO fragmented |
1136 | // TODO fragmented |
1046 | return ENOTSUP; |
1137 | return ENOTSUP; |
1047 | }else{ |
1138 | }else{ |
1048 | ERROR_PROPAGATE( packet_set_addr( packet, ( uint8_t * ) & header->source_address, ( uint8_t * ) & header->destination_address, IP_ADDR )); |
1139 | ERROR_PROPAGATE( packet_set_addr( packet, ( uint8_t * ) & header->source_address, ( uint8_t * ) & header->destination_address, IP_ADDR )); |
1049 | fibril_rwlock_read_lock( & ip_globals.protos_lock ); |
1140 | fibril_rwlock_read_lock( & ip_globals.protos_lock ); |
1050 | proto = ip_protos_find( & ip_globals.protos, header->protocol ); |
1141 | proto = ip_protos_find( & ip_globals.protos, header->protocol ); |
1051 | if( ! proto ){ |
1142 | if( ! proto ){ |
1052 | fibril_rwlock_read_unlock( & ip_globals.protos_lock ); |
1143 | fibril_rwlock_read_unlock( & ip_globals.protos_lock ); |
- | 1144 | phone = ip_prepare_icmp_and_get_phone( error, packet, header ); |
|
- | 1145 | if( phone >= 0 ){ |
|
- | 1146 | // unreachable ICMP |
|
- | 1147 | icmp_destination_unreachable_msg( phone, ICMP_PROT_UNREACH, 0, packet ); |
|
- | 1148 | } |
|
1053 | return ENOENT; |
1149 | return ENOENT; |
1054 | } |
1150 | } |
1055 | if( proto->received_msg ){ |
1151 | if( proto->received_msg ){ |
1056 | ERROR_CODE = proto->received_msg( device_id, packet, SERVICE_IP ); |
1152 | ERROR_CODE = proto->received_msg( device_id, packet, proto->service, error ); |
1057 | }else{ |
1153 | }else{ |
1058 | ERROR_CODE = tl_received_msg( proto->phone, device_id, packet, proto->service ); |
1154 | ERROR_CODE = tl_received_msg( proto->phone, device_id, packet, proto->service, error ); |
1059 | } |
1155 | } |
1060 | fibril_rwlock_read_unlock( & ip_globals.protos_lock ); |
1156 | fibril_rwlock_read_unlock( & ip_globals.protos_lock ); |
1061 | return ERROR_CODE; |
1157 | return ERROR_CODE; |
1062 | } |
1158 | } |
1063 | } |
1159 | } |
1064 | 1160 | ||
1065 | in_addr_t ip_get_destination( ip_header_ref header ){ |
1161 | in_addr_t ip_get_destination( ip_header_ref header ){ |
1066 | in_addr_t destination; |
1162 | in_addr_t destination; |
1067 | 1163 | ||
1068 | // TODO search set ipopt route? |
1164 | // TODO search set ipopt route? |
1069 | destination.s_addr = header->destination_address; //ntohl( header->destination_address ); |
1165 | destination.s_addr = header->destination_address; |
1070 | return destination; |
1166 | return destination; |
1071 | } |
1167 | } |
1072 | 1168 | ||
- | 1169 | int ip_prepare_icmp( packet_t packet, ip_header_ref header ){ |
|
- | 1170 | packet_t next; |
|
- | 1171 | ||
- | 1172 | // detach the first packet and release the others |
|
- | 1173 | next = pq_detach( packet ); |
|
- | 1174 | if( next ){ |
|
- | 1175 | pq_release( ip_globals.net_phone, packet_get_id( next )); |
|
- | 1176 | } |
|
- | 1177 | if( ! header ){ |
|
- | 1178 | if( packet_get_data_length( packet ) <= sizeof( ip_header_t )) return ENOMEM; |
|
- | 1179 | // get header |
|
- | 1180 | header = ( ip_header_ref ) packet_get_data( packet ); |
|
- | 1181 | if( ! header ) return EINVAL; |
|
- | 1182 | } |
|
- | 1183 | // only for the first fragment |
|
- | 1184 | if( header->fragment_offset ) return EINVAL; |
|
- | 1185 | // set the destination address |
|
- | 1186 | return packet_set_addr( packet, NULL, ( uint8_t * ) & header->source_address, sizeof( header->source_address )); |
|
- | 1187 | } |
|
- | 1188 | ||
- | 1189 | int ip_get_icmp_phone( void ){ |
|
- | 1190 | ip_proto_ref proto; |
|
- | 1191 | int phone; |
|
- | 1192 | ||
- | 1193 | fibril_rwlock_read_lock( & ip_globals.protos_lock ); |
|
- | 1194 | proto = ip_protos_find( & ip_globals.protos, IPPROTO_ICMP ); |
|
- | 1195 | phone = proto ? proto->phone : ENOENT; |
|
- | 1196 | fibril_rwlock_read_unlock( & ip_globals.protos_lock ); |
|
- | 1197 | return phone; |
|
- | 1198 | } |
|
- | 1199 | ||
- | 1200 | int ip_prepare_icmp_and_get_phone( services_t error, packet_t packet, ip_header_ref header ){ |
|
- | 1201 | int phone; |
|
- | 1202 | ||
- | 1203 | phone = ip_get_icmp_phone(); |
|
- | 1204 | if( error || ( phone < 0 ) || ip_prepare_icmp( packet, header )){ |
|
- | 1205 | return release_and_return( packet, EINVAL ); |
|
- | 1206 | } |
|
- | 1207 | return phone; |
|
- | 1208 | } |
|
- | 1209 | ||
- | 1210 | static int release_and_return( packet_t packet, int result ){ |
|
- | 1211 | pq_release( ip_globals.net_phone, packet_get_id( packet )); |
|
- | 1212 | return result; |
|
- | 1213 | } |
|
- | 1214 | ||
1073 | /** @} |
1215 | /** @} |
1074 | */ |
1216 | */ |