Changeset 89c57b6 in mainline for uspace/srv/net/il/ip/ip.c


Ignore:
Timestamp:
2011-04-13T14:45:41Z (14 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
88634420
Parents:
cefb126 (diff), 17279ead (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge mainline changes.

File:
1 edited

Legend:

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

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