Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/net/il/ip/ip.c

    r02314f8 rc62ae1d6  
    2828
    2929/** @addtogroup ip
    30  * @{
     30 *  @{
    3131 */
    3232
    3333/** @file
    34  * IP module implementation.
    35  * @see arp.h
    36  */
    37 
    38 #include "ip.h"
    39 #include "ip_module.h"
     34 *  IP module implementation.
     35 *  @see arp.h
     36 */
    4037
    4138#include <async.h>
    4239#include <errno.h>
     40#include <err.h>
    4341#include <fibril_synch.h>
    4442#include <stdio.h>
     
    5351#include <byteorder.h>
    5452
    55 #include <adt/measured_strings.h>
    56 #include <adt/module_map.h>
    57 
    58 #include <packet_client.h>
    5953#include <net/socket_codes.h>
    6054#include <net/in.h>
     
    7367#include <ip_client.h>
    7468#include <ip_interface.h>
    75 #include <ip_header.h>
    7669#include <net_interface.h>
    7770#include <nil_interface.h>
    7871#include <tl_interface.h>
     72#include <adt/measured_strings.h>
     73#include <adt/module_map.h>
     74#include <packet_client.h>
    7975#include <packet_remote.h>
    8076#include <il_local.h>
    8177
    82 /** IP module name. */
    83 #define NAME                    "ip"
    84 
    85 /** IP version 4. */
    86 #define IPV4                    4
    87 
    88 /** Default network interface IP version. */
     78#include "ip.h"
     79#include "ip_header.h"
     80#include "ip_module.h"
     81#include "ip_local.h"
     82
     83/** IP module name.
     84 */
     85#define NAME  "ip"
     86
     87/** IP version 4.
     88 */
     89#define IPV4                            4
     90
     91/** Default network interface IP version.
     92 */
    8993#define NET_DEFAULT_IPV         IPV4
    9094
    91 /** Default network interface IP routing. */
     95/** Default network interface IP routing.
     96 */
    9297#define NET_DEFAULT_IP_ROUTING  false
    9398
    94 /** Minimum IP packet content. */
    95 #define IP_MIN_CONTENT          576
    96 
    97 /** ARP module name. */
    98 #define ARP_NAME                "arp"
    99 
    100 /** ARP module filename. */
    101 #define ARP_FILENAME            "/srv/arp"
    102 
    103 /** IP packet address length. */
    104 #define IP_ADDR                 sizeof(struct sockaddr_in6)
    105 
    106 /** IP packet prefix length. */
    107 #define IP_PREFIX               sizeof(ip_header_t)
    108 
    109 /** IP packet suffix length. */
    110 #define IP_SUFFIX               0
    111 
    112 /** IP packet maximum content length. */
    113 #define IP_MAX_CONTENT          65535
    114 
    115 /** The IP localhost address. */
     99/** Minimum IP packet content.
     100 */
     101#define IP_MIN_CONTENT  576
     102
     103/** ARP module name.
     104 */
     105#define ARP_NAME                                "arp"
     106
     107/** ARP module filename.
     108 */
     109#define ARP_FILENAME                    "/srv/arp"
     110
     111/** IP packet address length.
     112 */
     113#define IP_ADDR                                                 sizeof(struct sockaddr_in6)
     114
     115/** IP packet prefix length.
     116 */
     117#define IP_PREFIX                                               sizeof(ip_header_t)
     118
     119/** IP packet suffix length.
     120 */
     121#define IP_SUFFIX                                               0
     122
     123/** IP packet maximum content length.
     124 */
     125#define IP_MAX_CONTENT                                  65535
     126
     127/** The IP localhost address.
     128 */
    116129#define IPV4_LOCALHOST_ADDRESS  htonl((127 << 24) + 1)
    117130
    118 /** IP global data. */
    119 ip_globals_t ip_globals;
    120 
    121 DEVICE_MAP_IMPLEMENT(ip_netifs, ip_netif_t);
    122 INT_MAP_IMPLEMENT(ip_protos, ip_proto_t);
    123 GENERIC_FIELD_IMPLEMENT(ip_routes, ip_route_t);
     131/** IP global data.
     132 */
     133ip_globals_t    ip_globals;
     134
     135DEVICE_MAP_IMPLEMENT(ip_netifs, ip_netif_t)
     136
     137INT_MAP_IMPLEMENT(ip_protos, ip_proto_t)
     138
     139GENERIC_FIELD_IMPLEMENT(ip_routes, ip_route_t)
     140
     141/** Updates the device content length according to the new MTU value.
     142 *  @param[in] device_id The device identifier.
     143 *  @param[in] mtu The new mtu value.
     144 *  @returns EOK on success.
     145 *  @returns ENOENT if device is not found.
     146 */
     147int ip_mtu_changed_message(device_id_t device_id, size_t mtu);
     148
     149/** Updates the device state.
     150 *  @param[in] device_id The device identifier.
     151 *  @param[in] state The new state value.
     152 *  @returns EOK on success.
     153 *  @returns ENOENT if device is not found.
     154 */
     155int ip_device_state_message(device_id_t device_id, device_state_t state);
     156
     157/** Returns the device packet dimensions for sending.
     158 *  @param[in] phone The service module phone.
     159 *  @param[in] message The service specific message.
     160 *  @param[in] device_id The device identifier.
     161 *  @param[out] addr_len The minimum reserved address length.
     162 *  @param[out] prefix The minimum reserved prefix size.
     163 *  @param[out] content The maximum content size.
     164 *  @param[out] suffix The minimum reserved suffix size.
     165 *  @returns EOK on success.
     166 */
     167int ip_packet_size_message(device_id_t device_id, size_t * addr_len, size_t * prefix, size_t * content, size_t * suffix);
     168
     169/** Registers the transport layer protocol.
     170 *  The traffic of this protocol will be supplied using either the receive function or IPC message.
     171 *  @param[in] protocol The transport layer module protocol.
     172 *  @param[in] service The transport layer module service.
     173 *  @param[in] phone The transport layer module phone.
     174 *  @param[in] tl_received_msg The receiving function.
     175 *  @returns EOK on success.
     176 *  @returns EINVAL if the protocol parameter and/or the service parameter is zero (0).
     177 *  @returns EINVAL if the phone parameter is not a positive number and the tl_receive_msg is NULL.
     178 *  @returns ENOMEM if there is not enough memory left.
     179 */
     180int ip_register(int protocol, services_t service, int phone, tl_received_msg_t tl_received_msg);
     181
     182/** Initializes a new network interface specific data.
     183 *  Connects to the network interface layer module, reads the netif configuration, starts an ARP module if needed and sets the netif routing table.
     184 *  The device identifier and the nil service has to be set.
     185 *  @param[in,out] ip_netif Network interface specific data.
     186 *  @returns EOK on success.
     187 *  @returns ENOTSUP if DHCP is configured.
     188 *  @returns ENOTSUP if IPv6 is configured.
     189 *  @returns EINVAL if any of the addresses is invalid.
     190 *  @returns EINVAL if the used ARP module is not known.
     191 *  @returns ENOMEM if there is not enough memory left.
     192 *  @returns Other error codes as defined for the net_get_device_conf_req() function.
     193 *  @returns Other error codes as defined for the bind_service() function.
     194 *  @returns Other error codes as defined for the specific arp_device_req() function.
     195 *  @returns Other error codes as defined for the nil_packet_size_req() function.
     196 */
     197int ip_netif_initialize(ip_netif_ref ip_netif);
     198
     199/** Sends the packet or the packet queue via the specified route.
     200 *  The ICMP_HOST_UNREACH error notification may be sent if route hardware destination address is found.
     201 *  @param[in,out] packet The packet to be sent.
     202 *  @param[in] netif The target network interface.
     203 *  @param[in] route The target route.
     204 *  @param[in] src The source address.
     205 *  @param[in] dest The destination address.
     206 *  @param[in] error The error module service.
     207 *  @returns EOK on success.
     208 *  @returns Other error codes as defined for the arp_translate_req() function.
     209 *  @returns Other error codes as defined for the ip_prepare_packet() function.
     210 */
     211int 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);
     212
     213/** Prepares the outgoing packet or the packet queue.
     214 *  The packet queue is a fragmented packet
     215 *  Updates the first packet's IP header.
     216 *  Prefixes the additional packets with fragment headers.
     217 *  @param[in] source The source address.
     218 *  @param[in] dest The destination address.
     219 *  @param[in,out] packet The packet to be sent.
     220 *  @param[in] destination The destination hardware address.
     221 *  @returns EOK on success.
     222 *  @returns EINVAL if the packet is too small to contain the IP header.
     223 *  @returns EINVAL if the packet is too long than the IP allows.
     224 *  @returns ENOMEM if there is not enough memory left.
     225 *  @returns Other error codes as defined for the packet_set_addr() function.
     226 */
     227int ip_prepare_packet(in_addr_t * source, in_addr_t dest, packet_t packet, measured_string_ref destination);
     228
     229/** Checks the packet queue lengths and fragments the packets if needed.
     230 *  The ICMP_FRAG_NEEDED error notification may be sent if the packet needs to be fragmented and the fragmentation is not allowed.
     231 *  @param[in,out] packet The packet or the packet queue to be checked.
     232 *  @param[in] prefix The minimum prefix size.
     233 *  @param[in] content The maximum content size.
     234 *  @param[in] suffix The minimum suffix size.
     235 *  @param[in] addr_len The minimum address length.
     236 *  @param[in] error The error module service.
     237 *  @returns The packet or the packet queue of the allowed length.
     238 *  @returns NULL if there are no packets left.
     239 */
     240packet_t ip_split_packet(packet_t packet, size_t prefix, size_t content, size_t suffix, socklen_t addr_len, services_t error);
     241
     242/** Checks the packet length and fragments it if needed.
     243 *  The new fragments are queued before the original packet.
     244 *  @param[in,out] packet The packet to be checked.
     245 *  @param[in] length The maximum packet length.
     246 *  @param[in] prefix The minimum prefix size.
     247 *  @param[in] suffix The minimum suffix size.
     248 *  @param[in] addr_len The minimum address length.
     249 *  @returns EOK on success.
     250 *  @returns EINVAL if the packet_get_addr() function fails.
     251 *  @returns EINVAL if the packet does not contain the IP header.
     252 *  @returns EPERM if the packet needs to be fragmented and the fragmentation is not allowed.
     253 *  @returns ENOMEM if there is not enough memory left.
     254 *  @returns ENOMEM if there is no packet available.
     255 *  @returns ENOMEM if the packet is too small to contain the IP header.
     256 *  @returns Other error codes as defined for the packet_trim() function.
     257 *  @returns Other error codes as defined for the ip_create_middle_header() function.
     258 *  @returns Other error codes as defined for the ip_fragment_packet_data() function.
     259 */
     260int ip_fragment_packet(packet_t packet, size_t length, size_t prefix, size_t suffix, socklen_t addr_len);
     261
     262/** Fragments the packet from the end.
     263 *  @param[in] packet The packet to be fragmented.
     264 *  @param[in,out] new_packet The new packet fragment.
     265 *  @param[in,out] header The original packet header.
     266 *  @param[in,out] new_header The new packet fragment header.
     267 *  @param[in] length The new fragment length.
     268 *  @param[in] src The source address.
     269 *  @param[in] dest The destiantion address.
     270 *  @param[in] addrlen The address length.
     271 *  @returns EOK on success.
     272 *  @returns ENOMEM if the target packet is too small.
     273 *  @returns Other error codes as defined for the packet_set_addr() function.
     274 *  @returns Other error codes as defined for the pq_insert_after() function.
     275 */
     276int 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);
     277
     278/** Prefixes a middle fragment header based on the last fragment header to the packet.
     279 *  @param[in] packet The packet to be prefixed.
     280 *  @param[in] last The last header to be copied.
     281 *  @returns The prefixed middle header.
     282 *  @returns NULL on error.
     283 */
     284ip_header_ref ip_create_middle_header(packet_t packet, ip_header_ref last);
     285
     286/** Copies the fragment header.
     287 *  Copies only the header itself and relevant IP options.
     288 *  @param[out] last The created header.
     289 *  @param[in] first The original header to be copied.
     290 */
     291void ip_create_last_header(ip_header_ref last, ip_header_ref first);
     292
     293/** Returns the network interface's IP address.
     294 *  @param[in] netif The network interface.
     295 *  @returns The IP address.
     296 *  @returns NULL if no IP address was found.
     297 */
     298in_addr_t * ip_netif_address(ip_netif_ref netif);
     299
     300/** Searches all network interfaces if there is a suitable route.
     301 *  @param[in] destination The destination address.
     302 *  @returns The found route.
     303 *  @returns NULL if no route was found.
     304 */
     305ip_route_ref ip_find_route(in_addr_t destination);
     306
     307/** Searches the network interfaces if there is a suitable route.
     308 *  @param[in] netif The network interface to be searched for routes. May be NULL.
     309 *  @param[in] destination The destination address.
     310 *  @returns The found route.
     311 *  @returns NULL if no route was found.
     312 */
     313ip_route_ref ip_netif_find_route(ip_netif_ref netif, in_addr_t destination);
     314
     315/** Processes the received IP packet or the packet queue one by one.
     316 *  The packet is either passed to another module or released on error.
     317 *  @param[in] device_id The source device identifier.
     318 *  @param[in,out] packet The received packet.
     319 *  @returns EOK on success and the packet is no longer needed.
     320 *  @returns EINVAL if the packet is too small to carry the IP packet.
     321 *  @returns EINVAL if the received address lengths differs from the registered values.
     322 *  @returns ENOENT if the device is not found in the cache.
     323 *  @returns ENOENT if the protocol for the device is not found in the cache.
     324 *  @returns ENOMEM if there is not enough memory left.
     325 */
     326int ip_receive_message(device_id_t device_id, packet_t packet);
     327
     328/** Processes the received packet.
     329 *  The packet is either passed to another module or released on error.
     330 *  The ICMP_PARAM_POINTER error notification may be sent if the checksum is invalid.
     331 *  The ICMP_EXC_TTL error notification may be sent if the TTL is less than two (2).
     332 *  The ICMP_HOST_UNREACH error notification may be sent if no route was found.
     333 *  The ICMP_HOST_UNREACH error notification may be sent if the packet is for another host and the routing is disabled.
     334 *  @param[in] device_id The source device identifier.
     335 *  @param[in] packet The received packet to be processed.
     336 *  @returns EOK on success.
     337 *  @returns EINVAL if the TTL is less than two (2).
     338 *  @returns EINVAL if the checksum is invalid.
     339 *  @returns EAFNOSUPPORT if the address family is not supported.
     340 *  @returns ENOENT if no route was found.
     341 *  @returns ENOENT if the packet is for another host and the routing is disabled.
     342 */
     343int ip_process_packet(device_id_t device_id, packet_t packet);
     344
     345/** Returns the packet destination address from the IP header.
     346 *  @param[in] header The packet IP header to be read.
     347 *  @returns The packet destination address.
     348 */
     349in_addr_t ip_get_destination(ip_header_ref header);
     350
     351/** Delivers the packet to the local host.
     352 *  The packet is either passed to another module or released on error.
     353 *  The ICMP_PROT_UNREACH error notification may be sent if the protocol is not found.
     354 *  @param[in] device_id The source device identifier.
     355 *  @param[in] packet The packet to be delivered.
     356 *  @param[in] header The first packet IP header. May be NULL.
     357 *  @param[in] error The packet error service.
     358 *  @returns EOK on success.
     359 *  @returns ENOTSUP if the packet is a fragment.
     360 *  @returns EAFNOSUPPORT if the address family is not supported.
     361 *  @returns ENOENT if the target protocol is not found.
     362 *  @returns Other error codes as defined for the packet_set_addr() function.
     363 *  @returns Other error codes as defined for the packet_trim() function.
     364 *  @returns Other error codes as defined for the protocol specific tl_received_msg function.
     365 */
     366int ip_deliver_local(device_id_t device_id, packet_t packet, ip_header_ref header, services_t error);
     367
     368/** Prepares the ICMP notification packet.
     369 *  Releases additional packets and keeps only the first one.
     370 *  All packets is released on error.
     371 *  @param[in] error The packet error service.
     372 *  @param[in] packet The packet or the packet queue to be reported as faulty.
     373 *  @param[in] header The first packet IP header. May be NULL.
     374 *  @returns The found ICMP phone.
     375 *  @returns EINVAL if the error parameter is set.
     376 *  @returns EINVAL if the ICMP phone is not found.
     377 *  @returns EINVAL if the ip_prepare_icmp() fails.
     378 */
     379int ip_prepare_icmp_and_get_phone(services_t error, packet_t packet, ip_header_ref header);
     380
     381/** Returns the ICMP phone.
     382 *  Searches the registered protocols.
     383 *  @returns The found ICMP phone.
     384 *  @returns ENOENT if the ICMP is not registered.
     385 */
     386int ip_get_icmp_phone(void);
     387
     388/** Prepares the ICMP notification packet.
     389 *  Releases additional packets and keeps only the first one.
     390 *  @param[in] packet The packet or the packet queue to be reported as faulty.
     391 *  @param[in] header The first packet IP header. May be NULL.
     392 *  @returns EOK on success.
     393 *  @returns EINVAL if there are no data in the packet.
     394 *  @returns EINVAL if the packet is a fragment.
     395 *  @returns ENOMEM if the packet is too short to contain the IP header.
     396 *  @returns EAFNOSUPPORT if the address family is not supported.
     397 *  @returns EPERM if the protocol is not allowed to send ICMP notifications. The ICMP protocol itself.
     398 *  @returns Other error codes as defined for the packet_set_addr().
     399 */
     400int ip_prepare_icmp(packet_t packet, ip_header_ref header);
    124401
    125402/** Releases the packet and returns the result.
    126  *
    127  * @param[in] packet    The packet queue to be released.
    128  * @param[in] result    The result to be returned.
    129  * @return              The result parameter.
    130  */
    131 static int ip_release_and_return(packet_t packet, int result)
    132 {
    133         pq_release_remote(ip_globals.net_phone, packet_get_id(packet));
    134         return result;
    135 }
    136 
    137 /** Returns the ICMP phone.
    138  *
    139  * Searches the registered protocols.
    140  *
    141  * @returns             The found ICMP phone.
    142  * @returns             ENOENT if the ICMP is not registered.
    143  */
    144 static int ip_get_icmp_phone(void)
    145 {
    146         ip_proto_ref proto;
    147         int phone;
    148 
    149         fibril_rwlock_read_lock(&ip_globals.protos_lock);
    150         proto = ip_protos_find(&ip_globals.protos, IPPROTO_ICMP);
    151         phone = proto ? proto->phone : ENOENT;
    152         fibril_rwlock_read_unlock(&ip_globals.protos_lock);
    153         return phone;
    154 }
    155 
    156 /** Prepares the ICMP notification packet.
    157  *
    158  * Releases additional packets and keeps only the first one.
    159  *
    160  * @param[in] packet    The packet or the packet queue to be reported as faulty.
    161  * @param[in] header    The first packet IP header. May be NULL.
    162  * @returns             EOK on success.
    163  * @returns             EINVAL if there are no data in the packet.
    164  * @returns             EINVAL if the packet is a fragment.
    165  * @returns             ENOMEM if the packet is too short to contain the IP
    166  *                      header.
    167  * @returns             EAFNOSUPPORT if the address family is not supported.
    168  * @returns             EPERM if the protocol is not allowed to send ICMP
    169  *                      notifications. The ICMP protocol itself.
    170  * @returns             Other error codes as defined for the packet_set_addr().
    171  */
    172 static int ip_prepare_icmp(packet_t packet, ip_header_ref header)
    173 {
    174         packet_t next;
    175         struct sockaddr *dest;
    176         struct sockaddr_in dest_in;
    177         socklen_t addrlen;
    178 
    179         // detach the first packet and release the others
    180         next = pq_detach(packet);
    181         if (next)
    182                 pq_release_remote(ip_globals.net_phone, packet_get_id(next));
    183 
    184         if (!header) {
    185                 if (packet_get_data_length(packet) <= sizeof(ip_header_t))
    186                         return ENOMEM;
    187 
    188                 // get header
    189                 header = (ip_header_ref) packet_get_data(packet);
    190                 if (!header)
    191                         return EINVAL;
    192 
    193         }
    194 
    195         // only for the first fragment
    196         if (IP_FRAGMENT_OFFSET(header))
    197                 return EINVAL;
    198 
    199         // not for the ICMP protocol
    200         if (header->protocol == IPPROTO_ICMP)
    201                 return EPERM;
    202 
    203         // set the destination address
    204         switch (header->version) {
    205         case IPVERSION:
    206                 addrlen = sizeof(dest_in);
    207                 bzero(&dest_in, addrlen);
    208                 dest_in.sin_family = AF_INET;
    209                 memcpy(&dest_in.sin_addr.s_addr, &header->source_address,
    210                     sizeof(header->source_address));
    211                 dest = (struct sockaddr *) &dest_in;
    212                 break;
    213 
    214         default:
    215                 return EAFNOSUPPORT;
    216         }
    217 
    218         return packet_set_addr(packet, NULL, (uint8_t *) dest, addrlen);
    219 }
    220 
    221 /** Prepares the ICMP notification packet.
    222  *
    223  * Releases additional packets and keeps only the first one.
    224  * All packets are released on error.
    225  *
    226  * @param[in] error     The packet error service.
    227  * @param[in] packet    The packet or the packet queue to be reported as faulty.
    228  * @param[in] header    The first packet IP header. May be NULL.
    229  * @returns             The found ICMP phone.
    230  * @returns             EINVAL if the error parameter is set.
    231  * @returns             EINVAL if the ICMP phone is not found.
    232  * @returns             EINVAL if the ip_prepare_icmp() fails.
    233  */
    234 static int
    235 ip_prepare_icmp_and_get_phone(services_t error, packet_t packet,
    236     ip_header_ref header)
    237 {
    238         int phone;
    239 
    240         phone = ip_get_icmp_phone();
    241         if (error || (phone < 0) || ip_prepare_icmp(packet, header))
    242                 return ip_release_and_return(packet, EINVAL);
    243         return phone;
    244 }
    245 
    246 /** Initializes the IP module.
    247  *
    248  * @param[in] client_connection The client connection processing function. The
    249  *                      module skeleton propagates its own one.
    250  * @returns             EOK on success.
    251  * @returns             ENOMEM if there is not enough memory left.
    252  */
    253 int ip_initialize(async_client_conn_t client_connection)
    254 {
    255         int rc;
     403 *  @param[in] packet The packet queue to be released.
     404 *  @param[in] result The result to be returned.
     405 *  @return The result parameter.
     406 */
     407int ip_release_and_return(packet_t packet, int result);
     408
     409int ip_initialize(async_client_conn_t client_connection){
     410        ERROR_DECLARE;
    256411
    257412        fibril_rwlock_initialize(&ip_globals.lock);
     
    264419        ip_globals.gateway.gateway.s_addr = 0;
    265420        ip_globals.gateway.netif = NULL;
     421        ERROR_PROPAGATE(ip_netifs_initialize(&ip_globals.netifs));
     422        ERROR_PROPAGATE(ip_protos_initialize(&ip_globals.protos));
    266423        ip_globals.client_connection = client_connection;
    267        
    268         rc = ip_netifs_initialize(&ip_globals.netifs);
    269         if (rc != EOK)
    270                 goto out;
    271         rc = ip_protos_initialize(&ip_globals.protos);
    272         if (rc != EOK)
    273                 goto out;
    274         rc = modules_initialize(&ip_globals.modules);
    275         if (rc != EOK)
    276                 goto out;
    277         rc = add_module(NULL, &ip_globals.modules, ARP_NAME, ARP_FILENAME,
    278             SERVICE_ARP, 0, arp_connect_module);
    279 
    280 out:
     424        ERROR_PROPAGATE(modules_initialize(&ip_globals.modules));
     425        ERROR_PROPAGATE(add_module(NULL, &ip_globals.modules, ARP_NAME, ARP_FILENAME, SERVICE_ARP, 0, arp_connect_module));
    281426        fibril_rwlock_write_unlock(&ip_globals.lock);
    282 
    283         return rc;
    284 }
    285 
    286 /** Initializes a new network interface specific data.
    287  *
    288  * Connects to the network interface layer module, reads the netif
    289  * configuration, starts an ARP module if needed and sets the netif routing
    290  * table.
    291  *
    292  * The device identifier and the nil service has to be set.
    293  *
    294  * @param[in,out] ip_netif Network interface specific data.
    295  * @returns             EOK on success.
    296  * @returns             ENOTSUP if DHCP is configured.
    297  * @returns             ENOTSUP if IPv6 is configured.
    298  * @returns             EINVAL if any of the addresses is invalid.
    299  * @returns             EINVAL if the used ARP module is not known.
    300  * @returns             ENOMEM if there is not enough memory left.
    301  * @returns             Other error codes as defined for the
    302  *                      net_get_device_conf_req() function.
    303  * @returns             Other error codes as defined for the bind_service()
    304  *                      function.
    305  * @returns             Other error codes as defined for the specific
    306  *                      arp_device_req() function.
    307  * @returns             Other error codes as defined for the
    308  *                      nil_packet_size_req() function.
    309  */
    310 static int ip_netif_initialize(ip_netif_ref ip_netif)
    311 {
    312         measured_string_t names[] = {
    313                 {
    314                         (char *) "IPV",
    315                         3
    316                 },
    317                 {
    318                         (char *) "IP_CONFIG",
    319                         9
    320                 },
    321                 {
    322                         (char *) "IP_ADDR",
    323                         7
    324                 },
    325                 {
    326                         (char *) "IP_NETMASK",
    327                         10
    328                 },
    329                 {
    330                         (char *) "IP_GATEWAY",
    331                         10
    332                 },
    333                 {
    334                         (char *) "IP_BROADCAST",
    335                         12
    336                 },
    337                 {
    338                         (char *) "ARP",
    339                         3
    340                 },
    341                 {
    342                         (char *) "IP_ROUTING",
    343                         10
    344                 }
    345         };
    346         measured_string_ref configuration;
    347         size_t count = sizeof(names) / sizeof(measured_string_t);
    348         char *data;
    349         measured_string_t address;
    350         ip_route_ref route;
    351         in_addr_t gateway;
    352         int index;
    353         int rc;
    354 
    355         ip_netif->arp = NULL;
    356         route = NULL;
    357         ip_netif->ipv = NET_DEFAULT_IPV;
    358         ip_netif->dhcp = false;
    359         ip_netif->routing = NET_DEFAULT_IP_ROUTING;
    360         configuration = &names[0];
    361 
    362         // get configuration
    363         rc = net_get_device_conf_req(ip_globals.net_phone, ip_netif->device_id,
    364             &configuration, count, &data);
    365         if (rc != EOK)
    366                 return rc;
    367        
    368         if (configuration) {
    369                 if (configuration[0].value)
    370                         ip_netif->ipv = strtol(configuration[0].value, NULL, 0);
    371 
    372                 ip_netif->dhcp = !str_lcmp(configuration[1].value, "dhcp",
    373                     configuration[1].length);
    374                
    375                 if (ip_netif->dhcp) {
    376                         // TODO dhcp
    377                         net_free_settings(configuration, data);
    378                         return ENOTSUP;
    379                 } else if (ip_netif->ipv == IPV4) {
    380                         route = (ip_route_ref) malloc(sizeof(ip_route_t));
    381                         if (!route) {
    382                                 net_free_settings(configuration, data);
    383                                 return ENOMEM;
    384                         }
    385                         route->address.s_addr = 0;
    386                         route->netmask.s_addr = 0;
    387                         route->gateway.s_addr = 0;
    388                         route->netif = ip_netif;
    389                         index = ip_routes_add(&ip_netif->routes, route);
    390                         if (index < 0) {
    391                                 net_free_settings(configuration, data);
    392                                 free(route);
    393                                 return index;
    394                         }
    395                        
    396                         if ((inet_pton(AF_INET, configuration[2].value,
    397                             (uint8_t *) &route->address.s_addr) != EOK) ||
    398                             (inet_pton(AF_INET, configuration[3].value,
    399                             (uint8_t *) &route->netmask.s_addr) != EOK) ||
    400                             (inet_pton(AF_INET, configuration[4].value,
    401                             (uint8_t *) &gateway.s_addr) == EINVAL) ||
    402                             (inet_pton(AF_INET, configuration[5].value,
    403                             (uint8_t *) &ip_netif->broadcast.s_addr) == EINVAL))
    404                             {
    405                                 net_free_settings(configuration, data);
    406                                 return EINVAL;
    407                         }
    408                 } else {
    409                         // TODO ipv6 in separate module
    410                         net_free_settings(configuration, data);
    411                         return ENOTSUP;
    412                 }
    413 
    414                 if (configuration[6].value) {
    415                         ip_netif->arp = get_running_module(&ip_globals.modules,
    416                             configuration[6].value);
    417                         if (!ip_netif->arp) {
    418                                 printf("Failed to start the arp %s\n",
    419                                     configuration[6].value);
    420                                 net_free_settings(configuration, data);
    421                                 return EINVAL;
    422                         }
    423                 }
    424                 if (configuration[7].value)
    425                         ip_netif->routing = (configuration[7].value[0] == 'y');
    426 
    427                 net_free_settings(configuration, data);
    428         }
    429 
    430         // binds the netif service which also initializes the device
    431         ip_netif->phone = nil_bind_service(ip_netif->service,
    432             (ipcarg_t) ip_netif->device_id, SERVICE_IP,
    433             ip_globals.client_connection);
    434         if (ip_netif->phone < 0) {
    435                 printf("Failed to contact the nil service %d\n",
    436                     ip_netif->service);
    437                 return ip_netif->phone;
    438         }
    439 
    440         // has to be after the device netif module initialization
    441         if (ip_netif->arp) {
    442                 if (route) {
    443                         address.value = (char *) &route->address.s_addr;
    444                         address.length = CONVERT_SIZE(in_addr_t, char, 1);
    445                        
    446                         rc = arp_device_req(ip_netif->arp->phone,
    447                             ip_netif->device_id, SERVICE_IP, ip_netif->service,
    448                             &address);
    449                         if (rc != EOK)
    450                                 return rc;
    451                 } else {
    452                         ip_netif->arp = 0;
    453                 }
    454         }
    455 
    456         // get packet dimensions
    457         rc = nil_packet_size_req(ip_netif->phone, ip_netif->device_id,
    458             &ip_netif->packet_dimension);
    459         if (rc != EOK)
    460                 return rc;
    461        
    462         if (ip_netif->packet_dimension.content < IP_MIN_CONTENT) {
    463                 printf("Maximum transmission unit %d bytes is too small, at "
    464                     "least %d bytes are needed\n",
    465                     ip_netif->packet_dimension.content, IP_MIN_CONTENT);
    466                 ip_netif->packet_dimension.content = IP_MIN_CONTENT;
    467         }
    468 
    469         index = ip_netifs_add(&ip_globals.netifs, ip_netif->device_id, ip_netif);
    470         if (index < 0)
    471                 return index;
    472        
    473         if (gateway.s_addr) {
    474                 // the default gateway
    475                 ip_globals.gateway.address.s_addr = 0;
    476                 ip_globals.gateway.netmask.s_addr = 0;
    477                 ip_globals.gateway.gateway.s_addr = gateway.s_addr;
    478                 ip_globals.gateway.netif = ip_netif;
    479         }
    480 
    481427        return EOK;
    482428}
    483429
    484 /** Updates the device content length according to the new MTU value.
    485  *
    486  * @param[in] device_id The device identifier.
    487  * @param[in] mtu       The new mtu value.
    488  * @returns             EOK on success.
    489  * @returns             ENOENT if device is not found.
    490  */
    491 static int ip_mtu_changed_message(device_id_t device_id, size_t mtu)
    492 {
    493         ip_netif_ref netif;
    494 
    495         fibril_rwlock_write_lock(&ip_globals.netifs_lock);
    496         netif = ip_netifs_find(&ip_globals.netifs, device_id);
    497         if (!netif) {
    498                 fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
    499                 return ENOENT;
    500         }
    501         netif->packet_dimension.content = mtu;
    502         fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
    503 
    504         printf("%s: Device %d changed MTU to %d\n", NAME, device_id, mtu);
    505 
    506         return EOK;
    507 }
    508 
    509 /** Updates the device state.
    510  *
    511  * @param[in] device_id The device identifier.
    512  * @param[in] state     The new state value.
    513  * @returns             EOK on success.
    514  * @returns             ENOENT if device is not found.
    515  */
    516 static int ip_device_state_message(device_id_t device_id, device_state_t state)
    517 {
    518         ip_netif_ref netif;
    519 
    520         fibril_rwlock_write_lock(&ip_globals.netifs_lock);
    521         // find the device
    522         netif = ip_netifs_find(&ip_globals.netifs, device_id);
    523         if (!netif) {
    524                 fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
    525                 return ENOENT;
    526         }
    527         netif->state = state;
    528         fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
    529 
    530         printf("%s: Device %d changed state to %d\n", NAME, device_id, state);
    531 
    532         return EOK;
    533 }
    534 
    535 
    536 /** Prefixes a middle fragment header based on the last fragment header to the
    537  * packet.
    538  *
    539  * @param[in] packet    The packet to be prefixed.
    540  * @param[in] last      The last header to be copied.
    541  * @returns             The prefixed middle header.
    542  * @returns             NULL on error.
    543  */
    544 static ip_header_ref
    545 ip_create_middle_header(packet_t packet, ip_header_ref last)
    546 {
    547         ip_header_ref middle;
    548 
    549         middle = (ip_header_ref) packet_suffix(packet, IP_HEADER_LENGTH(last));
    550         if (!middle)
    551                 return NULL;
    552         memcpy(middle, last, IP_HEADER_LENGTH(last));
    553         middle->flags |= IPFLAG_MORE_FRAGMENTS;
    554         return middle;
    555 }
    556 
    557 /** Copies the fragment header.
    558  *
    559  * Copies only the header itself and relevant IP options.
    560  *
    561  * @param[out] last     The created header.
    562  * @param[in] first     The original header to be copied.
    563  */
    564 static void ip_create_last_header(ip_header_ref last, ip_header_ref first)
    565 {
    566         ip_option_ref option;
    567         size_t next;
    568         size_t length;
    569 
    570         // copy first itself
    571         memcpy(last, first, sizeof(ip_header_t));
    572         length = sizeof(ip_header_t);
    573         next = sizeof(ip_header_t);
    574 
    575         // process all ip options
    576         while (next < first->header_length) {
    577                 option = (ip_option_ref) (((uint8_t *) first) + next);
    578                 // skip end or noop
    579                 if ((option->type == IPOPT_END) ||
    580                     (option->type == IPOPT_NOOP)) {
    581                         next++;
    582                 } else {
    583                         // copy if told so or skip
    584                         if (IPOPT_COPIED(option->type)) {
    585                                 memcpy(((uint8_t *) last) + length,
    586                                     ((uint8_t *) first) + next, option->length);
    587                                 length += option->length;
    588                         }
    589                         // next option
    590                         next += option->length;
    591                 }
    592         }
    593 
    594         // align 4 byte boundary
    595         if (length % 4) {
    596                 bzero(((uint8_t *) last) + length, 4 - (length % 4));
    597                 last->header_length = length / 4 + 1;
    598         } else {
    599                 last->header_length = length / 4;
    600         }
    601 
    602         last->header_checksum = 0;
    603 }
    604 
    605 /** Prepares the outgoing packet or the packet queue.
    606  *
    607  * The packet queue is a fragmented packet
    608  * Updates the first packet's IP header.
    609  * Prefixes the additional packets with fragment headers.
    610  *
    611  * @param[in] source    The source address.
    612  * @param[in] dest      The destination address.
    613  * @param[in,out] packet The packet to be sent.
    614  * @param[in] destination The destination hardware address.
    615  * @returns             EOK on success.
    616  * @returns             EINVAL if the packet is too small to contain the IP
    617  *                      header.
    618  * @returns             EINVAL if the packet is too long than the IP allows.
    619  * @returns             ENOMEM if there is not enough memory left.
    620  * @returns             Other error codes as defined for the packet_set_addr()
    621  *                      function.
    622  */
    623 static int
    624 ip_prepare_packet(in_addr_t *source, in_addr_t dest, packet_t packet,
    625     measured_string_ref destination)
    626 {
    627         size_t length;
    628         ip_header_ref header;
    629         ip_header_ref last_header;
    630         ip_header_ref middle_header;
    631         packet_t next;
    632         int rc;
    633 
    634         length = packet_get_data_length(packet);
    635         if ((length < sizeof(ip_header_t)) || (length > IP_MAX_CONTENT))
    636                 return EINVAL;
    637 
    638         header = (ip_header_ref) packet_get_data(packet);
    639         if (destination) {
    640                 rc = packet_set_addr(packet, NULL, (uint8_t *) destination->value,
    641                     CONVERT_SIZE(char, uint8_t, destination->length));
    642         } else {
    643                 rc = packet_set_addr(packet, NULL, NULL, 0);
    644         }
    645         if (rc != EOK)
    646                 return rc;
    647        
    648         header->version = IPV4;
    649         header->fragment_offset_high = 0;
    650         header->fragment_offset_low = 0;
    651         header->header_checksum = 0;
    652         if (source)
    653                 header->source_address = source->s_addr;
    654         header->destination_address = dest.s_addr;
    655 
    656         fibril_rwlock_write_lock(&ip_globals.lock);
    657         ip_globals.packet_counter++;
    658         header->identification = htons(ip_globals.packet_counter);
    659         fibril_rwlock_write_unlock(&ip_globals.lock);
    660 
    661         if (pq_next(packet)) {
    662                 last_header = (ip_header_ref) malloc(IP_HEADER_LENGTH(header));
    663                 if (!last_header)
    664                         return ENOMEM;
    665                 ip_create_last_header(last_header, header);
    666                 next = pq_next(packet);
    667                 while (pq_next(next)) {
    668                         middle_header = (ip_header_ref) packet_prefix(next,
    669                             IP_HEADER_LENGTH(last_header));
    670                         if (!middle_header) {
    671                                 free(last_header);
    672                                 return ENOMEM;
    673                         }
    674 
    675                         memcpy(middle_header, last_header,
    676                             IP_HEADER_LENGTH(last_header));
    677                         header->flags |= IPFLAG_MORE_FRAGMENTS;
    678                         middle_header->total_length =
    679                             htons(packet_get_data_length(next));
    680                         middle_header->fragment_offset_high =
    681                             IP_COMPUTE_FRAGMENT_OFFSET_HIGH(length);
    682                         middle_header->fragment_offset_low =
    683                             IP_COMPUTE_FRAGMENT_OFFSET_LOW(length);
    684                         middle_header->header_checksum =
    685                             IP_HEADER_CHECKSUM(middle_header);
    686                         if (destination) {
    687                                 rc = packet_set_addr(next, NULL,
    688                                     (uint8_t *) destination->value,
    689                                     CONVERT_SIZE(char, uint8_t,
    690                                     destination->length));
    691                                 if (rc != EOK) {
    692                                         free(last_header);
    693                                         return rc;
    694                                 }
    695                         }
    696                         length += packet_get_data_length(next);
    697                         next = pq_next(next);
    698                 }
    699 
    700                 middle_header = (ip_header_ref) packet_prefix(next,
    701                     IP_HEADER_LENGTH(last_header));
    702                 if (!middle_header) {
    703                         free(last_header);
    704                         return ENOMEM;
    705                 }
    706 
    707                 memcpy(middle_header, last_header,
    708                     IP_HEADER_LENGTH(last_header));
    709                 middle_header->total_length =
    710                     htons(packet_get_data_length(next));
    711                 middle_header->fragment_offset_high =
    712                     IP_COMPUTE_FRAGMENT_OFFSET_HIGH(length);
    713                 middle_header->fragment_offset_low =
    714                     IP_COMPUTE_FRAGMENT_OFFSET_LOW(length);
    715                 middle_header->header_checksum =
    716                     IP_HEADER_CHECKSUM(middle_header);
    717                 if (destination) {
    718                         rc = packet_set_addr(next, NULL,
    719                             (uint8_t *) destination->value,
    720                             CONVERT_SIZE(char, uint8_t, destination->length));
    721                         if (rc != EOK) {
    722                                 free(last_header);
    723                                 return rc;
    724                         }
    725                 }
    726                 length += packet_get_data_length(next);
    727                 free(last_header);
    728                 header->flags |= IPFLAG_MORE_FRAGMENTS;
    729         }
    730 
    731         header->total_length = htons(length);
    732         // unnecessary for all protocols
    733         header->header_checksum = IP_HEADER_CHECKSUM(header);
    734 
    735         return EOK;
    736 }
    737 
    738 /** Fragments the packet from the end.
    739  *
    740  * @param[in] packet    The packet to be fragmented.
    741  * @param[in,out] new_packet The new packet fragment.
    742  * @param[in,out] header The original packet header.
    743  * @param[in,out] new_header The new packet fragment header.
    744  * @param[in] length    The new fragment length.
    745  * @param[in] src       The source address.
    746  * @param[in] dest      The destiantion address.
    747  * @param[in] addrlen   The address length.
    748  * @returns             EOK on success.
    749  * @returns             ENOMEM if the target packet is too small.
    750  * @returns             Other error codes as defined for the packet_set_addr()
    751  *                      function.
    752  * @returns             Other error codes as defined for the pq_insert_after()
    753  *                      function.
    754  */
    755 static int
    756 ip_fragment_packet_data(packet_t packet, packet_t new_packet,
    757     ip_header_ref header, ip_header_ref new_header, size_t length,
    758     const struct sockaddr *src, const struct sockaddr *dest, socklen_t addrlen)
    759 {
    760         void *data;
    761         size_t offset;
    762         int rc;
    763 
    764         data = packet_suffix(new_packet, length);
    765         if (!data)
    766                 return ENOMEM;
    767 
    768         memcpy(data, ((void *) header) + IP_TOTAL_LENGTH(header) - length,
    769             length);
    770        
    771         rc = packet_trim(packet, 0, length);
    772         if (rc != EOK)
    773                 return rc;
    774        
    775         header->total_length = htons(IP_TOTAL_LENGTH(header) - length);
    776         new_header->total_length = htons(IP_HEADER_LENGTH(new_header) + length);
    777         offset = IP_FRAGMENT_OFFSET(header) + IP_HEADER_DATA_LENGTH(header);
    778         new_header->fragment_offset_high =
    779             IP_COMPUTE_FRAGMENT_OFFSET_HIGH(offset);
    780         new_header->fragment_offset_low =
    781             IP_COMPUTE_FRAGMENT_OFFSET_LOW(offset);
    782         new_header->header_checksum = IP_HEADER_CHECKSUM(new_header);
    783        
    784         rc = packet_set_addr(new_packet, (const uint8_t *) src,
    785             (const uint8_t *) dest, addrlen);
    786         if (rc != EOK)
    787                 return rc;
    788 
    789         return pq_insert_after(packet, new_packet);
    790 }
    791 
    792 /** Checks the packet length and fragments it if needed.
    793  *
    794  * The new fragments are queued before the original packet.
    795  *
    796  * @param[in,out] packet The packet to be checked.
    797  * @param[in] length    The maximum packet length.
    798  * @param[in] prefix    The minimum prefix size.
    799  * @param[in] suffix    The minimum suffix size.
    800  * @param[in] addr_len  The minimum address length.
    801  * @returns             EOK on success.
    802  * @returns             EINVAL if the packet_get_addr() function fails.
    803  * @returns             EINVAL if the packet does not contain the IP header.
    804  * @returns             EPERM if the packet needs to be fragmented and the
    805  *                      fragmentation is not allowed.
    806  * @returns             ENOMEM if there is not enough memory left.
    807  * @returns             ENOMEM if there is no packet available.
    808  * @returns             ENOMEM if the packet is too small to contain the IP
    809  *                      header.
    810  * @returns             Other error codes as defined for the packet_trim()
    811  *                      function.
    812  * @returns             Other error codes as defined for the
    813  *                      ip_create_middle_header() function.
    814  * @returns             Other error codes as defined for the
    815  *                      ip_fragment_packet_data() function.
    816  */
    817 static int
    818 ip_fragment_packet(packet_t packet, size_t length, size_t prefix, size_t suffix,
    819     socklen_t addr_len)
    820 {
    821         packet_t new_packet;
    822         ip_header_ref header;
    823         ip_header_ref middle_header;
    824         ip_header_ref last_header;
    825         struct sockaddr *src;
    826         struct sockaddr *dest;
    827         socklen_t addrlen;
    828         int result;
    829         int rc;
    830 
    831         result = packet_get_addr(packet, (uint8_t **) &src, (uint8_t **) &dest);
    832         if (result <= 0)
    833                 return EINVAL;
    834 
    835         addrlen = (socklen_t) result;
    836         if (packet_get_data_length(packet) <= sizeof(ip_header_t))
    837                 return ENOMEM;
    838 
    839         // get header
    840         header = (ip_header_ref) packet_get_data(packet);
    841         if (!header)
    842                 return EINVAL;
    843 
    844         // fragmentation forbidden?
    845         if(header->flags & IPFLAG_DONT_FRAGMENT)
    846                 return EPERM;
    847 
    848         // create the last fragment
    849         new_packet = packet_get_4_remote(ip_globals.net_phone, prefix, length,
    850             suffix, ((addrlen > addr_len) ? addrlen : addr_len));
    851         if (!new_packet)
    852                 return ENOMEM;
    853 
    854         // allocate as much as originally
    855         last_header = (ip_header_ref) packet_suffix(new_packet,
    856             IP_HEADER_LENGTH(header));
    857         if (!last_header)
    858                 return ip_release_and_return(packet, ENOMEM);
    859 
    860         ip_create_last_header(last_header, header);
    861 
    862         // trim the unused space
    863         rc = packet_trim(new_packet, 0,
    864             IP_HEADER_LENGTH(header) - IP_HEADER_LENGTH(last_header));
    865         if (rc != EOK)
    866                 return ip_release_and_return(packet, rc);
    867 
    868         // biggest multiple of 8 lower than content
    869         // TODO even fragmentation?
    870         length = length & ~0x7;
    871        
    872         rc = ip_fragment_packet_data(packet, new_packet, header, last_header,
    873             ((IP_HEADER_DATA_LENGTH(header) -
    874             ((length - IP_HEADER_LENGTH(header)) & ~0x7)) %
    875             ((length - IP_HEADER_LENGTH(last_header)) & ~0x7)),
    876             src, dest, addrlen);
    877         if (rc != EOK)
    878                 return ip_release_and_return(packet, rc);
    879 
    880         // mark the first as fragmented
    881         header->flags |= IPFLAG_MORE_FRAGMENTS;
    882 
    883         // create middle framgents
    884         while (IP_TOTAL_LENGTH(header) > length) {
    885                 new_packet = packet_get_4_remote(ip_globals.net_phone, prefix,
    886                     length, suffix,
    887                     ((addrlen >= addr_len) ? addrlen : addr_len));
    888                 if (!new_packet)
    889                         return ENOMEM;
    890 
    891                 middle_header = ip_create_middle_header(new_packet,
    892                     last_header);
    893                 if (!middle_header)
    894                         return ip_release_and_return(packet, ENOMEM);
    895 
    896                 rc = ip_fragment_packet_data(packet, new_packet, header,
    897                     middle_header,
    898                     (length - IP_HEADER_LENGTH(middle_header)) & ~0x7,
    899                     src, dest, addrlen);
    900                 if (rc != EOK)
    901                         return ip_release_and_return(packet, rc);
    902         }
    903 
    904         // finish the first fragment
    905         header->header_checksum = IP_HEADER_CHECKSUM(header);
    906 
    907         return EOK;
    908 }
    909 
    910 /** Checks the packet queue lengths and fragments the packets if needed.
    911  *
    912  * The ICMP_FRAG_NEEDED error notification may be sent if the packet needs to
    913  * be fragmented and the fragmentation is not allowed.
    914  *
    915  * @param[in,out] packet The packet or the packet queue to be checked.
    916  * @param[in] prefix    The minimum prefix size.
    917  * @param[in] content   The maximum content size.
    918  * @param[in] suffix    The minimum suffix size.
    919  * @param[in] addr_len  The minimum address length.
    920  * @param[in] error     The error module service.
    921  * @returns             The packet or the packet queue of the allowed length.
    922  * @returns             NULL if there are no packets left.
    923  */
    924 static packet_t
    925 ip_split_packet(packet_t packet, size_t prefix, size_t content, size_t suffix,
    926     socklen_t addr_len, services_t error)
    927 {
    928         size_t length;
    929         packet_t next;
    930         packet_t new_packet;
    931         int result;
    932         int phone;
    933 
    934         next = packet;
    935         // check all packets
    936         while (next) {
    937                 length = packet_get_data_length(next);
    938                
    939                 if (length <= content) {
    940                         next = pq_next(next);
    941                         continue;
    942                 }
    943 
    944                 // too long
    945                 result = ip_fragment_packet(next, content, prefix,
    946                     suffix, addr_len);
    947                 if (result != EOK) {
    948                         new_packet = pq_detach(next);
    949                         if (next == packet) {
    950                                 // the new first packet of the queue
    951                                 packet = new_packet;
    952                         }
    953                         // fragmentation needed?
    954                         if (result == EPERM) {
    955                                 phone = ip_prepare_icmp_and_get_phone(
    956                                     error, next, NULL);
    957                                 if (phone >= 0) {
    958                                         // fragmentation necessary ICMP
    959                                         icmp_destination_unreachable_msg(phone,
    960                                             ICMP_FRAG_NEEDED, content, next);
    961                                 }
    962                         } else {
    963                                 pq_release_remote(ip_globals.net_phone,
    964                                     packet_get_id(next));
    965                         }
    966 
    967                         next = new_packet;
    968                         continue;
    969                 }
    970 
    971                 next = pq_next(next);
    972         }
    973 
    974         return packet;
    975 }
    976 
    977 /** Sends the packet or the packet queue via the specified route.
    978  *
    979  * The ICMP_HOST_UNREACH error notification may be sent if route hardware
    980  * destination address is found.
    981  *
    982  * @param[in,out] packet The packet to be sent.
    983  * @param[in] netif     The target network interface.
    984  * @param[in] route     The target route.
    985  * @param[in] src       The source address.
    986  * @param[in] dest      The destination address.
    987  * @param[in] error     The error module service.
    988  * @returns             EOK on success.
    989  * @returns             Other error codes as defined for the arp_translate_req()
    990  *                      function.
    991  * @returns             Other error codes as defined for the ip_prepare_packet()
    992  *                      function.
    993  */
    994 static int
    995 ip_send_route(packet_t packet, ip_netif_ref netif, ip_route_ref route,
    996     in_addr_t *src, in_addr_t dest, services_t error)
    997 {
    998         measured_string_t destination;
    999         measured_string_ref translation;
    1000         char *data;
    1001         int phone;
    1002         int rc;
    1003 
    1004         // get destination hardware address
    1005         if (netif->arp && (route->address.s_addr != dest.s_addr)) {
    1006                 destination.value = route->gateway.s_addr ?
    1007                     (char *) &route->gateway.s_addr : (char *) &dest.s_addr;
    1008                 destination.length = CONVERT_SIZE(dest.s_addr, char, 1);
    1009 
    1010                 rc = arp_translate_req(netif->arp->phone, netif->device_id,
    1011                     SERVICE_IP, &destination, &translation, &data);
    1012                 if (rc != EOK) {
    1013                         pq_release_remote(ip_globals.net_phone,
    1014                             packet_get_id(packet));
    1015                         return rc;
    1016                 }
    1017 
    1018                 if (!translation || !translation->value) {
    1019                         if (translation) {
    1020                                 free(translation);
    1021                                 free(data);
    1022                         }
    1023                         phone = ip_prepare_icmp_and_get_phone(error, packet,
    1024                             NULL);
    1025                         if (phone >= 0) {
    1026                                 // unreachable ICMP if no routing
    1027                                 icmp_destination_unreachable_msg(phone,
    1028                                     ICMP_HOST_UNREACH, 0, packet);
    1029                         }
    1030                         return EINVAL;
    1031                 }
    1032 
    1033         } else {
    1034                 translation = NULL;
    1035         }
    1036 
    1037         rc = ip_prepare_packet(src, dest, packet, translation);
    1038         if (rc != EOK) {
    1039                 pq_release_remote(ip_globals.net_phone, packet_get_id(packet));
    1040         } else {
    1041                 packet = ip_split_packet(packet, netif->packet_dimension.prefix,
    1042                     netif->packet_dimension.content,
    1043                     netif->packet_dimension.suffix,
    1044                     netif->packet_dimension.addr_len, error);
    1045                 if (packet) {
    1046                         nil_send_msg(netif->phone, netif->device_id, packet,
    1047                             SERVICE_IP);
    1048                 }
    1049         }
    1050 
    1051         if (translation) {
    1052                 free(translation);
    1053                 free(data);
    1054         }
    1055 
    1056         return rc;
    1057 }
    1058 
    1059 /** Searches the network interfaces if there is a suitable route.
    1060  *
    1061  * @param[in] netif     The network interface to be searched for routes. May be
    1062  *                      NULL.
    1063  * @param[in] destination The destination address.
    1064  * @returns             The found route.
    1065  * @returns             NULL if no route was found.
    1066  */
    1067 static ip_route_ref
    1068 ip_netif_find_route(ip_netif_ref netif, in_addr_t destination)
    1069 {
    1070         int index;
    1071         ip_route_ref route;
    1072 
    1073         if (!netif)
    1074                 return NULL;
    1075 
    1076         // start with the first one - the direct route
    1077         for (index = 0; index < ip_routes_count(&netif->routes); index++) {
    1078                 route = ip_routes_get_index(&netif->routes, index);
    1079                 if (route &&
    1080                     ((route->address.s_addr & route->netmask.s_addr) ==
    1081                     (destination.s_addr & route->netmask.s_addr))) {
    1082                         return route;
    1083                 }
    1084         }
    1085 
    1086         return NULL;
    1087 }
    1088 
    1089 /** Searches all network interfaces if there is a suitable route.
    1090  *
    1091  * @param[in] destination The destination address.
    1092  * @returns             The found route.
    1093  * @returns             NULL if no route was found.
    1094  */
    1095 static ip_route_ref ip_find_route(in_addr_t destination) {
    1096         int index;
    1097         ip_route_ref route;
    1098         ip_netif_ref netif;
    1099 
    1100         // start with the last netif - the newest one
    1101         index = ip_netifs_count(&ip_globals.netifs) - 1;
    1102         while (index >= 0) {
    1103                 netif = ip_netifs_get_index(&ip_globals.netifs, index);
    1104                 if (netif && (netif->state == NETIF_ACTIVE)) {
    1105                         route = ip_netif_find_route(netif, destination);
    1106                         if (route)
    1107                                 return route;
    1108                 }
    1109                 index--;
    1110         }
    1111 
    1112         return &ip_globals.gateway;
    1113 }
    1114 
    1115 /** Returns the network interface's IP address.
    1116  *
    1117  * @param[in] netif     The network interface.
    1118  * @returns             The IP address.
    1119  * @returns             NULL if no IP address was found.
    1120  */
    1121 static in_addr_t *ip_netif_address(ip_netif_ref netif)
    1122 {
    1123         ip_route_ref route;
    1124 
    1125         route = ip_routes_get_index(&netif->routes, 0);
    1126         return route ? &route->address : NULL;
    1127 }
    1128 
    1129 /** Registers the transport layer protocol.
    1130  *
    1131  * The traffic of this protocol will be supplied using either the receive
    1132  * function or IPC message.
    1133  *
    1134  * @param[in] protocol  The transport layer module protocol.
    1135  * @param[in] service   The transport layer module service.
    1136  * @param[in] phone     The transport layer module phone.
    1137  * @param[in] received_msg The receiving function.
    1138  * @returns             EOK on success.
    1139  * @returns             EINVAL if the protocol parameter and/or the service
    1140  *                      parameter is zero.
    1141  * @returns             EINVAL if the phone parameter is not a positive number
    1142  *                      and the tl_receive_msg is NULL.
    1143  * @returns             ENOMEM if there is not enough memory left.
    1144  */
    1145 static int
    1146 ip_register(int protocol, services_t service, int phone,
    1147     tl_received_msg_t received_msg)
    1148 {
    1149         ip_proto_ref proto;
    1150         int index;
    1151 
    1152         if (!protocol || !service || ((phone < 0) && !received_msg))
    1153                 return EINVAL;
    1154 
    1155         proto = (ip_proto_ref) malloc(sizeof(ip_protos_t));
    1156         if (!proto)
    1157                 return ENOMEM;
    1158 
    1159         proto->protocol = protocol;
    1160         proto->service = service;
    1161         proto->phone = phone;
    1162         proto->received_msg = received_msg;
    1163 
    1164         fibril_rwlock_write_lock(&ip_globals.protos_lock);
    1165         index = ip_protos_add(&ip_globals.protos, proto->protocol, proto);
    1166         if (index < 0) {
    1167                 fibril_rwlock_write_unlock(&ip_globals.protos_lock);
    1168                 free(proto);
    1169                 return index;
    1170         }
    1171         fibril_rwlock_write_unlock(&ip_globals.protos_lock);
    1172 
    1173         printf("%s: Protocol registered (protocol: %d, phone: %d)\n",
    1174             NAME, proto->protocol, proto->phone);
    1175 
    1176         return EOK;
    1177 }
    1178 
    1179 static int
    1180 ip_device_req_local(int il_phone, device_id_t device_id, services_t netif)
    1181 {
     430int ip_device_req_local(int il_phone, device_id_t device_id, services_t netif){
     431        ERROR_DECLARE;
     432
    1182433        ip_netif_ref ip_netif;
    1183434        ip_route_ref route;
    1184435        int index;
    1185         int rc;
    1186436
    1187437        ip_netif = (ip_netif_ref) malloc(sizeof(ip_netif_t));
    1188         if (!ip_netif)
     438        if(! ip_netif){
    1189439                return ENOMEM;
    1190 
    1191         rc = ip_routes_initialize(&ip_netif->routes);
    1192         if (rc != EOK) {
     440        }
     441        if(ERROR_OCCURRED(ip_routes_initialize(&ip_netif->routes))){
    1193442                free(ip_netif);
    1194                 return rc;
    1195         }
    1196 
     443                return ERROR_CODE;
     444        }
    1197445        ip_netif->device_id = device_id;
    1198446        ip_netif->service = netif;
    1199447        ip_netif->state = NETIF_STOPPED;
    1200 
    1201448        fibril_rwlock_write_lock(&ip_globals.netifs_lock);
    1202 
    1203         rc = ip_netif_initialize(ip_netif);
    1204         if (rc != EOK) {
     449        if(ERROR_OCCURRED(ip_netif_initialize(ip_netif))){
    1205450                fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
    1206451                ip_routes_destroy(&ip_netif->routes);
    1207452                free(ip_netif);
    1208                 return rc;
    1209         }
    1210         if (ip_netif->arp)
    1211                 ip_netif->arp->usage++;
    1212 
     453                return ERROR_CODE;
     454        }
     455        if(ip_netif->arp){
     456                ++ ip_netif->arp->usage;
     457        }
    1213458        // print the settings
    1214459        printf("%s: Device registered (id: %d, phone: %d, ipv: %d, conf: %s)\n",
     
    1222467        char gateway[INET_ADDRSTRLEN];
    1223468       
    1224         for (index = 0; index < ip_routes_count(&ip_netif->routes); index++) {
     469        for (index = 0; index < ip_routes_count(&ip_netif->routes); ++ index){
    1225470                route = ip_routes_get_index(&ip_netif->routes, index);
    1226471                if (route) {
    1227                         inet_ntop(AF_INET, (uint8_t *) &route->address.s_addr,
    1228                             address, INET_ADDRSTRLEN);
    1229                         inet_ntop(AF_INET, (uint8_t *) &route->netmask.s_addr,
    1230                             netmask, INET_ADDRSTRLEN);
    1231                         inet_ntop(AF_INET, (uint8_t *) &route->gateway.s_addr,
    1232                             gateway, INET_ADDRSTRLEN);
    1233                         printf("%s: Route %d (address: %s, netmask: %s, "
    1234                             "gateway: %s)\n", NAME, index, address, netmask,
    1235                             gateway);
     472                        inet_ntop(AF_INET, (uint8_t *) &route->address.s_addr, address, INET_ADDRSTRLEN);
     473                        inet_ntop(AF_INET, (uint8_t *) &route->netmask.s_addr, netmask, INET_ADDRSTRLEN);
     474                        inet_ntop(AF_INET, (uint8_t *) &route->gateway.s_addr, gateway, INET_ADDRSTRLEN);
     475                        printf("%s: Route %d (address: %s, netmask: %s, gateway: %s)\n",
     476                            NAME, index, address, netmask, gateway);
    1236477                }
    1237478        }
    1238479       
    1239         inet_ntop(AF_INET, (uint8_t *) &ip_netif->broadcast.s_addr, address,
    1240             INET_ADDRSTRLEN);
     480        inet_ntop(AF_INET, (uint8_t *) &ip_netif->broadcast.s_addr, address, INET_ADDRSTRLEN);
     481        printf("%s: Broadcast (%s)\n", NAME, address);
     482       
    1241483        fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
    1242 
    1243         printf("%s: Broadcast (%s)\n", NAME, address);
    1244 
    1245484        return EOK;
    1246485}
    1247486
    1248 static int
    1249 ip_send_msg_local(int il_phone, device_id_t device_id, packet_t packet,
    1250     services_t sender, services_t error)
    1251 {
     487int ip_netif_initialize(ip_netif_ref ip_netif){
     488        ERROR_DECLARE;
     489
     490        measured_string_t names[] = {{str_dup("IPV"), 3}, {str_dup("IP_CONFIG"), 9}, {str_dup("IP_ADDR"), 7}, {str_dup("IP_NETMASK"), 10}, {str_dup("IP_GATEWAY"), 10}, {str_dup("IP_BROADCAST"), 12}, {str_dup("ARP"), 3}, {str_dup("IP_ROUTING"), 10}};
     491        measured_string_ref configuration;
     492        size_t count = sizeof(names) / sizeof(measured_string_t);
     493        char * data;
     494        measured_string_t address;
     495        int index;
     496        ip_route_ref route;
     497        in_addr_t gateway;
     498
     499        ip_netif->arp = NULL;
     500        route = NULL;
     501        ip_netif->ipv = NET_DEFAULT_IPV;
     502        ip_netif->dhcp = false;
     503        ip_netif->routing = NET_DEFAULT_IP_ROUTING;
     504        configuration = &names[0];
     505        // get configuration
     506        ERROR_PROPAGATE(net_get_device_conf_req(ip_globals.net_phone, ip_netif->device_id, &configuration, count, &data));
     507        if(configuration){
     508                if(configuration[0].value){
     509                        ip_netif->ipv = strtol(configuration[0].value, NULL, 0);
     510                }
     511                ip_netif->dhcp = ! str_lcmp(configuration[1].value, "dhcp", configuration[1].length);
     512                if(ip_netif->dhcp){
     513                        // TODO dhcp
     514                        net_free_settings(configuration, data);
     515                        return ENOTSUP;
     516                }else if(ip_netif->ipv == IPV4){
     517                        route = (ip_route_ref) malloc(sizeof(ip_route_t));
     518                        if(! route){
     519                                net_free_settings(configuration, data);
     520                                return ENOMEM;
     521                        }
     522                        route->address.s_addr = 0;
     523                        route->netmask.s_addr = 0;
     524                        route->gateway.s_addr = 0;
     525                        route->netif = ip_netif;
     526                        index = ip_routes_add(&ip_netif->routes, route);
     527                        if(index < 0){
     528                                net_free_settings(configuration, data);
     529                                free(route);
     530                                return index;
     531                        }
     532                        if(ERROR_OCCURRED(inet_pton(AF_INET, configuration[2].value, (uint8_t *) &route->address.s_addr))
     533                                || ERROR_OCCURRED(inet_pton(AF_INET, configuration[3].value, (uint8_t *) &route->netmask.s_addr))
     534                                || (inet_pton(AF_INET, configuration[4].value, (uint8_t *) &gateway.s_addr) == EINVAL)
     535                                || (inet_pton(AF_INET, configuration[5].value, (uint8_t *) &ip_netif->broadcast.s_addr) == EINVAL)){
     536                                net_free_settings(configuration, data);
     537                                return EINVAL;
     538                        }
     539                }else{
     540                        // TODO ipv6 in separate module
     541                        net_free_settings(configuration, data);
     542                        return ENOTSUP;
     543                }
     544                if(configuration[6].value){
     545                        ip_netif->arp = get_running_module(&ip_globals.modules, configuration[6].value);
     546                        if(! ip_netif->arp){
     547                                printf("Failed to start the arp %s\n", configuration[6].value);
     548                                net_free_settings(configuration, data);
     549                                return EINVAL;
     550                        }
     551                }
     552                if(configuration[7].value){
     553                        ip_netif->routing = (configuration[7].value[0] == 'y');
     554                }
     555                net_free_settings(configuration, data);
     556        }
     557        // binds the netif service which also initializes the device
     558        ip_netif->phone = nil_bind_service(ip_netif->service, (ipcarg_t) ip_netif->device_id, SERVICE_IP, ip_globals.client_connection);
     559        if(ip_netif->phone < 0){
     560                printf("Failed to contact the nil service %d\n", ip_netif->service);
     561                return ip_netif->phone;
     562        }
     563        // has to be after the device netif module initialization
     564        if(ip_netif->arp){
     565                if(route){
     566                        address.value = (char *) &route->address.s_addr;
     567                        address.length = CONVERT_SIZE(in_addr_t, char, 1);
     568                        ERROR_PROPAGATE(arp_device_req(ip_netif->arp->phone, ip_netif->device_id, SERVICE_IP, ip_netif->service, &address));
     569                }else{
     570                        ip_netif->arp = 0;
     571                }
     572        }
     573        // get packet dimensions
     574        ERROR_PROPAGATE(nil_packet_size_req(ip_netif->phone, ip_netif->device_id, &ip_netif->packet_dimension));
     575        if(ip_netif->packet_dimension.content < IP_MIN_CONTENT){
     576                printf("Maximum transmission unit %d bytes is too small, at least %d bytes are needed\n", ip_netif->packet_dimension.content, IP_MIN_CONTENT);
     577                ip_netif->packet_dimension.content = IP_MIN_CONTENT;
     578        }
     579        index = ip_netifs_add(&ip_globals.netifs, ip_netif->device_id, ip_netif);
     580        if(index < 0){
     581                return index;
     582        }
     583        if(gateway.s_addr){
     584                // the default gateway
     585                ip_globals.gateway.address.s_addr = 0;
     586                ip_globals.gateway.netmask.s_addr = 0;
     587                ip_globals.gateway.gateway.s_addr = gateway.s_addr;
     588                ip_globals.gateway.netif = ip_netif;
     589        }
     590        return EOK;
     591}
     592
     593int ip_mtu_changed_message(device_id_t device_id, size_t mtu){
     594        ip_netif_ref netif;
     595
     596        fibril_rwlock_write_lock(&ip_globals.netifs_lock);
     597        netif = ip_netifs_find(&ip_globals.netifs, device_id);
     598        if(! netif){
     599                fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
     600                return ENOENT;
     601        }
     602        netif->packet_dimension.content = mtu;
     603        printf("%s: Device %d changed MTU to %d\n", NAME, device_id, mtu);
     604        fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
     605        return EOK;
     606}
     607
     608int ip_device_state_message(device_id_t device_id, device_state_t state){
     609        ip_netif_ref netif;
     610
     611        fibril_rwlock_write_lock(&ip_globals.netifs_lock);
     612        // find the device
     613        netif = ip_netifs_find(&ip_globals.netifs, device_id);
     614        if(! netif){
     615                fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
     616                return ENOENT;
     617        }
     618        netif->state = state;
     619        printf("%s: Device %d changed state to %d\n", NAME, device_id, state);
     620        fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
     621        return EOK;
     622}
     623
     624int ip_register(int protocol, services_t service, int phone, tl_received_msg_t received_msg){
     625        ip_proto_ref proto;
     626        int index;
     627
     628        if(!(protocol && service && ((phone > 0) || (received_msg)))){
     629                return EINVAL;
     630        }
     631        proto = (ip_proto_ref) malloc(sizeof(ip_protos_t));
     632        if(! proto){
     633                return ENOMEM;
     634        }
     635        proto->protocol = protocol;
     636        proto->service = service;
     637        proto->phone = phone;
     638        proto->received_msg = received_msg;
     639        fibril_rwlock_write_lock(&ip_globals.protos_lock);
     640        index = ip_protos_add(&ip_globals.protos, proto->protocol, proto);
     641        if(index < 0){
     642                fibril_rwlock_write_unlock(&ip_globals.protos_lock);
     643                free(proto);
     644                return index;
     645        }
     646       
     647        printf("%s: Protocol registered (protocol: %d, phone: %d)\n",
     648            NAME, proto->protocol, proto->phone);
     649       
     650        fibril_rwlock_write_unlock(&ip_globals.protos_lock);
     651        return EOK;
     652}
     653
     654int ip_send_msg_local(int il_phone, device_id_t device_id, packet_t packet, services_t sender, services_t error){
     655        ERROR_DECLARE;
     656
    1252657        int addrlen;
    1253658        ip_netif_ref netif;
    1254659        ip_route_ref route;
    1255         struct sockaddr *addr;
    1256         struct sockaddr_in *address_in;
    1257         in_addr_t *dest;
    1258         in_addr_t *src;
     660        struct sockaddr * addr;
     661        struct sockaddr_in * address_in;
     662//      struct sockaddr_in6 *   address_in6;
     663        in_addr_t * dest;
     664        in_addr_t * src;
    1259665        int phone;
    1260         int rc;
    1261666
    1262667        // addresses in the host byte order
    1263668        // should be the next hop address or the target destination address
    1264669        addrlen = packet_get_addr(packet, NULL, (uint8_t **) &addr);
    1265         if (addrlen < 0)
     670        if(addrlen < 0){
    1266671                return ip_release_and_return(packet, addrlen);
    1267         if ((size_t) addrlen < sizeof(struct sockaddr))
     672        }
     673        if((size_t) addrlen < sizeof(struct sockaddr)){
    1268674                return ip_release_and_return(packet, EINVAL);
    1269 
    1270         switch (addr->sa_family) {
    1271         case AF_INET:
    1272                 if (addrlen != sizeof(struct sockaddr_in))
    1273                         return ip_release_and_return(packet, EINVAL);
    1274                 address_in = (struct sockaddr_in *) addr;
    1275                 dest = &address_in->sin_addr;
    1276                 if (!dest->s_addr)
    1277                         dest->s_addr = IPV4_LOCALHOST_ADDRESS;
    1278                 break;
    1279         case AF_INET6:
    1280         default:
    1281                 return ip_release_and_return(packet, EAFNOSUPPORT);
    1282         }
    1283 
     675        }
     676        switch(addr->sa_family){
     677                case AF_INET:
     678                        if(addrlen != sizeof(struct sockaddr_in)){
     679                                return ip_release_and_return(packet, EINVAL);
     680                        }
     681                        address_in = (struct sockaddr_in *) addr;
     682                        dest = &address_in->sin_addr;
     683                        if(! dest->s_addr){
     684                                dest->s_addr = IPV4_LOCALHOST_ADDRESS;
     685                        }
     686                        break;
     687                // TODO IPv6
     688/*              case AF_INET6:
     689                        if(addrlen != sizeof(struct sockaddr_in6)){
     690                                return EINVAL;
     691                        }
     692                        address_in6 = (struct sockaddr_in6 *) dest;
     693                        address_in6.sin6_addr.s6_addr;
     694                        IPV6_LOCALHOST_ADDRESS;
     695*/              default:
     696                        return ip_release_and_return(packet, EAFNOSUPPORT);
     697        }
    1284698        netif = NULL;
    1285699        route = NULL;
    1286700        fibril_rwlock_read_lock(&ip_globals.netifs_lock);
    1287 
    1288701        // device specified?
    1289         if (device_id > 0) {
     702        if(device_id > 0){
    1290703                netif = ip_netifs_find(&ip_globals.netifs, device_id);
    1291704                route = ip_netif_find_route(netif, * dest);
    1292                 if (netif && !route && (ip_globals.gateway.netif == netif))
     705                if(netif && (! route) && (ip_globals.gateway.netif == netif)){
    1293706                        route = &ip_globals.gateway;
    1294         }
    1295 
    1296         if (!route) {
     707                }
     708        }
     709        if(! route){
    1297710                route = ip_find_route(*dest);
    1298711                netif = route ? route->netif : NULL;
    1299712        }
    1300         if (!netif || !route) {
     713        if(!(netif && route)){
    1301714                fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
    1302715                phone = ip_prepare_icmp_and_get_phone(error, packet, NULL);
    1303                 if (phone >= 0) {
     716                if(phone >= 0){
    1304717                        // unreachable ICMP if no routing
    1305                         icmp_destination_unreachable_msg(phone,
    1306                             ICMP_NET_UNREACH, 0, packet);
     718                        icmp_destination_unreachable_msg(phone, ICMP_NET_UNREACH, 0, packet);
    1307719                }
    1308720                return ENOENT;
    1309721        }
    1310 
    1311         if (error) {
    1312                 // do not send for broadcast, anycast packets or network
    1313                 // broadcast
    1314                 if (!dest->s_addr || !(~dest->s_addr) ||
    1315                     !(~((dest->s_addr & ~route->netmask.s_addr) |
    1316                     route->netmask.s_addr)) ||
    1317                     (!(dest->s_addr & ~route->netmask.s_addr))) {
     722        if(error){
     723                // do not send for broadcast, anycast packets or network broadcast
     724                if((! dest->s_addr)
     725                        || (!(~ dest->s_addr))
     726                        || (!(~((dest->s_addr &(~ route->netmask.s_addr)) | route->netmask.s_addr)))
     727                        || (!(dest->s_addr &(~ route->netmask.s_addr)))){
    1318728                        return ip_release_and_return(packet, EINVAL);
    1319729                }
    1320730        }
    1321 
    1322731        // if the local host is the destination
    1323         if ((route->address.s_addr == dest->s_addr) &&
    1324             (dest->s_addr != IPV4_LOCALHOST_ADDRESS)) {
     732        if((route->address.s_addr == dest->s_addr)
     733                && (dest->s_addr != IPV4_LOCALHOST_ADDRESS)){
    1325734                // find the loopback device to deliver
    1326735                dest->s_addr = IPV4_LOCALHOST_ADDRESS;
    1327736                route = ip_find_route(*dest);
    1328737                netif = route ? route->netif : NULL;
    1329                 if (!netif || !route) {
     738                if(!(netif && route)){
    1330739                        fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
    1331                         phone = ip_prepare_icmp_and_get_phone(error, packet,
    1332                             NULL);
    1333                         if (phone >= 0) {
     740                        phone = ip_prepare_icmp_and_get_phone(error, packet, NULL);
     741                        if(phone >= 0){
    1334742                                // unreachable ICMP if no routing
    1335                                 icmp_destination_unreachable_msg(phone,
    1336                                     ICMP_HOST_UNREACH, 0, packet);
     743                                icmp_destination_unreachable_msg(phone, ICMP_HOST_UNREACH, 0, packet);
    1337744                        }
    1338745                        return ENOENT;
    1339746                }
    1340747        }
    1341        
    1342748        src = ip_netif_address(netif);
    1343         if (!src) {
     749        if(! src){
    1344750                fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
    1345751                return ip_release_and_return(packet, ENOENT);
    1346752        }
    1347 
    1348         rc = ip_send_route(packet, netif, route, src, *dest, error);
     753        ERROR_CODE = ip_send_route(packet, netif, route, src, * dest, error);
    1349754        fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
    1350 
    1351         return rc;
    1352 }
    1353 
    1354 /** Returns the device packet dimensions for sending.
    1355  *
    1356  * @param[in] phone     The service module phone.
    1357  * @param[in] message   The service specific message.
    1358  * @param[in] device_id The device identifier.
    1359  * @param[out] addr_len The minimum reserved address length.
    1360  * @param[out] prefix   The minimum reserved prefix size.
    1361  * @param[out] content  The maximum content size.
    1362  * @param[out] suffix   The minimum reserved suffix size.
    1363  * @returns             EOK on success.
    1364  */
    1365 static int
    1366 ip_packet_size_message(device_id_t device_id, size_t *addr_len, size_t *prefix,
    1367     size_t *content, size_t *suffix)
     755        return ERROR_CODE;
     756}
     757
     758in_addr_t * ip_netif_address(ip_netif_ref netif){
     759        ip_route_ref route;
     760
     761        route = ip_routes_get_index(&netif->routes, 0);
     762        return route ? &route->address : NULL;
     763}
     764
     765int 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){
     766        ERROR_DECLARE;
     767
     768        measured_string_t destination;
     769        measured_string_ref translation;
     770        char * data;
     771        int phone;
     772
     773        // get destination hardware address
     774        if(netif->arp && (route->address.s_addr != dest.s_addr)){
     775                destination.value = route->gateway.s_addr ? (char *) &route->gateway.s_addr : (char *) &dest.s_addr;
     776                destination.length = CONVERT_SIZE(dest.s_addr, char, 1);
     777                if(ERROR_OCCURRED(arp_translate_req(netif->arp->phone, netif->device_id, SERVICE_IP, &destination, &translation, &data))){
     778//                      sleep(1);
     779//                      ERROR_PROPAGATE(arp_translate_req(netif->arp->phone, netif->device_id, SERVICE_IP, &destination, &translation, &data));
     780                        pq_release_remote(ip_globals.net_phone, packet_get_id(packet));
     781                        return ERROR_CODE;
     782                }
     783                if(!(translation && translation->value)){
     784                        if(translation){
     785                                free(translation);
     786                                free(data);
     787                        }
     788                        phone = ip_prepare_icmp_and_get_phone(error, packet, NULL);
     789                        if(phone >= 0){
     790                                // unreachable ICMP if no routing
     791                                icmp_destination_unreachable_msg(phone, ICMP_HOST_UNREACH, 0, packet);
     792                        }
     793                        return EINVAL;
     794                }
     795        }else translation = NULL;
     796        if(ERROR_OCCURRED(ip_prepare_packet(src, dest, packet, translation))){
     797                pq_release_remote(ip_globals.net_phone, packet_get_id(packet));
     798        }else{
     799                packet = ip_split_packet(packet, netif->packet_dimension.prefix, netif->packet_dimension.content, netif->packet_dimension.suffix, netif->packet_dimension.addr_len, error);
     800                if(packet){
     801                        nil_send_msg(netif->phone, netif->device_id, packet, SERVICE_IP);
     802                }
     803        }
     804        if(translation){
     805                free(translation);
     806                free(data);
     807        }
     808        return ERROR_CODE;
     809}
     810
     811int ip_prepare_packet(in_addr_t * source, in_addr_t dest, packet_t packet, measured_string_ref destination){
     812        ERROR_DECLARE;
     813
     814        size_t length;
     815        ip_header_ref header;
     816        ip_header_ref last_header;
     817        ip_header_ref middle_header;
     818        packet_t next;
     819
     820        length = packet_get_data_length(packet);
     821        if((length < sizeof(ip_header_t)) || (length > IP_MAX_CONTENT)){
     822                return EINVAL;
     823        }
     824        header = (ip_header_ref) packet_get_data(packet);
     825        if(destination){
     826                ERROR_PROPAGATE(packet_set_addr(packet, NULL, (uint8_t *) destination->value, CONVERT_SIZE(char, uint8_t, destination->length)));
     827        }else{
     828                ERROR_PROPAGATE(packet_set_addr(packet, NULL, NULL, 0));
     829        }
     830        header->version = IPV4;
     831        header->fragment_offset_high = 0;
     832        header->fragment_offset_low = 0;
     833        header->header_checksum = 0;
     834        if(source){
     835                header->source_address = source->s_addr;
     836        }
     837        header->destination_address = dest.s_addr;
     838        fibril_rwlock_write_lock(&ip_globals.lock);
     839        ++ ip_globals.packet_counter;
     840        header->identification = htons(ip_globals.packet_counter);
     841        fibril_rwlock_write_unlock(&ip_globals.lock);
     842//      length = packet_get_data_length(packet);
     843        if(pq_next(packet)){
     844                last_header = (ip_header_ref) malloc(IP_HEADER_LENGTH(header));
     845                if(! last_header){
     846                        return ENOMEM;
     847                }
     848                ip_create_last_header(last_header, header);
     849                next = pq_next(packet);
     850                while(pq_next(next)){
     851                        middle_header = (ip_header_ref) packet_prefix(next, IP_HEADER_LENGTH(last_header));
     852                        if(! middle_header){
     853                                return ENOMEM;
     854                        }
     855                        memcpy(middle_header, last_header, IP_HEADER_LENGTH(last_header));
     856                        header->flags |= IPFLAG_MORE_FRAGMENTS;
     857                        middle_header->total_length = htons(packet_get_data_length(next));
     858                        middle_header->fragment_offset_high = IP_COMPUTE_FRAGMENT_OFFSET_HIGH(length);
     859                        middle_header->fragment_offset_low = IP_COMPUTE_FRAGMENT_OFFSET_LOW(length);
     860                        middle_header->header_checksum = IP_HEADER_CHECKSUM(middle_header);
     861                        if(destination){
     862                                ERROR_PROPAGATE(packet_set_addr(next, NULL, (uint8_t *) destination->value, CONVERT_SIZE(char, uint8_t, destination->length)));
     863                        }
     864                        length += packet_get_data_length(next);
     865                        next = pq_next(next);
     866                }
     867                middle_header = (ip_header_ref) packet_prefix(next, IP_HEADER_LENGTH(last_header));
     868                if(! middle_header){
     869                        return ENOMEM;
     870                }
     871                memcpy(middle_header, last_header, IP_HEADER_LENGTH(last_header));
     872                middle_header->total_length = htons(packet_get_data_length(next));
     873                middle_header->fragment_offset_high = IP_COMPUTE_FRAGMENT_OFFSET_HIGH(length);
     874                middle_header->fragment_offset_low = IP_COMPUTE_FRAGMENT_OFFSET_LOW(length);
     875                middle_header->header_checksum = IP_HEADER_CHECKSUM(middle_header);
     876                if(destination){
     877                        ERROR_PROPAGATE(packet_set_addr(next, NULL, (uint8_t *) destination->value, CONVERT_SIZE(char, uint8_t, destination->length)));
     878                }
     879                length += packet_get_data_length(next);
     880                free(last_header);
     881                header->flags |= IPFLAG_MORE_FRAGMENTS;
     882        }
     883        header->total_length = htons(length);
     884        // unnecessary for all protocols
     885        header->header_checksum = IP_HEADER_CHECKSUM(header);
     886        return EOK;
     887}
     888
     889int ip_message_standalone(ipc_callid_t callid, ipc_call_t *call,
     890    ipc_call_t *answer, int * answer_count)
    1368891{
    1369         ip_netif_ref netif;
    1370         int index;
    1371 
    1372         if (!addr_len || !prefix || !content || !suffix)
    1373                 return EBADMEM;
    1374 
    1375         *content = IP_MAX_CONTENT - IP_PREFIX;
    1376         fibril_rwlock_read_lock(&ip_globals.netifs_lock);
    1377         if (device_id < 0) {
    1378                 *addr_len = IP_ADDR;
    1379                 *prefix = 0;
    1380                 *suffix = 0;
    1381 
    1382                 for (index = ip_netifs_count(&ip_globals.netifs) - 1;
    1383                     index >= 0; index--) {
    1384                         netif = ip_netifs_get_index(&ip_globals.netifs, index);
    1385                         if (!netif)
    1386                                 continue;
    1387                        
    1388                         if (netif->packet_dimension.addr_len > *addr_len)
    1389                                 *addr_len = netif->packet_dimension.addr_len;
    1390                        
    1391                         if (netif->packet_dimension.prefix > *prefix)
    1392                                 *prefix = netif->packet_dimension.prefix;
    1393                                
    1394                         if (netif->packet_dimension.suffix > *suffix)
    1395                                 *suffix = netif->packet_dimension.suffix;
    1396                 }
    1397 
    1398                 *prefix = *prefix + IP_PREFIX;
    1399                 *suffix = *suffix + IP_SUFFIX;
    1400         } else {
    1401                 netif = ip_netifs_find(&ip_globals.netifs, device_id);
    1402                 if (!netif) {
    1403                         fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
    1404                         return ENOENT;
    1405                 }
    1406 
    1407                 *addr_len = (netif->packet_dimension.addr_len > IP_ADDR) ?
    1408                     netif->packet_dimension.addr_len : IP_ADDR;
    1409                 *prefix = netif->packet_dimension.prefix + IP_PREFIX;
    1410                 *suffix = netif->packet_dimension.suffix + IP_SUFFIX;
    1411         }
    1412         fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
    1413 
    1414         return EOK;
    1415 }
    1416 
    1417 /** Returns the packet destination address from the IP header.
    1418  *
    1419  * @param[in] header    The packet IP header to be read.
    1420  * @returns             The packet destination address.
    1421  */
    1422 static in_addr_t ip_get_destination(ip_header_ref header)
    1423 {
    1424         in_addr_t destination;
    1425 
    1426         // TODO search set ipopt route?
    1427         destination.s_addr = header->destination_address;
    1428         return destination;
    1429 }
    1430 
    1431 /** Delivers the packet to the local host.
    1432  *
    1433  * The packet is either passed to another module or released on error.
    1434  * The ICMP_PROT_UNREACH error notification may be sent if the protocol is not
    1435  * found.
    1436  *
    1437  * @param[in] device_id The source device identifier.
    1438  * @param[in] packet    The packet to be delivered.
    1439  * @param[in] header    The first packet IP header. May be NULL.
    1440  * @param[in] error     The packet error service.
    1441  * @returns             EOK on success.
    1442  * @returns             ENOTSUP if the packet is a fragment.
    1443  * @returns             EAFNOSUPPORT if the address family is not supported.
    1444  * @returns             ENOENT if the target protocol is not found.
    1445  * @returns             Other error codes as defined for the packet_set_addr()
    1446  *                      function.
    1447  * @returns             Other error codes as defined for the packet_trim()
    1448  *                      function.
    1449  * @returns             Other error codes as defined for the protocol specific
    1450  *                      tl_received_msg() function.
    1451  */
    1452 static int
    1453 ip_deliver_local(device_id_t device_id, packet_t packet, ip_header_ref header,
    1454     services_t error)
    1455 {
    1456         ip_proto_ref proto;
    1457         int phone;
    1458         services_t service;
    1459         tl_received_msg_t received_msg;
    1460         struct sockaddr *src;
    1461         struct sockaddr *dest;
    1462         struct sockaddr_in src_in;
    1463         struct sockaddr_in dest_in;
    1464         socklen_t addrlen;
    1465         int rc;
    1466 
    1467         if ((header->flags & IPFLAG_MORE_FRAGMENTS) ||
    1468             IP_FRAGMENT_OFFSET(header)) {
    1469                 // TODO fragmented
    1470                 return ENOTSUP;
    1471         }
     892        ERROR_DECLARE;
    1472893       
    1473         switch (header->version) {
    1474         case IPVERSION:
    1475                 addrlen = sizeof(src_in);
    1476                 bzero(&src_in, addrlen);
    1477                 src_in.sin_family = AF_INET;
    1478                 memcpy(&dest_in, &src_in, addrlen);
    1479                 memcpy(&src_in.sin_addr.s_addr, &header->source_address,
    1480                     sizeof(header->source_address));
    1481                 memcpy(&dest_in.sin_addr.s_addr, &header->destination_address,
    1482                     sizeof(header->destination_address));
    1483                 src = (struct sockaddr *) &src_in;
    1484                 dest = (struct sockaddr *) &dest_in;
    1485                 break;
    1486 
    1487         default:
    1488                 return ip_release_and_return(packet, EAFNOSUPPORT);
    1489         }
    1490 
    1491         rc = packet_set_addr(packet, (uint8_t *) src, (uint8_t *) dest,
    1492             addrlen);
    1493         if (rc != EOK)
    1494                 return ip_release_and_return(packet, rc);
    1495 
    1496         // trim padding if present
    1497         if (!error &&
    1498             (IP_TOTAL_LENGTH(header) < packet_get_data_length(packet))) {
    1499                 rc = packet_trim(packet, 0,
    1500                     packet_get_data_length(packet) - IP_TOTAL_LENGTH(header));
    1501                 if (rc != EOK)
    1502                         return ip_release_and_return(packet, rc);
    1503         }
    1504 
    1505         fibril_rwlock_read_lock(&ip_globals.protos_lock);
    1506 
    1507         proto = ip_protos_find(&ip_globals.protos, header->protocol);
    1508         if (!proto) {
    1509                 fibril_rwlock_read_unlock(&ip_globals.protos_lock);
    1510                 phone = ip_prepare_icmp_and_get_phone(error, packet, header);
    1511                 if (phone >= 0) {
    1512                         // unreachable ICMP
    1513                         icmp_destination_unreachable_msg(phone,
    1514                             ICMP_PROT_UNREACH, 0, packet);
    1515                 }
    1516                 return ENOENT;
    1517         }
    1518 
    1519         if (proto->received_msg) {
    1520                 service = proto->service;
    1521                 received_msg = proto->received_msg;
    1522                 fibril_rwlock_read_unlock(&ip_globals.protos_lock);
    1523                 rc = received_msg(device_id, packet, service, error);
    1524         } else {
    1525                 rc = tl_received_msg(proto->phone, device_id, packet,
    1526                     proto->service, error);
    1527                 fibril_rwlock_read_unlock(&ip_globals.protos_lock);
    1528         }
    1529 
    1530         return rc;
    1531 }
    1532 
    1533 /** Processes the received packet.
    1534  *
    1535  * The packet is either passed to another module or released on error.
    1536  *
    1537  * The ICMP_PARAM_POINTER error notification may be sent if the checksum is
    1538  * invalid.
    1539  * The ICMP_EXC_TTL error notification may be sent if the TTL is less than two.
    1540  * The ICMP_HOST_UNREACH error notification may be sent if no route was found.
    1541  * The ICMP_HOST_UNREACH error notification may be sent if the packet is for
    1542  * another host and the routing is disabled.
    1543  *
    1544  * @param[in] device_id The source device identifier.
    1545  * @param[in] packet    The received packet to be processed.
    1546  * @returns             EOK on success.
    1547  * @returns             EINVAL if the TTL is less than two.
    1548  * @returns             EINVAL if the checksum is invalid.
    1549  * @returns             EAFNOSUPPORT if the address family is not supported.
    1550  * @returns             ENOENT if no route was found.
    1551  * @returns             ENOENT if the packet is for another host and the routing
    1552  *                      is disabled.
    1553  */
    1554 static int
    1555 ip_process_packet(device_id_t device_id, packet_t packet)
    1556 {
    1557         ip_header_ref header;
    1558         in_addr_t dest;
    1559         ip_route_ref route;
    1560         int phone;
    1561         struct sockaddr *addr;
    1562         struct sockaddr_in addr_in;
    1563         socklen_t addrlen;
    1564         int rc;
    1565 
    1566         header = (ip_header_ref) packet_get_data(packet);
    1567         if (!header)
    1568                 return ip_release_and_return(packet, ENOMEM);
    1569 
    1570         // checksum
    1571         if ((header->header_checksum) &&
    1572             (IP_HEADER_CHECKSUM(header) != IP_CHECKSUM_ZERO)) {
    1573                 phone = ip_prepare_icmp_and_get_phone(0, packet, header);
    1574                 if (phone >= 0) {
    1575                         // checksum error ICMP
    1576                         icmp_parameter_problem_msg(phone, ICMP_PARAM_POINTER,
    1577                             ((size_t) ((void *) &header->header_checksum)) -
    1578                             ((size_t) ((void *) header)), packet);
    1579                 }
    1580                 return EINVAL;
    1581         }
    1582 
    1583         if (header->ttl <= 1) {
    1584                 phone = ip_prepare_icmp_and_get_phone(0, packet, header);
    1585                 if (phone >= 0) {
    1586                         // ttl exceeded ICMP
    1587                         icmp_time_exceeded_msg(phone, ICMP_EXC_TTL, packet);
    1588                 }
    1589                 return EINVAL;
    1590         }
    1591 
    1592         // process ipopt and get destination
    1593         dest = ip_get_destination(header);
    1594 
    1595         // set the addrination address
    1596         switch (header->version) {
    1597         case IPVERSION:
    1598                 addrlen = sizeof(addr_in);
    1599                 bzero(&addr_in, addrlen);
    1600                 addr_in.sin_family = AF_INET;
    1601                 memcpy(&addr_in.sin_addr.s_addr, &dest, sizeof(dest));
    1602                 addr = (struct sockaddr *) &addr_in;
    1603                 break;
    1604 
    1605         default:
    1606                 return ip_release_and_return(packet, EAFNOSUPPORT);
    1607         }
    1608 
    1609         rc = packet_set_addr(packet, NULL, (uint8_t *) &addr, addrlen);
    1610         if (rc != EOK)
    1611                 return rc;
    1612 
    1613         route = ip_find_route(dest);
    1614         if (!route) {
    1615                 phone = ip_prepare_icmp_and_get_phone(0, packet, header);
    1616                 if (phone >= 0) {
    1617                         // unreachable ICMP
    1618                         icmp_destination_unreachable_msg(phone,
    1619                             ICMP_HOST_UNREACH, 0, packet);
    1620                 }
    1621                 return ENOENT;
    1622         }
    1623 
    1624         if (route->address.s_addr == dest.s_addr) {
    1625                 // local delivery
    1626                 return ip_deliver_local(device_id, packet, header, 0);
    1627         }
    1628 
    1629         if (route->netif->routing) {
    1630                 header->ttl--;
    1631                 return ip_send_route(packet, route->netif, route, NULL, dest,
    1632                     0);
    1633         }
    1634 
    1635         phone = ip_prepare_icmp_and_get_phone(0, packet, header);
    1636         if (phone >= 0) {
    1637                 // unreachable ICMP if no routing
    1638                 icmp_destination_unreachable_msg(phone, ICMP_HOST_UNREACH, 0,
    1639                     packet);
    1640         }
    1641        
    1642         return ENOENT;
    1643 }
    1644 
    1645 static int
    1646 ip_add_route_req_local(int ip_phone, device_id_t device_id, in_addr_t address,
    1647     in_addr_t netmask, in_addr_t gateway)
    1648 {
    1649         ip_route_ref route;
    1650         ip_netif_ref netif;
    1651         int index;
    1652 
    1653         fibril_rwlock_write_lock(&ip_globals.netifs_lock);
    1654 
    1655         netif = ip_netifs_find(&ip_globals.netifs, device_id);
    1656         if (!netif) {
    1657                 fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
    1658                 return ENOENT;
    1659         }
    1660 
    1661         route = (ip_route_ref) malloc(sizeof(ip_route_t));
    1662         if (!route) {
    1663                 fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
    1664                 return ENOMEM;
    1665         }
    1666 
    1667         route->address.s_addr = address.s_addr;
    1668         route->netmask.s_addr = netmask.s_addr;
    1669         route->gateway.s_addr = gateway.s_addr;
    1670         route->netif = netif;
    1671         index = ip_routes_add(&netif->routes, route);
    1672         if (index < 0)
    1673                 free(route);
    1674 
    1675         fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
    1676        
    1677         return index;
    1678 }
    1679 
    1680 static int
    1681 ip_set_gateway_req_local(int ip_phone, device_id_t device_id, in_addr_t gateway)
    1682 {
    1683         ip_netif_ref netif;
    1684 
    1685         fibril_rwlock_write_lock(&ip_globals.netifs_lock);
    1686 
    1687         netif = ip_netifs_find(&ip_globals.netifs, device_id);
    1688         if (!netif) {
    1689                 fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
    1690                 return ENOENT;
    1691         }
    1692 
    1693         ip_globals.gateway.address.s_addr = 0;
    1694         ip_globals.gateway.netmask.s_addr = 0;
    1695         ip_globals.gateway.gateway.s_addr = gateway.s_addr;
    1696         ip_globals.gateway.netif = netif;
    1697        
    1698         fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
    1699        
    1700         return EOK;
    1701 }
    1702 
    1703 /** Notify the IP module about the received error notification packet.
    1704  *
    1705  * @param[in] ip_phone  The IP module phone used for (semi)remote calls.
    1706  * @param[in] device_id The device identifier.
    1707  * @param[in] packet    The received packet or the received packet queue.
    1708  * @param[in] target    The target internetwork module service to be
    1709  *                      delivered to.
    1710  * @param[in] error     The packet error reporting service. Prefixes the
    1711  *                      received packet.
    1712  * @return              EOK on success.
    1713  *
    1714  */
    1715 static int
    1716 ip_received_error_msg_local(int ip_phone, device_id_t device_id,
    1717     packet_t packet, services_t target, services_t error)
    1718 {
    1719         uint8_t *data;
    1720         int offset;
    1721         icmp_type_t type;
    1722         icmp_code_t code;
    1723         ip_netif_ref netif;
    1724         measured_string_t address;
    1725         ip_route_ref route;
    1726         ip_header_ref header;
    1727 
    1728         switch (error) {
    1729         case SERVICE_ICMP:
    1730                 offset = icmp_client_process_packet(packet, &type, &code, NULL,
    1731                     NULL);
    1732                 if (offset < 0)
    1733                         return ip_release_and_return(packet, ENOMEM);
    1734 
    1735                 data = packet_get_data(packet);
    1736                 header = (ip_header_ref)(data + offset);
    1737 
    1738                 // destination host unreachable?
    1739                 if ((type != ICMP_DEST_UNREACH) ||
    1740                     (code != ICMP_HOST_UNREACH)) {
    1741                         // no, something else
    1742                         break;
    1743                 }
    1744 
    1745                 fibril_rwlock_read_lock(&ip_globals.netifs_lock);
    1746 
    1747                 netif = ip_netifs_find(&ip_globals.netifs, device_id);
    1748                 if (!netif || !netif->arp) {
    1749                         fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
    1750                         break;
    1751                 }
    1752 
    1753                 route = ip_routes_get_index(&netif->routes, 0);
    1754 
    1755                 // from the same network?
    1756                 if (route && ((route->address.s_addr & route->netmask.s_addr) ==
    1757                     (header->destination_address & route->netmask.s_addr))) {
    1758                         // clear the ARP mapping if any
    1759                         address.value = (char *) &header->destination_address;
    1760                         address.length = CONVERT_SIZE(uint8_t, char,
    1761                             sizeof(header->destination_address));
    1762                         arp_clear_address_req(netif->arp->phone,
    1763                             netif->device_id, SERVICE_IP, &address);
    1764                 }
    1765 
    1766                 fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
    1767                 break;
    1768 
    1769         default:
    1770                 return ip_release_and_return(packet, ENOTSUP);
    1771         }
    1772 
    1773         return ip_deliver_local(device_id, packet, header, error);
    1774 }
    1775 
    1776 static int
    1777 ip_get_route_req_local(int ip_phone, ip_protocol_t protocol,
    1778     const struct sockaddr *destination, socklen_t addrlen,
    1779     device_id_t *device_id, void **header, size_t *headerlen)
    1780 {
    1781         struct sockaddr_in *address_in;
    1782         in_addr_t *dest;
    1783         in_addr_t *src;
    1784         ip_route_ref route;
    1785         ipv4_pseudo_header_ref header_in;
    1786 
    1787         if (!destination || (addrlen <= 0))
    1788                 return EINVAL;
    1789 
    1790         if (!device_id || !header || !headerlen)
    1791                 return EBADMEM;
    1792 
    1793         if ((size_t) addrlen < sizeof(struct sockaddr))
    1794                 return EINVAL;
    1795 
    1796         switch (destination->sa_family) {
    1797         case AF_INET:
    1798                 if (addrlen != sizeof(struct sockaddr_in))
    1799                         return EINVAL;
    1800                 address_in = (struct sockaddr_in *) destination;
    1801                 dest = &address_in->sin_addr;
    1802                 if (!dest->s_addr)
    1803                         dest->s_addr = IPV4_LOCALHOST_ADDRESS;
    1804                 break;
    1805 
    1806         case AF_INET6:
    1807         default:
    1808                 return EAFNOSUPPORT;
    1809         }
    1810 
    1811         fibril_rwlock_read_lock(&ip_globals.lock);
    1812         route = ip_find_route(*dest);
    1813         // if the local host is the destination
    1814         if (route && (route->address.s_addr == dest->s_addr) &&
    1815             (dest->s_addr != IPV4_LOCALHOST_ADDRESS)) {
    1816                 // find the loopback device to deliver
    1817                 dest->s_addr = IPV4_LOCALHOST_ADDRESS;
    1818                 route = ip_find_route(*dest);
    1819         }
    1820 
    1821         if (!route || !route->netif) {
    1822                 fibril_rwlock_read_unlock(&ip_globals.lock);
    1823                 return ENOENT;
    1824         }
    1825 
    1826         *device_id = route->netif->device_id;
    1827         src = ip_netif_address(route->netif);
    1828         fibril_rwlock_read_unlock(&ip_globals.lock);
    1829 
    1830         *headerlen = sizeof(*header_in);
    1831         header_in = (ipv4_pseudo_header_ref) malloc(*headerlen);
    1832         if (!header_in)
    1833                 return ENOMEM;
    1834 
    1835         bzero(header_in, *headerlen);
    1836         header_in->destination_address = dest->s_addr;
    1837         header_in->source_address = src->s_addr;
    1838         header_in->protocol = protocol;
    1839         header_in->data_length = 0;
    1840         *header = header_in;
    1841 
    1842         return EOK;
    1843 }
    1844 
    1845 /** Processes the received IP packet or the packet queue one by one.
    1846  *
    1847  * The packet is either passed to another module or released on error.
    1848  *
    1849  * @param[in] device_id The source device identifier.
    1850  * @param[in,out] packet The received packet.
    1851  * @returns             EOK on success and the packet is no longer needed.
    1852  * @returns             EINVAL if the packet is too small to carry the IP
    1853  *                      packet.
    1854  * @returns             EINVAL if the received address lengths differs from the
    1855  *                      registered values.
    1856  * @returns             ENOENT if the device is not found in the cache.
    1857  * @returns             ENOENT if the protocol for the device is not found in
    1858  *                      the cache.
    1859  * @returns             ENOMEM if there is not enough memory left.
    1860  */
    1861 static int ip_receive_message(device_id_t device_id, packet_t packet)
    1862 {
    1863         packet_t next;
    1864 
    1865         do {
    1866                 next = pq_detach(packet);
    1867                 ip_process_packet(device_id, packet);
    1868                 packet = next;
    1869         } while (packet);
    1870 
    1871         return EOK;
    1872 }
    1873 
    1874 /** Processes the IP message.
    1875  *
    1876  * @param[in] callid    The message identifier.
    1877  * @param[in] call      The message parameters.
    1878  * @param[out] answer   The message answer parameters.
    1879  * @param[out] answer_count The last parameter for the actual answer in the
    1880  *                      answer parameter.
    1881  * @returns             EOK on success.
    1882  * @returns             ENOTSUP if the message is not known.
    1883  *
    1884  * @see ip_interface.h
    1885  * @see il_interface.h
    1886  * @see IS_NET_IP_MESSAGE()
    1887  */
    1888 int
    1889 ip_message_standalone(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer,
    1890     int *answer_count)
    1891 {
    1892894        packet_t packet;
    1893895        struct sockaddr *addr;
     
    1899901        size_t headerlen;
    1900902        device_id_t device_id;
    1901         int rc;
    1902903       
    1903904        *answer_count = 0;
    1904905        switch (IPC_GET_METHOD(*call)) {
    1905         case IPC_M_PHONE_HUNGUP:
    1906                 return EOK;
    1907        
    1908         case IPC_M_CONNECT_TO_ME:
    1909                 return ip_register(IL_GET_PROTO(call), IL_GET_SERVICE(call),
    1910                     IPC_GET_PHONE(call), NULL);
    1911        
    1912         case NET_IL_DEVICE:
    1913                 return ip_device_req_local(0, IPC_GET_DEVICE(call),
    1914                     IPC_GET_SERVICE(call));
    1915        
    1916         case NET_IL_SEND:
    1917                 rc = packet_translate_remote(ip_globals.net_phone, &packet,
    1918                     IPC_GET_PACKET(call));
    1919                 if (rc != EOK)
    1920                         return rc;
    1921                 return ip_send_msg_local(0, IPC_GET_DEVICE(call), packet, 0,
    1922                     IPC_GET_ERROR(call));
    1923        
    1924         case NET_IL_DEVICE_STATE:
    1925                 return ip_device_state_message(IPC_GET_DEVICE(call),
    1926                     IPC_GET_STATE(call));
    1927        
    1928         case NET_IL_RECEIVED:
    1929                 rc = packet_translate_remote(ip_globals.net_phone, &packet,
    1930                     IPC_GET_PACKET(call));
    1931                 if (rc != EOK)
    1932                         return rc;
    1933                 return ip_receive_message(IPC_GET_DEVICE(call), packet);
    1934        
    1935         case NET_IP_RECEIVED_ERROR:
    1936                 rc = packet_translate_remote(ip_globals.net_phone, &packet,
    1937                     IPC_GET_PACKET(call));
    1938                 if (rc != EOK)
    1939                         return rc;
    1940                 return ip_received_error_msg_local(0, IPC_GET_DEVICE(call),
    1941                     packet, IPC_GET_TARGET(call), IPC_GET_ERROR(call));
    1942        
    1943         case NET_IP_ADD_ROUTE:
    1944                 return ip_add_route_req_local(0, IPC_GET_DEVICE(call),
    1945                     IP_GET_ADDRESS(call), IP_GET_NETMASK(call),
    1946                     IP_GET_GATEWAY(call));
    1947 
    1948         case NET_IP_SET_GATEWAY:
    1949                 return ip_set_gateway_req_local(0, IPC_GET_DEVICE(call),
    1950                     IP_GET_GATEWAY(call));
    1951 
    1952         case NET_IP_GET_ROUTE:
    1953                 rc = data_receive((void **) &addr, &addrlen);
    1954                 if (rc != EOK)
    1955                         return rc;
    1956                
    1957                 rc = ip_get_route_req_local(0, IP_GET_PROTOCOL(call), addr,
    1958                     (socklen_t) addrlen, &device_id, &header, &headerlen);
    1959                 if (rc != EOK)
    1960                         return rc;
    1961                
    1962                 IPC_SET_DEVICE(answer, device_id);
    1963                 IP_SET_HEADERLEN(answer, headerlen);
    1964                
    1965                 *answer_count = 2;
    1966                
    1967                 rc = data_reply(&headerlen, sizeof(headerlen));
    1968                 if (rc == EOK)
    1969                         rc = data_reply(header, headerlen);
     906                case IPC_M_PHONE_HUNGUP:
     907                        return EOK;
     908                case NET_IL_DEVICE:
     909                        return ip_device_req_local(0, IPC_GET_DEVICE(call),
     910                            IPC_GET_SERVICE(call));
     911                case IPC_M_CONNECT_TO_ME:
     912                        return ip_register(IL_GET_PROTO(call), IL_GET_SERVICE(call),
     913                            IPC_GET_PHONE(call), NULL);
     914                case NET_IL_SEND:
     915                        ERROR_PROPAGATE(packet_translate_remote(ip_globals.net_phone, &packet,
     916                            IPC_GET_PACKET(call)));
     917                        return ip_send_msg_local(0, IPC_GET_DEVICE(call), packet, 0,
     918                            IPC_GET_ERROR(call));
     919                case NET_IL_DEVICE_STATE:
     920                        return ip_device_state_message(IPC_GET_DEVICE(call),
     921                            IPC_GET_STATE(call));
     922                case NET_IL_RECEIVED:
     923                        ERROR_PROPAGATE(packet_translate_remote(ip_globals.net_phone, &packet,
     924                            IPC_GET_PACKET(call)));
     925                        return ip_receive_message(IPC_GET_DEVICE(call), packet);
     926                case NET_IP_RECEIVED_ERROR:
     927                        ERROR_PROPAGATE(packet_translate_remote(ip_globals.net_phone, &packet,
     928                            IPC_GET_PACKET(call)));
     929                        return ip_received_error_msg_local(0, IPC_GET_DEVICE(call), packet,
     930                            IPC_GET_TARGET(call), IPC_GET_ERROR(call));
     931                case NET_IP_ADD_ROUTE:
     932                        return ip_add_route_req_local(0, IPC_GET_DEVICE(call),
     933                            IP_GET_ADDRESS(call), IP_GET_NETMASK(call), IP_GET_GATEWAY(call));
     934                case NET_IP_SET_GATEWAY:
     935                        return ip_set_gateway_req_local(0, IPC_GET_DEVICE(call),
     936                            IP_GET_GATEWAY(call));
     937                case NET_IP_GET_ROUTE:
     938                        ERROR_PROPAGATE(data_receive((void **) &addr, &addrlen));
     939                        ERROR_PROPAGATE(ip_get_route_req_local(0, IP_GET_PROTOCOL(call),
     940                            addr, (socklen_t) addrlen, &device_id, &header, &headerlen));
     941                        IPC_SET_DEVICE(answer, device_id);
     942                        IP_SET_HEADERLEN(answer, headerlen);
    1970943                       
    1971                 free(header);
    1972                 return rc;
    1973        
    1974         case NET_IL_PACKET_SPACE:
    1975                 rc = ip_packet_size_message(IPC_GET_DEVICE(call), &addrlen,
    1976                     &prefix, &content, &suffix);
    1977                 if (rc != EOK)
    1978                         return rc;
    1979                
    1980                 IPC_SET_ADDR(answer, addrlen);
    1981                 IPC_SET_PREFIX(answer, prefix);
    1982                 IPC_SET_CONTENT(answer, content);
    1983                 IPC_SET_SUFFIX(answer, suffix);
    1984                 *answer_count = 4;
    1985                 return EOK;
    1986        
    1987         case NET_IL_MTU_CHANGED:
    1988                 return ip_mtu_changed_message(IPC_GET_DEVICE(call),
    1989                     IPC_GET_MTU(call));
     944                        *answer_count = 2;
     945                       
     946                        if (!ERROR_OCCURRED(data_reply(&headerlen, sizeof(headerlen))))
     947                                ERROR_CODE = data_reply(header, headerlen);
     948                       
     949                        free(header);
     950                        return ERROR_CODE;
     951                case NET_IL_PACKET_SPACE:
     952                        ERROR_PROPAGATE(ip_packet_size_message(IPC_GET_DEVICE(call),
     953                            &addrlen, &prefix, &content, &suffix));
     954                        IPC_SET_ADDR(answer, addrlen);
     955                        IPC_SET_PREFIX(answer, prefix);
     956                        IPC_SET_CONTENT(answer, content);
     957                        IPC_SET_SUFFIX(answer, suffix);
     958                        *answer_count = 4;
     959                        return EOK;
     960                case NET_IL_MTU_CHANGED:
     961                        return ip_mtu_changed_message(IPC_GET_DEVICE(call),
     962                            IPC_GET_MTU(call));
    1990963        }
    1991964       
     
    1993966}
    1994967
     968int ip_packet_size_req_local(int ip_phone, device_id_t device_id,
     969    packet_dimension_ref packet_dimension)
     970{
     971        if (!packet_dimension)
     972                return EBADMEM;
     973       
     974        return ip_packet_size_message(device_id, &packet_dimension->addr_len,
     975            &packet_dimension->prefix, &packet_dimension->content,
     976            &packet_dimension->suffix);
     977}
     978
     979int ip_packet_size_message(device_id_t device_id, size_t * addr_len, size_t * prefix, size_t * content, size_t * suffix){
     980        ip_netif_ref netif;
     981        int index;
     982
     983        if(!(addr_len && prefix && content && suffix)){
     984                return EBADMEM;
     985        }
     986        *content = IP_MAX_CONTENT - IP_PREFIX;
     987        fibril_rwlock_read_lock(&ip_globals.netifs_lock);
     988        if(device_id < 0){
     989                *addr_len = IP_ADDR;
     990                *prefix = 0;
     991                *suffix = 0;
     992                for(index = ip_netifs_count(&ip_globals.netifs) - 1; index >= 0; -- index){
     993                        netif = ip_netifs_get_index(&ip_globals.netifs, index);
     994                        if(netif){
     995                                if(netif->packet_dimension.addr_len > * addr_len){
     996                                        *addr_len = netif->packet_dimension.addr_len;
     997                                }
     998                                if(netif->packet_dimension.prefix > * prefix){
     999                                        *prefix = netif->packet_dimension.prefix;
     1000                                }
     1001                                if(netif->packet_dimension.suffix > * suffix){
     1002                                        *suffix = netif->packet_dimension.suffix;
     1003                                }
     1004                        }
     1005                }
     1006                *prefix = * prefix + IP_PREFIX;
     1007                *suffix = * suffix + IP_SUFFIX;
     1008        }else{
     1009                netif = ip_netifs_find(&ip_globals.netifs, device_id);
     1010                if(! netif){
     1011                        fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
     1012                        return ENOENT;
     1013                }
     1014                *addr_len = (netif->packet_dimension.addr_len > IP_ADDR) ? netif->packet_dimension.addr_len : IP_ADDR;
     1015                *prefix = netif->packet_dimension.prefix + IP_PREFIX;
     1016                *suffix = netif->packet_dimension.suffix + IP_SUFFIX;
     1017        }
     1018        fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
     1019        return EOK;
     1020}
     1021
     1022int ip_add_route_req_local(int ip_phone, device_id_t device_id, in_addr_t address, in_addr_t netmask, in_addr_t gateway){
     1023        ip_route_ref route;
     1024        ip_netif_ref netif;
     1025        int index;
     1026
     1027        fibril_rwlock_write_lock(&ip_globals.netifs_lock);
     1028        netif = ip_netifs_find(&ip_globals.netifs, device_id);
     1029        if(! netif){
     1030                fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
     1031                return ENOENT;
     1032        }
     1033        route = (ip_route_ref) malloc(sizeof(ip_route_t));
     1034        if(! route){
     1035                fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
     1036                return ENOMEM;
     1037        }
     1038        route->address.s_addr = address.s_addr;
     1039        route->netmask.s_addr = netmask.s_addr;
     1040        route->gateway.s_addr = gateway.s_addr;
     1041        route->netif = netif;
     1042        index = ip_routes_add(&netif->routes, route);
     1043        if(index < 0){
     1044                free(route);
     1045        }
     1046        fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
     1047        return index;
     1048}
     1049
     1050ip_route_ref ip_find_route(in_addr_t destination){
     1051        int index;
     1052        ip_route_ref route;
     1053        ip_netif_ref netif;
     1054
     1055        // start with the last netif - the newest one
     1056        index = ip_netifs_count(&ip_globals.netifs) - 1;
     1057        while(index >= 0){
     1058                netif = ip_netifs_get_index(&ip_globals.netifs, index);
     1059                if(netif && (netif->state == NETIF_ACTIVE)){
     1060                        route = ip_netif_find_route(netif, destination);
     1061                        if(route){
     1062                                return route;
     1063                        }
     1064                }
     1065                -- index;
     1066        }
     1067        return &ip_globals.gateway;
     1068}
     1069
     1070ip_route_ref ip_netif_find_route(ip_netif_ref netif, in_addr_t destination){
     1071        int index;
     1072        ip_route_ref route;
     1073
     1074        if(netif){
     1075                // start with the first one - the direct route
     1076                for(index = 0; index < ip_routes_count(&netif->routes); ++ index){
     1077                        route = ip_routes_get_index(&netif->routes, index);
     1078                        if(route && ((route->address.s_addr &route->netmask.s_addr) == (destination.s_addr &route->netmask.s_addr))){
     1079                                return route;
     1080                        }
     1081                }
     1082        }
     1083        return NULL;
     1084}
     1085
     1086int ip_set_gateway_req_local(int ip_phone, device_id_t device_id, in_addr_t gateway)
     1087{
     1088        ip_netif_ref netif;
     1089
     1090        fibril_rwlock_write_lock(&ip_globals.netifs_lock);
     1091        netif = ip_netifs_find(&ip_globals.netifs, device_id);
     1092        if(! netif){
     1093                fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
     1094                return ENOENT;
     1095        }
     1096        ip_globals.gateway.address.s_addr = 0;
     1097        ip_globals.gateway.netmask.s_addr = 0;
     1098        ip_globals.gateway.gateway.s_addr = gateway.s_addr;
     1099        ip_globals.gateway.netif = netif;
     1100        fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
     1101        return EOK;
     1102}
     1103
     1104packet_t ip_split_packet(packet_t packet, size_t prefix, size_t content, size_t suffix, socklen_t addr_len, services_t error){
     1105        size_t length;
     1106        packet_t next;
     1107        packet_t new_packet;
     1108        int result;
     1109        int phone;
     1110
     1111        next = packet;
     1112        // check all packets
     1113        while(next){
     1114                length = packet_get_data_length(next);
     1115                // too long?
     1116                if(length > content){
     1117                        result = ip_fragment_packet(next, content, prefix, suffix, addr_len);
     1118                        if(result != EOK){
     1119                                new_packet = pq_detach(next);
     1120                                if(next == packet){
     1121                                        // the new first packet of the queue
     1122                                        packet = new_packet;
     1123                                }
     1124                                // fragmentation needed?
     1125                                if(result == EPERM){
     1126                                        phone = ip_prepare_icmp_and_get_phone(error, next, NULL);
     1127                                        if(phone >= 0){
     1128                                                // fragmentation necessary ICMP
     1129                                                icmp_destination_unreachable_msg(phone, ICMP_FRAG_NEEDED, content, next);
     1130                                        }
     1131                                }else{
     1132                                        pq_release_remote(ip_globals.net_phone, packet_get_id(next));
     1133                                }
     1134                                next = new_packet;
     1135                                continue;
     1136                        }
     1137                }
     1138                next = pq_next(next);
     1139        }
     1140        return packet;
     1141}
     1142
     1143int ip_fragment_packet(packet_t packet, size_t length, size_t prefix, size_t suffix, socklen_t addr_len){
     1144        ERROR_DECLARE;
     1145
     1146        packet_t new_packet;
     1147        ip_header_ref header;
     1148        ip_header_ref middle_header;
     1149        ip_header_ref last_header;
     1150        struct sockaddr * src;
     1151        struct sockaddr * dest;
     1152        socklen_t addrlen;
     1153        int result;
     1154
     1155        result = packet_get_addr(packet, (uint8_t **) &src, (uint8_t **) &dest);
     1156        if(result <= 0){
     1157                return EINVAL;
     1158        }
     1159        addrlen = (socklen_t) result;
     1160        if(packet_get_data_length(packet) <= sizeof(ip_header_t)){
     1161                return ENOMEM;
     1162        }
     1163        // get header
     1164        header = (ip_header_ref) packet_get_data(packet);
     1165        if(! header){
     1166                return EINVAL;
     1167        }
     1168        // fragmentation forbidden?
     1169        if(header->flags &IPFLAG_DONT_FRAGMENT){
     1170                return EPERM;
     1171        }
     1172        // create the last fragment
     1173        new_packet = packet_get_4_remote(ip_globals.net_phone, prefix, length, suffix, ((addrlen > addr_len) ? addrlen : addr_len));
     1174        if(! new_packet){
     1175                return ENOMEM;
     1176        }
     1177        // allocate as much as originally
     1178        last_header = (ip_header_ref) packet_suffix(new_packet, IP_HEADER_LENGTH(header));
     1179        if(! last_header){
     1180                return ip_release_and_return(packet, ENOMEM);
     1181        }
     1182        ip_create_last_header(last_header, header);
     1183        // trim the unused space
     1184        if(ERROR_OCCURRED(packet_trim(new_packet, 0, IP_HEADER_LENGTH(header) - IP_HEADER_LENGTH(last_header)))){
     1185                return ip_release_and_return(packet, ERROR_CODE);
     1186        }
     1187        // biggest multiple of 8 lower than content
     1188        // TODO even fragmentation?
     1189        length = length &(~ 0x7);// (content / 8) * 8
     1190        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))){
     1191                return ip_release_and_return(packet, ERROR_CODE);
     1192        }
     1193        // mark the first as fragmented
     1194        header->flags |= IPFLAG_MORE_FRAGMENTS;
     1195        // create middle framgents
     1196        while(IP_TOTAL_LENGTH(header) > length){
     1197                new_packet = packet_get_4_remote(ip_globals.net_phone, prefix, length, suffix, ((addrlen >= addr_len) ? addrlen : addr_len));
     1198                if(! new_packet){
     1199                        return ENOMEM;
     1200                }
     1201                middle_header = ip_create_middle_header(new_packet, last_header);
     1202                if(! middle_header){
     1203                        return ip_release_and_return(packet, ENOMEM);
     1204                }
     1205                if(ERROR_OCCURRED(ip_fragment_packet_data(packet, new_packet, header, middle_header, (length - IP_HEADER_LENGTH(middle_header)) &(~ 0x7), src, dest, addrlen))){
     1206                        return ip_release_and_return(packet, ERROR_CODE);
     1207                }
     1208        }
     1209        // finish the first fragment
     1210        header->header_checksum = IP_HEADER_CHECKSUM(header);
     1211        return EOK;
     1212}
     1213
     1214int 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){
     1215        ERROR_DECLARE;
     1216
     1217        void * data;
     1218        size_t offset;
     1219
     1220        data = packet_suffix(new_packet, length);
     1221        if(! data){
     1222                return ENOMEM;
     1223        }
     1224        memcpy(data, ((void *) header) + IP_TOTAL_LENGTH(header) - length, length);
     1225        ERROR_PROPAGATE(packet_trim(packet, 0, length));
     1226        header->total_length = htons(IP_TOTAL_LENGTH(header) - length);
     1227        new_header->total_length = htons(IP_HEADER_LENGTH(new_header) + length);
     1228        offset = IP_FRAGMENT_OFFSET(header) + IP_HEADER_DATA_LENGTH(header);
     1229        new_header->fragment_offset_high = IP_COMPUTE_FRAGMENT_OFFSET_HIGH(offset);
     1230        new_header->fragment_offset_low = IP_COMPUTE_FRAGMENT_OFFSET_LOW(offset);
     1231        new_header->header_checksum = IP_HEADER_CHECKSUM(new_header);
     1232        ERROR_PROPAGATE(packet_set_addr(new_packet, (const uint8_t *) src, (const uint8_t *) dest, addrlen));
     1233        return pq_insert_after(packet, new_packet);
     1234}
     1235
     1236ip_header_ref ip_create_middle_header(packet_t packet, ip_header_ref last){
     1237        ip_header_ref middle;
     1238
     1239        middle = (ip_header_ref) packet_suffix(packet, IP_HEADER_LENGTH(last));
     1240        if(! middle){
     1241                return NULL;
     1242        }
     1243        memcpy(middle, last, IP_HEADER_LENGTH(last));
     1244        middle->flags |= IPFLAG_MORE_FRAGMENTS;
     1245        return middle;
     1246}
     1247
     1248void ip_create_last_header(ip_header_ref last, ip_header_ref first){
     1249        ip_option_ref option;
     1250        size_t next;
     1251        size_t length;
     1252
     1253        // copy first itself
     1254        memcpy(last, first, sizeof(ip_header_t));
     1255        length = sizeof(ip_header_t);
     1256        next = sizeof(ip_header_t);
     1257        // process all ip options
     1258        while(next < first->header_length){
     1259                option = (ip_option_ref) (((uint8_t *) first) + next);
     1260                // skip end or noop
     1261                if((option->type == IPOPT_END) || (option->type == IPOPT_NOOP)){
     1262                        ++ next;
     1263                }else{
     1264                        // copy if said so or skip
     1265                        if(IPOPT_COPIED(option->type)){
     1266                                memcpy(((uint8_t *) last) + length, ((uint8_t *) first) + next, option->length);
     1267                                length += option->length;
     1268                        }
     1269                        // next option
     1270                        next += option->length;
     1271                }
     1272        }
     1273        // align 4 byte boundary
     1274        if(length % 4){
     1275                bzero(((uint8_t *) last) + length, 4 - (length % 4));
     1276                last->header_length = length / 4 + 1;
     1277        }else{
     1278                last->header_length = length / 4;
     1279        }
     1280        last->header_checksum = 0;
     1281}
     1282
     1283int ip_receive_message(device_id_t device_id, packet_t packet){
     1284        packet_t next;
     1285
     1286        do{
     1287                next = pq_detach(packet);
     1288                ip_process_packet(device_id, packet);
     1289                packet = next;
     1290        }while(packet);
     1291        return EOK;
     1292}
     1293
     1294int ip_process_packet(device_id_t device_id, packet_t packet){
     1295        ERROR_DECLARE;
     1296
     1297        ip_header_ref header;
     1298        in_addr_t dest;
     1299        ip_route_ref route;
     1300        int phone;
     1301        struct sockaddr * addr;
     1302        struct sockaddr_in addr_in;
     1303//      struct sockaddr_in      addr_in6;
     1304        socklen_t addrlen;
     1305
     1306        header = (ip_header_ref) packet_get_data(packet);
     1307        if(! header){
     1308                return ip_release_and_return(packet, ENOMEM);
     1309        }
     1310        // checksum
     1311        if((header->header_checksum) && (IP_HEADER_CHECKSUM(header) != IP_CHECKSUM_ZERO)){
     1312                phone = ip_prepare_icmp_and_get_phone(0, packet, header);
     1313                if(phone >= 0){
     1314                        // checksum error ICMP
     1315                        icmp_parameter_problem_msg(phone, ICMP_PARAM_POINTER, ((size_t) ((void *) &header->header_checksum)) - ((size_t) ((void *) header)), packet);
     1316                }
     1317                return EINVAL;
     1318        }
     1319        if(header->ttl <= 1){
     1320                phone = ip_prepare_icmp_and_get_phone(0, packet, header);
     1321                if(phone >= 0){
     1322                        // ttl oxceeded ICMP
     1323                        icmp_time_exceeded_msg(phone, ICMP_EXC_TTL, packet);
     1324                }
     1325                return EINVAL;
     1326        }
     1327        // process ipopt and get destination
     1328        dest = ip_get_destination(header);
     1329        // set the addrination address
     1330        switch(header->version){
     1331                case IPVERSION:
     1332                        addrlen = sizeof(addr_in);
     1333                        bzero(&addr_in, addrlen);
     1334                        addr_in.sin_family = AF_INET;
     1335                        memcpy(&addr_in.sin_addr.s_addr, &dest, sizeof(dest));
     1336                        addr = (struct sockaddr *) &addr_in;
     1337                        break;
     1338/*              case IPv6VERSION:
     1339                        addrlen = sizeof(dest_in6);
     1340                        bzero(&dest_in6, addrlen);
     1341                        dest_in6.sin6_family = AF_INET6;
     1342                        memcpy(&dest_in6.sin6_addr.s6_addr,);
     1343                        dest = (struct sockaddr *) &dest_in;
     1344                        break;
     1345*/              default:
     1346                        return ip_release_and_return(packet, EAFNOSUPPORT);
     1347        }
     1348        ERROR_PROPAGATE(packet_set_addr(packet, NULL, (uint8_t *) &addr, addrlen));
     1349        route = ip_find_route(dest);
     1350        if(! route){
     1351                phone = ip_prepare_icmp_and_get_phone(0, packet, header);
     1352                if(phone >= 0){
     1353                        // unreachable ICMP
     1354                        icmp_destination_unreachable_msg(phone, ICMP_HOST_UNREACH, 0, packet);
     1355                }
     1356                return ENOENT;
     1357        }
     1358        if(route->address.s_addr == dest.s_addr){
     1359                // local delivery
     1360                return ip_deliver_local(device_id, packet, header, 0);
     1361        }else{
     1362                // only if routing enabled
     1363                if(route->netif->routing){
     1364                        -- header->ttl;
     1365                        return ip_send_route(packet, route->netif, route, NULL, dest, 0);
     1366                }else{
     1367                        phone = ip_prepare_icmp_and_get_phone(0, packet, header);
     1368                        if(phone >= 0){
     1369                                // unreachable ICMP if no routing
     1370                                icmp_destination_unreachable_msg(phone, ICMP_HOST_UNREACH, 0, packet);
     1371                        }
     1372                        return ENOENT;
     1373                }
     1374        }
     1375}
     1376
     1377/** Notify the IP module about the received error notification packet.
     1378 *
     1379 * @param[in] ip_phone  The IP module phone used for (semi)remote calls.
     1380 * @param[in] device_id The device identifier.
     1381 * @param[in] packet    The received packet or the received packet queue.
     1382 * @param[in] target    The target internetwork module service to be
     1383 *                      delivered to.
     1384 * @param[in] error     The packet error reporting service. Prefixes the
     1385 *                      received packet.
     1386 *
     1387 * @return EOK on success.
     1388 *
     1389 */
     1390int ip_received_error_msg_local(int ip_phone, device_id_t device_id, packet_t packet, services_t target, services_t error){
     1391        uint8_t * data;
     1392        int offset;
     1393        icmp_type_t type;
     1394        icmp_code_t code;
     1395        ip_netif_ref netif;
     1396        measured_string_t address;
     1397        ip_route_ref route;
     1398        ip_header_ref header;
     1399
     1400        switch(error){
     1401                case SERVICE_ICMP:
     1402                        offset = icmp_client_process_packet(packet, &type, &code, NULL, NULL);
     1403                        if(offset < 0){
     1404                                return ip_release_and_return(packet, ENOMEM);
     1405                        }
     1406                        data = packet_get_data(packet);
     1407                        header = (ip_header_ref)(data + offset);
     1408                        // destination host unreachable?
     1409                        if((type == ICMP_DEST_UNREACH) && (code == ICMP_HOST_UNREACH)){
     1410                                fibril_rwlock_read_lock(&ip_globals.netifs_lock);
     1411                                netif = ip_netifs_find(&ip_globals.netifs, device_id);
     1412                                if(netif && netif->arp){
     1413                                        route = ip_routes_get_index(&netif->routes, 0);
     1414                                        // from the same network?
     1415                                        if(route && ((route->address.s_addr &route->netmask.s_addr) == (header->destination_address &route->netmask.s_addr))){
     1416                                                // clear the ARP mapping if any
     1417                                                address.value = (char *) &header->destination_address;
     1418                                                address.length = CONVERT_SIZE(uint8_t, char, sizeof(header->destination_address));
     1419                                                arp_clear_address_req(netif->arp->phone, netif->device_id, SERVICE_IP, &address);
     1420                                        }
     1421                                }
     1422                                fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
     1423                        }
     1424                        break;
     1425                default:
     1426                        return ip_release_and_return(packet, ENOTSUP);
     1427        }
     1428        return ip_deliver_local(device_id, packet, header, error);
     1429}
     1430
     1431int ip_deliver_local(device_id_t device_id, packet_t packet, ip_header_ref header, services_t error){
     1432        ERROR_DECLARE;
     1433
     1434        ip_proto_ref proto;
     1435        int phone;
     1436        services_t service;
     1437        tl_received_msg_t received_msg;
     1438        struct sockaddr * src;
     1439        struct sockaddr * dest;
     1440        struct sockaddr_in src_in;
     1441        struct sockaddr_in dest_in;
     1442//      struct sockaddr_in      src_in6;
     1443//      struct sockaddr_in      dest_in6;
     1444        socklen_t addrlen;
     1445
     1446        if((header->flags &IPFLAG_MORE_FRAGMENTS) || IP_FRAGMENT_OFFSET(header)){
     1447                // TODO fragmented
     1448                return ENOTSUP;
     1449        }else{
     1450                switch(header->version){
     1451                        case IPVERSION:
     1452                                addrlen = sizeof(src_in);
     1453                                bzero(&src_in, addrlen);
     1454                                src_in.sin_family = AF_INET;
     1455                                memcpy(&dest_in, &src_in, addrlen);
     1456                                memcpy(&src_in.sin_addr.s_addr, &header->source_address, sizeof(header->source_address));
     1457                                memcpy(&dest_in.sin_addr.s_addr, &header->destination_address, sizeof(header->destination_address));
     1458                                src = (struct sockaddr *) &src_in;
     1459                                dest = (struct sockaddr *) &dest_in;
     1460                                break;
     1461/*                      case IPv6VERSION:
     1462                                addrlen = sizeof(src_in6);
     1463                                bzero(&src_in6, addrlen);
     1464                                src_in6.sin6_family = AF_INET6;
     1465                                memcpy(&dest_in6, &src_in6, addrlen);
     1466                                memcpy(&src_in6.sin6_addr.s6_addr,);
     1467                                memcpy(&dest_in6.sin6_addr.s6_addr,);
     1468                                src = (struct sockaddr *) &src_in;
     1469                                dest = (struct sockaddr *) &dest_in;
     1470                                break;
     1471*/                      default:
     1472                                return ip_release_and_return(packet, EAFNOSUPPORT);
     1473                }
     1474                if(ERROR_OCCURRED(packet_set_addr(packet, (uint8_t *) src, (uint8_t *) dest, addrlen))){
     1475                        return ip_release_and_return(packet, ERROR_CODE);
     1476                }
     1477                // trim padding if present
     1478                if((! error) && (IP_TOTAL_LENGTH(header) < packet_get_data_length(packet))){
     1479                        if(ERROR_OCCURRED(packet_trim(packet, 0, packet_get_data_length(packet) - IP_TOTAL_LENGTH(header)))){
     1480                                return ip_release_and_return(packet, ERROR_CODE);
     1481                        }
     1482                }
     1483                fibril_rwlock_read_lock(&ip_globals.protos_lock);
     1484                proto = ip_protos_find(&ip_globals.protos, header->protocol);
     1485                if(! proto){
     1486                        fibril_rwlock_read_unlock(&ip_globals.protos_lock);
     1487                        phone = ip_prepare_icmp_and_get_phone(error, packet, header);
     1488                        if(phone >= 0){
     1489                                // unreachable ICMP
     1490                                icmp_destination_unreachable_msg(phone, ICMP_PROT_UNREACH, 0, packet);
     1491                        }
     1492                        return ENOENT;
     1493                }
     1494                if(proto->received_msg){
     1495                        service = proto->service;
     1496                        received_msg = proto->received_msg;
     1497                        fibril_rwlock_read_unlock(&ip_globals.protos_lock);
     1498                        ERROR_CODE = received_msg(device_id, packet, service, error);
     1499                }else{
     1500                        ERROR_CODE = tl_received_msg(proto->phone, device_id, packet, proto->service, error);
     1501                        fibril_rwlock_read_unlock(&ip_globals.protos_lock);
     1502                }
     1503                return ERROR_CODE;
     1504        }
     1505}
     1506
     1507in_addr_t ip_get_destination(ip_header_ref header){
     1508        in_addr_t destination;
     1509
     1510        // TODO search set ipopt route?
     1511        destination.s_addr = header->destination_address;
     1512        return destination;
     1513}
     1514
     1515int ip_prepare_icmp(packet_t packet, ip_header_ref header){
     1516        packet_t next;
     1517        struct sockaddr * dest;
     1518        struct sockaddr_in dest_in;
     1519//      struct sockaddr_in      dest_in6;
     1520        socklen_t addrlen;
     1521
     1522        // detach the first packet and release the others
     1523        next = pq_detach(packet);
     1524        if(next){
     1525                pq_release_remote(ip_globals.net_phone, packet_get_id(next));
     1526        }
     1527        if(! header){
     1528                if(packet_get_data_length(packet) <= sizeof(ip_header_t)){
     1529                        return ENOMEM;
     1530                }
     1531                // get header
     1532                header = (ip_header_ref) packet_get_data(packet);
     1533                if(! header){
     1534                        return EINVAL;
     1535                }
     1536        }
     1537        // only for the first fragment
     1538        if(IP_FRAGMENT_OFFSET(header)){
     1539                return EINVAL;
     1540        }
     1541        // not for the ICMP protocol
     1542        if(header->protocol == IPPROTO_ICMP){
     1543                return EPERM;
     1544        }
     1545        // set the destination address
     1546        switch(header->version){
     1547                case IPVERSION:
     1548                        addrlen = sizeof(dest_in);
     1549                        bzero(&dest_in, addrlen);
     1550                        dest_in.sin_family = AF_INET;
     1551                        memcpy(&dest_in.sin_addr.s_addr, &header->source_address, sizeof(header->source_address));
     1552                        dest = (struct sockaddr *) &dest_in;
     1553                        break;
     1554/*              case IPv6VERSION:
     1555                        addrlen = sizeof(dest_in6);
     1556                        bzero(&dest_in6, addrlen);
     1557                        dest_in6.sin6_family = AF_INET6;
     1558                        memcpy(&dest_in6.sin6_addr.s6_addr,);
     1559                        dest = (struct sockaddr *) &dest_in;
     1560                        break;
     1561*/              default:
     1562                        return EAFNOSUPPORT;
     1563        }
     1564        return packet_set_addr(packet, NULL, (uint8_t *) dest, addrlen);
     1565}
     1566
     1567int ip_get_icmp_phone(void){
     1568        ip_proto_ref proto;
     1569        int phone;
     1570
     1571        fibril_rwlock_read_lock(&ip_globals.protos_lock);
     1572        proto = ip_protos_find(&ip_globals.protos, IPPROTO_ICMP);
     1573        phone = proto ? proto->phone : ENOENT;
     1574        fibril_rwlock_read_unlock(&ip_globals.protos_lock);
     1575        return phone;
     1576}
     1577
     1578int ip_prepare_icmp_and_get_phone(services_t error, packet_t packet, ip_header_ref header){
     1579        int phone;
     1580
     1581        phone = ip_get_icmp_phone();
     1582        if(error || (phone < 0) || ip_prepare_icmp(packet, header)){
     1583                return ip_release_and_return(packet, EINVAL);
     1584        }
     1585        return phone;
     1586}
     1587
     1588int ip_release_and_return(packet_t packet, int result){
     1589        pq_release_remote(ip_globals.net_phone, packet_get_id(packet));
     1590        return result;
     1591}
     1592
     1593int ip_get_route_req_local(int ip_phone, ip_protocol_t protocol, const struct sockaddr * destination, socklen_t addrlen, device_id_t * device_id, void **header, size_t * headerlen){
     1594        struct sockaddr_in * address_in;
     1595//      struct sockaddr_in6 *   address_in6;
     1596        in_addr_t * dest;
     1597        in_addr_t * src;
     1598        ip_route_ref route;
     1599        ipv4_pseudo_header_ref header_in;
     1600
     1601        if(!(destination && (addrlen > 0))){
     1602                return EINVAL;
     1603        }
     1604        if(!(device_id && header && headerlen)){
     1605                return EBADMEM;
     1606        }
     1607        if((size_t) addrlen < sizeof(struct sockaddr)){
     1608                return EINVAL;
     1609        }
     1610        switch(destination->sa_family){
     1611                case AF_INET:
     1612                        if(addrlen != sizeof(struct sockaddr_in)){
     1613                                return EINVAL;
     1614                        }
     1615                        address_in = (struct sockaddr_in *) destination;
     1616                        dest = &address_in->sin_addr;
     1617                        if(! dest->s_addr){
     1618                                dest->s_addr = IPV4_LOCALHOST_ADDRESS;
     1619                        }
     1620                        break;
     1621                // TODO IPv6
     1622/*              case AF_INET6:
     1623                        if(addrlen != sizeof(struct sockaddr_in6)){
     1624                                return EINVAL;
     1625                        }
     1626                        address_in6 = (struct sockaddr_in6 *) dest;
     1627                        address_in6.sin6_addr.s6_addr;
     1628*/              default:
     1629                        return EAFNOSUPPORT;
     1630        }
     1631        fibril_rwlock_read_lock(&ip_globals.lock);
     1632        route = ip_find_route(*dest);
     1633        // if the local host is the destination
     1634        if(route && (route->address.s_addr == dest->s_addr)
     1635                && (dest->s_addr != IPV4_LOCALHOST_ADDRESS)){
     1636                // find the loopback device to deliver
     1637                dest->s_addr = IPV4_LOCALHOST_ADDRESS;
     1638                route = ip_find_route(*dest);
     1639        }
     1640        if(!(route && route->netif)){
     1641                fibril_rwlock_read_unlock(&ip_globals.lock);
     1642                return ENOENT;
     1643        }
     1644        *device_id = route->netif->device_id;
     1645        src = ip_netif_address(route->netif);
     1646        fibril_rwlock_read_unlock(&ip_globals.lock);
     1647        *headerlen = sizeof(*header_in);
     1648        header_in = (ipv4_pseudo_header_ref) malloc(*headerlen);
     1649        if(! header_in){
     1650                return ENOMEM;
     1651        }
     1652        bzero(header_in, * headerlen);
     1653        header_in->destination_address = dest->s_addr;
     1654        header_in->source_address = src->s_addr;
     1655        header_in->protocol = protocol;
     1656        header_in->data_length = 0;
     1657        *header = header_in;
     1658        return EOK;
     1659}
     1660
    19951661/** Default thread for new connections.
    19961662 *
    1997  * @param[in] iid       The initial message identifier.
    1998  * @param[in] icall     The initial message call structure.
    1999  */
    2000 static void il_client_connection(ipc_callid_t iid, ipc_call_t *icall)
     1663 *  @param[in] iid The initial message identifier.
     1664 *  @param[in] icall The initial message call structure.
     1665 *
     1666 */
     1667static void il_client_connection(ipc_callid_t iid, ipc_call_t * icall)
    20011668{
    20021669        /*
     
    20061673        ipc_answer_0(iid, EOK);
    20071674       
    2008         while (true) {
     1675        while(true) {
    20091676                ipc_call_t answer;
    20101677                int answer_count;
     
    20211688                    &answer_count);
    20221689               
    2023                 /*
    2024                  * End if told to either by the message or the processing
    2025                  * result.
    2026                  */
    2027                 if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) ||
    2028                     (res == EHANGUP)) {
     1690                /* End if said to either by the message or the processing result */
     1691                if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) || (res == EHANGUP))
    20291692                        return;
    2030                 }
    20311693               
    20321694                /* Answer the message */
     
    20371699/** Starts the module.
    20381700 *
    2039  * @returns EOK on success.
    2040  * @returns Other error codes as defined for each specific module start function.
     1701 *  @param argc The count of the command line arguments. Ignored parameter.
     1702 *  @param argv The command line parameters. Ignored parameter.
     1703 *
     1704 *  @returns EOK on success.
     1705 *  @returns Other error codes as defined for each specific module start function.
     1706 *
    20411707 */
    20421708int main(int argc, char *argv[])
    20431709{
    2044         int rc;
     1710        ERROR_DECLARE;
    20451711       
    20461712        /* Start the module */
    2047         rc = il_module_start_standalone(il_client_connection);
    2048         return rc;
     1713        if (ERROR_OCCURRED(il_module_start_standalone(il_client_connection)))
     1714                return ERROR_CODE;
     1715       
     1716        return EOK;
    20491717}
    20501718
Note: See TracChangeset for help on using the changeset viewer.