Rev 4702 | Rev 4708 | Go to most recent revision | Show entire file | Ignore 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 ); |
| 1030 | } |
1077 | }else{ |
| - | 1078 | phone = ip_prepare_icmp_and_get_phone( 0, packet, header ); |
|
| 1031 | else |
1079 | if( phone >= 0 ){ |
| - | 1080 | // unreachable ICMP if no routing |
|
| - | 1081 | icmp_destination_unreachable_msg( phone, ICMP_HOST_UNREACH, 0, packet ); |
|
| 1032 | { |
1082 | } |
| 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 | */ |