Subversion Repositories HelenOS

Rev

Rev 4728 | Rev 4735 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright (c) 2009 Lukas Mejdrech
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  *
  9.  * - Redistributions of source code must retain the above copyright
  10.  *   notice, this list of conditions and the following disclaimer.
  11.  * - Redistributions in binary form must reproduce the above copyright
  12.  *   notice, this list of conditions and the following disclaimer in the
  13.  *   documentation and/or other materials provided with the distribution.
  14.  * - The name of the author may not be used to endorse or promote products
  15.  *   derived from this software without specific prior written permission.
  16.  *
  17.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  18.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  19.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  20.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  21.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  22.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  23.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  24.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27.  */
  28.  
  29. /** @addtogroup ip
  30.  *  @{
  31.  */
  32.  
  33. /** @file
  34.  *  IP module implementation.
  35.  *  @see arp.h
  36.  *  \todo
  37.  */
  38.  
  39. #include <async.h>
  40. #include <errno.h>
  41. #include <fibril_sync.h>
  42. #include <stdio.h>
  43. #include <string.h>
  44.  
  45. #include <ipc/ipc.h>
  46. #include <ipc/services.h>
  47.  
  48. #include <sys/types.h>
  49.  
  50. #include "../../err.h"
  51. #include "../../messages.h"
  52. #include "../../modules.h"
  53.  
  54. #include "../../include/arp_interface.h"
  55. #include "../../include/byteorder.h"
  56. #include "../../include/crc.h"
  57. #include "../../include/device.h"
  58. #include "../../include/icmp_client.h"
  59. #include "../../include/icmp_codes.h"
  60. #include "../../include/icmp_interface.h"
  61. #include "../../include/il_interface.h"
  62. #include "../../include/in.h"
  63. #include "../../include/in6.h"
  64. #include "../../include/inet.h"
  65. #include "../../include/ip_client.h"
  66. #include "../../include/ip_interface.h"
  67. #include "../../include/net_interface.h"
  68. #include "../../include/nil_interface.h"
  69. #include "../../include/tl_interface.h"
  70. #include "../../include/socket_codes.h"
  71. #include "../../include/socket_errno.h"
  72. #include "../../structures/measured_strings.h"
  73. #include "../../structures/module_map.h"
  74. #include "../../structures/packet/packet_client.h"
  75.  
  76. #include "../../nil/nil_messages.h"
  77.  
  78. #include "../il_messages.h"
  79.  
  80. #include "ip.h"
  81. #include "ip_header.h"
  82. #include "ip_messages.h"
  83. #include "ip_module.h"
  84.  
  85. /** IP version 4.
  86.  */
  87. #define IPV4                4
  88.  
  89. /** Default network interface IP version.
  90.  */
  91. #define NET_DEFAULT_IPV     IPV4
  92.  
  93. /** Default network interface IP routing.
  94.  */
  95. #define NET_DEFAULT_IP_ROUTING  false
  96.  
  97. /** Minimum IP packet content.
  98.  */
  99. #define IP_MIN_CONTENT  576
  100.  
  101. /** ARP module name.
  102.  */
  103. #define ARP_NAME                "arp"
  104.  
  105. /** ARP module filename.
  106.  */
  107. #define ARP_FILENAME            "/srv/arp"
  108.  
  109. /** IP packet address length.
  110.  */
  111. #define IP_ADDR                         sizeof( struct sockaddr_in6 )
  112.  
  113. /** IP packet prefix length.
  114.  */
  115. #define IP_PREFIX                       sizeof( ip_header_t )
  116.  
  117. /** IP packet suffix length.
  118.  */
  119. #define IP_SUFFIX                       0
  120.  
  121. /** IP packet maximum content length.
  122.  */
  123. #define IP_MAX_CONTENT                  65535
  124.  
  125. /** The IP localhost address.
  126.  */
  127. #define IPV4_LOCALHOST_ADDRESS  htonl(( 127 << 24 ) + 1 )
  128.  
  129. /** IP global data.
  130.  */
  131. ip_globals_t    ip_globals;
  132.  
  133. DEVICE_MAP_IMPLEMENT( ip_netifs, ip_netif_t )
  134.  
  135. INT_MAP_IMPLEMENT( ip_protos, ip_proto_t )
  136.  
  137. GENERIC_FIELD_IMPLEMENT( ip_routes, ip_route_t )
  138.  
  139. /** Updates the device content length according to the new MTU value.
  140.  *  @param device_id The device identifier. Input parameter.
  141.  *  @param mtu The new mtu value. Input parameter.
  142.  *  @returns EOK on success.
  143.  *  @returns ENOENT if device is not found.
  144.  */
  145. int ip_mtu_changed_message( device_id_t device_id, size_t mtu );
  146.  
  147. /** Updates the device state.
  148.  *  @param device_id The device identifier. Input parameter.
  149.  *  @param state The new state value. Input parameter.
  150.  *  @returns EOK on success.
  151.  *  @returns ENOENT if device is not found.
  152.  */
  153. int ip_device_state_message( device_id_t device_id, device_state_t state );
  154.  
  155. int ip_register( int protocol, services_t service, int phone, tl_received_msg_t tl_received_msg );
  156.  
  157. /** Initializes a new network interface specific data.
  158.  *  Connects to the network interface layer module, reads the netif configuration, starts an ARP module if needed and sets the netif routing table.
  159.  *  The device identifier and the nil service has to be set.
  160.  *  @param ip_netif Network interface specific data. Input/output parameter.
  161.  *  @returns EOK on success.
  162.  *  @returns ENOTSUP if DHCP is configured.
  163.  *  @returns ENOTSUP if IPv6 is configured.
  164.  *  @returns EINVAL if any of the addresses is invalid.
  165.  *  @returns EINVAL if the used ARP module is not known.
  166.  *  @returns ENOMEM if there is not enough memory left.
  167.  *  @returns Other error codes as defined for the net_get_device_conf_req() function.
  168.  *  @returns Other error codes as defined for the bind_service() function.
  169.  *  @returns Other error codes as defined for the specific arp_device_req() function.
  170.  *  @returns Other error codes as defined for the nil_packet_size_req() function.
  171.  */
  172. int ip_netif_initialize( ip_netif_ref ip_netif );
  173.  
  174. 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 );
  175. int ip_prepare_packet( in_addr_t * source, in_addr_t dest, packet_t packet, measured_string_ref destination );
  176.  
  177. packet_t    ip_split_packet( packet_t packet, size_t prefix, size_t content, size_t suffix, socklen_t addr_len, services_t error );
  178. int ip_fragment_packet( packet_t packet, size_t length, size_t prefix, size_t suffix, socklen_t addr_len );
  179. int ip_fragment_packet_data( packet_t packet, packet_t new_packet, ip_header_ref header, ip_header_ref new_header, size_t length, const struct sockaddr * src, const struct sockaddr * dest, socklen_t addrlen );
  180. ip_header_ref   ip_create_middle_header( packet_t packet, ip_header_ref last );
  181. void ip_create_last_header( ip_header_ref last, ip_header_ref first );
  182.  
  183. in_addr_t * ip_netif_address( ip_netif_ref netif );
  184. ip_route_ref    ip_find_route( in_addr_t destination );
  185. ip_route_ref    ip_netif_find_route( ip_netif_ref netif, in_addr_t destination );
  186.  
  187. /** Processes the received IP packet.
  188.  *  @param device_id The source device identifier. Input parameter.
  189.  *  @param packet The received packet. Input/output parameter.
  190.  *  @returns EOK on success and the packet is no longer needed.
  191.  *  @returns EINVAL if the packet is too small to carry the IP packet.
  192.  *  @returns EINVAL if the received address lengths differs from the registered values.
  193.  *  @returns ENOENT if the device is not found in the cache.
  194.  *  @returns ENOENT if the protocol for the device is not found in the cache.
  195.  *  @returns ENOMEM if there is not enough memory left.
  196.  */
  197. int ip_receive_message( device_id_t device_id, packet_t packet );
  198.  
  199. int ip_process_packet( device_id_t device_id, packet_t packet );
  200. in_addr_t   ip_get_destination( ip_header_ref header );
  201. int ip_deliver_local( device_id_t device_id, packet_t packet, ip_header_ref header, services_t error );
  202.  
  203. int ip_prepare_icmp_and_get_phone( services_t error, packet_t packet, ip_header_ref header );
  204. int ip_get_icmp_phone( void );
  205. int ip_prepare_icmp( packet_t packet, ip_header_ref header );
  206.  
  207. int ip_release_and_return( packet_t packet, int result );
  208.  
  209. int ip_initialize( async_client_conn_t client_connection ){
  210.     ERROR_DECLARE;
  211.  
  212.     fibril_rwlock_initialize( & ip_globals.lock );
  213.     fibril_rwlock_write_lock( & ip_globals.lock );
  214.     fibril_rwlock_initialize( & ip_globals.protos_lock );
  215.     fibril_rwlock_initialize( & ip_globals.netifs_lock );
  216.     ip_globals.packet_counter = 0;
  217.     ip_globals.gateway.address.s_addr = 0;
  218.     ip_globals.gateway.netmask.s_addr = 0;
  219.     ip_globals.gateway.gateway.s_addr = 0;
  220.     ip_globals.gateway.netif = NULL;
  221.     ERROR_PROPAGATE( ip_netifs_initialize( & ip_globals.netifs ));
  222.     ERROR_PROPAGATE( ip_protos_initialize( & ip_globals.protos ));
  223.     ip_globals.client_connection = client_connection;
  224.     ERROR_PROPAGATE( modules_initialize( & ip_globals.modules ));
  225.     ERROR_PROPAGATE( add_module( NULL, & ip_globals.modules, ARP_NAME, ARP_FILENAME, SERVICE_ARP, arp_task_get_id(), arp_connect_module ));
  226.     fibril_rwlock_write_unlock( & ip_globals.lock );
  227.     return EOK;
  228. }
  229.  
  230. int ip_device_req( int il_phone, device_id_t device_id, services_t netif ){
  231.     ERROR_DECLARE;
  232.  
  233.     ip_netif_ref    ip_netif;
  234.     ip_route_ref    route;
  235.     int             index;
  236.     char *          data;
  237.  
  238.     ip_netif = ( ip_netif_ref ) malloc( sizeof( ip_netif_t ));
  239.     if( ! ip_netif ) return ENOMEM;
  240.     if( ERROR_OCCURRED( ip_routes_initialize( & ip_netif->routes ))){
  241.         free( ip_netif );
  242.         return ERROR_CODE;
  243.     }
  244.     ip_netif->device_id = device_id;
  245.     ip_netif->service = netif;
  246.     ip_netif->state = NETIF_STOPPED;
  247.     fibril_rwlock_write_lock( & ip_globals.netifs_lock );
  248.     if( ERROR_OCCURRED( ip_netif_initialize( ip_netif ))){
  249.         fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
  250.         ip_routes_destroy( & ip_netif->routes );
  251.         free( ip_netif );
  252.         return ERROR_CODE;
  253.     }
  254.     if( ip_netif->arp ) ++ ip_netif->arp->usage;
  255.     // print the settings
  256.     printf( "New device registered:\n\tid\t= %d\n\tphone\t= %d\n\tIPV\t= %d\n", ip_netif->device_id, ip_netif->phone, ip_netif->ipv );
  257.     printf( "\tconfiguration\t= %s\n", ip_netif->dhcp ? "dhcp" : "static" );
  258.     // TODO ipv6 addresses
  259.     data = ( char * ) malloc( INET_ADDRSTRLEN );
  260.     if( data ){
  261.         for( index = 0; index < ip_routes_count( & ip_netif->routes ); ++ index ){
  262.             route = ip_routes_get_index( & ip_netif->routes, index );
  263.             if( route ){
  264.                 printf( "\tRouting %d:\n", index );
  265.                 inet_ntop( AF_INET, ( uint8_t * ) & route->address.s_addr, data, INET_ADDRSTRLEN );
  266.                 printf( "\t\taddress\t= %s\n", data );
  267.                 inet_ntop( AF_INET, ( uint8_t * ) & route->netmask.s_addr, data, INET_ADDRSTRLEN );
  268.                 printf( "\t\tnetmask\t= %s\n", data );
  269.                 inet_ntop( AF_INET, ( uint8_t * ) & route->gateway.s_addr, data, INET_ADDRSTRLEN );
  270.                 printf( "\t\tgateway\t= %s\n", data );
  271.             }
  272.         }
  273.         inet_ntop( AF_INET, ( uint8_t * ) & ip_netif->broadcast.s_addr, data, INET_ADDRSTRLEN );
  274.         printf( "\tbroadcast\t= %s\n", data );
  275.         inet_ntop( AF_INET, ( uint8_t * ) & ip_netif->dns1, data, INET_ADDRSTRLEN );
  276.         printf( "\tdns1\t= %s\n", data );
  277.         inet_ntop( AF_INET, ( uint8_t * ) & ip_netif->dns2, data, INET_ADDRSTRLEN );
  278.         printf( "\tdns2\t= %s\n", data );
  279.         free( data );
  280.     }
  281.     fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
  282.     return EOK;
  283. }
  284.  
  285. int ip_netif_initialize( ip_netif_ref ip_netif ){
  286.     ERROR_DECLARE;
  287.  
  288.     measured_string_t   names[] = {{ "IPV", 3 }, { "IP_CONFIG", 9 }, { "IP_ADDR", 7 }, { "NETMASK", 7 }, { "GATEWAY", 7 }, { "BROADCAST", 9 }, { "DNS1", 4 }, { "DNS2", 4 }, { "ARP", 3 }, { "IP_ROUTING", 10 }};
  289.     measured_string_ref configuration;
  290.     size_t              count = sizeof( names ) / sizeof( measured_string_t );
  291.     char *              data;
  292.     measured_string_t   address;
  293.     int                 index;
  294.     ip_route_ref        route;
  295.     in_addr_t           gateway;
  296.  
  297.     ip_netif->arp = NULL;
  298.     route = NULL;
  299.     ip_netif->ipv = NET_DEFAULT_IPV;
  300.     ip_netif->dhcp = false;
  301.     ip_netif->routing = NET_DEFAULT_IP_ROUTING;
  302.     configuration = & names[ 0 ];
  303.     // get configuration
  304.     ERROR_PROPAGATE( net_get_device_conf_req( ip_globals.net_phone, ip_netif->device_id, & configuration, count, & data ));
  305.     if( configuration ){
  306.         if( configuration[ 0 ].value ){
  307.             ip_netif->ipv = strtol( configuration[ 0 ].value, NULL, 0 );
  308.         }
  309.         ip_netif->dhcp = ! str_lcmp( configuration[ 1 ].value, "dhcp", configuration[ 1 ].length );
  310.         if( ip_netif->dhcp ){
  311.             // TODO dhcp
  312.             net_free_settings( configuration, data );
  313.             return ENOTSUP;
  314.         }else if( ip_netif->ipv == IPV4 ){
  315.             route = ( ip_route_ref ) malloc( sizeof( ip_route_t ));
  316.             if( ! route ){
  317.                 net_free_settings( configuration, data );
  318.                 return ENOMEM;
  319.             }
  320.             route->address.s_addr = 0;
  321.             route->netmask.s_addr = 0;
  322.             route->gateway.s_addr = 0;
  323.             route->netif = ip_netif;
  324.             index = ip_routes_add( & ip_netif->routes, route );
  325.             if( index < 0 ){
  326.                 net_free_settings( configuration, data );
  327.                 free( route );
  328.                 return index;
  329.             }
  330.             if( ERROR_OCCURRED( inet_pton( AF_INET, configuration[ 2 ].value, ( uint8_t * ) & route->address.s_addr ))
  331.             || ERROR_OCCURRED( inet_pton( AF_INET, configuration[ 3 ].value, ( uint8_t * ) & route->netmask.s_addr ))
  332.             || ( inet_pton( AF_INET, configuration[ 4 ].value, ( uint8_t * ) & gateway.s_addr ) == EINVAL )
  333.             || ( inet_pton( AF_INET, configuration[ 5 ].value, ( uint8_t * ) & ip_netif->broadcast.s_addr ) == EINVAL )
  334.             || ( inet_pton( AF_INET, configuration[ 6 ].value, ( uint8_t * ) & ip_netif->dns1 ) == EINVAL )
  335.             || ( inet_pton( AF_INET, configuration[ 7 ].value, ( uint8_t * ) & ip_netif->dns2 ) == EINVAL )){
  336.                 net_free_settings( configuration, data );
  337.                 return EINVAL;
  338.             }
  339.         }else{
  340.             // TODO ipv6 in separate module
  341.             net_free_settings( configuration, data );
  342.             return ENOTSUP;
  343.         }
  344.         if( configuration[ 8 ].value ){
  345.             ip_netif->arp = get_running_module( & ip_globals.modules, configuration[ 8 ].value );
  346.             if( ! ip_netif->arp ){
  347.                 printf( "Failed to start the arp %s\n", configuration[ 8 ].value );
  348.                 net_free_settings( configuration, data );
  349.                 return EINVAL;
  350.             }
  351.         }
  352.         if( configuration[ 9 ].value ){
  353.             ip_netif->routing = ( configuration[ 9 ].value[ 0 ] == 'y' );
  354.         }
  355.         net_free_settings( configuration, data );
  356.     }
  357.     // binds the netif service which also initializes the device
  358.     ip_netif->phone = bind_service( ip_netif->service, ( ipcarg_t ) ip_netif->device_id, SERVICE_IP, 0, ip_globals.client_connection );
  359.     if( ip_netif->phone < 0 ){
  360.         printf( "Failed to contact the nil service %d\n", ip_netif->service );
  361.         return ip_netif->phone;
  362.     }
  363.     // has to be after the device netif module initialization
  364.     if( ip_netif->arp ){
  365.         if( route ){
  366.             address.value = ( char * ) & route->address.s_addr;
  367.             address.length = CONVERT_SIZE( in_addr_t, char, 1 );
  368.             ERROR_PROPAGATE( arp_device_req( ip_netif->arp->phone, ip_netif->device_id, SERVICE_IP, ip_netif->service, & address ));
  369.         }else{
  370.             ip_netif->arp = 0;
  371.         }
  372.     }
  373.     // get packet dimensions
  374.     ERROR_PROPAGATE( nil_packet_size_req( ip_netif->phone, ip_netif->device_id, & ip_netif->addr_len, & ip_netif->prefix, & ip_netif->content, & ip_netif->suffix ));
  375.     if( ip_netif->content < IP_MIN_CONTENT ){
  376.         printf( "Maximum transmission unit %d bytes is too small, at least %d bytes are needed\n", ip_netif->content, IP_MIN_CONTENT );
  377.         ip_netif->content = IP_MIN_CONTENT;
  378.     }
  379.     index = ip_netifs_add( & ip_globals.netifs, ip_netif->device_id, ip_netif );
  380.     if( index < 0 ) return index;
  381.     if( gateway.s_addr ){
  382.         // the default gateway
  383.         ip_globals.gateway.address.s_addr = 0;
  384.         ip_globals.gateway.netmask.s_addr = 0;
  385.         ip_globals.gateway.gateway.s_addr = gateway.s_addr;
  386.         ip_globals.gateway.netif = ip_netif;
  387.     }
  388.     return EOK;
  389. }
  390.  
  391. int ip_mtu_changed_message( device_id_t device_id, size_t mtu ){
  392.     ip_netif_ref    netif;
  393.  
  394.     fibril_rwlock_write_lock( & ip_globals.netifs_lock );
  395.     netif = ip_netifs_find( & ip_globals.netifs, device_id );
  396.     if( ! netif ){
  397.         fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
  398.         return ENOENT;
  399.     }
  400.     netif->content = mtu;
  401.     printf( "ip - device %d changed mtu to %d\n\n", device_id, mtu );
  402.     fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
  403.     return EOK;
  404. }
  405.  
  406. int ip_device_state_message( device_id_t device_id, device_state_t state ){
  407.     ip_netif_ref    netif;
  408.  
  409.     fibril_rwlock_write_lock( & ip_globals.netifs_lock );
  410.     // find the device
  411.     netif = ip_netifs_find( & ip_globals.netifs, device_id );
  412.     if( ! netif ){
  413.         fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
  414.         return ENOENT;
  415.     }
  416.     netif->state = state;
  417.     printf( "ip - device %d changed state to %d\n\n", device_id, state );
  418.     fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
  419.     return EOK;
  420. }
  421.  
  422. int ip_connect_module( services_t service ){
  423.     return EOK;
  424. }
  425.  
  426. int ip_bind_service( services_t service, int protocol, services_t me, async_client_conn_t receiver, tl_received_msg_t received_msg ){
  427.     return ip_register( protocol, me, 0, received_msg );
  428. }
  429.  
  430. int ip_register( int protocol, services_t service, int phone, tl_received_msg_t received_msg ){
  431.     ip_proto_ref    proto;
  432.     int             index;
  433.  
  434.     if( !( protocol && service && (( phone > 0 ) || ( received_msg )))) return EINVAL;
  435.     proto = ( ip_proto_ref ) malloc( sizeof( ip_protos_t ));
  436.     if( ! proto ) return ENOMEM;
  437.     proto->protocol = protocol;
  438.     proto->service = service;
  439.     proto->phone = phone;
  440.     proto->received_msg = received_msg;
  441.     fibril_rwlock_write_lock( & ip_globals.protos_lock );
  442.     index = ip_protos_add( & ip_globals.protos, proto->protocol, proto );
  443.     if( index < 0 ){
  444.         fibril_rwlock_write_unlock( & ip_globals.protos_lock );
  445.         free( proto );
  446.         return index;
  447.     }
  448.     printf( "New protocol registered:\n\tprotocol\t= %d\n\tphone\t= %d\n", proto->protocol, proto->phone );
  449.     fibril_rwlock_write_unlock( & ip_globals.protos_lock );
  450.     return EOK;
  451. }
  452.  
  453. int ip_send_msg( int il_phone, device_id_t device_id, packet_t packet, services_t sender, services_t error ){
  454.     ERROR_DECLARE;
  455.  
  456.     int                 addrlen;
  457.     ip_netif_ref        netif;
  458.     ip_route_ref        route;
  459.     struct sockaddr *       addr;
  460.     struct sockaddr_in *    address_in;
  461. //  struct sockaddr_in6 *   address_in6;
  462.     in_addr_t *         dest;
  463.     in_addr_t *         src;
  464.     int                 phone;
  465.  
  466.     // addresses in the host byte order
  467.     // should be the next hop address or the target destination address
  468.     addrlen = packet_get_addr( packet, NULL, ( uint8_t ** ) & addr );
  469.     if( addrlen < 0 ){
  470.         return ip_release_and_return( packet, addrlen );
  471.     }
  472.     if( addrlen < sizeof( struct sockaddr )){
  473.         return ip_release_and_return( packet, EINVAL );
  474.     }
  475.     switch( addr->sa_family ){
  476.         case AF_INET:
  477.             if( addrlen != sizeof( struct sockaddr_in )){
  478.                 return ip_release_and_return( packet, EINVAL );
  479.             }
  480.             address_in = ( struct sockaddr_in * ) addr;
  481.             dest = & address_in->sin_addr;
  482.             break;
  483.         // TODO IPv6
  484. /*      case AF_INET6:
  485.             if( addrlen != sizeof( struct sockaddr_in6 )) return EINVAL;
  486.             address_in6 = ( struct sockaddr_in6 * ) dest;
  487.             address_in6.sin6_addr.s6_addr;
  488. */      default:
  489.             return ip_release_and_return( packet, EAFNOSUPPORT );
  490.     }
  491.     fibril_rwlock_read_lock( & ip_globals.netifs_lock );
  492.     // device specified?
  493.     if( device_id > 0 ){
  494.         netif = ip_netifs_find( & ip_globals.netifs, device_id );
  495.         route = ip_netif_find_route( netif, * dest );
  496.     }else{
  497.         route = ip_find_route( * dest );
  498.         netif = route ? route->netif : NULL;
  499.     }
  500.     if( !( netif && route )){
  501.         fibril_rwlock_read_unlock( & ip_globals.netifs_lock );
  502.         phone = ip_prepare_icmp_and_get_phone( error, packet, NULL );
  503.         if( phone >= 0 ){
  504.             // unreachable ICMP if no routing
  505.             icmp_destination_unreachable_msg( phone, ICMP_NET_UNREACH, 0, packet );
  506.         }
  507.         return ENOENT;
  508.     }
  509.     if( error ){
  510.         // do not send for broadcast, anycast packets or network broadcast
  511.         if(( ! dest->s_addr )
  512.         || ( !( ~ dest->s_addr ))
  513.         || ( !( ~(( dest->s_addr & ( ~ route->netmask.s_addr )) | route->netmask.s_addr )))
  514.         || ( !( dest->s_addr & ( ~ route->netmask.s_addr )))){
  515.             return ip_release_and_return( packet, EINVAL );
  516.         }
  517.     }
  518.     if( route->address.s_addr == dest->s_addr ){
  519.         // find the loopback device to deliver
  520.         dest->s_addr = IPV4_LOCALHOST_ADDRESS;
  521.         route = ip_find_route( * dest );
  522.         netif = route ? route->netif : NULL;
  523.         if( !( netif && route )){
  524.             fibril_rwlock_read_unlock( & ip_globals.netifs_lock );
  525.             phone = ip_prepare_icmp_and_get_phone( error, packet, NULL );
  526.             if( phone >= 0 ){
  527.                 // unreachable ICMP if no routing
  528.                 icmp_destination_unreachable_msg( phone, ICMP_HOST_UNREACH, 0, packet );
  529.             }
  530.             return ENOENT;
  531.         }
  532.     }
  533.     src = ip_netif_address( netif );
  534.     if( ! src ){
  535.         fibril_rwlock_read_unlock( & ip_globals.netifs_lock );
  536.         return ip_release_and_return( packet, ENOENT );
  537.     }
  538.     ERROR_CODE = ip_send_route( packet, netif, route, src, * dest, error );
  539.     fibril_rwlock_read_unlock( & ip_globals.netifs_lock );
  540.     return ERROR_CODE;
  541. }
  542.  
  543. in_addr_t * ip_netif_address( ip_netif_ref netif ){
  544.     ip_route_ref    route;
  545.  
  546.     route = ip_routes_get_index( & netif->routes, 0 );
  547.     return route ? & route->address : NULL;
  548. }
  549.  
  550. 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 ){
  551.     ERROR_DECLARE;
  552.  
  553.     measured_string_t   destination;
  554.     measured_string_ref translation;
  555.     char *              data;
  556.     int                 phone;
  557.  
  558.     // get destination hardware address
  559.     if( netif->arp && ( route->address.s_addr != dest.s_addr )){
  560.         destination.value = route->gateway.s_addr ? ( char * ) & route->gateway.s_addr : ( char * ) & dest.s_addr;
  561.         destination.length = CONVERT_SIZE( dest.s_addr, char, 1 );
  562.         if( ERROR_OCCURRED( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & destination, & translation, & data ))){
  563. //          sleep( 1 );
  564. //          ERROR_PROPAGATE( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & destination, & translation, & data ));
  565.             pq_release( ip_globals.net_phone, packet_get_id( packet ));
  566.             return ERROR_CODE;
  567.         }
  568.         if( !( translation && translation->value )){
  569.             if( translation ){
  570.                 free( translation );
  571.                 free( data );
  572.             }
  573.             phone = ip_prepare_icmp_and_get_phone( error, packet, NULL );
  574.             if( phone >= 0 ){
  575.                 // unreachable ICMP if no routing
  576.                 icmp_destination_unreachable_msg( phone, ICMP_HOST_UNREACH, 0, packet );
  577.             }
  578.             return EINVAL;
  579.         }
  580.     }else translation = NULL;
  581.     if( ERROR_OCCURRED( ip_prepare_packet( src, dest, packet, translation ))){
  582.         pq_release( ip_globals.net_phone, packet_get_id( packet ));
  583.     }else{
  584.         packet = ip_split_packet( packet, netif->prefix, netif->content, netif->suffix, netif->addr_len, error );
  585.         if( packet ){
  586.             nil_send_msg( netif->phone, netif->device_id, packet, SERVICE_IP );
  587.         }
  588.     }
  589.     if( translation ){
  590.         free( translation );
  591.         free( data );
  592.     }
  593.     return ERROR_CODE;
  594. }
  595.  
  596. int ip_prepare_packet( in_addr_t * source, in_addr_t dest, packet_t packet, measured_string_ref destination ){
  597.     ERROR_DECLARE;
  598.  
  599.     size_t              length;
  600.     ip_header_ref       header;
  601.     ip_header_ref       last_header;
  602.     ip_header_ref       middle_header;
  603.     packet_t            next;
  604.  
  605.     length = packet_get_data_length( packet );
  606.     if(( length < sizeof( ip_header_t )) || ( length > IP_MAX_CONTENT )) return EINVAL;
  607.     header = ( ip_header_ref ) packet_get_data( packet );
  608.     if( destination ){
  609.         ERROR_PROPAGATE( packet_set_addr( packet, NULL, ( uint8_t * ) destination->value, CONVERT_SIZE( char, uint8_t, destination->length )));
  610.     }else{
  611.         ERROR_PROPAGATE( packet_set_addr( packet, NULL, NULL, 0 ));
  612.     }
  613.     header->version = IPV4;
  614.     header->fragment_offset_high = 0;
  615.     header->fragment_offset_low = 0;
  616.     header->header_checksum = 0;
  617.     if( source ) header->source_address = source->s_addr;
  618.     header->destination_address = dest.s_addr;
  619.     fibril_rwlock_write_lock( & ip_globals.lock );
  620.     ++ ip_globals.packet_counter;
  621.     header->identification = htons( ip_globals.packet_counter );
  622.     fibril_rwlock_write_unlock( & ip_globals.lock );
  623. //  length = packet_get_data_length( packet );
  624.     if( pq_next( packet )){
  625.         last_header = ( ip_header_ref ) malloc( IP_HEADER_LENGTH( header ));
  626.         if( ! last_header ) return ENOMEM;
  627.         ip_create_last_header( last_header, header );
  628.         next = pq_next( packet );
  629.         while( pq_next( next )){
  630.             middle_header = ( ip_header_ref ) packet_prefix( next, IP_HEADER_LENGTH( last_header ));
  631.             if( ! middle_header ) return ENOMEM;
  632.             memcpy( middle_header, last_header, IP_HEADER_LENGTH( last_header ));
  633.             header->flags |= IPFLAG_MORE_FRAGMENTS;
  634.             middle_header->total_length = htons( packet_get_data_length( next ));
  635.             middle_header->fragment_offset_high = IP_COMPUTE_FRAGMENT_OFFSET_HIGH( length );
  636.             middle_header->fragment_offset_low = IP_COMPUTE_FRAGMENT_OFFSET_LOW( length );
  637.             middle_header->header_checksum = IP_HEADER_CHECKSUM( middle_header );
  638.             if( destination ){
  639.                 ERROR_PROPAGATE( packet_set_addr( next, NULL, ( uint8_t * ) destination->value, CONVERT_SIZE( char, uint8_t, destination->length )));
  640.             }
  641.             length += packet_get_data_length( next );
  642.             next = pq_next( next );
  643.         }
  644.         middle_header = ( ip_header_ref ) packet_prefix( next, IP_HEADER_LENGTH( last_header ));
  645.         if( ! middle_header ) return ENOMEM;
  646.         memcpy( middle_header, last_header, IP_HEADER_LENGTH( last_header ));
  647.         middle_header->total_length = htons( packet_get_data_length( next ));
  648.         middle_header->fragment_offset_high = IP_COMPUTE_FRAGMENT_OFFSET_HIGH( length );
  649.         middle_header->fragment_offset_low = IP_COMPUTE_FRAGMENT_OFFSET_LOW( length );
  650.         middle_header->header_checksum = IP_HEADER_CHECKSUM( middle_header );
  651.         if( destination ){
  652.             ERROR_PROPAGATE( packet_set_addr( next, NULL, ( uint8_t * ) destination->value, CONVERT_SIZE( char, uint8_t, destination->length )));
  653.         }
  654.         length += packet_get_data_length( next );
  655.         free( last_header );
  656.         header->flags |= IPFLAG_MORE_FRAGMENTS;
  657.     }
  658.     header->total_length = htons( length );
  659.     // unnecessary for all protocols
  660.     header->header_checksum = IP_HEADER_CHECKSUM( header );
  661.     return EOK;
  662. }
  663.  
  664. int ip_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){
  665.     ERROR_DECLARE;
  666.  
  667.     packet_t                packet;
  668.     struct sockaddr *       addr;
  669.     size_t                  addrlen;
  670.     ip_pseudo_header_ref    header;
  671.     size_t                  headerlen;
  672.  
  673.     * answer_count = 0;
  674.     switch( IPC_GET_METHOD( * call )){
  675.         case IPC_M_PHONE_HUNGUP:
  676.             return EOK;
  677.         case NET_IL_DEVICE:
  678.             return ip_device_req( 0, IPC_GET_DEVICE( call ), IPC_GET_SERVICE( call ));
  679.         case IPC_M_CONNECT_TO_ME:
  680.             return ip_register( IL_GET_PROTO( call ), IL_GET_SERVICE( call ), IPC_GET_PHONE( call ), NULL );
  681.         case NET_IL_SEND:
  682.             ERROR_PROPAGATE( packet_translate( ip_globals.net_phone, & packet, IPC_GET_PACKET( call )));
  683.             return ip_send_msg( 0, IPC_GET_DEVICE( call ), packet, 0, IPC_GET_ERROR( call ));
  684.         case NET_IL_DEVICE_STATE:
  685.             return ip_device_state_message( IPC_GET_DEVICE( call ), IPC_GET_STATE( call ));
  686.         case NET_IL_RECEIVED:
  687.             ERROR_PROPAGATE( packet_translate( ip_globals.net_phone, & packet, IPC_GET_PACKET( call )));
  688.             return ip_receive_message( IPC_GET_DEVICE( call ), packet );
  689.         case NET_IP_RECEIVED_ERROR:
  690.             ERROR_PROPAGATE( packet_translate( ip_globals.net_phone, & packet, IPC_GET_PACKET( call )));
  691.             return ip_received_error_msg( 0, IPC_GET_DEVICE( call ), packet, IPC_GET_TARGET( call ), IPC_GET_ERROR( call ));
  692.         case NET_IP_ADD_ROUTE:
  693.             return ip_add_route_req( 0, IPC_GET_DEVICE( call ), IP_GET_ADDRESS( call ), IP_GET_NETMASK( call ), IP_GET_GATEWAY( call ));
  694.         case NET_IP_SET_GATEWAY:
  695.             return ip_set_gateway_req( 0, IPC_GET_DEVICE( call ), IP_GET_GATEWAY( call ));
  696.         case NET_IP_GET_ROUTE:
  697.             ERROR_PROPAGATE( data_receive(( void ** ) & addr, & addrlen ));
  698.             ERROR_PROPAGATE( ip_get_route_req( 0, IP_GET_PROTOCOL( call ), addr, ( socklen_t ) addrlen, IPC_SET_DEVICE( answer ), & header, & headerlen ));
  699.             * IP_SET_HEADERLEN( answer ) = headerlen;
  700.             if( ! ERROR_OCCURRED( data_reply( & headerlen, sizeof( headerlen )))){
  701.                 ERROR_CODE = data_reply( header, headerlen );
  702.             }
  703.             free( header );
  704.             return ERROR_CODE;
  705.         case NET_IL_PACKET_SPACE:
  706.             ERROR_PROPAGATE( ip_packet_size_req( 0, IPC_GET_DEVICE( call ), IPC_SET_ADDR( answer ), IPC_SET_PREFIX( answer ), IPC_SET_CONTENT( answer ), IPC_SET_SUFFIX( answer )));
  707.             * answer_count = 3;
  708.             return EOK;
  709.         case NET_IL_MTU_CHANGED:
  710.             return ip_mtu_changed_message( IPC_GET_DEVICE( call ), IPC_GET_MTU( call ));
  711.     }
  712.     return ENOTSUP;
  713. }
  714.  
  715. int ip_packet_size_req( int ip_phone, device_id_t device_id, size_t * addr_len, size_t * prefix, size_t * content, size_t * suffix ){
  716.     ip_netif_ref    netif;
  717.     int             index;
  718.  
  719.     if( !( addr_len && prefix && content && suffix )) return EBADMEM;
  720.     * content = IP_MAX_CONTENT - IP_PREFIX;
  721.     fibril_rwlock_read_lock( & ip_globals.netifs_lock );
  722.     if( device_id < 0 ){
  723.         * addr_len = IP_ADDR;
  724.         * prefix = 0;
  725.         * suffix = 0;
  726.         for( index = ip_netifs_count( & ip_globals.netifs ) - 1; index >= 0; -- index ){
  727.             netif = ip_netifs_get_index( & ip_globals.netifs, index );
  728.             if( netif ){
  729.                 if( netif->addr_len > * addr_len ) * addr_len = netif->addr_len;
  730.                 if( netif->prefix > * prefix ) * prefix = netif->prefix;
  731.                 if( netif->suffix > * suffix ) * suffix = netif->suffix;
  732.             }
  733.         }
  734.         * prefix = * prefix + IP_PREFIX;
  735.         * suffix = * suffix + IP_SUFFIX;
  736.     }else{
  737.         netif = ip_netifs_find( & ip_globals.netifs, device_id );
  738.         if( ! netif ){
  739.             fibril_rwlock_read_unlock( & ip_globals.netifs_lock );
  740.             return ENOENT;
  741.         }
  742.         * addr_len = ( netif->addr_len > IP_ADDR ) ? netif->addr_len : IP_ADDR;
  743.         * prefix = netif->prefix + IP_PREFIX;
  744.         * suffix = netif->suffix + IP_SUFFIX;
  745.     }
  746.     fibril_rwlock_read_unlock( & ip_globals.netifs_lock );
  747.     return EOK;
  748. }
  749.  
  750. int ip_add_route_req( int ip_phone, device_id_t device_id, in_addr_t address, in_addr_t netmask, in_addr_t gateway ){
  751.     ip_route_ref    route;
  752.     ip_netif_ref    netif;
  753.     int             index;
  754.  
  755.     fibril_rwlock_write_lock( & ip_globals.netifs_lock );
  756.     netif = ip_netifs_find( & ip_globals.netifs, device_id );
  757.     if( ! netif ){
  758.         fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
  759.         return ENOENT;
  760.     }
  761.     route = ( ip_route_ref ) malloc( sizeof( ip_route_t ));
  762.     if( ! route ){
  763.         fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
  764.         return ENOMEM;
  765.     }
  766.     route->address.s_addr = address.s_addr;
  767.     route->netmask.s_addr = netmask.s_addr;
  768.     route->gateway.s_addr = gateway.s_addr;
  769.     route->netif = netif;
  770.     index = ip_routes_add( & netif->routes, route );
  771.     if( index < 0 ) free( route );
  772.     fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
  773.     return index;
  774. }
  775.  
  776. ip_route_ref ip_find_route( in_addr_t destination ){
  777.     int             index;
  778.     ip_route_ref    route;
  779.     ip_netif_ref    netif;
  780.  
  781.     // start with the last netif - the newest one
  782.     index = ip_netifs_count( & ip_globals.netifs ) - 1;
  783.     while( index >= 0 ){
  784.         netif = ip_netifs_get_index( & ip_globals.netifs, index );
  785.         if( netif && ( netif->state == NETIF_ACTIVE )){
  786.             route = ip_netif_find_route( netif, destination );
  787.             if( route ) return route;
  788.         }
  789.         -- index;
  790.     }
  791.     return & ip_globals.gateway;
  792. }
  793.  
  794. ip_route_ref ip_netif_find_route( ip_netif_ref netif, in_addr_t destination ){
  795.     int             index;
  796.     ip_route_ref    route;
  797.  
  798.     if( netif ){
  799.         // start with the first one - the direct route
  800.         for( index = 0; index < ip_routes_count( & netif->routes ); ++ index ){
  801.             route = ip_routes_get_index( & netif->routes, index );
  802.             if( route && (( route->address.s_addr & route->netmask.s_addr ) == ( destination.s_addr & route->netmask.s_addr ))){
  803.                 return route;
  804.             }
  805.         }
  806.     }
  807.     return NULL;
  808. }
  809.  
  810. int ip_set_gateway_req( int ip_phone, device_id_t device_id, in_addr_t gateway ){
  811.     ip_netif_ref    netif;
  812.  
  813.     fibril_rwlock_write_lock( & ip_globals.netifs_lock );
  814.     netif = ip_netifs_find( & ip_globals.netifs, device_id );
  815.     if( ! netif ){
  816.         fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
  817.         return ENOENT;
  818.     }
  819.     ip_globals.gateway.address.s_addr = 0;
  820.     ip_globals.gateway.netmask.s_addr = 0;
  821.     ip_globals.gateway.gateway.s_addr = gateway.s_addr;
  822.     ip_globals.gateway.netif = netif;
  823.     fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
  824.     return EOK;
  825. }
  826.  
  827. packet_t ip_split_packet( packet_t packet, size_t prefix, size_t content, size_t suffix, socklen_t addr_len, services_t error ){
  828.     size_t          length;
  829.     packet_t        next;
  830.     packet_t        new_packet;
  831.     int             result;
  832.     int             phone;
  833.  
  834.     next = packet;
  835.     // check all packets
  836.     while( next ){
  837.         length = packet_get_data_length( next );
  838.         // too long?
  839.         if( length > content ){
  840.             result = ip_fragment_packet( next, content, prefix, suffix, addr_len );
  841.             if( result != EOK ){
  842.                 new_packet = pq_detach( next );
  843.                 if( next == packet ){
  844.                     // the new first packet of the queue
  845.                     packet = new_packet;
  846.                 }
  847.                 // fragmentation needed?
  848.                 if( result == EPERM ){
  849.                     phone = ip_prepare_icmp_and_get_phone( error, next, NULL );
  850.                     if( phone >= 0 ){
  851.                         // fragmentation necessary ICMP
  852.                         icmp_destination_unreachable_msg( phone, ICMP_FRAG_NEEDED, content, next );
  853.                     }
  854.                 }else{
  855.                     pq_release( ip_globals.net_phone, packet_get_id( next ));
  856.                 }
  857.                 next = new_packet;
  858.                 continue;
  859.             }
  860.         }
  861.         next = pq_next( next );
  862.     }
  863.     return packet;
  864. }
  865.  
  866. int ip_fragment_packet( packet_t packet, size_t length, size_t prefix, size_t suffix, socklen_t addr_len ){
  867.     ERROR_DECLARE;
  868.  
  869.     packet_t        new_packet;
  870.     ip_header_ref   header;
  871.     ip_header_ref   middle_header;
  872.     ip_header_ref   last_header;
  873.     struct sockaddr *       src;
  874.     struct sockaddr *       dest;
  875.     socklen_t       addrlen;
  876.     int             result;
  877.  
  878.     result = packet_get_addr( packet, ( uint8_t ** ) & src, ( uint8_t ** ) & dest );
  879.     if( result <= 0 ) return EINVAL;
  880.     addrlen = ( socklen_t ) result;
  881.     if( packet_get_data_length( packet ) <= sizeof( ip_header_t )) return ENOMEM;
  882.     // get header
  883.     header = ( ip_header_ref ) packet_get_data( packet );
  884.     if( ! header ) return EINVAL;
  885.     // fragmentation forbidden?
  886.     if( header->flags & IPFLAG_DONT_FRAGMENT ){
  887.         return EPERM;
  888.     }
  889.     // create the last fragment
  890.     new_packet = packet_get_4( ip_globals.net_phone, prefix, length, suffix, (( addrlen > addr_len ) ? addrlen : addr_len ));
  891.     if( ! new_packet ) return ENOMEM;
  892.     // allocate as much as originally
  893.     last_header = ( ip_header_ref ) packet_suffix( new_packet, IP_HEADER_LENGTH( header ));
  894.     if( ! last_header ){
  895.         return ip_release_and_return( packet, ENOMEM );
  896.     }
  897.     ip_create_last_header( last_header, header );
  898.     // trim the unused space
  899.     if( ERROR_OCCURRED( packet_trim( new_packet, 0, IP_HEADER_LENGTH( header ) - IP_HEADER_LENGTH( last_header )))){
  900.         return ip_release_and_return( packet, ERROR_CODE );
  901.     }
  902.     // biggest multiple of 8 lower than content
  903.     // TODO even fragmentation?
  904.     length = length & ( ~ 0x7 );// ( content / 8 ) * 8
  905.     if( ERROR_OCCURRED( ip_fragment_packet_data( packet, new_packet, header, last_header, (( IP_HEADER_DATA_LENGTH( header ) - (( length - IP_HEADER_LENGTH( header )) & ( ~ 0x7 ))) % (( length - IP_HEADER_LENGTH( last_header )) & ( ~ 0x7 ))), src, dest, addrlen ))){
  906.         return ip_release_and_return( packet, ERROR_CODE );
  907.     }
  908.     // mark the first as fragmented
  909.     header->flags |= IPFLAG_MORE_FRAGMENTS;
  910.     // create middle framgents
  911.     while( IP_TOTAL_LENGTH( header ) > length ){
  912.         new_packet = packet_get_4( ip_globals.net_phone, prefix, length, suffix, (( addrlen >= addr_len ) ? addrlen : addr_len ));
  913.         if( ! new_packet ) return ENOMEM;
  914.         middle_header = ip_create_middle_header( new_packet, last_header );
  915.         if( ! middle_header ){
  916.             return ip_release_and_return( packet, ENOMEM );
  917.         }
  918.         if( ERROR_OCCURRED( ip_fragment_packet_data( packet, new_packet, header, middle_header, ( length - IP_HEADER_LENGTH( middle_header )) & ( ~ 0x7 ), src, dest, addrlen ))){
  919.             return ip_release_and_return( packet, ERROR_CODE );
  920.         }
  921.     }
  922.     // finish the first fragment
  923.     header->header_checksum = IP_HEADER_CHECKSUM( header );
  924.     return EOK;
  925. }
  926.  
  927. int ip_fragment_packet_data( packet_t packet, packet_t new_packet, ip_header_ref header, ip_header_ref new_header, size_t length, const struct sockaddr * src, const struct sockaddr * dest, socklen_t addrlen ){
  928.     ERROR_DECLARE;
  929.  
  930.     void *          data;
  931.     size_t          offset;
  932.  
  933.     data = packet_suffix( new_packet, length );
  934.     if( ! data ) return ENOMEM;
  935.     memcpy( data, (( void * ) header ) + IP_TOTAL_LENGTH( header ) - length, length );
  936.     ERROR_PROPAGATE( packet_trim( packet, 0, length ));
  937.     header->total_length = htons( IP_TOTAL_LENGTH( header ) - length );
  938.     new_header->total_length = htons( IP_HEADER_LENGTH( new_header ) + length );
  939.     offset = IP_FRAGMENT_OFFSET( header ) + IP_HEADER_DATA_LENGTH( header );
  940.     printf( "offset %d = %d + %d\n", offset, IP_FRAGMENT_OFFSET( header ), IP_HEADER_DATA_LENGTH( header ));
  941.     new_header->fragment_offset_high = IP_COMPUTE_FRAGMENT_OFFSET_HIGH( offset );
  942.     new_header->fragment_offset_low = IP_COMPUTE_FRAGMENT_OFFSET_LOW( offset );
  943.     new_header->header_checksum = IP_HEADER_CHECKSUM( new_header );
  944.     ERROR_PROPAGATE( packet_set_addr( new_packet, ( const uint8_t * ) src, ( const uint8_t * ) dest, addrlen ));
  945.     return pq_insert_after( packet, new_packet );
  946. }
  947.  
  948. ip_header_ref ip_create_middle_header( packet_t packet, ip_header_ref last ){
  949.     ip_header_ref   middle;
  950.  
  951.     middle = ( ip_header_ref ) packet_suffix( packet, IP_HEADER_LENGTH( last ));
  952.     if( ! middle ) return NULL;
  953.     memcpy( middle, last, IP_HEADER_LENGTH( last ));
  954.     middle->flags |= IPFLAG_MORE_FRAGMENTS;
  955.     return middle;
  956. }
  957.  
  958. void ip_create_last_header( ip_header_ref last, ip_header_ref first ){
  959.     ip_option_ref   option;
  960.     size_t          next;
  961.     size_t          length;
  962.  
  963.     // copy first itself
  964.     memcpy( last, first, sizeof( ip_header_t ));
  965.     length = sizeof( ip_header_t );
  966.     next = sizeof( ip_header_t );
  967.     // process all ip options
  968.     while( next < first->header_length ){
  969.         option = ( ip_option_ref ) ((( uint8_t * ) first ) + next );
  970.         // skip end or noop
  971.         if(( option->type == IPOPT_END ) || ( option->type == IPOPT_NOOP )){
  972.             ++ next;
  973.         }else{
  974.             // copy if said so or skip
  975.             if( IPOPT_COPIED( option->type )){
  976.                 memcpy((( uint8_t * ) last ) + length, (( uint8_t * ) first ) + next, option->length );
  977.                 length += option->length;
  978.             }
  979.             // next option
  980.             next += option->length;
  981.         }
  982.     }
  983.     // align 4 byte boundary
  984.     if( length % 4 ){
  985.         bzero((( uint8_t * ) last ) + length, 4 - ( length % 4 ));
  986.         last->header_length = length / 4 + 1;
  987.     }else{
  988.         last->header_length = length / 4;
  989.     }
  990.     last->header_checksum = 0;
  991. }
  992.  
  993. int ip_receive_message( device_id_t device_id, packet_t packet ){
  994.     packet_t        next;
  995.  
  996.     do{
  997.         next = pq_detach( packet );
  998.         ip_process_packet( device_id, packet );
  999.         packet = next;
  1000.     }while( packet );
  1001.     return EOK;
  1002. }
  1003.  
  1004. int ip_process_packet( device_id_t device_id, packet_t packet ){
  1005.     ERROR_DECLARE;
  1006.  
  1007.     ip_header_ref   header;
  1008.     in_addr_t       dest;
  1009.     ip_route_ref    route;
  1010.     int             phone;
  1011.     struct sockaddr *   addr;
  1012.     struct sockaddr_in  addr_in;
  1013. //  struct sockaddr_in  addr_in6;
  1014.     socklen_t       addrlen;
  1015.  
  1016.     header = ( ip_header_ref ) packet_get_data( packet );
  1017.     if( ! header ){
  1018.         return ip_release_and_return( packet, ENOMEM );
  1019.     }
  1020.     // checksum
  1021.     if(( header->header_checksum ) && ( IP_HEADER_CHECKSUM( header ))){
  1022.         phone = ip_prepare_icmp_and_get_phone( 0, packet, header );
  1023.         if( phone >= 0 ){
  1024.             // checksum error ICMP
  1025.             icmp_parameter_problem_msg( phone, ICMP_PARAM_POINTER, (( size_t ) (( void * ) & header->header_checksum )) - (( size_t ) (( void * ) header )), packet );
  1026.         }
  1027.         return EINVAL;
  1028.     }
  1029.     if( header->ttl <= 1 ){
  1030.         phone = ip_prepare_icmp_and_get_phone( 0, packet, header );
  1031.         if( phone >= 0 ){
  1032.             // ttl oxceeded ICMP
  1033.             icmp_time_exceeded_msg( phone, ICMP_EXC_TTL, packet );
  1034.         }
  1035.         return EINVAL;
  1036.     }
  1037.     // process ipopt and get destination
  1038.     dest = ip_get_destination( header );
  1039.     // set the addrination address
  1040.     switch( header->version ){
  1041.         case IPVERSION:
  1042.             addrlen = sizeof( addr_in );
  1043.             bzero( & addr_in, addrlen );
  1044.             addr_in.sin_family = AF_INET;
  1045.             memcpy( & addr_in.sin_addr.s_addr, & dest, sizeof( dest ));
  1046.             addr = ( struct sockaddr * ) & addr_in;
  1047.             break;
  1048. /*      case IPv6VERSION:
  1049.             addrlen = sizeof( dest_in6 );
  1050.             bzero( & dest_in6, addrlen );
  1051.             dest_in6.sin6_family = AF_INET6;
  1052.             memcpy( & dest_in6.sin6_addr.s6_addr, );
  1053.             dest = ( struct sockaddr * ) & dest_in;
  1054.             break;
  1055. */      default:
  1056.             return EAFNOSUPPORT;
  1057.     }
  1058.     ERROR_PROPAGATE( packet_set_addr( packet, NULL, ( uint8_t * ) & addr, addrlen ));
  1059.     route = ip_find_route( dest );
  1060.     if( ! route ){
  1061.         phone = ip_prepare_icmp_and_get_phone( 0, packet, header );
  1062.         if( phone >= 0 ){
  1063.             // unreachable ICMP
  1064.             icmp_destination_unreachable_msg( phone, ICMP_HOST_UNREACH, 0, packet );
  1065.         }
  1066.         return ENOENT;
  1067.     }
  1068.     if( route->address.s_addr == dest.s_addr ){
  1069.         // local delivery
  1070.         return ip_deliver_local( device_id, packet, header, 0 );
  1071.     }else{
  1072.         // only if routing enabled
  1073.         if( route->netif->routing ){
  1074.             -- header->ttl;
  1075.             return ip_send_route( packet, route->netif, route, NULL, dest, 0 );
  1076.         }else{
  1077.             phone = ip_prepare_icmp_and_get_phone( 0, packet, header );
  1078.             if( phone >= 0 ){
  1079.                 // unreachable ICMP if no routing
  1080.                 icmp_destination_unreachable_msg( phone, ICMP_HOST_UNREACH, 0, packet );
  1081.             }
  1082.             return ENOENT;
  1083.         }
  1084.     }
  1085. }
  1086.  
  1087. int ip_received_error_msg( int ip_phone, device_id_t device_id, packet_t packet, services_t target, services_t error ){
  1088.     uint8_t *           data;
  1089.     int                 offset;
  1090.     icmp_type_t         type;
  1091.     icmp_code_t         code;
  1092.     ip_netif_ref        netif;
  1093.     measured_string_t   address;
  1094.     ip_route_ref        route;
  1095.     ip_header_ref       header;
  1096.  
  1097.     switch( error ){
  1098.         case SERVICE_ICMP:
  1099.             offset = icmp_client_process_packet( packet, & type, & code, NULL, NULL );
  1100.             if( offset < 0 ){
  1101.                 return ip_release_and_return( packet, ENOMEM );
  1102.             }
  1103.             data = packet_get_data( packet );
  1104.             header = ( ip_header_ref )( data + offset );
  1105.             // destination host unreachable?
  1106.             if(( type == ICMP_DEST_UNREACH ) && ( code == ICMP_HOST_UNREACH )){
  1107.                 fibril_rwlock_read_lock( & ip_globals.netifs_lock );
  1108.                 netif = ip_netifs_find( & ip_globals.netifs, device_id );
  1109.                 if( netif && netif->arp ){
  1110.                     route = ip_routes_get_index( & netif->routes, 0 );
  1111.                     // from the same network?
  1112.                     if( route && (( route->address.s_addr & route->netmask.s_addr ) == ( header->destination_address & route->netmask.s_addr ))){
  1113.                         // clear the ARP mapping if any
  1114.                         address.value = ( char * ) & header->destination_address;
  1115.                         address.length = CONVERT_SIZE( uint8_t, char, sizeof( header->destination_address ));
  1116.                         arp_clear_address_req( netif->arp->phone, netif->device_id, SERVICE_IP, & address );
  1117.                     }
  1118.                 }
  1119.                 fibril_rwlock_read_unlock( & ip_globals.netifs_lock );
  1120.             }
  1121.             break;
  1122.         default:
  1123.             return ip_release_and_return( packet, ENOTSUP );
  1124.     }
  1125.     return ip_deliver_local( device_id, packet, header, error );
  1126. }
  1127.  
  1128. int ip_deliver_local( device_id_t device_id, packet_t packet, ip_header_ref header, services_t error ){
  1129.     ERROR_DECLARE;
  1130.  
  1131.     ip_proto_ref    proto;
  1132.     int             phone;
  1133.     services_t      service;
  1134.     tl_received_msg_t   received_msg;
  1135.     struct sockaddr *   src;
  1136.     struct sockaddr *   dest;
  1137.     struct sockaddr_in  src_in;
  1138.     struct sockaddr_in  dest_in;
  1139. //  struct sockaddr_in  src_in6;
  1140. //  struct sockaddr_in  dest_in6;
  1141.     socklen_t       addrlen;
  1142.  
  1143.     if(( header->flags & IPFLAG_MORE_FRAGMENTS ) || IP_FRAGMENT_OFFSET( header )){
  1144.         // TODO fragmented
  1145.         return ENOTSUP;
  1146.     }else{
  1147.         switch( header->version ){
  1148.             case IPVERSION:
  1149.                 addrlen = sizeof( src_in );
  1150.                 bzero( & src_in, addrlen );
  1151.                 src_in.sin_family = AF_INET;
  1152.                 memcpy( & dest_in, & src_in, addrlen );
  1153.                 memcpy( & src_in.sin_addr.s_addr, & header->source_address, sizeof( header->source_address ));
  1154.                 memcpy( & dest_in.sin_addr.s_addr, & header->destination_address, sizeof( header->destination_address ));
  1155.                 src = ( struct sockaddr * ) & src_in;
  1156.                 dest = ( struct sockaddr * ) & dest_in;
  1157.                 break;
  1158. /*          case IPv6VERSION:
  1159.                 addrlen = sizeof( src_in6 );
  1160.                 bzero( & src_in6, addrlen );
  1161.                 src_in6.sin6_family = AF_INET6;
  1162.                 memcpy( & dest_in6, & src_in6, addrlen );
  1163.                 memcpy( & src_in6.sin6_addr.s6_addr, );
  1164.                 memcpy( & dest_in6.sin6_addr.s6_addr, );
  1165.                 src = ( struct sockaddr * ) & src_in;
  1166.                 dest = ( struct sockaddr * ) & dest_in;
  1167.                 break;
  1168. */          default:
  1169.                 return EAFNOSUPPORT;
  1170.         }
  1171.         ERROR_PROPAGATE( packet_set_addr( packet, ( uint8_t * ) src, ( uint8_t * ) dest, addrlen ));
  1172.         fibril_rwlock_read_lock( & ip_globals.protos_lock );
  1173.         proto = ip_protos_find( & ip_globals.protos, header->protocol );
  1174.         if( ! proto ){
  1175.             fibril_rwlock_read_unlock( & ip_globals.protos_lock );
  1176.             phone = ip_prepare_icmp_and_get_phone( error, packet, header );
  1177.             if( phone >= 0 ){
  1178.                 // unreachable ICMP
  1179.                 icmp_destination_unreachable_msg( phone, ICMP_PROT_UNREACH, 0, packet );
  1180.             }
  1181.             return ENOENT;
  1182.         }
  1183.         if( proto->received_msg ){
  1184.             service = proto->service;
  1185.             received_msg = proto->received_msg;
  1186.             fibril_rwlock_read_unlock( & ip_globals.protos_lock );
  1187.             ERROR_CODE = received_msg( device_id, packet, service, error );
  1188.         }else{
  1189.             ERROR_CODE = tl_received_msg( proto->phone, device_id, packet, proto->service, error );
  1190.             fibril_rwlock_read_unlock( & ip_globals.protos_lock );
  1191.         }
  1192.         return ERROR_CODE;
  1193.     }
  1194. }
  1195.  
  1196. in_addr_t ip_get_destination( ip_header_ref header ){
  1197.     in_addr_t   destination;
  1198.  
  1199.     // TODO search set ipopt route?
  1200.     destination.s_addr = header->destination_address;
  1201.     return destination;
  1202. }
  1203.  
  1204. int ip_prepare_icmp( packet_t packet, ip_header_ref header ){
  1205.     packet_t    next;
  1206.     struct sockaddr *   dest;
  1207.     struct sockaddr_in  dest_in;
  1208. //  struct sockaddr_in  dest_in6;
  1209.     socklen_t       addrlen;
  1210.  
  1211.     // detach the first packet and release the others
  1212.     next = pq_detach( packet );
  1213.     if( next ){
  1214.         pq_release( ip_globals.net_phone, packet_get_id( next ));
  1215.     }
  1216.     if( ! header ){
  1217.         if( packet_get_data_length( packet ) <= sizeof( ip_header_t )) return ENOMEM;
  1218.         // get header
  1219.         header = ( ip_header_ref ) packet_get_data( packet );
  1220.         if( ! header ) return EINVAL;
  1221.     }
  1222.     // only for the first fragment
  1223.     if( IP_FRAGMENT_OFFSET( header )) return EINVAL;
  1224.     // set the destination address
  1225.     switch( header->version ){
  1226.         case IPVERSION:
  1227.             addrlen = sizeof( dest_in );
  1228.             bzero( & dest_in, addrlen );
  1229.             dest_in.sin_family = AF_INET;
  1230.             memcpy( & dest_in.sin_addr.s_addr, & header->source_address, sizeof( header->source_address ));
  1231.             dest = ( struct sockaddr * ) & dest_in;
  1232.             break;
  1233. /*      case IPv6VERSION:
  1234.             addrlen = sizeof( dest_in6 );
  1235.             bzero( & dest_in6, addrlen );
  1236.             dest_in6.sin6_family = AF_INET6;
  1237.             memcpy( & dest_in6.sin6_addr.s6_addr, );
  1238.             dest = ( struct sockaddr * ) & dest_in;
  1239.             break;
  1240. */      default:
  1241.             return EAFNOSUPPORT;
  1242.     }
  1243.     return packet_set_addr( packet, NULL, ( uint8_t * ) dest, addrlen );
  1244. }
  1245.  
  1246. int ip_get_icmp_phone( void ){
  1247.     ip_proto_ref    proto;
  1248.     int             phone;
  1249.  
  1250.     fibril_rwlock_read_lock( & ip_globals.protos_lock );
  1251.     proto = ip_protos_find( & ip_globals.protos, IPPROTO_ICMP );
  1252.     phone = proto ? proto->phone : ENOENT;
  1253.     fibril_rwlock_read_unlock( & ip_globals.protos_lock );
  1254.     return phone;
  1255. }
  1256.  
  1257. int ip_prepare_icmp_and_get_phone( services_t error, packet_t packet, ip_header_ref header ){
  1258.     int phone;
  1259.  
  1260.     phone = ip_get_icmp_phone();
  1261.     if( error || ( phone < 0 ) || ip_prepare_icmp( packet, header )){
  1262.         return ip_release_and_return( packet, EINVAL );
  1263.     }
  1264.     return phone;
  1265. }
  1266.  
  1267. int ip_release_and_return( packet_t packet, int result ){
  1268.     pq_release( ip_globals.net_phone, packet_get_id( packet ));
  1269.     return result;
  1270. }
  1271.  
  1272. int ip_get_route_req( int ip_phone, ip_protocol_t protocol, const struct sockaddr * destination, socklen_t addrlen, device_id_t * device_id, ip_pseudo_header_ref * header, size_t * headerlen ){
  1273.     struct sockaddr_in *    address_in;
  1274. //  struct sockaddr_in6 *   address_in6;
  1275.     in_addr_t *             dest;
  1276.     in_addr_t *             src;
  1277.     ip_route_ref            route;
  1278.     ipv4_pseudo_header_ref  header_in;
  1279.  
  1280.     if( !( destination && ( addrlen > 0 ))) return EINVAL;
  1281.     if( !( device_id && header && headerlen )) return EBADMEM;
  1282.     if( addrlen < sizeof( struct sockaddr )){
  1283.         return EINVAL;
  1284.     }
  1285.     switch( destination->sa_family ){
  1286.         case AF_INET:
  1287.             if( addrlen != sizeof( struct sockaddr_in )){
  1288.                 return EINVAL;
  1289.             }
  1290.             address_in = ( struct sockaddr_in * ) destination;
  1291.             dest = & address_in->sin_addr;
  1292.             break;
  1293.         // TODO IPv6
  1294. /*      case AF_INET6:
  1295.             if( addrlen != sizeof( struct sockaddr_in6 )) return EINVAL;
  1296.             address_in6 = ( struct sockaddr_in6 * ) dest;
  1297.             address_in6.sin6_addr.s6_addr;
  1298. */      default:
  1299.             return EAFNOSUPPORT;
  1300.     }
  1301.     fibril_rwlock_read_lock( & ip_globals.lock );
  1302.     route = ip_find_route( * dest );
  1303.     if( !( route && route->netif )){
  1304.         fibril_rwlock_read_unlock( & ip_globals.lock );
  1305.         return ENOENT;
  1306.     }
  1307.     * device_id = route->netif->device_id;
  1308.     src = ip_netif_address( route->netif );
  1309.     fibril_rwlock_read_unlock( & ip_globals.lock );
  1310.     * headerlen = sizeof( * header_in );
  1311.     header_in = ( ipv4_pseudo_header_ref ) malloc( * headerlen );
  1312.     if( ! header_in ) return ENOMEM;
  1313.     bzero( header_in, * headerlen );
  1314.     header_in->destination_address = dest->s_addr;
  1315.     header_in->source_address = src->s_addr;
  1316.     header_in->protocol = protocol;
  1317.     header_in->data_length = 0;
  1318.     * header = ( ip_pseudo_header_ref ) header_in;
  1319.     return EOK;
  1320. }
  1321.  
  1322. /** @}
  1323.  */
  1324.