Changeset 0b749a3 in mainline for uspace/srv/net/il/ip/ip.c


Ignore:
Timestamp:
2010-11-22T15:39:53Z (15 years ago)
Author:
Vojtech Horky <vojtechhorky@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
0eddb76, aae339e9
Parents:
9a1d8ab (diff), 8cd1aa5e (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 development/ changes

File:
1 edited

Legend:

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

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