Subversion Repositories HelenOS

Rev

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