Subversion Repositories HelenOS

Rev

Rev 4731 | Rev 4743 | 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.         if( netif && ( ! route ) && ( ip_globals.gateway.netif == netif )){
  497.             route = & ip_globals.gateway;
  498.         }
  499.     }else{
  500.         route = ip_find_route( * dest );
  501.         netif = route ? route->netif : NULL;
  502.     }
  503.     if( !( netif && route )){
  504.         fibril_rwlock_read_unlock( & ip_globals.netifs_lock );
  505.         phone = ip_prepare_icmp_and_get_phone( error, packet, NULL );
  506.         if( phone >= 0 ){
  507.             // unreachable ICMP if no routing
  508.             icmp_destination_unreachable_msg( phone, ICMP_NET_UNREACH, 0, packet );
  509.         }
  510.         return ENOENT;
  511.     }
  512.     if( error ){
  513.         // do not send for broadcast, anycast packets or network broadcast
  514.         if(( ! dest->s_addr )
  515.         || ( !( ~ dest->s_addr ))
  516.         || ( !( ~(( dest->s_addr & ( ~ route->netmask.s_addr )) | route->netmask.s_addr )))
  517.         || ( !( dest->s_addr & ( ~ route->netmask.s_addr )))){
  518.             return ip_release_and_return( packet, EINVAL );
  519.         }
  520.     }
  521.     if( route->address.s_addr == dest->s_addr ){
  522.         // find the loopback device to deliver
  523.         dest->s_addr = IPV4_LOCALHOST_ADDRESS;
  524.         route = ip_find_route( * dest );
  525.         netif = route ? route->netif : NULL;
  526.         if( !( netif && route )){
  527.             fibril_rwlock_read_unlock( & ip_globals.netifs_lock );
  528.             phone = ip_prepare_icmp_and_get_phone( error, packet, NULL );
  529.             if( phone >= 0 ){
  530.                 // unreachable ICMP if no routing
  531.                 icmp_destination_unreachable_msg( phone, ICMP_HOST_UNREACH, 0, packet );
  532.             }
  533.             return ENOENT;
  534.         }
  535.     }
  536.     src = ip_netif_address( netif );
  537.     if( ! src ){
  538.         fibril_rwlock_read_unlock( & ip_globals.netifs_lock );
  539.         return ip_release_and_return( packet, ENOENT );
  540.     }
  541.     ERROR_CODE = ip_send_route( packet, netif, route, src, * dest, error );
  542.     fibril_rwlock_read_unlock( & ip_globals.netifs_lock );
  543.     return ERROR_CODE;
  544. }
  545.  
  546. in_addr_t * ip_netif_address( ip_netif_ref netif ){
  547.     ip_route_ref    route;
  548.  
  549.     route = ip_routes_get_index( & netif->routes, 0 );
  550.     return route ? & route->address : NULL;
  551. }
  552.  
  553. 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 ){
  554.     ERROR_DECLARE;
  555.  
  556.     measured_string_t   destination;
  557.     measured_string_ref translation;
  558.     char *              data;
  559.     int                 phone;
  560.  
  561.     // get destination hardware address
  562.     if( netif->arp && ( route->address.s_addr != dest.s_addr )){
  563.         destination.value = route->gateway.s_addr ? ( char * ) & route->gateway.s_addr : ( char * ) & dest.s_addr;
  564.         destination.length = CONVERT_SIZE( dest.s_addr, char, 1 );
  565.         if( ERROR_OCCURRED( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & destination, & translation, & data ))){
  566. //          sleep( 1 );
  567. //          ERROR_PROPAGATE( arp_translate_req( netif->arp->phone, netif->device_id, SERVICE_IP, & destination, & translation, & data ));
  568.             pq_release( ip_globals.net_phone, packet_get_id( packet ));
  569.             return ERROR_CODE;
  570.         }
  571.         if( !( translation && translation->value )){
  572.             if( translation ){
  573.                 free( translation );
  574.                 free( data );
  575.             }
  576.             phone = ip_prepare_icmp_and_get_phone( error, packet, NULL );
  577.             if( phone >= 0 ){
  578.                 // unreachable ICMP if no routing
  579.                 icmp_destination_unreachable_msg( phone, ICMP_HOST_UNREACH, 0, packet );
  580.             }
  581.             return EINVAL;
  582.         }
  583.     }else translation = NULL;
  584.     if( ERROR_OCCURRED( ip_prepare_packet( src, dest, packet, translation ))){
  585.         pq_release( ip_globals.net_phone, packet_get_id( packet ));
  586.     }else{
  587.         packet = ip_split_packet( packet, netif->prefix, netif->content, netif->suffix, netif->addr_len, error );
  588.         if( packet ){
  589.             nil_send_msg( netif->phone, netif->device_id, packet, SERVICE_IP );
  590.         }
  591.     }
  592.     if( translation ){
  593.         free( translation );
  594.         free( data );
  595.     }
  596.     return ERROR_CODE;
  597. }
  598.  
  599. int ip_prepare_packet( in_addr_t * source, in_addr_t dest, packet_t packet, measured_string_ref destination ){
  600.     ERROR_DECLARE;
  601.  
  602.     size_t              length;
  603.     ip_header_ref       header;
  604.     ip_header_ref       last_header;
  605.     ip_header_ref       middle_header;
  606.     packet_t            next;
  607.  
  608.     length = packet_get_data_length( packet );
  609.     if(( length < sizeof( ip_header_t )) || ( length > IP_MAX_CONTENT )) return EINVAL;
  610.     header = ( ip_header_ref ) packet_get_data( packet );
  611.     if( destination ){
  612.         ERROR_PROPAGATE( packet_set_addr( packet, NULL, ( uint8_t * ) destination->value, CONVERT_SIZE( char, uint8_t, destination->length )));
  613.     }else{
  614.         ERROR_PROPAGATE( packet_set_addr( packet, NULL, NULL, 0 ));
  615.     }
  616.     header->version = IPV4;
  617.     header->fragment_offset_high = 0;
  618.     header->fragment_offset_low = 0;
  619.     header->header_checksum = 0;
  620.     if( source ) header->source_address = source->s_addr;
  621.     header->destination_address = dest.s_addr;
  622.     fibril_rwlock_write_lock( & ip_globals.lock );
  623.     ++ ip_globals.packet_counter;
  624.     header->identification = htons( ip_globals.packet_counter );
  625.     fibril_rwlock_write_unlock( & ip_globals.lock );
  626. //  length = packet_get_data_length( packet );
  627.     if( pq_next( packet )){
  628.         last_header = ( ip_header_ref ) malloc( IP_HEADER_LENGTH( header ));
  629.         if( ! last_header ) return ENOMEM;
  630.         ip_create_last_header( last_header, header );
  631.         next = pq_next( packet );
  632.         while( pq_next( next )){
  633.             middle_header = ( ip_header_ref ) packet_prefix( next, IP_HEADER_LENGTH( last_header ));
  634.             if( ! middle_header ) return ENOMEM;
  635.             memcpy( middle_header, last_header, IP_HEADER_LENGTH( last_header ));
  636.             header->flags |= IPFLAG_MORE_FRAGMENTS;
  637.             middle_header->total_length = htons( packet_get_data_length( next ));
  638.             middle_header->fragment_offset_high = IP_COMPUTE_FRAGMENT_OFFSET_HIGH( length );
  639.             middle_header->fragment_offset_low = IP_COMPUTE_FRAGMENT_OFFSET_LOW( length );
  640.             middle_header->header_checksum = IP_HEADER_CHECKSUM( middle_header );
  641.             if( destination ){
  642.                 ERROR_PROPAGATE( packet_set_addr( next, NULL, ( uint8_t * ) destination->value, CONVERT_SIZE( char, uint8_t, destination->length )));
  643.             }
  644.             length += packet_get_data_length( next );
  645.             next = pq_next( next );
  646.         }
  647.         middle_header = ( ip_header_ref ) packet_prefix( next, IP_HEADER_LENGTH( last_header ));
  648.         if( ! middle_header ) return ENOMEM;
  649.         memcpy( middle_header, last_header, IP_HEADER_LENGTH( last_header ));
  650.         middle_header->total_length = htons( packet_get_data_length( next ));
  651.         middle_header->fragment_offset_high = IP_COMPUTE_FRAGMENT_OFFSET_HIGH( length );
  652.         middle_header->fragment_offset_low = IP_COMPUTE_FRAGMENT_OFFSET_LOW( length );
  653.         middle_header->header_checksum = IP_HEADER_CHECKSUM( middle_header );
  654.         if( destination ){
  655.             ERROR_PROPAGATE( packet_set_addr( next, NULL, ( uint8_t * ) destination->value, CONVERT_SIZE( char, uint8_t, destination->length )));
  656.         }
  657.         length += packet_get_data_length( next );
  658.         free( last_header );
  659.         header->flags |= IPFLAG_MORE_FRAGMENTS;
  660.     }
  661.     header->total_length = htons( length );
  662.     // unnecessary for all protocols
  663.     header->header_checksum = IP_HEADER_CHECKSUM( header );
  664.     return EOK;
  665. }
  666.  
  667. int ip_message( ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count ){
  668.     ERROR_DECLARE;
  669.  
  670.     packet_t                packet;
  671.     struct sockaddr *       addr;
  672.     size_t                  addrlen;
  673.     ip_pseudo_header_ref    header;
  674.     size_t                  headerlen;
  675.  
  676.     * answer_count = 0;
  677.     switch( IPC_GET_METHOD( * call )){
  678.         case IPC_M_PHONE_HUNGUP:
  679.             return EOK;
  680.         case NET_IL_DEVICE:
  681.             return ip_device_req( 0, IPC_GET_DEVICE( call ), IPC_GET_SERVICE( call ));
  682.         case IPC_M_CONNECT_TO_ME:
  683.             return ip_register( IL_GET_PROTO( call ), IL_GET_SERVICE( call ), IPC_GET_PHONE( call ), NULL );
  684.         case NET_IL_SEND:
  685.             ERROR_PROPAGATE( packet_translate( ip_globals.net_phone, & packet, IPC_GET_PACKET( call )));
  686.             return ip_send_msg( 0, IPC_GET_DEVICE( call ), packet, 0, IPC_GET_ERROR( call ));
  687.         case NET_IL_DEVICE_STATE:
  688.             return ip_device_state_message( IPC_GET_DEVICE( call ), IPC_GET_STATE( call ));
  689.         case NET_IL_RECEIVED:
  690.             ERROR_PROPAGATE( packet_translate( ip_globals.net_phone, & packet, IPC_GET_PACKET( call )));
  691.             return ip_receive_message( IPC_GET_DEVICE( call ), packet );
  692.         case NET_IP_RECEIVED_ERROR:
  693.             ERROR_PROPAGATE( packet_translate( ip_globals.net_phone, & packet, IPC_GET_PACKET( call )));
  694.             return ip_received_error_msg( 0, IPC_GET_DEVICE( call ), packet, IPC_GET_TARGET( call ), IPC_GET_ERROR( call ));
  695.         case NET_IP_ADD_ROUTE:
  696.             return ip_add_route_req( 0, IPC_GET_DEVICE( call ), IP_GET_ADDRESS( call ), IP_GET_NETMASK( call ), IP_GET_GATEWAY( call ));
  697.         case NET_IP_SET_GATEWAY:
  698.             return ip_set_gateway_req( 0, IPC_GET_DEVICE( call ), IP_GET_GATEWAY( call ));
  699.         case NET_IP_GET_ROUTE:
  700.             ERROR_PROPAGATE( data_receive(( void ** ) & addr, & addrlen ));
  701.             ERROR_PROPAGATE( ip_get_route_req( 0, IP_GET_PROTOCOL( call ), addr, ( socklen_t ) addrlen, IPC_SET_DEVICE( answer ), & header, & headerlen ));
  702.             * IP_SET_HEADERLEN( answer ) = headerlen;
  703.             * answer_count = 2;
  704.             if( ! ERROR_OCCURRED( data_reply( & headerlen, sizeof( headerlen )))){
  705.                 ERROR_CODE = data_reply( header, headerlen );
  706.             }
  707.             free( header );
  708.             return ERROR_CODE;
  709.         case NET_IL_PACKET_SPACE:
  710.             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 )));
  711.             * answer_count = 3;
  712.             return EOK;
  713.         case NET_IL_MTU_CHANGED:
  714.             return ip_mtu_changed_message( IPC_GET_DEVICE( call ), IPC_GET_MTU( call ));
  715.     }
  716.     return ENOTSUP;
  717. }
  718.  
  719. 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 ){
  720.     ip_netif_ref    netif;
  721.     int             index;
  722.  
  723.     if( !( addr_len && prefix && content && suffix )) return EBADMEM;
  724.     * content = IP_MAX_CONTENT - IP_PREFIX;
  725.     fibril_rwlock_read_lock( & ip_globals.netifs_lock );
  726.     if( device_id < 0 ){
  727.         * addr_len = IP_ADDR;
  728.         * prefix = 0;
  729.         * suffix = 0;
  730.         for( index = ip_netifs_count( & ip_globals.netifs ) - 1; index >= 0; -- index ){
  731.             netif = ip_netifs_get_index( & ip_globals.netifs, index );
  732.             if( netif ){
  733.                 if( netif->addr_len > * addr_len ) * addr_len = netif->addr_len;
  734.                 if( netif->prefix > * prefix ) * prefix = netif->prefix;
  735.                 if( netif->suffix > * suffix ) * suffix = netif->suffix;
  736.             }
  737.         }
  738.         * prefix = * prefix + IP_PREFIX;
  739.         * suffix = * suffix + IP_SUFFIX;
  740.     }else{
  741.         netif = ip_netifs_find( & ip_globals.netifs, device_id );
  742.         if( ! netif ){
  743.             fibril_rwlock_read_unlock( & ip_globals.netifs_lock );
  744.             return ENOENT;
  745.         }
  746.         * addr_len = ( netif->addr_len > IP_ADDR ) ? netif->addr_len : IP_ADDR;
  747.         * prefix = netif->prefix + IP_PREFIX;
  748.         * suffix = netif->suffix + IP_SUFFIX;
  749.     }
  750.     fibril_rwlock_read_unlock( & ip_globals.netifs_lock );
  751.     return EOK;
  752. }
  753.  
  754. 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 ){
  755.     ip_route_ref    route;
  756.     ip_netif_ref    netif;
  757.     int             index;
  758.  
  759.     fibril_rwlock_write_lock( & ip_globals.netifs_lock );
  760.     netif = ip_netifs_find( & ip_globals.netifs, device_id );
  761.     if( ! netif ){
  762.         fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
  763.         return ENOENT;
  764.     }
  765.     route = ( ip_route_ref ) malloc( sizeof( ip_route_t ));
  766.     if( ! route ){
  767.         fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
  768.         return ENOMEM;
  769.     }
  770.     route->address.s_addr = address.s_addr;
  771.     route->netmask.s_addr = netmask.s_addr;
  772.     route->gateway.s_addr = gateway.s_addr;
  773.     route->netif = netif;
  774.     index = ip_routes_add( & netif->routes, route );
  775.     if( index < 0 ) free( route );
  776.     fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
  777.     return index;
  778. }
  779.  
  780. ip_route_ref ip_find_route( in_addr_t destination ){
  781.     int             index;
  782.     ip_route_ref    route;
  783.     ip_netif_ref    netif;
  784.  
  785.     // start with the last netif - the newest one
  786.     index = ip_netifs_count( & ip_globals.netifs ) - 1;
  787.     while( index >= 0 ){
  788.         netif = ip_netifs_get_index( & ip_globals.netifs, index );
  789.         if( netif && ( netif->state == NETIF_ACTIVE )){
  790.             route = ip_netif_find_route( netif, destination );
  791.             if( route ) return route;
  792.         }
  793.         -- index;
  794.     }
  795.     return & ip_globals.gateway;
  796. }
  797.  
  798. ip_route_ref ip_netif_find_route( ip_netif_ref netif, in_addr_t destination ){
  799.     int             index;
  800.     ip_route_ref    route;
  801.  
  802.     if( netif ){
  803.         // start with the first one - the direct route
  804.         for( index = 0; index < ip_routes_count( & netif->routes ); ++ index ){
  805.             route = ip_routes_get_index( & netif->routes, index );
  806.             if( route && (( route->address.s_addr & route->netmask.s_addr ) == ( destination.s_addr & route->netmask.s_addr ))){
  807.                 return route;
  808.             }
  809.         }
  810.     }
  811.     return NULL;
  812. }
  813.  
  814. int ip_set_gateway_req( int ip_phone, device_id_t device_id, in_addr_t gateway ){
  815.     ip_netif_ref    netif;
  816.  
  817.     fibril_rwlock_write_lock( & ip_globals.netifs_lock );
  818.     netif = ip_netifs_find( & ip_globals.netifs, device_id );
  819.     if( ! netif ){
  820.         fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
  821.         return ENOENT;
  822.     }
  823.     ip_globals.gateway.address.s_addr = 0;
  824.     ip_globals.gateway.netmask.s_addr = 0;
  825.     ip_globals.gateway.gateway.s_addr = gateway.s_addr;
  826.     ip_globals.gateway.netif = netif;
  827.     fibril_rwlock_write_unlock( & ip_globals.netifs_lock );
  828.     return EOK;
  829. }
  830.  
  831. packet_t ip_split_packet( packet_t packet, size_t prefix, size_t content, size_t suffix, socklen_t addr_len, services_t error ){
  832.     size_t          length;
  833.     packet_t        next;
  834.     packet_t        new_packet;
  835.     int             result;
  836.     int             phone;
  837.  
  838.     next = packet;
  839.     // check all packets
  840.     while( next ){
  841.         length = packet_get_data_length( next );
  842.         // too long?
  843.         if( length > content ){
  844.             result = ip_fragment_packet( next, content, prefix, suffix, addr_len );
  845.             if( result != EOK ){
  846.                 new_packet = pq_detach( next );
  847.                 if( next == packet ){
  848.                     // the new first packet of the queue
  849.                     packet = new_packet;
  850.                 }
  851.                 // fragmentation needed?
  852.                 if( result == EPERM ){
  853.                     phone = ip_prepare_icmp_and_get_phone( error, next, NULL );
  854.                     if( phone >= 0 ){
  855.                         // fragmentation necessary ICMP
  856.                         icmp_destination_unreachable_msg( phone, ICMP_FRAG_NEEDED, content, next );
  857.                     }
  858.                 }else{
  859.                     pq_release( ip_globals.net_phone, packet_get_id( next ));
  860.                 }
  861.                 next = new_packet;
  862.                 continue;
  863.             }
  864.         }
  865.         next = pq_next( next );
  866.     }
  867.     return packet;
  868. }
  869.  
  870. int ip_fragment_packet( packet_t packet, size_t length, size_t prefix, size_t suffix, socklen_t addr_len ){
  871.     ERROR_DECLARE;
  872.  
  873.     packet_t        new_packet;
  874.     ip_header_ref   header;
  875.     ip_header_ref   middle_header;
  876.     ip_header_ref   last_header;
  877.     struct sockaddr *       src;
  878.     struct sockaddr *       dest;
  879.     socklen_t       addrlen;
  880.     int             result;
  881.  
  882.     result = packet_get_addr( packet, ( uint8_t ** ) & src, ( uint8_t ** ) & dest );
  883.     if( result <= 0 ) return EINVAL;
  884.     addrlen = ( socklen_t ) result;
  885.     if( packet_get_data_length( packet ) <= sizeof( ip_header_t )) return ENOMEM;
  886.     // get header
  887.     header = ( ip_header_ref ) packet_get_data( packet );
  888.     if( ! header ) return EINVAL;
  889.     // fragmentation forbidden?
  890.     if( header->flags & IPFLAG_DONT_FRAGMENT ){
  891.         return EPERM;
  892.     }
  893.     // create the last fragment
  894.     new_packet = packet_get_4( ip_globals.net_phone, prefix, length, suffix, (( addrlen > addr_len ) ? addrlen : addr_len ));
  895.     if( ! new_packet ) return ENOMEM;
  896.     // allocate as much as originally
  897.     last_header = ( ip_header_ref ) packet_suffix( new_packet, IP_HEADER_LENGTH( header ));
  898.     if( ! last_header ){
  899.         return ip_release_and_return( packet, ENOMEM );
  900.     }
  901.     ip_create_last_header( last_header, header );
  902.     // trim the unused space
  903.     if( ERROR_OCCURRED( packet_trim( new_packet, 0, IP_HEADER_LENGTH( header ) - IP_HEADER_LENGTH( last_header )))){
  904.         return ip_release_and_return( packet, ERROR_CODE );
  905.     }
  906.     // biggest multiple of 8 lower than content
  907.     // TODO even fragmentation?
  908.     length = length & ( ~ 0x7 );// ( content / 8 ) * 8
  909.     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 ))){
  910.         return ip_release_and_return( packet, ERROR_CODE );
  911.     }
  912.     // mark the first as fragmented
  913.     header->flags |= IPFLAG_MORE_FRAGMENTS;
  914.     // create middle framgents
  915.     while( IP_TOTAL_LENGTH( header ) > length ){
  916.         new_packet = packet_get_4( ip_globals.net_phone, prefix, length, suffix, (( addrlen >= addr_len ) ? addrlen : addr_len ));
  917.         if( ! new_packet ) return ENOMEM;
  918.         middle_header = ip_create_middle_header( new_packet, last_header );
  919.         if( ! middle_header ){
  920.             return ip_release_and_return( packet, ENOMEM );
  921.         }
  922.         if( ERROR_OCCURRED( ip_fragment_packet_data( packet, new_packet, header, middle_header, ( length - IP_HEADER_LENGTH( middle_header )) & ( ~ 0x7 ), src, dest, addrlen ))){
  923.             return ip_release_and_return( packet, ERROR_CODE );
  924.         }
  925.     }
  926.     // finish the first fragment
  927.     header->header_checksum = IP_HEADER_CHECKSUM( header );
  928.     return EOK;
  929. }
  930.  
  931. 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 ){
  932.     ERROR_DECLARE;
  933.  
  934.     void *          data;
  935.     size_t          offset;
  936.  
  937.     data = packet_suffix( new_packet, length );
  938.     if( ! data ) return ENOMEM;
  939.     memcpy( data, (( void * ) header ) + IP_TOTAL_LENGTH( header ) - length, length );
  940.     ERROR_PROPAGATE( packet_trim( packet, 0, length ));
  941.     header->total_length = htons( IP_TOTAL_LENGTH( header ) - length );
  942.     new_header->total_length = htons( IP_HEADER_LENGTH( new_header ) + length );
  943.     offset = IP_FRAGMENT_OFFSET( header ) + IP_HEADER_DATA_LENGTH( header );
  944.     new_header->fragment_offset_high = IP_COMPUTE_FRAGMENT_OFFSET_HIGH( offset );
  945.     new_header->fragment_offset_low = IP_COMPUTE_FRAGMENT_OFFSET_LOW( offset );
  946.     new_header->header_checksum = IP_HEADER_CHECKSUM( new_header );
  947.     ERROR_PROPAGATE( packet_set_addr( new_packet, ( const uint8_t * ) src, ( const uint8_t * ) dest, addrlen ));
  948.     return pq_insert_after( packet, new_packet );
  949. }
  950.  
  951. ip_header_ref ip_create_middle_header( packet_t packet, ip_header_ref last ){
  952.     ip_header_ref   middle;
  953.  
  954.     middle = ( ip_header_ref ) packet_suffix( packet, IP_HEADER_LENGTH( last ));
  955.     if( ! middle ) return NULL;
  956.     memcpy( middle, last, IP_HEADER_LENGTH( last ));
  957.     middle->flags |= IPFLAG_MORE_FRAGMENTS;
  958.     return middle;
  959. }
  960.  
  961. void ip_create_last_header( ip_header_ref last, ip_header_ref first ){
  962.     ip_option_ref   option;
  963.     size_t          next;
  964.     size_t          length;
  965.  
  966.     // copy first itself
  967.     memcpy( last, first, sizeof( ip_header_t ));
  968.     length = sizeof( ip_header_t );
  969.     next = sizeof( ip_header_t );
  970.     // process all ip options
  971.     while( next < first->header_length ){
  972.         option = ( ip_option_ref ) ((( uint8_t * ) first ) + next );
  973.         // skip end or noop
  974.         if(( option->type == IPOPT_END ) || ( option->type == IPOPT_NOOP )){
  975.             ++ next;
  976.         }else{
  977.             // copy if said so or skip
  978.             if( IPOPT_COPIED( option->type )){
  979.                 memcpy((( uint8_t * ) last ) + length, (( uint8_t * ) first ) + next, option->length );
  980.                 length += option->length;
  981.             }
  982.             // next option
  983.             next += option->length;
  984.         }
  985.     }
  986.     // align 4 byte boundary
  987.     if( length % 4 ){
  988.         bzero((( uint8_t * ) last ) + length, 4 - ( length % 4 ));
  989.         last->header_length = length / 4 + 1;
  990.     }else{
  991.         last->header_length = length / 4;
  992.     }
  993.     last->header_checksum = 0;
  994. }
  995.  
  996. int ip_receive_message( device_id_t device_id, packet_t packet ){
  997.     packet_t        next;
  998.  
  999.     do{
  1000.         next = pq_detach( packet );
  1001.         ip_process_packet( device_id, packet );
  1002.         packet = next;
  1003.     }while( packet );
  1004.     return EOK;
  1005. }
  1006.  
  1007. int ip_process_packet( device_id_t device_id, packet_t packet ){
  1008.     ERROR_DECLARE;
  1009.  
  1010.     ip_header_ref   header;
  1011.     in_addr_t       dest;
  1012.     ip_route_ref    route;
  1013.     int             phone;
  1014.     struct sockaddr *   addr;
  1015.     struct sockaddr_in  addr_in;
  1016. //  struct sockaddr_in  addr_in6;
  1017.     socklen_t       addrlen;
  1018.  
  1019.     header = ( ip_header_ref ) packet_get_data( packet );
  1020.     if( ! header ){
  1021.         return ip_release_and_return( packet, ENOMEM );
  1022.     }
  1023.     // checksum
  1024.     if(( header->header_checksum ) && ( IP_HEADER_CHECKSUM( header ))){
  1025.         phone = ip_prepare_icmp_and_get_phone( 0, packet, header );
  1026.         if( phone >= 0 ){
  1027.             // checksum error ICMP
  1028.             icmp_parameter_problem_msg( phone, ICMP_PARAM_POINTER, (( size_t ) (( void * ) & header->header_checksum )) - (( size_t ) (( void * ) header )), packet );
  1029.         }
  1030.         return EINVAL;
  1031.     }
  1032.     if( header->ttl <= 1 ){
  1033.         phone = ip_prepare_icmp_and_get_phone( 0, packet, header );
  1034.         if( phone >= 0 ){
  1035.             // ttl oxceeded ICMP
  1036.             icmp_time_exceeded_msg( phone, ICMP_EXC_TTL, packet );
  1037.         }
  1038.         return EINVAL;
  1039.     }
  1040.     // process ipopt and get destination
  1041.     dest = ip_get_destination( header );
  1042.     // set the addrination address
  1043.     switch( header->version ){
  1044.         case IPVERSION:
  1045.             addrlen = sizeof( addr_in );
  1046.             bzero( & addr_in, addrlen );
  1047.             addr_in.sin_family = AF_INET;
  1048.             memcpy( & addr_in.sin_addr.s_addr, & dest, sizeof( dest ));
  1049.             addr = ( struct sockaddr * ) & addr_in;
  1050.             break;
  1051. /*      case IPv6VERSION:
  1052.             addrlen = sizeof( dest_in6 );
  1053.             bzero( & dest_in6, addrlen );
  1054.             dest_in6.sin6_family = AF_INET6;
  1055.             memcpy( & dest_in6.sin6_addr.s6_addr, );
  1056.             dest = ( struct sockaddr * ) & dest_in;
  1057.             break;
  1058. */      default:
  1059.             return EAFNOSUPPORT;
  1060.     }
  1061.     ERROR_PROPAGATE( packet_set_addr( packet, NULL, ( uint8_t * ) & addr, addrlen ));
  1062.     route = ip_find_route( dest );
  1063.     if( ! route ){
  1064.         phone = ip_prepare_icmp_and_get_phone( 0, packet, header );
  1065.         if( phone >= 0 ){
  1066.             // unreachable ICMP
  1067.             icmp_destination_unreachable_msg( phone, ICMP_HOST_UNREACH, 0, packet );
  1068.         }
  1069.         return ENOENT;
  1070.     }
  1071.     if( route->address.s_addr == dest.s_addr ){
  1072.         // local delivery
  1073.         return ip_deliver_local( device_id, packet, header, 0 );
  1074.     }else{
  1075.         // only if routing enabled
  1076.         if( route->netif->routing ){
  1077.             -- header->ttl;
  1078.             return ip_send_route( packet, route->netif, route, NULL, dest, 0 );
  1079.         }else{
  1080.             phone = ip_prepare_icmp_and_get_phone( 0, packet, header );
  1081.             if( phone >= 0 ){
  1082.                 // unreachable ICMP if no routing
  1083.                 icmp_destination_unreachable_msg( phone, ICMP_HOST_UNREACH, 0, packet );
  1084.             }
  1085.             return ENOENT;
  1086.         }
  1087.     }
  1088. }
  1089.  
  1090. int ip_received_error_msg( int ip_phone, device_id_t device_id, packet_t packet, services_t target, services_t error ){
  1091.     uint8_t *           data;
  1092.     int                 offset;
  1093.     icmp_type_t         type;
  1094.     icmp_code_t         code;
  1095.     ip_netif_ref        netif;
  1096.     measured_string_t   address;
  1097.     ip_route_ref        route;
  1098.     ip_header_ref       header;
  1099.  
  1100.     switch( error ){
  1101.         case SERVICE_ICMP:
  1102.             offset = icmp_client_process_packet( packet, & type, & code, NULL, NULL );
  1103.             if( offset < 0 ){
  1104.                 return ip_release_and_return( packet, ENOMEM );
  1105.             }
  1106.             data = packet_get_data( packet );
  1107.             header = ( ip_header_ref )( data + offset );
  1108.             // destination host unreachable?
  1109.             if(( type == ICMP_DEST_UNREACH ) && ( code == ICMP_HOST_UNREACH )){
  1110.                 fibril_rwlock_read_lock( & ip_globals.netifs_lock );
  1111.                 netif = ip_netifs_find( & ip_globals.netifs, device_id );
  1112.                 if( netif && netif->arp ){
  1113.                     route = ip_routes_get_index( & netif->routes, 0 );
  1114.                     // from the same network?
  1115.                     if( route && (( route->address.s_addr & route->netmask.s_addr ) == ( header->destination_address & route->netmask.s_addr ))){
  1116.                         // clear the ARP mapping if any
  1117.                         address.value = ( char * ) & header->destination_address;
  1118.                         address.length = CONVERT_SIZE( uint8_t, char, sizeof( header->destination_address ));
  1119.                         arp_clear_address_req( netif->arp->phone, netif->device_id, SERVICE_IP, & address );
  1120.                     }
  1121.                 }
  1122.                 fibril_rwlock_read_unlock( & ip_globals.netifs_lock );
  1123.             }
  1124.             break;
  1125.         default:
  1126.             return ip_release_and_return( packet, ENOTSUP );
  1127.     }
  1128.     return ip_deliver_local( device_id, packet, header, error );
  1129. }
  1130.  
  1131. int ip_deliver_local( device_id_t device_id, packet_t packet, ip_header_ref header, services_t error ){
  1132.     ERROR_DECLARE;
  1133.  
  1134.     ip_proto_ref    proto;
  1135.     int             phone;
  1136.     services_t      service;
  1137.     tl_received_msg_t   received_msg;
  1138.     struct sockaddr *   src;
  1139.     struct sockaddr *   dest;
  1140.     struct sockaddr_in  src_in;
  1141.     struct sockaddr_in  dest_in;
  1142. //  struct sockaddr_in  src_in6;
  1143. //  struct sockaddr_in  dest_in6;
  1144.     socklen_t       addrlen;
  1145.  
  1146.     if(( header->flags & IPFLAG_MORE_FRAGMENTS ) || IP_FRAGMENT_OFFSET( header )){
  1147.         // TODO fragmented
  1148.         return ENOTSUP;
  1149.     }else{
  1150.         switch( header->version ){
  1151.             case IPVERSION:
  1152.                 addrlen = sizeof( src_in );
  1153.                 bzero( & src_in, addrlen );
  1154.                 src_in.sin_family = AF_INET;
  1155.                 memcpy( & dest_in, & src_in, addrlen );
  1156.                 memcpy( & src_in.sin_addr.s_addr, & header->source_address, sizeof( header->source_address ));
  1157.                 memcpy( & dest_in.sin_addr.s_addr, & header->destination_address, sizeof( header->destination_address ));
  1158.                 src = ( struct sockaddr * ) & src_in;
  1159.                 dest = ( struct sockaddr * ) & dest_in;
  1160.                 break;
  1161. /*          case IPv6VERSION:
  1162.                 addrlen = sizeof( src_in6 );
  1163.                 bzero( & src_in6, addrlen );
  1164.                 src_in6.sin6_family = AF_INET6;
  1165.                 memcpy( & dest_in6, & src_in6, addrlen );
  1166.                 memcpy( & src_in6.sin6_addr.s6_addr, );
  1167.                 memcpy( & dest_in6.sin6_addr.s6_addr, );
  1168.                 src = ( struct sockaddr * ) & src_in;
  1169.                 dest = ( struct sockaddr * ) & dest_in;
  1170.                 break;
  1171. */          default:
  1172.                 return ip_release_and_return( packet, EAFNOSUPPORT );
  1173.         }
  1174.         if( ERROR_OCCURRED( packet_set_addr( packet, ( uint8_t * ) src, ( uint8_t * ) dest, addrlen ))){
  1175.             return ip_release_and_return( packet, ERROR_CODE );
  1176.         }
  1177.         // trim padding if present
  1178.         if(( ! error ) && ( IP_TOTAL_LENGTH( header ) < packet_get_data_length( packet ))){
  1179.             if( ERROR_OCCURRED( packet_trim( packet, 0, packet_get_data_length( packet ) - IP_TOTAL_LENGTH( header )))){
  1180.                 return ip_release_and_return( packet, ERROR_CODE );
  1181.             }
  1182.         }
  1183.         fibril_rwlock_read_lock( & ip_globals.protos_lock );
  1184.         proto = ip_protos_find( & ip_globals.protos, header->protocol );
  1185.         if( ! proto ){
  1186.             fibril_rwlock_read_unlock( & ip_globals.protos_lock );
  1187.             phone = ip_prepare_icmp_and_get_phone( error, packet, header );
  1188.             if( phone >= 0 ){
  1189.                 // unreachable ICMP
  1190.                 icmp_destination_unreachable_msg( phone, ICMP_PROT_UNREACH, 0, packet );
  1191.             }
  1192.             return ENOENT;
  1193.         }
  1194.         if( proto->received_msg ){
  1195.             service = proto->service;
  1196.             received_msg = proto->received_msg;
  1197.             fibril_rwlock_read_unlock( & ip_globals.protos_lock );
  1198.             ERROR_CODE = received_msg( device_id, packet, service, error );
  1199.         }else{
  1200.             ERROR_CODE = tl_received_msg( proto->phone, device_id, packet, proto->service, error );
  1201.             fibril_rwlock_read_unlock( & ip_globals.protos_lock );
  1202.         }
  1203.         return ERROR_CODE;
  1204.     }
  1205. }
  1206.  
  1207. in_addr_t ip_get_destination( ip_header_ref header ){
  1208.     in_addr_t   destination;
  1209.  
  1210.     // TODO search set ipopt route?
  1211.     destination.s_addr = header->destination_address;
  1212.     return destination;
  1213. }
  1214.  
  1215. int ip_prepare_icmp( packet_t packet, ip_header_ref header ){
  1216.     packet_t    next;
  1217.     struct sockaddr *   dest;
  1218.     struct sockaddr_in  dest_in;
  1219. //  struct sockaddr_in  dest_in6;
  1220.     socklen_t       addrlen;
  1221.  
  1222.     // detach the first packet and release the others
  1223.     next = pq_detach( packet );
  1224.     if( next ){
  1225.         pq_release( ip_globals.net_phone, packet_get_id( next ));
  1226.     }
  1227.     if( ! header ){
  1228.         if( packet_get_data_length( packet ) <= sizeof( ip_header_t )) return ENOMEM;
  1229.         // get header
  1230.         header = ( ip_header_ref ) packet_get_data( packet );
  1231.         if( ! header ) return EINVAL;
  1232.     }
  1233.     // only for the first fragment
  1234.     if( IP_FRAGMENT_OFFSET( header )) return EINVAL;
  1235.     // set the destination address
  1236.     switch( header->version ){
  1237.         case IPVERSION:
  1238.             addrlen = sizeof( dest_in );
  1239.             bzero( & dest_in, addrlen );
  1240.             dest_in.sin_family = AF_INET;
  1241.             memcpy( & dest_in.sin_addr.s_addr, & header->source_address, sizeof( header->source_address ));
  1242.             dest = ( struct sockaddr * ) & dest_in;
  1243.             break;
  1244. /*      case IPv6VERSION:
  1245.             addrlen = sizeof( dest_in6 );
  1246.             bzero( & dest_in6, addrlen );
  1247.             dest_in6.sin6_family = AF_INET6;
  1248.             memcpy( & dest_in6.sin6_addr.s6_addr, );
  1249.             dest = ( struct sockaddr * ) & dest_in;
  1250.             break;
  1251. */      default:
  1252.             return EAFNOSUPPORT;
  1253.     }
  1254.     return packet_set_addr( packet, NULL, ( uint8_t * ) dest, addrlen );
  1255. }
  1256.  
  1257. int ip_get_icmp_phone( void ){
  1258.     ip_proto_ref    proto;
  1259.     int             phone;
  1260.  
  1261.     fibril_rwlock_read_lock( & ip_globals.protos_lock );
  1262.     proto = ip_protos_find( & ip_globals.protos, IPPROTO_ICMP );
  1263.     phone = proto ? proto->phone : ENOENT;
  1264.     fibril_rwlock_read_unlock( & ip_globals.protos_lock );
  1265.     return phone;
  1266. }
  1267.  
  1268. int ip_prepare_icmp_and_get_phone( services_t error, packet_t packet, ip_header_ref header ){
  1269.     int phone;
  1270.  
  1271.     phone = ip_get_icmp_phone();
  1272.     if( error || ( phone < 0 ) || ip_prepare_icmp( packet, header )){
  1273.         return ip_release_and_return( packet, EINVAL );
  1274.     }
  1275.     return phone;
  1276. }
  1277.  
  1278. int ip_release_and_return( packet_t packet, int result ){
  1279.     pq_release( ip_globals.net_phone, packet_get_id( packet ));
  1280.     return result;
  1281. }
  1282.  
  1283. 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 ){
  1284.     struct sockaddr_in *    address_in;
  1285. //  struct sockaddr_in6 *   address_in6;
  1286.     in_addr_t *             dest;
  1287.     in_addr_t *             src;
  1288.     ip_route_ref            route;
  1289.     ipv4_pseudo_header_ref  header_in;
  1290.  
  1291.     if( !( destination && ( addrlen > 0 ))) return EINVAL;
  1292.     if( !( device_id && header && headerlen )) return EBADMEM;
  1293.     if( addrlen < sizeof( struct sockaddr )){
  1294.         return EINVAL;
  1295.     }
  1296.     switch( destination->sa_family ){
  1297.         case AF_INET:
  1298.             if( addrlen != sizeof( struct sockaddr_in )){
  1299.                 return EINVAL;
  1300.             }
  1301.             address_in = ( struct sockaddr_in * ) destination;
  1302.             dest = & address_in->sin_addr;
  1303.             break;
  1304.         // TODO IPv6
  1305. /*      case AF_INET6:
  1306.             if( addrlen != sizeof( struct sockaddr_in6 )) return EINVAL;
  1307.             address_in6 = ( struct sockaddr_in6 * ) dest;
  1308.             address_in6.sin6_addr.s6_addr;
  1309. */      default:
  1310.             return EAFNOSUPPORT;
  1311.     }
  1312.     fibril_rwlock_read_lock( & ip_globals.lock );
  1313.     route = ip_find_route( * dest );
  1314.     if( !( route && route->netif )){
  1315.         fibril_rwlock_read_unlock( & ip_globals.lock );
  1316.         return ENOENT;
  1317.     }
  1318.     * device_id = route->netif->device_id;
  1319.     src = ip_netif_address( route->netif );
  1320.     fibril_rwlock_read_unlock( & ip_globals.lock );
  1321.     * headerlen = sizeof( * header_in );
  1322.     header_in = ( ipv4_pseudo_header_ref ) malloc( * headerlen );
  1323.     if( ! header_in ) return ENOMEM;
  1324.     bzero( header_in, * headerlen );
  1325.     header_in->destination_address = dest->s_addr;
  1326.     header_in->source_address = src->s_addr;
  1327.     header_in->protocol = protocol;
  1328.     header_in->data_length = 0;
  1329.     * header = ( ip_pseudo_header_ref ) header_in;
  1330.     return EOK;
  1331. }
  1332.  
  1333. /** @}
  1334.  */
  1335.