Ignore:
File:
1 edited

Legend:

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

    rccca251 rfd8e8e1  
    3636 */
    3737
     38#include "ip.h"
     39#include "ip_module.h"
     40
    3841#include <async.h>
    3942#include <errno.h>
     43#include <err.h>
    4044#include <fibril_synch.h>
    4145#include <stdio.h>
    4246#include <str.h>
     47#include <ipc/ipc.h>
    4348#include <ipc/services.h>
    4449#include <ipc/net.h>
     
    4853#include <sys/types.h>
    4954#include <byteorder.h>
    50 #include "ip.h"
    5155
    5256#include <adt/measured_strings.h>
     
    6670#include <net_checksum.h>
    6771#include <icmp_client.h>
    68 #include <icmp_remote.h>
     72#include <icmp_interface.h>
     73#include <il_interface.h>
    6974#include <ip_client.h>
    7075#include <ip_interface.h>
    7176#include <ip_header.h>
    7277#include <net_interface.h>
    73 #include <nil_remote.h>
    74 #include <tl_remote.h>
     78#include <nil_interface.h>
     79#include <tl_interface.h>
    7580#include <packet_remote.h>
    76 #include <il_remote.h>
    77 #include <il_skel.h>
     81#include <il_local.h>
    7882
    7983/** IP module name. */
     
    120124GENERIC_FIELD_IMPLEMENT(ip_routes, ip_route_t);
    121125
    122 static void ip_receiver(ipc_callid_t, ipc_call_t *);
    123 
    124126/** Releases the packet and returns the result.
    125127 *
     
    128130 * @return              The result parameter.
    129131 */
    130 static int ip_release_and_return(packet_t *packet, int result)
     132static int ip_release_and_return(packet_t packet, int result)
    131133{
    132134        pq_release_remote(ip_globals.net_phone, packet_get_id(packet));
     
    138140 * Searches the registered protocols.
    139141 *
    140  * @return              The found ICMP phone.
    141  * @return              ENOENT if the ICMP is not registered.
     142 * @returns             The found ICMP phone.
     143 * @returns             ENOENT if the ICMP is not registered.
    142144 */
    143145static int ip_get_icmp_phone(void)
    144146{
    145         ip_proto_t *proto;
     147        ip_proto_ref proto;
    146148        int phone;
    147149
     
    159161 * @param[in] packet    The packet or the packet queue to be reported as faulty.
    160162 * @param[in] header    The first packet IP header. May be NULL.
    161  * @return              EOK on success.
    162  * @return              EINVAL if there are no data in the packet.
    163  * @return              EINVAL if the packet is a fragment.
    164  * @return              ENOMEM if the packet is too short to contain the IP
     163 * @returns             EOK on success.
     164 * @returns             EINVAL if there are no data in the packet.
     165 * @returns             EINVAL if the packet is a fragment.
     166 * @returns             ENOMEM if the packet is too short to contain the IP
    165167 *                      header.
    166  * @return              EAFNOSUPPORT if the address family is not supported.
    167  * @return              EPERM if the protocol is not allowed to send ICMP
     168 * @returns             EAFNOSUPPORT if the address family is not supported.
     169 * @returns             EPERM if the protocol is not allowed to send ICMP
    168170 *                      notifications. The ICMP protocol itself.
    169  * @return              Other error codes as defined for the packet_set_addr().
    170  */
    171 static int ip_prepare_icmp(packet_t *packet, ip_header_t *header)
    172 {
    173         packet_t *next;
     171 * @returns             Other error codes as defined for the packet_set_addr().
     172 */
     173static int ip_prepare_icmp(packet_t packet, ip_header_ref header)
     174{
     175        packet_t next;
    174176        struct sockaddr *dest;
    175177        struct sockaddr_in dest_in;
    176178        socklen_t addrlen;
    177179
    178         /* Detach the first packet and release the others */
     180        // detach the first packet and release the others
    179181        next = pq_detach(packet);
    180182        if (next)
     
    185187                        return ENOMEM;
    186188
    187                 /* Get header */
    188                 header = (ip_header_t *) packet_get_data(packet);
     189                // get header
     190                header = (ip_header_ref) packet_get_data(packet);
    189191                if (!header)
    190192                        return EINVAL;
     
    192194        }
    193195
    194         /* Only for the first fragment */
     196        // only for the first fragment
    195197        if (IP_FRAGMENT_OFFSET(header))
    196198                return EINVAL;
    197199
    198         /* Not for the ICMP protocol */
     200        // not for the ICMP protocol
    199201        if (header->protocol == IPPROTO_ICMP)
    200202                return EPERM;
    201203
    202         /* Set the destination address */
     204        // set the destination address
    203205        switch (header->version) {
    204206        case IPVERSION:
     
    226228 * @param[in] packet    The packet or the packet queue to be reported as faulty.
    227229 * @param[in] header    The first packet IP header. May be NULL.
    228  * @return              The found ICMP phone.
    229  * @return              EINVAL if the error parameter is set.
    230  * @return              EINVAL if the ICMP phone is not found.
    231  * @return              EINVAL if the ip_prepare_icmp() fails.
     230 * @returns             The found ICMP phone.
     231 * @returns             EINVAL if the error parameter is set.
     232 * @returns             EINVAL if the ICMP phone is not found.
     233 * @returns             EINVAL if the ip_prepare_icmp() fails.
    232234 */
    233235static int
    234 ip_prepare_icmp_and_get_phone(services_t error, packet_t *packet,
    235     ip_header_t *header)
     236ip_prepare_icmp_and_get_phone(services_t error, packet_t packet,
     237    ip_header_ref header)
    236238{
    237239        int phone;
     
    243245}
    244246
    245 int il_initialize(int net_phone)
    246 {
     247/** Initializes the IP module.
     248 *
     249 * @param[in] client_connection The client connection processing function. The
     250 *                      module skeleton propagates its own one.
     251 * @returns             EOK on success.
     252 * @returns             ENOMEM if there is not enough memory left.
     253 */
     254int ip_initialize(async_client_conn_t client_connection)
     255{
     256        ERROR_DECLARE;
     257
    247258        fibril_rwlock_initialize(&ip_globals.lock);
    248259        fibril_rwlock_write_lock(&ip_globals.lock);
    249260        fibril_rwlock_initialize(&ip_globals.protos_lock);
    250261        fibril_rwlock_initialize(&ip_globals.netifs_lock);
    251        
    252         ip_globals.net_phone = net_phone;
    253262        ip_globals.packet_counter = 0;
    254263        ip_globals.gateway.address.s_addr = 0;
     
    256265        ip_globals.gateway.gateway.s_addr = 0;
    257266        ip_globals.gateway.netif = NULL;
    258        
    259         int rc = ip_netifs_initialize(&ip_globals.netifs);
    260         if (rc != EOK)
    261                 goto out;
    262         rc = ip_protos_initialize(&ip_globals.protos);
    263         if (rc != EOK)
    264                 goto out;
    265         rc = modules_initialize(&ip_globals.modules);
    266         if (rc != EOK)
    267                 goto out;
    268         rc = add_module(NULL, &ip_globals.modules, (uint8_t *) ARP_NAME,
    269             (uint8_t *) ARP_FILENAME, SERVICE_ARP, 0, arp_connect_module);
    270 
    271 out:
     267        ERROR_PROPAGATE(ip_netifs_initialize(&ip_globals.netifs));
     268        ERROR_PROPAGATE(ip_protos_initialize(&ip_globals.protos));
     269        ip_globals.client_connection = client_connection;
     270        ERROR_PROPAGATE(modules_initialize(&ip_globals.modules));
     271        ERROR_PROPAGATE(add_module(NULL, &ip_globals.modules, ARP_NAME,
     272            ARP_FILENAME, SERVICE_ARP, 0, arp_connect_module));
    272273        fibril_rwlock_write_unlock(&ip_globals.lock);
    273274
    274         return rc;
     275        return EOK;
    275276}
    276277
     
    284285 *
    285286 * @param[in,out] ip_netif Network interface specific data.
    286  * @return              EOK on success.
    287  * @return              ENOTSUP if DHCP is configured.
    288  * @return              ENOTSUP if IPv6 is configured.
    289  * @return              EINVAL if any of the addresses is invalid.
    290  * @return              EINVAL if the used ARP module is not known.
    291  * @return              ENOMEM if there is not enough memory left.
    292  * @return              Other error codes as defined for the
     287 * @returns             EOK on success.
     288 * @returns             ENOTSUP if DHCP is configured.
     289 * @returns             ENOTSUP if IPv6 is configured.
     290 * @returns             EINVAL if any of the addresses is invalid.
     291 * @returns             EINVAL if the used ARP module is not known.
     292 * @returns             ENOMEM if there is not enough memory left.
     293 * @returns             Other error codes as defined for the
    293294 *                      net_get_device_conf_req() function.
    294  * @return              Other error codes as defined for the bind_service()
     295 * @returns             Other error codes as defined for the bind_service()
    295296 *                      function.
    296  * @return              Other error codes as defined for the specific
     297 * @returns             Other error codes as defined for the specific
    297298 *                      arp_device_req() function.
    298  * @return              Other error codes as defined for the
     299 * @returns             Other error codes as defined for the
    299300 *                      nil_packet_size_req() function.
    300301 */
    301 static int ip_netif_initialize(ip_netif_t *ip_netif)
    302 {
     302static int ip_netif_initialize(ip_netif_ref ip_netif)
     303{
     304        ERROR_DECLARE;
     305
    303306        measured_string_t names[] = {
    304307                {
    305                         (uint8_t *) "IPV",
     308                        (char *) "IPV",
    306309                        3
    307310                },
    308311                {
    309                         (uint8_t *) "IP_CONFIG",
     312                        (char *) "IP_CONFIG",
    310313                        9
    311314                },
    312315                {
    313                         (uint8_t *) "IP_ADDR",
     316                        (char *) "IP_ADDR",
    314317                        7
    315318                },
    316319                {
    317                         (uint8_t *) "IP_NETMASK",
     320                        (char *) "IP_NETMASK",
    318321                        10
    319322                },
    320323                {
    321                         (uint8_t *) "IP_GATEWAY",
     324                        (char *) "IP_GATEWAY",
    322325                        10
    323326                },
    324327                {
    325                         (uint8_t *) "IP_BROADCAST",
     328                        (char *) "IP_BROADCAST",
    326329                        12
    327330                },
    328331                {
    329                         (uint8_t *) "ARP",
     332                        (char *) "ARP",
    330333                        3
    331334                },
    332335                {
    333                         (uint8_t *) "IP_ROUTING",
     336                        (char *) "IP_ROUTING",
    334337                        10
    335338                }
    336339        };
    337         measured_string_t *configuration;
     340        measured_string_ref configuration;
    338341        size_t count = sizeof(names) / sizeof(measured_string_t);
    339         uint8_t *data;
     342        char *data;
    340343        measured_string_t address;
    341         ip_route_t *route;
     344        int index;
     345        ip_route_ref route;
    342346        in_addr_t gateway;
    343         int index;
    344         int rc;
    345347
    346348        ip_netif->arp = NULL;
     
    351353        configuration = &names[0];
    352354
    353         /* Get configuration */
    354         rc = net_get_device_conf_req(ip_globals.net_phone, ip_netif->device_id,
    355             &configuration, count, &data);
    356         if (rc != EOK)
    357                 return rc;
    358        
     355        // get configuration
     356        ERROR_PROPAGATE(net_get_device_conf_req(ip_globals.net_phone,
     357            ip_netif->device_id, &configuration, count, &data));
    359358        if (configuration) {
    360359                if (configuration[0].value)
    361                         ip_netif->ipv = strtol((char *) configuration[0].value, NULL, 0);
    362                
    363                 ip_netif->dhcp = !str_lcmp((char *) configuration[1].value, "dhcp",
     360                        ip_netif->ipv = strtol(configuration[0].value, NULL, 0);
     361
     362                ip_netif->dhcp = !str_lcmp(configuration[1].value, "dhcp",
    364363                    configuration[1].length);
    365364               
     
    369368                        return ENOTSUP;
    370369                } else if (ip_netif->ipv == IPV4) {
    371                         route = (ip_route_t *) malloc(sizeof(ip_route_t));
     370                        route = (ip_route_ref) malloc(sizeof(ip_route_t));
    372371                        if (!route) {
    373372                                net_free_settings(configuration, data);
     
    384383                                return index;
    385384                        }
    386                        
    387                         if ((inet_pton(AF_INET, (char *) configuration[2].value,
    388                             (uint8_t *) &route->address.s_addr) != EOK) ||
    389                             (inet_pton(AF_INET, (char *) configuration[3].value,
    390                             (uint8_t *) &route->netmask.s_addr) != EOK) ||
    391                             (inet_pton(AF_INET, (char *) configuration[4].value,
     385                        if (ERROR_OCCURRED(inet_pton(AF_INET,
     386                            configuration[2].value,
     387                            (uint8_t *) &route->address.s_addr)) ||
     388                            ERROR_OCCURRED(inet_pton(AF_INET,
     389                            configuration[3].value,
     390                            (uint8_t *) &route->netmask.s_addr)) ||
     391                            (inet_pton(AF_INET, configuration[4].value,
    392392                            (uint8_t *) &gateway.s_addr) == EINVAL) ||
    393                             (inet_pton(AF_INET, (char *) configuration[5].value,
     393                            (inet_pton(AF_INET, configuration[5].value,
    394394                            (uint8_t *) &ip_netif->broadcast.s_addr) == EINVAL))
    395395                            {
     
    419419        }
    420420
    421         /* Bind netif service which also initializes the device */
     421        // binds the netif service which also initializes the device
    422422        ip_netif->phone = nil_bind_service(ip_netif->service,
    423             (sysarg_t) ip_netif->device_id, SERVICE_IP,
    424             ip_receiver);
     423            (ipcarg_t) ip_netif->device_id, SERVICE_IP,
     424            ip_globals.client_connection);
    425425        if (ip_netif->phone < 0) {
    426426                printf("Failed to contact the nil service %d\n",
     
    429429        }
    430430
    431         /* Has to be after the device netif module initialization */
     431        // has to be after the device netif module initialization
    432432        if (ip_netif->arp) {
    433433                if (route) {
    434                         address.value = (uint8_t *) &route->address.s_addr;
    435                         address.length = sizeof(in_addr_t);
    436                        
    437                         rc = arp_device_req(ip_netif->arp->phone,
     434                        address.value = (char *) &route->address.s_addr;
     435                        address.length = CONVERT_SIZE(in_addr_t, char, 1);
     436                        ERROR_PROPAGATE(arp_device_req(ip_netif->arp->phone,
    438437                            ip_netif->device_id, SERVICE_IP, ip_netif->service,
    439                             &address);
    440                         if (rc != EOK)
    441                                 return rc;
     438                            &address));
    442439                } else {
    443440                        ip_netif->arp = 0;
     
    445442        }
    446443
    447         /* Get packet dimensions */
    448         rc = nil_packet_size_req(ip_netif->phone, ip_netif->device_id,
    449             &ip_netif->packet_dimension);
    450         if (rc != EOK)
    451                 return rc;
    452        
     444        // get packet dimensions
     445        ERROR_PROPAGATE(nil_packet_size_req(ip_netif->phone,
     446            ip_netif->device_id, &ip_netif->packet_dimension));
    453447        if (ip_netif->packet_dimension.content < IP_MIN_CONTENT) {
    454                 printf("Maximum transmission unit %zu bytes is too small, at "
     448                printf("Maximum transmission unit %d bytes is too small, at "
    455449                    "least %d bytes are needed\n",
    456450                    ip_netif->packet_dimension.content, IP_MIN_CONTENT);
     
    463457       
    464458        if (gateway.s_addr) {
    465                 /* The default gateway */
     459                // the default gateway
    466460                ip_globals.gateway.address.s_addr = 0;
    467461                ip_globals.gateway.netmask.s_addr = 0;
    468462                ip_globals.gateway.gateway.s_addr = gateway.s_addr;
    469463                ip_globals.gateway.netif = ip_netif;
     464        }
     465
     466        return EOK;
     467}
     468
     469/** Updates the device content length according to the new MTU value.
     470 *
     471 * @param[in] device_id The device identifier.
     472 * @param[in] mtu       The new mtu value.
     473 * @returns             EOK on success.
     474 * @returns             ENOENT if device is not found.
     475 */
     476static int ip_mtu_changed_message(device_id_t device_id, size_t mtu)
     477{
     478        ip_netif_ref netif;
     479
     480        fibril_rwlock_write_lock(&ip_globals.netifs_lock);
     481        netif = ip_netifs_find(&ip_globals.netifs, device_id);
     482        if (!netif) {
     483                fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
     484                return ENOENT;
     485        }
     486        netif->packet_dimension.content = mtu;
     487        fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
     488
     489        printf("%s: Device %d changed MTU to %d\n", NAME, device_id, mtu);
     490
     491        return EOK;
     492}
     493
     494/** Updates the device state.
     495 *
     496 * @param[in] device_id The device identifier.
     497 * @param[in] state     The new state value.
     498 * @returns             EOK on success.
     499 * @returns             ENOENT if device is not found.
     500 */
     501static int ip_device_state_message(device_id_t device_id, device_state_t state)
     502{
     503        ip_netif_ref netif;
     504
     505        fibril_rwlock_write_lock(&ip_globals.netifs_lock);
     506        // find the device
     507        netif = ip_netifs_find(&ip_globals.netifs, device_id);
     508        if (!netif) {
     509                fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
     510                return ENOENT;
     511        }
     512        netif->state = state;
     513        fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
     514
     515        printf("%s: Device %d changed state to %d\n", NAME, device_id, state);
     516
     517        return EOK;
     518}
     519
     520
     521/** Prefixes a middle fragment header based on the last fragment header to the
     522 * packet.
     523 *
     524 * @param[in] packet    The packet to be prefixed.
     525 * @param[in] last      The last header to be copied.
     526 * @returns             The prefixed middle header.
     527 * @returns             NULL on error.
     528 */
     529static ip_header_ref
     530ip_create_middle_header(packet_t packet, ip_header_ref last)
     531{
     532        ip_header_ref middle;
     533
     534        middle = (ip_header_ref) packet_suffix(packet, IP_HEADER_LENGTH(last));
     535        if (!middle)
     536                return NULL;
     537        memcpy(middle, last, IP_HEADER_LENGTH(last));
     538        middle->flags |= IPFLAG_MORE_FRAGMENTS;
     539        return middle;
     540}
     541
     542/** Copies the fragment header.
     543 *
     544 * Copies only the header itself and relevant IP options.
     545 *
     546 * @param[out] last     The created header.
     547 * @param[in] first     The original header to be copied.
     548 */
     549static void ip_create_last_header(ip_header_ref last, ip_header_ref first)
     550{
     551        ip_option_ref option;
     552        size_t next;
     553        size_t length;
     554
     555        // copy first itself
     556        memcpy(last, first, sizeof(ip_header_t));
     557        length = sizeof(ip_header_t);
     558        next = sizeof(ip_header_t);
     559
     560        // process all ip options
     561        while (next < first->header_length) {
     562                option = (ip_option_ref) (((uint8_t *) first) + next);
     563                // skip end or noop
     564                if ((option->type == IPOPT_END) ||
     565                    (option->type == IPOPT_NOOP)) {
     566                        next++;
     567                } else {
     568                        // copy if told so or skip
     569                        if (IPOPT_COPIED(option->type)) {
     570                                memcpy(((uint8_t *) last) + length,
     571                                    ((uint8_t *) first) + next, option->length);
     572                                length += option->length;
     573                        }
     574                        // next option
     575                        next += option->length;
     576                }
     577        }
     578
     579        // align 4 byte boundary
     580        if (length % 4) {
     581                bzero(((uint8_t *) last) + length, 4 - (length % 4));
     582                last->header_length = length / 4 + 1;
     583        } else {
     584                last->header_length = length / 4;
     585        }
     586
     587        last->header_checksum = 0;
     588}
     589
     590/** Prepares the outgoing packet or the packet queue.
     591 *
     592 * The packet queue is a fragmented packet
     593 * Updates the first packet's IP header.
     594 * Prefixes the additional packets with fragment headers.
     595 *
     596 * @param[in] source    The source address.
     597 * @param[in] dest      The destination address.
     598 * @param[in,out] packet The packet to be sent.
     599 * @param[in] destination The destination hardware address.
     600 * @returns             EOK on success.
     601 * @returns             EINVAL if the packet is too small to contain the IP
     602 *                      header.
     603 * @returns             EINVAL if the packet is too long than the IP allows.
     604 * @returns             ENOMEM if there is not enough memory left.
     605 * @returns             Other error codes as defined for the packet_set_addr()
     606 *                      function.
     607 */
     608static int
     609ip_prepare_packet(in_addr_t *source, in_addr_t dest, packet_t packet,
     610    measured_string_ref destination)
     611{
     612        ERROR_DECLARE;
     613
     614        size_t length;
     615        ip_header_ref header;
     616        ip_header_ref last_header;
     617        ip_header_ref middle_header;
     618        packet_t next;
     619
     620        length = packet_get_data_length(packet);
     621        if ((length < sizeof(ip_header_t)) || (length > IP_MAX_CONTENT))
     622                return EINVAL;
     623
     624        header = (ip_header_ref) packet_get_data(packet);
     625        if (destination) {
     626                ERROR_PROPAGATE(packet_set_addr(packet, NULL,
     627                    (uint8_t *) destination->value,
     628                    CONVERT_SIZE(char, uint8_t, destination->length)));
     629        } else {
     630                ERROR_PROPAGATE(packet_set_addr(packet, NULL, NULL, 0));
     631        }
     632        header->version = IPV4;
     633        header->fragment_offset_high = 0;
     634        header->fragment_offset_low = 0;
     635        header->header_checksum = 0;
     636        if (source)
     637                header->source_address = source->s_addr;
     638        header->destination_address = dest.s_addr;
     639
     640        fibril_rwlock_write_lock(&ip_globals.lock);
     641        ip_globals.packet_counter++;
     642        header->identification = htons(ip_globals.packet_counter);
     643        fibril_rwlock_write_unlock(&ip_globals.lock);
     644
     645        if (pq_next(packet)) {
     646                last_header = (ip_header_ref) malloc(IP_HEADER_LENGTH(header));
     647                if (!last_header)
     648                        return ENOMEM;
     649                ip_create_last_header(last_header, header);
     650                next = pq_next(packet);
     651                while (pq_next(next)) {
     652                        middle_header = (ip_header_ref) packet_prefix(next,
     653                            IP_HEADER_LENGTH(last_header));
     654                        if (!middle_header) {
     655                                free(last_header);
     656                                return ENOMEM;
     657                        }
     658
     659                        memcpy(middle_header, last_header,
     660                            IP_HEADER_LENGTH(last_header));
     661                        header->flags |= IPFLAG_MORE_FRAGMENTS;
     662                        middle_header->total_length =
     663                            htons(packet_get_data_length(next));
     664                        middle_header->fragment_offset_high =
     665                            IP_COMPUTE_FRAGMENT_OFFSET_HIGH(length);
     666                        middle_header->fragment_offset_low =
     667                            IP_COMPUTE_FRAGMENT_OFFSET_LOW(length);
     668                        middle_header->header_checksum =
     669                            IP_HEADER_CHECKSUM(middle_header);
     670                        if (destination) {
     671                                if (ERROR_OCCURRED(packet_set_addr(next, NULL,
     672                                    (uint8_t *) destination->value,
     673                                    CONVERT_SIZE(char, uint8_t,
     674                                    destination->length)))) {
     675                                        free(last_header);
     676                                        return ERROR_CODE;
     677                                }
     678                        }
     679                        length += packet_get_data_length(next);
     680                        next = pq_next(next);
     681                }
     682
     683                middle_header = (ip_header_ref) packet_prefix(next,
     684                    IP_HEADER_LENGTH(last_header));
     685                if (!middle_header) {
     686                        free(last_header);
     687                        return ENOMEM;
     688                }
     689
     690                memcpy(middle_header, last_header,
     691                    IP_HEADER_LENGTH(last_header));
     692                middle_header->total_length =
     693                    htons(packet_get_data_length(next));
     694                middle_header->fragment_offset_high =
     695                    IP_COMPUTE_FRAGMENT_OFFSET_HIGH(length);
     696                middle_header->fragment_offset_low =
     697                    IP_COMPUTE_FRAGMENT_OFFSET_LOW(length);
     698                middle_header->header_checksum =
     699                    IP_HEADER_CHECKSUM(middle_header);
     700                if (destination) {
     701                        if (ERROR_OCCURRED(packet_set_addr(next, NULL,
     702                            (uint8_t *) destination->value,
     703                            CONVERT_SIZE(char, uint8_t,
     704                            destination->length)))) {
     705                                free(last_header);
     706                                return ERROR_CODE;
     707                            }
     708                }
     709                length += packet_get_data_length(next);
     710                free(last_header);
     711                header->flags |= IPFLAG_MORE_FRAGMENTS;
     712        }
     713
     714        header->total_length = htons(length);
     715        // unnecessary for all protocols
     716        header->header_checksum = IP_HEADER_CHECKSUM(header);
     717
     718        return EOK;
     719}
     720
     721/** Fragments the packet from the end.
     722 *
     723 * @param[in] packet    The packet to be fragmented.
     724 * @param[in,out] new_packet The new packet fragment.
     725 * @param[in,out] header The original packet header.
     726 * @param[in,out] new_header The new packet fragment header.
     727 * @param[in] length    The new fragment length.
     728 * @param[in] src       The source address.
     729 * @param[in] dest      The destiantion address.
     730 * @param[in] addrlen   The address length.
     731 * @returns             EOK on success.
     732 * @returns             ENOMEM if the target packet is too small.
     733 * @returns             Other error codes as defined for the packet_set_addr()
     734 *                      function.
     735 * @returns             Other error codes as defined for the pq_insert_after()
     736 *                      function.
     737 */
     738static int
     739ip_fragment_packet_data(packet_t packet, packet_t new_packet,
     740    ip_header_ref header, ip_header_ref new_header, size_t length,
     741    const struct sockaddr *src, const struct sockaddr *dest, socklen_t addrlen)
     742{
     743        ERROR_DECLARE;
     744
     745        void *data;
     746        size_t offset;
     747
     748        data = packet_suffix(new_packet, length);
     749        if (!data)
     750                return ENOMEM;
     751
     752        memcpy(data, ((void *) header) + IP_TOTAL_LENGTH(header) - length,
     753            length);
     754        ERROR_PROPAGATE(packet_trim(packet, 0, length));
     755        header->total_length = htons(IP_TOTAL_LENGTH(header) - length);
     756        new_header->total_length = htons(IP_HEADER_LENGTH(new_header) + length);
     757        offset = IP_FRAGMENT_OFFSET(header) + IP_HEADER_DATA_LENGTH(header);
     758        new_header->fragment_offset_high =
     759            IP_COMPUTE_FRAGMENT_OFFSET_HIGH(offset);
     760        new_header->fragment_offset_low =
     761            IP_COMPUTE_FRAGMENT_OFFSET_LOW(offset);
     762        new_header->header_checksum = IP_HEADER_CHECKSUM(new_header);
     763        ERROR_PROPAGATE(packet_set_addr(new_packet, (const uint8_t *) src,
     764            (const uint8_t *) dest, addrlen));
     765
     766        return pq_insert_after(packet, new_packet);
     767}
     768
     769/** Checks the packet length and fragments it if needed.
     770 *
     771 * The new fragments are queued before the original packet.
     772 *
     773 * @param[in,out] packet The packet to be checked.
     774 * @param[in] length    The maximum packet length.
     775 * @param[in] prefix    The minimum prefix size.
     776 * @param[in] suffix    The minimum suffix size.
     777 * @param[in] addr_len  The minimum address length.
     778 * @returns             EOK on success.
     779 * @returns             EINVAL if the packet_get_addr() function fails.
     780 * @returns             EINVAL if the packet does not contain the IP header.
     781 * @returns             EPERM if the packet needs to be fragmented and the
     782 *                      fragmentation is not allowed.
     783 * @returns             ENOMEM if there is not enough memory left.
     784 * @returns             ENOMEM if there is no packet available.
     785 * @returns             ENOMEM if the packet is too small to contain the IP
     786 *                      header.
     787 * @returns             Other error codes as defined for the packet_trim()
     788 *                      function.
     789 * @returns             Other error codes as defined for the
     790 *                      ip_create_middle_header() function.
     791 * @returns             Other error codes as defined for the
     792 *                      ip_fragment_packet_data() function.
     793 */
     794static int
     795ip_fragment_packet(packet_t packet, size_t length, size_t prefix, size_t suffix,
     796    socklen_t addr_len)
     797{
     798        ERROR_DECLARE;
     799
     800        packet_t new_packet;
     801        ip_header_ref header;
     802        ip_header_ref middle_header;
     803        ip_header_ref last_header;
     804        struct sockaddr *src;
     805        struct sockaddr *dest;
     806        socklen_t addrlen;
     807        int result;
     808
     809        result = packet_get_addr(packet, (uint8_t **) &src, (uint8_t **) &dest);
     810        if (result <= 0)
     811                return EINVAL;
     812
     813        addrlen = (socklen_t) result;
     814        if (packet_get_data_length(packet) <= sizeof(ip_header_t))
     815                return ENOMEM;
     816
     817        // get header
     818        header = (ip_header_ref) packet_get_data(packet);
     819        if (!header)
     820                return EINVAL;
     821
     822        // fragmentation forbidden?
     823        if(header->flags & IPFLAG_DONT_FRAGMENT)
     824                return EPERM;
     825
     826        // create the last fragment
     827        new_packet = packet_get_4_remote(ip_globals.net_phone, prefix, length,
     828            suffix, ((addrlen > addr_len) ? addrlen : addr_len));
     829        if (!new_packet)
     830                return ENOMEM;
     831
     832        // allocate as much as originally
     833        last_header = (ip_header_ref) packet_suffix(new_packet,
     834            IP_HEADER_LENGTH(header));
     835        if (!last_header)
     836                return ip_release_and_return(packet, ENOMEM);
     837
     838        ip_create_last_header(last_header, header);
     839
     840        // trim the unused space
     841        if (ERROR_OCCURRED(packet_trim(new_packet, 0,
     842            IP_HEADER_LENGTH(header) - IP_HEADER_LENGTH(last_header)))) {
     843                return ip_release_and_return(packet, ERROR_CODE);
     844        }
     845
     846        // biggest multiple of 8 lower than content
     847        // TODO even fragmentation?
     848        length = length & ~0x7;
     849        if (ERROR_OCCURRED(ip_fragment_packet_data(packet, new_packet, header,
     850            last_header,
     851            ((IP_HEADER_DATA_LENGTH(header) -
     852            ((length - IP_HEADER_LENGTH(header)) & ~0x7)) %
     853            ((length - IP_HEADER_LENGTH(last_header)) & ~0x7)), src, dest,
     854            addrlen))) {
     855                return ip_release_and_return(packet, ERROR_CODE);
     856        }
     857
     858        // mark the first as fragmented
     859        header->flags |= IPFLAG_MORE_FRAGMENTS;
     860
     861        // create middle framgents
     862        while (IP_TOTAL_LENGTH(header) > length) {
     863                new_packet = packet_get_4_remote(ip_globals.net_phone, prefix,
     864                    length, suffix,
     865                    ((addrlen >= addr_len) ? addrlen : addr_len));
     866                if (!new_packet)
     867                        return ENOMEM;
     868
     869                middle_header = ip_create_middle_header(new_packet,
     870                    last_header);
     871                if (!middle_header)
     872                        return ip_release_and_return(packet, ENOMEM);
     873
     874                if (ERROR_OCCURRED(ip_fragment_packet_data(packet, new_packet,
     875                    header, middle_header,
     876                    (length - IP_HEADER_LENGTH(middle_header)) & ~0x7, src,
     877                    dest, addrlen))) {
     878                        return ip_release_and_return(packet, ERROR_CODE);
     879                }
     880        }
     881
     882        // finish the first fragment
     883        header->header_checksum = IP_HEADER_CHECKSUM(header);
     884
     885        return EOK;
     886}
     887
     888/** Checks the packet queue lengths and fragments the packets if needed.
     889 *
     890 * The ICMP_FRAG_NEEDED error notification may be sent if the packet needs to
     891 * be fragmented and the fragmentation is not allowed.
     892 *
     893 * @param[in,out] packet The packet or the packet queue to be checked.
     894 * @param[in] prefix    The minimum prefix size.
     895 * @param[in] content   The maximum content size.
     896 * @param[in] suffix    The minimum suffix size.
     897 * @param[in] addr_len  The minimum address length.
     898 * @param[in] error     The error module service.
     899 * @returns             The packet or the packet queue of the allowed length.
     900 * @returns             NULL if there are no packets left.
     901 */
     902static packet_t
     903ip_split_packet(packet_t packet, size_t prefix, size_t content, size_t suffix,
     904    socklen_t addr_len, services_t error)
     905{
     906        size_t length;
     907        packet_t next;
     908        packet_t new_packet;
     909        int result;
     910        int phone;
     911
     912        next = packet;
     913        // check all packets
     914        while (next) {
     915                length = packet_get_data_length(next);
    470916               
    471                 char defgateway[INET_ADDRSTRLEN];
    472                 inet_ntop(AF_INET, (uint8_t *) &gateway.s_addr,
    473                     defgateway, INET_ADDRSTRLEN);
    474                 printf("%s: Default gateway (%s)\n", NAME, defgateway);
    475         }
     917                if (length <= content) {
     918                        next = pq_next(next);
     919                        continue;
     920                }
     921
     922                // too long
     923                result = ip_fragment_packet(next, content, prefix,
     924                    suffix, addr_len);
     925                if (result != EOK) {
     926                        new_packet = pq_detach(next);
     927                        if (next == packet) {
     928                                // the new first packet of the queue
     929                                packet = new_packet;
     930                        }
     931                        // fragmentation needed?
     932                        if (result == EPERM) {
     933                                phone = ip_prepare_icmp_and_get_phone(
     934                                    error, next, NULL);
     935                                if (phone >= 0) {
     936                                        // fragmentation necessary ICMP
     937                                        icmp_destination_unreachable_msg(phone,
     938                                            ICMP_FRAG_NEEDED, content, next);
     939                                }
     940                        } else {
     941                                pq_release_remote(ip_globals.net_phone,
     942                                    packet_get_id(next));
     943                        }
     944
     945                        next = new_packet;
     946                        continue;
     947                }
     948
     949                next = pq_next(next);
     950        }
     951
     952        return packet;
     953}
     954
     955/** Sends the packet or the packet queue via the specified route.
     956 *
     957 * The ICMP_HOST_UNREACH error notification may be sent if route hardware
     958 * destination address is found.
     959 *
     960 * @param[in,out] packet The packet to be sent.
     961 * @param[in] netif     The target network interface.
     962 * @param[in] route     The target route.
     963 * @param[in] src       The source address.
     964 * @param[in] dest      The destination address.
     965 * @param[in] error     The error module service.
     966 * @returns             EOK on success.
     967 * @returns             Other error codes as defined for the arp_translate_req()
     968 *                      function.
     969 * @returns             Other error codes as defined for the ip_prepare_packet()
     970 *                      function.
     971 */
     972static int
     973ip_send_route(packet_t packet, ip_netif_ref netif, ip_route_ref route,
     974    in_addr_t *src, in_addr_t dest, services_t error)
     975{
     976        ERROR_DECLARE;
     977
     978        measured_string_t destination;
     979        measured_string_ref translation;
     980        char *data;
     981        int phone;
     982
     983        // get destination hardware address
     984        if (netif->arp && (route->address.s_addr != dest.s_addr)) {
     985                destination.value = route->gateway.s_addr ?
     986                    (char *) &route->gateway.s_addr : (char *) &dest.s_addr;
     987                destination.length = CONVERT_SIZE(dest.s_addr, char, 1);
     988
     989                if (ERROR_OCCURRED(arp_translate_req(netif->arp->phone,
     990                    netif->device_id, SERVICE_IP, &destination, &translation,
     991                    &data))) {
     992                        pq_release_remote(ip_globals.net_phone,
     993                            packet_get_id(packet));
     994                        return ERROR_CODE;
     995                }
     996
     997                if (!translation || !translation->value) {
     998                        if (translation) {
     999                                free(translation);
     1000                                free(data);
     1001                        }
     1002                        phone = ip_prepare_icmp_and_get_phone(error, packet,
     1003                            NULL);
     1004                        if (phone >= 0) {
     1005                                // unreachable ICMP if no routing
     1006                                icmp_destination_unreachable_msg(phone,
     1007                                    ICMP_HOST_UNREACH, 0, packet);
     1008                        }
     1009                        return EINVAL;
     1010                }
     1011
     1012        } else {
     1013                translation = NULL;
     1014        }
     1015
     1016        if (ERROR_OCCURRED(ip_prepare_packet(src, dest, packet, translation))) {
     1017                pq_release_remote(ip_globals.net_phone, packet_get_id(packet));
     1018        } else {
     1019                packet = ip_split_packet(packet, netif->packet_dimension.prefix,
     1020                    netif->packet_dimension.content,
     1021                    netif->packet_dimension.suffix,
     1022                    netif->packet_dimension.addr_len, error);
     1023                if (packet) {
     1024                        nil_send_msg(netif->phone, netif->device_id, packet,
     1025                            SERVICE_IP);
     1026                }
     1027        }
     1028
     1029        if (translation) {
     1030                free(translation);
     1031                free(data);
     1032        }
     1033
     1034        return ERROR_CODE;
     1035}
     1036
     1037/** Searches the network interfaces if there is a suitable route.
     1038 *
     1039 * @param[in] netif     The network interface to be searched for routes. May be
     1040 *                      NULL.
     1041 * @param[in] destination The destination address.
     1042 * @returns             The found route.
     1043 * @returns             NULL if no route was found.
     1044 */
     1045static ip_route_ref
     1046ip_netif_find_route(ip_netif_ref netif, in_addr_t destination)
     1047{
     1048        int index;
     1049        ip_route_ref route;
     1050
     1051        if (!netif)
     1052                return NULL;
     1053
     1054        // start with the first one - the direct route
     1055        for (index = 0; index < ip_routes_count(&netif->routes); index++) {
     1056                route = ip_routes_get_index(&netif->routes, index);
     1057                if (route &&
     1058                    ((route->address.s_addr & route->netmask.s_addr) ==
     1059                    (destination.s_addr & route->netmask.s_addr))) {
     1060                        return route;
     1061                }
     1062        }
     1063
     1064        return NULL;
     1065}
     1066
     1067/** Searches all network interfaces if there is a suitable route.
     1068 *
     1069 * @param[in] destination The destination address.
     1070 * @returns             The found route.
     1071 * @returns             NULL if no route was found.
     1072 */
     1073static ip_route_ref ip_find_route(in_addr_t destination) {
     1074        int index;
     1075        ip_route_ref route;
     1076        ip_netif_ref netif;
     1077
     1078        // start with the last netif - the newest one
     1079        index = ip_netifs_count(&ip_globals.netifs) - 1;
     1080        while (index >= 0) {
     1081                netif = ip_netifs_get_index(&ip_globals.netifs, index);
     1082                if (netif && (netif->state == NETIF_ACTIVE)) {
     1083                        route = ip_netif_find_route(netif, destination);
     1084                        if (route)
     1085                                return route;
     1086                }
     1087                index--;
     1088        }
     1089
     1090        return &ip_globals.gateway;
     1091}
     1092
     1093/** Returns the network interface's IP address.
     1094 *
     1095 * @param[in] netif     The network interface.
     1096 * @returns             The IP address.
     1097 * @returns             NULL if no IP address was found.
     1098 */
     1099static in_addr_t *ip_netif_address(ip_netif_ref netif)
     1100{
     1101        ip_route_ref route;
     1102
     1103        route = ip_routes_get_index(&netif->routes, 0);
     1104        return route ? &route->address : NULL;
     1105}
     1106
     1107/** Registers the transport layer protocol.
     1108 *
     1109 * The traffic of this protocol will be supplied using either the receive
     1110 * function or IPC message.
     1111 *
     1112 * @param[in] protocol  The transport layer module protocol.
     1113 * @param[in] service   The transport layer module service.
     1114 * @param[in] phone     The transport layer module phone.
     1115 * @param[in] received_msg The receiving function.
     1116 * @returns             EOK on success.
     1117 * @returns             EINVAL if the protocol parameter and/or the service
     1118 *                      parameter is zero.
     1119 * @returns             EINVAL if the phone parameter is not a positive number
     1120 *                      and the tl_receive_msg is NULL.
     1121 * @returns             ENOMEM if there is not enough memory left.
     1122 */
     1123static int
     1124ip_register(int protocol, services_t service, int phone,
     1125    tl_received_msg_t received_msg)
     1126{
     1127        ip_proto_ref proto;
     1128        int index;
     1129
     1130        if (!protocol || !service || ((phone < 0) && !received_msg))
     1131                return EINVAL;
     1132
     1133        proto = (ip_proto_ref) malloc(sizeof(ip_protos_t));
     1134        if (!proto)
     1135                return ENOMEM;
     1136
     1137        proto->protocol = protocol;
     1138        proto->service = service;
     1139        proto->phone = phone;
     1140        proto->received_msg = received_msg;
     1141
     1142        fibril_rwlock_write_lock(&ip_globals.protos_lock);
     1143        index = ip_protos_add(&ip_globals.protos, proto->protocol, proto);
     1144        if (index < 0) {
     1145                fibril_rwlock_write_unlock(&ip_globals.protos_lock);
     1146                free(proto);
     1147                return index;
     1148        }
     1149        fibril_rwlock_write_unlock(&ip_globals.protos_lock);
     1150
     1151        printf("%s: Protocol registered (protocol: %d, phone: %d)\n",
     1152            NAME, proto->protocol, proto->phone);
    4761153
    4771154        return EOK;
    4781155}
    4791156
    480 static int ip_device_req_local(int il_phone, device_id_t device_id,
    481     services_t netif)
    482 {
    483         ip_netif_t *ip_netif;
    484         ip_route_t *route;
     1157static int
     1158ip_device_req_local(int il_phone, device_id_t device_id, services_t netif)
     1159{
     1160        ERROR_DECLARE;
     1161
     1162        ip_netif_ref ip_netif;
     1163        ip_route_ref route;
    4851164        int index;
    486         int rc;
    487 
    488         ip_netif = (ip_netif_t *) malloc(sizeof(ip_netif_t));
     1165
     1166        ip_netif = (ip_netif_ref) malloc(sizeof(ip_netif_t));
    4891167        if (!ip_netif)
    4901168                return ENOMEM;
    4911169
    492         rc = ip_routes_initialize(&ip_netif->routes);
    493         if (rc != EOK) {
     1170        if (ERROR_OCCURRED(ip_routes_initialize(&ip_netif->routes))) {
    4941171                free(ip_netif);
    495                 return rc;
     1172                return ERROR_CODE;
    4961173        }
    4971174
     
    5011178
    5021179        fibril_rwlock_write_lock(&ip_globals.netifs_lock);
    503 
    504         rc = ip_netif_initialize(ip_netif);
    505         if (rc != EOK) {
     1180        if (ERROR_OCCURRED(ip_netif_initialize(ip_netif))) {
    5061181                fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
    507                 ip_routes_destroy(&ip_netif->routes, free);
     1182                ip_routes_destroy(&ip_netif->routes);
    5081183                free(ip_netif);
    509                 return rc;
     1184                return ERROR_CODE;
    5101185        }
    5111186        if (ip_netif->arp)
    5121187                ip_netif->arp->usage++;
    5131188
    514         /* Print the settings */
     1189        // print the settings
    5151190        printf("%s: Device registered (id: %d, phone: %d, ipv: %d, conf: %s)\n",
    5161191            NAME, ip_netif->device_id, ip_netif->phone, ip_netif->ipv,
     
    5471222}
    5481223
    549 /** Searches the network interfaces if there is a suitable route.
    550  *
    551  * @param[in] netif     The network interface to be searched for routes. May be
    552  *                      NULL.
    553  * @param[in] destination The destination address.
    554  * @return              The found route.
    555  * @return              NULL if no route was found.
    556  */
    557 static ip_route_t *ip_netif_find_route(ip_netif_t *netif,
    558     in_addr_t destination)
    559 {
    560         int index;
    561         ip_route_t *route;
    562        
    563         if (!netif)
    564                 return NULL;
    565        
    566         /* Start with the first one (the direct route) */
    567         for (index = 0; index < ip_routes_count(&netif->routes); index++) {
    568                 route = ip_routes_get_index(&netif->routes, index);
    569                 if ((route) &&
    570                     ((route->address.s_addr & route->netmask.s_addr) ==
    571                     (destination.s_addr & route->netmask.s_addr)))
    572                         return route;
    573         }
    574 
    575         return NULL;
    576 }
    577 
    578 /** Searches all network interfaces if there is a suitable route.
    579  *
    580  * @param[in] destination The destination address.
    581  * @return              The found route.
    582  * @return              NULL if no route was found.
    583  */
    584 static ip_route_t *ip_find_route(in_addr_t destination) {
    585         int index;
    586         ip_route_t *route;
    587         ip_netif_t *netif;
    588 
    589         /* Start with the last netif - the newest one */
    590         index = ip_netifs_count(&ip_globals.netifs) - 1;
    591         while (index >= 0) {
    592                 netif = ip_netifs_get_index(&ip_globals.netifs, index);
    593                 if (netif && (netif->state == NETIF_ACTIVE)) {
    594                         route = ip_netif_find_route(netif, destination);
    595                         if (route)
    596                                 return route;
    597                 }
    598                 index--;
    599         }
    600 
    601         return &ip_globals.gateway;
    602 }
    603 
    604 /** Returns the network interface's IP address.
    605  *
    606  * @param[in] netif     The network interface.
    607  * @return              The IP address.
    608  * @return              NULL if no IP address was found.
    609  */
    610 static in_addr_t *ip_netif_address(ip_netif_t *netif)
    611 {
    612         ip_route_t *route;
    613 
    614         route = ip_routes_get_index(&netif->routes, 0);
    615         return route ? &route->address : NULL;
    616 }
    617 
    618 /** Copies the fragment header.
    619  *
    620  * Copies only the header itself and relevant IP options.
    621  *
    622  * @param[out] last     The created header.
    623  * @param[in] first     The original header to be copied.
    624  */
    625 static void ip_create_last_header(ip_header_t *last, ip_header_t *first)
    626 {
    627         ip_option_t *option;
    628         size_t next;
    629         size_t length;
    630 
    631         /* Copy first itself */
    632         memcpy(last, first, sizeof(ip_header_t));
    633         length = sizeof(ip_header_t);
    634         next = sizeof(ip_header_t);
    635 
    636         /* Process all IP options */
    637         while (next < first->header_length) {
    638                 option = (ip_option_t *) (((uint8_t *) first) + next);
    639                 /* Skip end or noop */
    640                 if ((option->type == IPOPT_END) ||
    641                     (option->type == IPOPT_NOOP)) {
    642                         next++;
    643                 } else {
    644                         /* Copy if told so or skip */
    645                         if (IPOPT_COPIED(option->type)) {
    646                                 memcpy(((uint8_t *) last) + length,
    647                                     ((uint8_t *) first) + next, option->length);
    648                                 length += option->length;
    649                         }
    650                         /* Next option */
    651                         next += option->length;
    652                 }
    653         }
    654 
    655         /* Align 4 byte boundary */
    656         if (length % 4) {
    657                 bzero(((uint8_t *) last) + length, 4 - (length % 4));
    658                 last->header_length = length / 4 + 1;
    659         } else {
    660                 last->header_length = length / 4;
    661         }
    662 
    663         last->header_checksum = 0;
    664 }
    665 
    666 /** Prepares the outgoing packet or the packet queue.
    667  *
    668  * The packet queue is a fragmented packet
    669  * Updates the first packet's IP header.
    670  * Prefixes the additional packets with fragment headers.
    671  *
    672  * @param[in] source    The source address.
    673  * @param[in] dest      The destination address.
    674  * @param[in,out] packet The packet to be sent.
    675  * @param[in] destination The destination hardware address.
    676  * @return              EOK on success.
    677  * @return              EINVAL if the packet is too small to contain the IP
    678  *                      header.
    679  * @return              EINVAL if the packet is too long than the IP allows.
    680  * @return              ENOMEM if there is not enough memory left.
    681  * @return              Other error codes as defined for the packet_set_addr()
    682  *                      function.
    683  */
    684 static int ip_prepare_packet(in_addr_t *source, in_addr_t dest,
    685     packet_t *packet, measured_string_t *destination)
    686 {
    687         size_t length;
    688         ip_header_t *header;
    689         ip_header_t *last_header;
    690         ip_header_t *middle_header;
    691         packet_t *next;
    692         int rc;
    693 
    694         length = packet_get_data_length(packet);
    695         if ((length < sizeof(ip_header_t)) || (length > IP_MAX_CONTENT))
    696                 return EINVAL;
    697 
    698         header = (ip_header_t *) packet_get_data(packet);
    699         if (destination) {
    700                 rc = packet_set_addr(packet, NULL, (uint8_t *) destination->value,
    701                     destination->length);
    702         } else {
    703                 rc = packet_set_addr(packet, NULL, NULL, 0);
    704         }
    705         if (rc != EOK)
    706                 return rc;
    707        
    708         header->version = IPV4;
    709         header->fragment_offset_high = 0;
    710         header->fragment_offset_low = 0;
    711         header->header_checksum = 0;
    712         if (source)
    713                 header->source_address = source->s_addr;
    714         header->destination_address = dest.s_addr;
    715 
    716         fibril_rwlock_write_lock(&ip_globals.lock);
    717         ip_globals.packet_counter++;
    718         header->identification = htons(ip_globals.packet_counter);
    719         fibril_rwlock_write_unlock(&ip_globals.lock);
    720 
    721         if (pq_next(packet)) {
    722                 last_header = (ip_header_t *) malloc(IP_HEADER_LENGTH(header));
    723                 if (!last_header)
    724                         return ENOMEM;
    725                 ip_create_last_header(last_header, header);
    726                 next = pq_next(packet);
    727                 while (pq_next(next)) {
    728                         middle_header = (ip_header_t *) packet_prefix(next,
    729                             IP_HEADER_LENGTH(last_header));
    730                         if (!middle_header) {
    731                                 free(last_header);
    732                                 return ENOMEM;
    733                         }
    734 
    735                         memcpy(middle_header, last_header,
    736                             IP_HEADER_LENGTH(last_header));
    737                         header->flags |= IPFLAG_MORE_FRAGMENTS;
    738                         middle_header->total_length =
    739                             htons(packet_get_data_length(next));
    740                         middle_header->fragment_offset_high =
    741                             IP_COMPUTE_FRAGMENT_OFFSET_HIGH(length);
    742                         middle_header->fragment_offset_low =
    743                             IP_COMPUTE_FRAGMENT_OFFSET_LOW(length);
    744                         middle_header->header_checksum =
    745                             IP_HEADER_CHECKSUM(middle_header);
    746                         if (destination) {
    747                                 rc = packet_set_addr(next, NULL,
    748                                     (uint8_t *) destination->value,
    749                                     destination->length);
    750                                 if (rc != EOK) {
    751                                         free(last_header);
    752                                         return rc;
    753                                 }
    754                         }
    755                         length += packet_get_data_length(next);
    756                         next = pq_next(next);
    757                 }
    758 
    759                 middle_header = (ip_header_t *) packet_prefix(next,
    760                     IP_HEADER_LENGTH(last_header));
    761                 if (!middle_header) {
    762                         free(last_header);
    763                         return ENOMEM;
    764                 }
    765 
    766                 memcpy(middle_header, last_header,
    767                     IP_HEADER_LENGTH(last_header));
    768                 middle_header->total_length =
    769                     htons(packet_get_data_length(next));
    770                 middle_header->fragment_offset_high =
    771                     IP_COMPUTE_FRAGMENT_OFFSET_HIGH(length);
    772                 middle_header->fragment_offset_low =
    773                     IP_COMPUTE_FRAGMENT_OFFSET_LOW(length);
    774                 middle_header->header_checksum =
    775                     IP_HEADER_CHECKSUM(middle_header);
    776                 if (destination) {
    777                         rc = packet_set_addr(next, NULL,
    778                             (uint8_t *) destination->value,
    779                             destination->length);
    780                         if (rc != EOK) {
    781                                 free(last_header);
    782                                 return rc;
    783                         }
    784                 }
    785                 length += packet_get_data_length(next);
    786                 free(last_header);
    787                 header->flags |= IPFLAG_MORE_FRAGMENTS;
    788         }
    789 
    790         header->total_length = htons(length);
    791         /* Unnecessary for all protocols */
    792         header->header_checksum = IP_HEADER_CHECKSUM(header);
    793 
    794         return EOK;
    795 }
    796 
    797 /** Fragments the packet from the end.
    798  *
    799  * @param[in] packet    The packet to be fragmented.
    800  * @param[in,out] new_packet The new packet fragment.
    801  * @param[in,out] header The original packet header.
    802  * @param[in,out] new_header The new packet fragment header.
    803  * @param[in] length    The new fragment length.
    804  * @param[in] src       The source address.
    805  * @param[in] dest      The destiantion address.
    806  * @param[in] addrlen   The address length.
    807  * @return              EOK on success.
    808  * @return              ENOMEM if the target packet is too small.
    809  * @return              Other error codes as defined for the packet_set_addr()
    810  *                      function.
    811  * @return              Other error codes as defined for the pq_insert_after()
    812  *                      function.
    813  */
    814 static int ip_fragment_packet_data(packet_t *packet, packet_t *new_packet,
    815     ip_header_t *header, ip_header_t *new_header, size_t length,
    816     const struct sockaddr *src, const struct sockaddr *dest, socklen_t addrlen)
    817 {
    818         void *data;
    819         size_t offset;
    820         int rc;
    821 
    822         data = packet_suffix(new_packet, length);
    823         if (!data)
    824                 return ENOMEM;
    825 
    826         memcpy(data, ((void *) header) + IP_TOTAL_LENGTH(header) - length,
    827             length);
    828        
    829         rc = packet_trim(packet, 0, length);
    830         if (rc != EOK)
    831                 return rc;
    832        
    833         header->total_length = htons(IP_TOTAL_LENGTH(header) - length);
    834         new_header->total_length = htons(IP_HEADER_LENGTH(new_header) + length);
    835         offset = IP_FRAGMENT_OFFSET(header) + IP_HEADER_DATA_LENGTH(header);
    836         new_header->fragment_offset_high =
    837             IP_COMPUTE_FRAGMENT_OFFSET_HIGH(offset);
    838         new_header->fragment_offset_low =
    839             IP_COMPUTE_FRAGMENT_OFFSET_LOW(offset);
    840         new_header->header_checksum = IP_HEADER_CHECKSUM(new_header);
    841        
    842         rc = packet_set_addr(new_packet, (const uint8_t *) src,
    843             (const uint8_t *) dest, addrlen);
    844         if (rc != EOK)
    845                 return rc;
    846 
    847         return pq_insert_after(packet, new_packet);
    848 }
    849 
    850 /** Prefixes a middle fragment header based on the last fragment header to the
    851  * packet.
    852  *
    853  * @param[in] packet    The packet to be prefixed.
    854  * @param[in] last      The last header to be copied.
    855  * @return              The prefixed middle header.
    856  * @return              NULL on error.
    857  */
    858 static ip_header_t *ip_create_middle_header(packet_t *packet,
    859     ip_header_t *last)
    860 {
    861         ip_header_t *middle;
    862 
    863         middle = (ip_header_t *) packet_suffix(packet, IP_HEADER_LENGTH(last));
    864         if (!middle)
    865                 return NULL;
    866         memcpy(middle, last, IP_HEADER_LENGTH(last));
    867         middle->flags |= IPFLAG_MORE_FRAGMENTS;
    868         return middle;
    869 }
    870 
    871 /** Checks the packet length and fragments it if needed.
    872  *
    873  * The new fragments are queued before the original packet.
    874  *
    875  * @param[in,out] packet The packet to be checked.
    876  * @param[in] length    The maximum packet length.
    877  * @param[in] prefix    The minimum prefix size.
    878  * @param[in] suffix    The minimum suffix size.
    879  * @param[in] addr_len  The minimum address length.
    880  * @return              EOK on success.
    881  * @return              EINVAL if the packet_get_addr() function fails.
    882  * @return              EINVAL if the packet does not contain the IP header.
    883  * @return              EPERM if the packet needs to be fragmented and the
    884  *                      fragmentation is not allowed.
    885  * @return              ENOMEM if there is not enough memory left.
    886  * @return              ENOMEM if there is no packet available.
    887  * @return              ENOMEM if the packet is too small to contain the IP
    888  *                      header.
    889  * @return              Other error codes as defined for the packet_trim()
    890  *                      function.
    891  * @return              Other error codes as defined for the
    892  *                      ip_create_middle_header() function.
    893  * @return              Other error codes as defined for the
    894  *                      ip_fragment_packet_data() function.
    895  */
    8961224static int
    897 ip_fragment_packet(packet_t *packet, size_t length, size_t prefix, size_t suffix,
    898     socklen_t addr_len)
    899 {
    900         packet_t *new_packet;
    901         ip_header_t *header;
    902         ip_header_t *middle_header;
    903         ip_header_t *last_header;
    904         struct sockaddr *src;
    905         struct sockaddr *dest;
    906         socklen_t addrlen;
    907         int result;
    908         int rc;
    909 
    910         result = packet_get_addr(packet, (uint8_t **) &src, (uint8_t **) &dest);
    911         if (result <= 0)
    912                 return EINVAL;
    913 
    914         addrlen = (socklen_t) result;
    915         if (packet_get_data_length(packet) <= sizeof(ip_header_t))
    916                 return ENOMEM;
    917 
    918         /* Get header */
    919         header = (ip_header_t *) packet_get_data(packet);
    920         if (!header)
    921                 return EINVAL;
    922 
    923         /* Fragmentation forbidden? */
    924         if(header->flags & IPFLAG_DONT_FRAGMENT)
    925                 return EPERM;
    926 
    927         /* Create the last fragment */
    928         new_packet = packet_get_4_remote(ip_globals.net_phone, prefix, length,
    929             suffix, ((addrlen > addr_len) ? addrlen : addr_len));
    930         if (!new_packet)
    931                 return ENOMEM;
    932 
    933         /* Allocate as much as originally */
    934         last_header = (ip_header_t *) packet_suffix(new_packet,
    935             IP_HEADER_LENGTH(header));
    936         if (!last_header)
    937                 return ip_release_and_return(packet, ENOMEM);
    938 
    939         ip_create_last_header(last_header, header);
    940 
    941         /* Trim the unused space */
    942         rc = packet_trim(new_packet, 0,
    943             IP_HEADER_LENGTH(header) - IP_HEADER_LENGTH(last_header));
    944         if (rc != EOK)
    945                 return ip_release_and_return(packet, rc);
    946 
    947         /* Greatest multiple of 8 lower than content */
    948         // TODO even fragmentation?
    949         length = length & ~0x7;
    950        
    951         rc = ip_fragment_packet_data(packet, new_packet, header, last_header,
    952             ((IP_HEADER_DATA_LENGTH(header) -
    953             ((length - IP_HEADER_LENGTH(header)) & ~0x7)) %
    954             ((length - IP_HEADER_LENGTH(last_header)) & ~0x7)),
    955             src, dest, addrlen);
    956         if (rc != EOK)
    957                 return ip_release_and_return(packet, rc);
    958 
    959         /* Mark the first as fragmented */
    960         header->flags |= IPFLAG_MORE_FRAGMENTS;
    961 
    962         /* Create middle fragments */
    963         while (IP_TOTAL_LENGTH(header) > length) {
    964                 new_packet = packet_get_4_remote(ip_globals.net_phone, prefix,
    965                     length, suffix,
    966                     ((addrlen >= addr_len) ? addrlen : addr_len));
    967                 if (!new_packet)
    968                         return ENOMEM;
    969 
    970                 middle_header = ip_create_middle_header(new_packet,
    971                     last_header);
    972                 if (!middle_header)
    973                         return ip_release_and_return(packet, ENOMEM);
    974 
    975                 rc = ip_fragment_packet_data(packet, new_packet, header,
    976                     middle_header,
    977                     (length - IP_HEADER_LENGTH(middle_header)) & ~0x7,
    978                     src, dest, addrlen);
    979                 if (rc != EOK)
    980                         return ip_release_and_return(packet, rc);
    981         }
    982 
    983         /* Finish the first fragment */
    984         header->header_checksum = IP_HEADER_CHECKSUM(header);
    985 
    986         return EOK;
    987 }
    988 
    989 /** Checks the packet queue lengths and fragments the packets if needed.
    990  *
    991  * The ICMP_FRAG_NEEDED error notification may be sent if the packet needs to
    992  * be fragmented and the fragmentation is not allowed.
    993  *
    994  * @param[in,out] packet The packet or the packet queue to be checked.
    995  * @param[in] prefix    The minimum prefix size.
    996  * @param[in] content   The maximum content size.
    997  * @param[in] suffix    The minimum suffix size.
    998  * @param[in] addr_len  The minimum address length.
    999  * @param[in] error     The error module service.
    1000  * @return              The packet or the packet queue of the allowed length.
    1001  * @return              NULL if there are no packets left.
    1002  */
    1003 static packet_t *
    1004 ip_split_packet(packet_t *packet, size_t prefix, size_t content, size_t suffix,
    1005     socklen_t addr_len, services_t error)
    1006 {
    1007         size_t length;
    1008         packet_t *next;
    1009         packet_t *new_packet;
    1010         int result;
    1011         int phone;
    1012 
    1013         next = packet;
    1014         /* Check all packets */
    1015         while (next) {
    1016                 length = packet_get_data_length(next);
    1017                
    1018                 if (length <= content) {
    1019                         next = pq_next(next);
    1020                         continue;
    1021                 }
    1022 
    1023                 /* Too long */
    1024                 result = ip_fragment_packet(next, content, prefix,
    1025                     suffix, addr_len);
    1026                 if (result != EOK) {
    1027                         new_packet = pq_detach(next);
    1028                         if (next == packet) {
    1029                                 /* The new first packet of the queue */
    1030                                 packet = new_packet;
    1031                         }
    1032                         /* Fragmentation needed? */
    1033                         if (result == EPERM) {
    1034                                 phone = ip_prepare_icmp_and_get_phone(
    1035                                     error, next, NULL);
    1036                                 if (phone >= 0) {
    1037                                         /* Fragmentation necessary ICMP */
    1038                                         icmp_destination_unreachable_msg(phone,
    1039                                             ICMP_FRAG_NEEDED, content, next);
    1040                                 }
    1041                         } else {
    1042                                 pq_release_remote(ip_globals.net_phone,
    1043                                     packet_get_id(next));
    1044                         }
    1045 
    1046                         next = new_packet;
    1047                         continue;
    1048                 }
    1049 
    1050                 next = pq_next(next);
    1051         }
    1052 
    1053         return packet;
    1054 }
    1055 
    1056 /** Sends the packet or the packet queue via the specified route.
    1057  *
    1058  * The ICMP_HOST_UNREACH error notification may be sent if route hardware
    1059  * destination address is found.
    1060  *
    1061  * @param[in,out] packet The packet to be sent.
    1062  * @param[in] netif     The target network interface.
    1063  * @param[in] route     The target route.
    1064  * @param[in] src       The source address.
    1065  * @param[in] dest      The destination address.
    1066  * @param[in] error     The error module service.
    1067  * @return              EOK on success.
    1068  * @return              Other error codes as defined for the arp_translate_req()
    1069  *                      function.
    1070  * @return              Other error codes as defined for the ip_prepare_packet()
    1071  *                      function.
    1072  */
    1073 static int ip_send_route(packet_t *packet, ip_netif_t *netif,
    1074     ip_route_t *route, in_addr_t *src, in_addr_t dest, services_t error)
    1075 {
    1076         measured_string_t destination;
    1077         measured_string_t *translation;
    1078         uint8_t *data;
    1079         int phone;
    1080         int rc;
    1081 
    1082         /* Get destination hardware address */
    1083         if (netif->arp && (route->address.s_addr != dest.s_addr)) {
    1084                 destination.value = route->gateway.s_addr ?
    1085                     (uint8_t *) &route->gateway.s_addr : (uint8_t *) &dest.s_addr;
    1086                 destination.length = sizeof(dest.s_addr);
    1087 
    1088                 rc = arp_translate_req(netif->arp->phone, netif->device_id,
    1089                     SERVICE_IP, &destination, &translation, &data);
    1090                 if (rc != EOK) {
    1091                         pq_release_remote(ip_globals.net_phone,
    1092                             packet_get_id(packet));
    1093                         return rc;
    1094                 }
    1095 
    1096                 if (!translation || !translation->value) {
    1097                         if (translation) {
    1098                                 free(translation);
    1099                                 free(data);
    1100                         }
    1101                         phone = ip_prepare_icmp_and_get_phone(error, packet,
    1102                             NULL);
    1103                         if (phone >= 0) {
    1104                                 /* Unreachable ICMP if no routing */
    1105                                 icmp_destination_unreachable_msg(phone,
    1106                                     ICMP_HOST_UNREACH, 0, packet);
    1107                         }
    1108                         return EINVAL;
    1109                 }
    1110 
    1111         } else {
    1112                 translation = NULL;
    1113         }
    1114 
    1115         rc = ip_prepare_packet(src, dest, packet, translation);
    1116         if (rc != EOK) {
    1117                 pq_release_remote(ip_globals.net_phone, packet_get_id(packet));
    1118         } else {
    1119                 packet = ip_split_packet(packet, netif->packet_dimension.prefix,
    1120                     netif->packet_dimension.content,
    1121                     netif->packet_dimension.suffix,
    1122                     netif->packet_dimension.addr_len, error);
    1123                 if (packet) {
    1124                         nil_send_msg(netif->phone, netif->device_id, packet,
    1125                             SERVICE_IP);
    1126                 }
    1127         }
    1128 
    1129         if (translation) {
    1130                 free(translation);
    1131                 free(data);
    1132         }
    1133 
    1134         return rc;
    1135 }
    1136 
    1137 static int ip_send_msg_local(int il_phone, device_id_t device_id,
    1138     packet_t *packet, services_t sender, services_t error)
    1139 {
     1225ip_send_msg_local(int il_phone, device_id_t device_id, packet_t packet,
     1226    services_t sender, services_t error)
     1227{
     1228        ERROR_DECLARE;
     1229
    11401230        int addrlen;
    1141         ip_netif_t *netif;
    1142         ip_route_t *route;
     1231        ip_netif_ref netif;
     1232        ip_route_ref route;
    11431233        struct sockaddr *addr;
    11441234        struct sockaddr_in *address_in;
     
    11461236        in_addr_t *src;
    11471237        int phone;
    1148         int rc;
    1149 
    1150         /*
    1151          * Addresses in the host byte order
    1152          * Should be the next hop address or the target destination address
    1153          */
     1238
     1239        // addresses in the host byte order
     1240        // should be the next hop address or the target destination address
    11541241        addrlen = packet_get_addr(packet, NULL, (uint8_t **) &addr);
    11551242        if (addrlen < 0)
     
    11761263        fibril_rwlock_read_lock(&ip_globals.netifs_lock);
    11771264
    1178         /* Device specified? */
     1265        // device specified?
    11791266        if (device_id > 0) {
    11801267                netif = ip_netifs_find(&ip_globals.netifs, device_id);
    1181                 route = ip_netif_find_route(netif, *dest);
     1268                route = ip_netif_find_route(netif, * dest);
    11821269                if (netif && !route && (ip_globals.gateway.netif == netif))
    11831270                        route = &ip_globals.gateway;
     
    11921279                phone = ip_prepare_icmp_and_get_phone(error, packet, NULL);
    11931280                if (phone >= 0) {
    1194                         /* Unreachable ICMP if no routing */
     1281                        // unreachable ICMP if no routing
    11951282                        icmp_destination_unreachable_msg(phone,
    11961283                            ICMP_NET_UNREACH, 0, packet);
     
    12001287
    12011288        if (error) {
    1202                 /*
    1203                  * Do not send for broadcast, anycast packets or network
    1204                  * broadcast.
    1205                  */
     1289                // do not send for broadcast, anycast packets or network
     1290                // broadcast
    12061291                if (!dest->s_addr || !(~dest->s_addr) ||
    12071292                    !(~((dest->s_addr & ~route->netmask.s_addr) |
     
    12111296                }
    12121297        }
    1213        
    1214         /* If the local host is the destination */
     1298
     1299        // if the local host is the destination
    12151300        if ((route->address.s_addr == dest->s_addr) &&
    12161301            (dest->s_addr != IPV4_LOCALHOST_ADDRESS)) {
    1217                 /* Find the loopback device to deliver */
     1302                // find the loopback device to deliver
    12181303                dest->s_addr = IPV4_LOCALHOST_ADDRESS;
    12191304                route = ip_find_route(*dest);
     
    12241309                            NULL);
    12251310                        if (phone >= 0) {
    1226                                 /* Unreachable ICMP if no routing */
     1311                                // unreachable ICMP if no routing
    12271312                                icmp_destination_unreachable_msg(phone,
    12281313                                    ICMP_HOST_UNREACH, 0, packet);
     
    12381323        }
    12391324
    1240         rc = ip_send_route(packet, netif, route, src, *dest, error);
     1325        ERROR_CODE = ip_send_route(packet, netif, route, src, *dest, error);
    12411326        fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
    12421327
    1243         return rc;
    1244 }
    1245 
    1246 /** Updates the device state.
    1247  *
    1248  * @param[in] device_id The device identifier.
    1249  * @param[in] state     The new state value.
    1250  * @return              EOK on success.
    1251  * @return              ENOENT if device is not found.
    1252  */
    1253 static int ip_device_state_message(device_id_t device_id, device_state_t state)
    1254 {
    1255         ip_netif_t *netif;
    1256 
    1257         fibril_rwlock_write_lock(&ip_globals.netifs_lock);
    1258         /* Find the device */
    1259         netif = ip_netifs_find(&ip_globals.netifs, device_id);
    1260         if (!netif) {
    1261                 fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
    1262                 return ENOENT;
    1263         }
    1264         netif->state = state;
    1265         fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
    1266 
    1267         printf("%s: Device %d changed state to %d\n", NAME, device_id, state);
    1268 
    1269         return EOK;
    1270 }
    1271 
    1272 /** Returns the packet destination address from the IP header.
    1273  *
    1274  * @param[in] header    The packet IP header to be read.
    1275  * @return              The packet destination address.
    1276  */
    1277 static in_addr_t ip_get_destination(ip_header_t *header)
    1278 {
    1279         in_addr_t destination;
    1280 
    1281         // TODO search set ipopt route?
    1282         destination.s_addr = header->destination_address;
    1283         return destination;
    1284 }
    1285 
    1286 /** Delivers the packet to the local host.
    1287  *
    1288  * The packet is either passed to another module or released on error.
    1289  * The ICMP_PROT_UNREACH error notification may be sent if the protocol is not
    1290  * found.
    1291  *
    1292  * @param[in] device_id The source device identifier.
    1293  * @param[in] packet    The packet to be delivered.
    1294  * @param[in] header    The first packet IP header. May be NULL.
    1295  * @param[in] error     The packet error service.
    1296  * @return              EOK on success.
    1297  * @return              ENOTSUP if the packet is a fragment.
    1298  * @return              EAFNOSUPPORT if the address family is not supported.
    1299  * @return              ENOENT if the target protocol is not found.
    1300  * @return              Other error codes as defined for the packet_set_addr()
    1301  *                      function.
    1302  * @return              Other error codes as defined for the packet_trim()
    1303  *                      function.
    1304  * @return              Other error codes as defined for the protocol specific
    1305  *                      tl_received_msg() function.
    1306  */
    1307 static int ip_deliver_local(device_id_t device_id, packet_t *packet,
    1308     ip_header_t *header, services_t error)
    1309 {
    1310         ip_proto_t *proto;
    1311         int phone;
    1312         services_t service;
    1313         tl_received_msg_t received_msg;
    1314         struct sockaddr *src;
    1315         struct sockaddr *dest;
    1316         struct sockaddr_in src_in;
    1317         struct sockaddr_in dest_in;
    1318         socklen_t addrlen;
    1319         int rc;
    1320 
    1321         if ((header->flags & IPFLAG_MORE_FRAGMENTS) ||
    1322             IP_FRAGMENT_OFFSET(header)) {
    1323                 // TODO fragmented
    1324                 return ENOTSUP;
    1325         }
    1326        
    1327         switch (header->version) {
    1328         case IPVERSION:
    1329                 addrlen = sizeof(src_in);
    1330                 bzero(&src_in, addrlen);
    1331                 src_in.sin_family = AF_INET;
    1332                 memcpy(&dest_in, &src_in, addrlen);
    1333                 memcpy(&src_in.sin_addr.s_addr, &header->source_address,
    1334                     sizeof(header->source_address));
    1335                 memcpy(&dest_in.sin_addr.s_addr, &header->destination_address,
    1336                     sizeof(header->destination_address));
    1337                 src = (struct sockaddr *) &src_in;
    1338                 dest = (struct sockaddr *) &dest_in;
    1339                 break;
    1340 
    1341         default:
    1342                 return ip_release_and_return(packet, EAFNOSUPPORT);
    1343         }
    1344 
    1345         rc = packet_set_addr(packet, (uint8_t *) src, (uint8_t *) dest,
    1346             addrlen);
    1347         if (rc != EOK)
    1348                 return ip_release_and_return(packet, rc);
    1349 
    1350         /* Trim padding if present */
    1351         if (!error &&
    1352             (IP_TOTAL_LENGTH(header) < packet_get_data_length(packet))) {
    1353                 rc = packet_trim(packet, 0,
    1354                     packet_get_data_length(packet) - IP_TOTAL_LENGTH(header));
    1355                 if (rc != EOK)
    1356                         return ip_release_and_return(packet, rc);
    1357         }
    1358 
    1359         fibril_rwlock_read_lock(&ip_globals.protos_lock);
    1360 
    1361         proto = ip_protos_find(&ip_globals.protos, header->protocol);
    1362         if (!proto) {
    1363                 fibril_rwlock_read_unlock(&ip_globals.protos_lock);
    1364                 phone = ip_prepare_icmp_and_get_phone(error, packet, header);
    1365                 if (phone >= 0) {
    1366                         /* Unreachable ICMP */
    1367                         icmp_destination_unreachable_msg(phone,
    1368                             ICMP_PROT_UNREACH, 0, packet);
    1369                 }
    1370                 return ENOENT;
    1371         }
    1372 
    1373         if (proto->received_msg) {
    1374                 service = proto->service;
    1375                 received_msg = proto->received_msg;
    1376                 fibril_rwlock_read_unlock(&ip_globals.protos_lock);
    1377                 rc = received_msg(device_id, packet, service, error);
    1378         } else {
    1379                 rc = tl_received_msg(proto->phone, device_id, packet,
    1380                     proto->service, error);
    1381                 fibril_rwlock_read_unlock(&ip_globals.protos_lock);
    1382         }
    1383 
    1384         return rc;
    1385 }
    1386 
    1387 /** Processes the received packet.
    1388  *
    1389  * The packet is either passed to another module or released on error.
    1390  *
    1391  * The ICMP_PARAM_POINTER error notification may be sent if the checksum is
    1392  * invalid.
    1393  * The ICMP_EXC_TTL error notification may be sent if the TTL is less than two.
    1394  * The ICMP_HOST_UNREACH error notification may be sent if no route was found.
    1395  * The ICMP_HOST_UNREACH error notification may be sent if the packet is for
    1396  * another host and the routing is disabled.
    1397  *
    1398  * @param[in] device_id The source device identifier.
    1399  * @param[in] packet    The received packet to be processed.
    1400  * @return              EOK on success.
    1401  * @return              EINVAL if the TTL is less than two.
    1402  * @return              EINVAL if the checksum is invalid.
    1403  * @return              EAFNOSUPPORT if the address family is not supported.
    1404  * @return              ENOENT if no route was found.
    1405  * @return              ENOENT if the packet is for another host and the routing
    1406  *                      is disabled.
    1407  */
    1408 static int ip_process_packet(device_id_t device_id, packet_t *packet)
    1409 {
    1410         ip_header_t *header;
    1411         in_addr_t dest;
    1412         ip_route_t *route;
    1413         int phone;
    1414         struct sockaddr *addr;
    1415         struct sockaddr_in addr_in;
    1416         socklen_t addrlen;
    1417         int rc;
    1418        
    1419         header = (ip_header_t *) packet_get_data(packet);
    1420         if (!header)
    1421                 return ip_release_and_return(packet, ENOMEM);
    1422 
    1423         /* Checksum */
    1424         if ((header->header_checksum) &&
    1425             (IP_HEADER_CHECKSUM(header) != IP_CHECKSUM_ZERO)) {
    1426                 phone = ip_prepare_icmp_and_get_phone(0, packet, header);
    1427                 if (phone >= 0) {
    1428                         /* Checksum error ICMP */
    1429                         icmp_parameter_problem_msg(phone, ICMP_PARAM_POINTER,
    1430                             ((size_t) ((void *) &header->header_checksum)) -
    1431                             ((size_t) ((void *) header)), packet);
    1432                 }
    1433                 return EINVAL;
    1434         }
    1435 
    1436         if (header->ttl <= 1) {
    1437                 phone = ip_prepare_icmp_and_get_phone(0, packet, header);
    1438                 if (phone >= 0) {
    1439                         /* TTL exceeded ICMP */
    1440                         icmp_time_exceeded_msg(phone, ICMP_EXC_TTL, packet);
    1441                 }
    1442                 return EINVAL;
    1443         }
    1444        
    1445         /* Process ipopt and get destination */
    1446         dest = ip_get_destination(header);
    1447 
    1448         /* Set the destination address */
    1449         switch (header->version) {
    1450         case IPVERSION:
    1451                 addrlen = sizeof(addr_in);
    1452                 bzero(&addr_in, addrlen);
    1453                 addr_in.sin_family = AF_INET;
    1454                 memcpy(&addr_in.sin_addr.s_addr, &dest, sizeof(dest));
    1455                 addr = (struct sockaddr *) &addr_in;
    1456                 break;
    1457 
    1458         default:
    1459                 return ip_release_and_return(packet, EAFNOSUPPORT);
    1460         }
    1461 
    1462         rc = packet_set_addr(packet, NULL, (uint8_t *) &addr, addrlen);
    1463         if (rc != EOK)
    1464                 return rc;
    1465        
    1466         route = ip_find_route(dest);
    1467         if (!route) {
    1468                 phone = ip_prepare_icmp_and_get_phone(0, packet, header);
    1469                 if (phone >= 0) {
    1470                         /* Unreachable ICMP */
    1471                         icmp_destination_unreachable_msg(phone,
    1472                             ICMP_HOST_UNREACH, 0, packet);
    1473                 }
    1474                 return ENOENT;
    1475         }
    1476 
    1477         if (route->address.s_addr == dest.s_addr) {
    1478                 /* Local delivery */
    1479                 return ip_deliver_local(device_id, packet, header, 0);
    1480         }
    1481 
    1482         if (route->netif->routing) {
    1483                 header->ttl--;
    1484                 return ip_send_route(packet, route->netif, route, NULL, dest,
    1485                     0);
    1486         }
    1487 
    1488         phone = ip_prepare_icmp_and_get_phone(0, packet, header);
    1489         if (phone >= 0) {
    1490                 /* Unreachable ICMP if no routing */
    1491                 icmp_destination_unreachable_msg(phone, ICMP_HOST_UNREACH, 0,
    1492                     packet);
    1493         }
    1494        
    1495         return ENOENT;
     1328        return ERROR_CODE;
    14961329}
    14971330
     
    15051338 * @param[out] content  The maximum content size.
    15061339 * @param[out] suffix   The minimum reserved suffix size.
    1507  * @return              EOK on success.
    1508  */
    1509 static int ip_packet_size_message(device_id_t device_id, size_t *addr_len,
    1510     size_t *prefix, size_t *content, size_t *suffix)
    1511 {
    1512         ip_netif_t *netif;
     1340 * @returns             EOK on success.
     1341 */
     1342static int
     1343ip_packet_size_message(device_id_t device_id, size_t *addr_len, size_t *prefix,
     1344    size_t *content, size_t *suffix)
     1345{
     1346        ip_netif_ref netif;
    15131347        int index;
    15141348
     
    15581392}
    15591393
    1560 /** Updates the device content length according to the new MTU value.
    1561  *
    1562  * @param[in] device_id The device identifier.
    1563  * @param[in] mtu       The new mtu value.
    1564  * @return              EOK on success.
    1565  * @return              ENOENT if device is not found.
    1566  */
    1567 static int ip_mtu_changed_message(device_id_t device_id, size_t mtu)
    1568 {
    1569         ip_netif_t *netif;
     1394/** Returns the packet destination address from the IP header.
     1395 *
     1396 * @param[in] header    The packet IP header to be read.
     1397 * @returns             The packet destination address.
     1398 */
     1399static in_addr_t ip_get_destination(ip_header_ref header)
     1400{
     1401        in_addr_t destination;
     1402
     1403        // TODO search set ipopt route?
     1404        destination.s_addr = header->destination_address;
     1405        return destination;
     1406}
     1407
     1408/** Delivers the packet to the local host.
     1409 *
     1410 * The packet is either passed to another module or released on error.
     1411 * The ICMP_PROT_UNREACH error notification may be sent if the protocol is not
     1412 * found.
     1413 *
     1414 * @param[in] device_id The source device identifier.
     1415 * @param[in] packet    The packet to be delivered.
     1416 * @param[in] header    The first packet IP header. May be NULL.
     1417 * @param[in] error     The packet error service.
     1418 * @returns             EOK on success.
     1419 * @returns             ENOTSUP if the packet is a fragment.
     1420 * @returns             EAFNOSUPPORT if the address family is not supported.
     1421 * @returns             ENOENT if the target protocol is not found.
     1422 * @returns             Other error codes as defined for the packet_set_addr()
     1423 *                      function.
     1424 * @returns             Other error codes as defined for the packet_trim()
     1425 *                      function.
     1426 * @returns             Other error codes as defined for the protocol specific
     1427 *                      tl_received_msg() function.
     1428 */
     1429static int
     1430ip_deliver_local(device_id_t device_id, packet_t packet, ip_header_ref header,
     1431    services_t error)
     1432{
     1433        ERROR_DECLARE;
     1434
     1435        ip_proto_ref proto;
     1436        int phone;
     1437        services_t service;
     1438        tl_received_msg_t received_msg;
     1439        struct sockaddr *src;
     1440        struct sockaddr *dest;
     1441        struct sockaddr_in src_in;
     1442        struct sockaddr_in dest_in;
     1443        socklen_t addrlen;
     1444
     1445        if ((header->flags & IPFLAG_MORE_FRAGMENTS) ||
     1446            IP_FRAGMENT_OFFSET(header)) {
     1447                // TODO fragmented
     1448                return ENOTSUP;
     1449        }
     1450       
     1451        switch (header->version) {
     1452        case IPVERSION:
     1453                addrlen = sizeof(src_in);
     1454                bzero(&src_in, addrlen);
     1455                src_in.sin_family = AF_INET;
     1456                memcpy(&dest_in, &src_in, addrlen);
     1457                memcpy(&src_in.sin_addr.s_addr, &header->source_address,
     1458                    sizeof(header->source_address));
     1459                memcpy(&dest_in.sin_addr.s_addr, &header->destination_address,
     1460                    sizeof(header->destination_address));
     1461                src = (struct sockaddr *) &src_in;
     1462                dest = (struct sockaddr *) &dest_in;
     1463                break;
     1464
     1465        default:
     1466                return ip_release_and_return(packet, EAFNOSUPPORT);
     1467        }
     1468
     1469        if (ERROR_OCCURRED(packet_set_addr(packet, (uint8_t *) src,
     1470            (uint8_t *) dest, addrlen))) {
     1471                return ip_release_and_return(packet, ERROR_CODE);
     1472        }
     1473
     1474        // trim padding if present
     1475        if (!error &&
     1476            (IP_TOTAL_LENGTH(header) < packet_get_data_length(packet))) {
     1477                if (ERROR_OCCURRED(packet_trim(packet, 0,
     1478                    packet_get_data_length(packet) - IP_TOTAL_LENGTH(header))))
     1479                        return ip_release_and_return(packet, ERROR_CODE);
     1480        }
     1481
     1482        fibril_rwlock_read_lock(&ip_globals.protos_lock);
     1483
     1484        proto = ip_protos_find(&ip_globals.protos, header->protocol);
     1485        if (!proto) {
     1486                fibril_rwlock_read_unlock(&ip_globals.protos_lock);
     1487                phone = ip_prepare_icmp_and_get_phone(error, packet, header);
     1488                if (phone >= 0) {
     1489                        // unreachable ICMP
     1490                        icmp_destination_unreachable_msg(phone,
     1491                            ICMP_PROT_UNREACH, 0, packet);
     1492                }
     1493                return ENOENT;
     1494        }
     1495
     1496        if (proto->received_msg) {
     1497                service = proto->service;
     1498                received_msg = proto->received_msg;
     1499                fibril_rwlock_read_unlock(&ip_globals.protos_lock);
     1500                ERROR_CODE = received_msg(device_id, packet, service, error);
     1501        } else {
     1502                ERROR_CODE = tl_received_msg(proto->phone, device_id, packet,
     1503                    proto->service, error);
     1504                fibril_rwlock_read_unlock(&ip_globals.protos_lock);
     1505        }
     1506
     1507        return ERROR_CODE;
     1508}
     1509
     1510/** Processes the received packet.
     1511 *
     1512 * The packet is either passed to another module or released on error.
     1513 *
     1514 * The ICMP_PARAM_POINTER error notification may be sent if the checksum is
     1515 * invalid.
     1516 * The ICMP_EXC_TTL error notification may be sent if the TTL is less than two.
     1517 * The ICMP_HOST_UNREACH error notification may be sent if no route was found.
     1518 * The ICMP_HOST_UNREACH error notification may be sent if the packet is for
     1519 * another host and the routing is disabled.
     1520 *
     1521 * @param[in] device_id The source device identifier.
     1522 * @param[in] packet    The received packet to be processed.
     1523 * @returns             EOK on success.
     1524 * @returns             EINVAL if the TTL is less than two.
     1525 * @returns             EINVAL if the checksum is invalid.
     1526 * @returns             EAFNOSUPPORT if the address family is not supported.
     1527 * @returns             ENOENT if no route was found.
     1528 * @returns             ENOENT if the packet is for another host and the routing
     1529 *                      is disabled.
     1530 */
     1531static int
     1532ip_process_packet(device_id_t device_id, packet_t packet)
     1533{
     1534        ERROR_DECLARE;
     1535
     1536        ip_header_ref header;
     1537        in_addr_t dest;
     1538        ip_route_ref route;
     1539        int phone;
     1540        struct sockaddr *addr;
     1541        struct sockaddr_in addr_in;
     1542        socklen_t addrlen;
     1543
     1544        header = (ip_header_ref) packet_get_data(packet);
     1545        if (!header)
     1546                return ip_release_and_return(packet, ENOMEM);
     1547
     1548        // checksum
     1549        if ((header->header_checksum) &&
     1550            (IP_HEADER_CHECKSUM(header) != IP_CHECKSUM_ZERO)) {
     1551                phone = ip_prepare_icmp_and_get_phone(0, packet, header);
     1552                if (phone >= 0) {
     1553                        // checksum error ICMP
     1554                        icmp_parameter_problem_msg(phone, ICMP_PARAM_POINTER,
     1555                            ((size_t) ((void *) &header->header_checksum)) -
     1556                            ((size_t) ((void *) header)), packet);
     1557                }
     1558                return EINVAL;
     1559        }
     1560
     1561        if (header->ttl <= 1) {
     1562                phone = ip_prepare_icmp_and_get_phone(0, packet, header);
     1563                if (phone >= 0) {
     1564                        // ttl exceeded ICMP
     1565                        icmp_time_exceeded_msg(phone, ICMP_EXC_TTL, packet);
     1566                }
     1567                return EINVAL;
     1568        }
     1569
     1570        // process ipopt and get destination
     1571        dest = ip_get_destination(header);
     1572
     1573        // set the addrination address
     1574        switch (header->version) {
     1575        case IPVERSION:
     1576                addrlen = sizeof(addr_in);
     1577                bzero(&addr_in, addrlen);
     1578                addr_in.sin_family = AF_INET;
     1579                memcpy(&addr_in.sin_addr.s_addr, &dest, sizeof(dest));
     1580                addr = (struct sockaddr *) &addr_in;
     1581                break;
     1582
     1583        default:
     1584                return ip_release_and_return(packet, EAFNOSUPPORT);
     1585        }
     1586
     1587        ERROR_PROPAGATE(packet_set_addr(packet, NULL, (uint8_t *) &addr,
     1588            addrlen));
     1589
     1590        route = ip_find_route(dest);
     1591        if (!route) {
     1592                phone = ip_prepare_icmp_and_get_phone(0, packet, header);
     1593                if (phone >= 0) {
     1594                        // unreachable ICMP
     1595                        icmp_destination_unreachable_msg(phone,
     1596                            ICMP_HOST_UNREACH, 0, packet);
     1597                }
     1598                return ENOENT;
     1599        }
     1600
     1601        if (route->address.s_addr == dest.s_addr) {
     1602                // local delivery
     1603                return ip_deliver_local(device_id, packet, header, 0);
     1604        }
     1605
     1606        if (route->netif->routing) {
     1607                header->ttl--;
     1608                return ip_send_route(packet, route->netif, route, NULL, dest,
     1609                    0);
     1610        }
     1611
     1612        phone = ip_prepare_icmp_and_get_phone(0, packet, header);
     1613        if (phone >= 0) {
     1614                // unreachable ICMP if no routing
     1615                icmp_destination_unreachable_msg(phone, ICMP_HOST_UNREACH, 0,
     1616                    packet);
     1617        }
     1618       
     1619        return ENOENT;
     1620}
     1621
     1622static int
     1623ip_add_route_req_local(int ip_phone, device_id_t device_id, in_addr_t address,
     1624    in_addr_t netmask, in_addr_t gateway)
     1625{
     1626        ip_route_ref route;
     1627        ip_netif_ref netif;
     1628        int index;
    15701629
    15711630        fibril_rwlock_write_lock(&ip_globals.netifs_lock);
     1631
    15721632        netif = ip_netifs_find(&ip_globals.netifs, device_id);
    15731633        if (!netif) {
     
    15751635                return ENOENT;
    15761636        }
    1577         netif->packet_dimension.content = mtu;
    1578         fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
    1579 
    1580         printf("%s: Device %d changed MTU to %zu\n", NAME, device_id, mtu);
    1581 
    1582         return EOK;
    1583 }
    1584 
    1585 /** Process IPC messages from the registered device driver modules
    1586  *
    1587  * @param[in]     iid   Message identifier.
    1588  * @param[in,out] icall Message parameters.
    1589  *
    1590  */
    1591 static void ip_receiver(ipc_callid_t iid, ipc_call_t *icall)
    1592 {
    1593         packet_t *packet;
    1594         int rc;
    1595        
    1596         while (true) {
    1597                 switch (IPC_GET_IMETHOD(*icall)) {
    1598                 case NET_IL_DEVICE_STATE:
    1599                         rc = ip_device_state_message(IPC_GET_DEVICE(*icall),
    1600                             IPC_GET_STATE(*icall));
    1601                         async_answer_0(iid, (sysarg_t) rc);
    1602                         break;
    1603                
    1604                 case NET_IL_RECEIVED:
    1605                         rc = packet_translate_remote(ip_globals.net_phone, &packet,
    1606                             IPC_GET_PACKET(*icall));
    1607                         if (rc == EOK) {
    1608                                 do {
    1609                                         packet_t *next = pq_detach(packet);
    1610                                         ip_process_packet(IPC_GET_DEVICE(*icall), packet);
    1611                                         packet = next;
    1612                                 } while (packet);
    1613                         }
    1614                        
    1615                         async_answer_0(iid, (sysarg_t) rc);
    1616                         break;
    1617                
    1618                 case NET_IL_MTU_CHANGED:
    1619                         rc = ip_mtu_changed_message(IPC_GET_DEVICE(*icall),
    1620                             IPC_GET_MTU(*icall));
    1621                         async_answer_0(iid, (sysarg_t) rc);
    1622                         break;
    1623                
    1624                 default:
    1625                         async_answer_0(iid, (sysarg_t) ENOTSUP);
    1626                 }
    1627                
    1628                 iid = async_get_call(icall);
    1629         }
    1630 }
    1631 
    1632 /** Registers the transport layer protocol.
    1633  *
    1634  * The traffic of this protocol will be supplied using either the receive
    1635  * function or IPC message.
    1636  *
    1637  * @param[in] protocol  The transport layer module protocol.
    1638  * @param[in] service   The transport layer module service.
    1639  * @param[in] phone     The transport layer module phone.
    1640  * @param[in] received_msg The receiving function.
    1641  * @return              EOK on success.
    1642  * @return              EINVAL if the protocol parameter and/or the service
    1643  *                      parameter is zero.
    1644  * @return              EINVAL if the phone parameter is not a positive number
    1645  *                      and the tl_receive_msg is NULL.
    1646  * @return              ENOMEM if there is not enough memory left.
    1647  */
    1648 static int
    1649 ip_register(int protocol, services_t service, int phone,
    1650     tl_received_msg_t received_msg)
    1651 {
    1652         ip_proto_t *proto;
    1653         int index;
    1654 
    1655         if (!protocol || !service || ((phone < 0) && !received_msg))
    1656                 return EINVAL;
    1657 
    1658         proto = (ip_proto_t *) malloc(sizeof(ip_protos_t));
    1659         if (!proto)
    1660                 return ENOMEM;
    1661 
    1662         proto->protocol = protocol;
    1663         proto->service = service;
    1664         proto->phone = phone;
    1665         proto->received_msg = received_msg;
    1666 
    1667         fibril_rwlock_write_lock(&ip_globals.protos_lock);
    1668         index = ip_protos_add(&ip_globals.protos, proto->protocol, proto);
    1669         if (index < 0) {
    1670                 fibril_rwlock_write_unlock(&ip_globals.protos_lock);
    1671                 free(proto);
    1672                 return index;
    1673         }
    1674         fibril_rwlock_write_unlock(&ip_globals.protos_lock);
    1675 
    1676         printf("%s: Protocol registered (protocol: %d, phone: %d)\n",
    1677             NAME, proto->protocol, proto->phone);
    1678 
    1679         return EOK;
    1680 }
    1681 
    1682 
    1683 static int
    1684 ip_add_route_req_local(int ip_phone, device_id_t device_id, in_addr_t address,
    1685     in_addr_t netmask, in_addr_t gateway)
    1686 {
    1687         ip_route_t *route;
    1688         ip_netif_t *netif;
    1689         int index;
    1690 
    1691         fibril_rwlock_write_lock(&ip_globals.netifs_lock);
    1692 
    1693         netif = ip_netifs_find(&ip_globals.netifs, device_id);
    1694         if (!netif) {
    1695                 fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
    1696                 return ENOENT;
    1697         }
    1698 
    1699         route = (ip_route_t *) malloc(sizeof(ip_route_t));
     1637
     1638        route = (ip_route_ref) malloc(sizeof(ip_route_t));
    17001639        if (!route) {
    17011640                fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
     
    17191658ip_set_gateway_req_local(int ip_phone, device_id_t device_id, in_addr_t gateway)
    17201659{
    1721         ip_netif_t *netif;
     1660        ip_netif_ref netif;
    17221661
    17231662        fibril_rwlock_write_lock(&ip_globals.netifs_lock);
     
    17531692static int
    17541693ip_received_error_msg_local(int ip_phone, device_id_t device_id,
    1755     packet_t *packet, services_t target, services_t error)
     1694    packet_t packet, services_t target, services_t error)
    17561695{
    17571696        uint8_t *data;
     
    17591698        icmp_type_t type;
    17601699        icmp_code_t code;
    1761         ip_netif_t *netif;
     1700        ip_netif_ref netif;
    17621701        measured_string_t address;
    1763         ip_route_t *route;
    1764         ip_header_t *header;
     1702        ip_route_ref route;
     1703        ip_header_ref header;
    17651704
    17661705        switch (error) {
     
    17721711
    17731712                data = packet_get_data(packet);
    1774                 header = (ip_header_t *)(data + offset);
    1775 
    1776                 /* Destination host unreachable? */
     1713                header = (ip_header_ref)(data + offset);
     1714
     1715                // destination host unreachable?
    17771716                if ((type != ICMP_DEST_UNREACH) ||
    17781717                    (code != ICMP_HOST_UNREACH)) {
    1779                         /* No, something else */
     1718                        // no, something else
    17801719                        break;
    17811720                }
     
    17911730                route = ip_routes_get_index(&netif->routes, 0);
    17921731
    1793                 /* From the same network? */
     1732                // from the same network?
    17941733                if (route && ((route->address.s_addr & route->netmask.s_addr) ==
    17951734                    (header->destination_address & route->netmask.s_addr))) {
    1796                         /* Clear the ARP mapping if any */
    1797                         address.value = (uint8_t *) &header->destination_address;
    1798                         address.length = sizeof(header->destination_address);
     1735                        // clear the ARP mapping if any
     1736                        address.value = (char *) &header->destination_address;
     1737                        address.length = CONVERT_SIZE(uint8_t, char,
     1738                            sizeof(header->destination_address));
    17991739                        arp_clear_address_req(netif->arp->phone,
    18001740                            netif->device_id, SERVICE_IP, &address);
     
    18191759        in_addr_t *dest;
    18201760        in_addr_t *src;
    1821         ip_route_t *route;
    1822         ipv4_pseudo_header_t *header_in;
     1761        ip_route_ref route;
     1762        ipv4_pseudo_header_ref header_in;
    18231763
    18241764        if (!destination || (addrlen <= 0))
     
    18481788        fibril_rwlock_read_lock(&ip_globals.lock);
    18491789        route = ip_find_route(*dest);
    1850         /* If the local host is the destination */
     1790        // if the local host is the destination
    18511791        if (route && (route->address.s_addr == dest->s_addr) &&
    18521792            (dest->s_addr != IPV4_LOCALHOST_ADDRESS)) {
    1853                 /* Find the loopback device to deliver */
     1793                // find the loopback device to deliver
    18541794                dest->s_addr = IPV4_LOCALHOST_ADDRESS;
    18551795                route = ip_find_route(*dest);
     
    18661806
    18671807        *headerlen = sizeof(*header_in);
    1868         header_in = (ipv4_pseudo_header_t *) malloc(*headerlen);
     1808        header_in = (ipv4_pseudo_header_ref) malloc(*headerlen);
    18691809        if (!header_in)
    18701810                return ENOMEM;
     
    18801820}
    18811821
     1822/** Processes the received IP packet or the packet queue one by one.
     1823 *
     1824 * The packet is either passed to another module or released on error.
     1825 *
     1826 * @param[in] device_id The source device identifier.
     1827 * @param[in,out] packet The received packet.
     1828 * @returns             EOK on success and the packet is no longer needed.
     1829 * @returns             EINVAL if the packet is too small to carry the IP
     1830 *                      packet.
     1831 * @returns             EINVAL if the received address lengths differs from the
     1832 *                      registered values.
     1833 * @returns             ENOENT if the device is not found in the cache.
     1834 * @returns             ENOENT if the protocol for the device is not found in
     1835 *                      the cache.
     1836 * @returns             ENOMEM if there is not enough memory left.
     1837 */
     1838static int ip_receive_message(device_id_t device_id, packet_t packet)
     1839{
     1840        packet_t next;
     1841
     1842        do {
     1843                next = pq_detach(packet);
     1844                ip_process_packet(device_id, packet);
     1845                packet = next;
     1846        } while (packet);
     1847
     1848        return EOK;
     1849}
     1850
    18821851/** Processes the IP message.
    18831852 *
     
    18871856 * @param[out] answer_count The last parameter for the actual answer in the
    18881857 *                      answer parameter.
    1889  * @return              EOK on success.
    1890  * @return              ENOTSUP if the message is not known.
     1858 * @returns             EOK on success.
     1859 * @returns             ENOTSUP if the message is not known.
    18911860 *
    18921861 * @see ip_interface.h
    1893  * @see il_remote.h
     1862 * @see il_interface.h
    18941863 * @see IS_NET_IP_MESSAGE()
    18951864 */
    1896 int il_module_message(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer,
    1897     size_t *answer_count)
    1898 {
    1899         packet_t *packet;
     1865int
     1866ip_message_standalone(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer,
     1867    int *answer_count)
     1868{
     1869        ERROR_DECLARE;
     1870       
     1871        packet_t packet;
    19001872        struct sockaddr *addr;
    1901         void *header;
    1902         size_t headerlen;
    19031873        size_t addrlen;
    19041874        size_t prefix;
    19051875        size_t suffix;
    19061876        size_t content;
     1877        void *header;
     1878        size_t headerlen;
    19071879        device_id_t device_id;
    1908         int rc;
    19091880       
    19101881        *answer_count = 0;
    1911         switch (IPC_GET_IMETHOD(*call)) {
     1882        switch (IPC_GET_METHOD(*call)) {
    19121883        case IPC_M_PHONE_HUNGUP:
    19131884                return EOK;
    19141885       
    19151886        case IPC_M_CONNECT_TO_ME:
    1916                 return ip_register(IL_GET_PROTO(*call), IL_GET_SERVICE(*call),
    1917                     IPC_GET_PHONE(*call), NULL);
    1918        
    1919         case NET_IP_DEVICE:
    1920                 return ip_device_req_local(0, IPC_GET_DEVICE(*call),
    1921                     IPC_GET_SERVICE(*call));
     1887                return ip_register(IL_GET_PROTO(call), IL_GET_SERVICE(call),
     1888                    IPC_GET_PHONE(call), NULL);
     1889       
     1890        case NET_IL_DEVICE:
     1891                return ip_device_req_local(0, IPC_GET_DEVICE(call),
     1892                    IPC_GET_SERVICE(call));
     1893       
     1894        case NET_IL_SEND:
     1895                ERROR_PROPAGATE(packet_translate_remote(ip_globals.net_phone,
     1896                    &packet, IPC_GET_PACKET(call)));
     1897                return ip_send_msg_local(0, IPC_GET_DEVICE(call), packet, 0,
     1898                    IPC_GET_ERROR(call));
     1899       
     1900        case NET_IL_DEVICE_STATE:
     1901                return ip_device_state_message(IPC_GET_DEVICE(call),
     1902                    IPC_GET_STATE(call));
     1903       
     1904        case NET_IL_RECEIVED:
     1905                ERROR_PROPAGATE(packet_translate_remote(ip_globals.net_phone,
     1906                    &packet, IPC_GET_PACKET(call)));
     1907                return ip_receive_message(IPC_GET_DEVICE(call), packet);
    19221908       
    19231909        case NET_IP_RECEIVED_ERROR:
    1924                 rc = packet_translate_remote(ip_globals.net_phone, &packet,
    1925                     IPC_GET_PACKET(*call));
    1926                 if (rc != EOK)
    1927                         return rc;
    1928                 return ip_received_error_msg_local(0, IPC_GET_DEVICE(*call),
    1929                     packet, IPC_GET_TARGET(*call), IPC_GET_ERROR(*call));
     1910                ERROR_PROPAGATE(packet_translate_remote(ip_globals.net_phone,
     1911                    &packet, IPC_GET_PACKET(call)));
     1912                return ip_received_error_msg_local(0, IPC_GET_DEVICE(call),
     1913                    packet, IPC_GET_TARGET(call), IPC_GET_ERROR(call));
    19301914       
    19311915        case NET_IP_ADD_ROUTE:
    1932                 return ip_add_route_req_local(0, IPC_GET_DEVICE(*call),
    1933                     IP_GET_ADDRESS(*call), IP_GET_NETMASK(*call),
    1934                     IP_GET_GATEWAY(*call));
     1916                return ip_add_route_req_local(0, IPC_GET_DEVICE(call),
     1917                    IP_GET_ADDRESS(call), IP_GET_NETMASK(call),
     1918                    IP_GET_GATEWAY(call));
    19351919
    19361920        case NET_IP_SET_GATEWAY:
    1937                 return ip_set_gateway_req_local(0, IPC_GET_DEVICE(*call),
    1938                     IP_GET_GATEWAY(*call));
     1921                return ip_set_gateway_req_local(0, IPC_GET_DEVICE(call),
     1922                    IP_GET_GATEWAY(call));
    19391923
    19401924        case NET_IP_GET_ROUTE:
    1941                 rc = async_data_write_accept((void **) &addr, false, 0, 0, 0,
    1942                     &addrlen);
    1943                 if (rc != EOK)
    1944                         return rc;
    1945                
    1946                 rc = ip_get_route_req_local(0, IP_GET_PROTOCOL(*call), addr,
    1947                     (socklen_t) addrlen, &device_id, &header, &headerlen);
    1948                 if (rc != EOK)
    1949                         return rc;
    1950                
    1951                 IPC_SET_DEVICE(*answer, device_id);
    1952                 IP_SET_HEADERLEN(*answer, headerlen);
     1925                ERROR_PROPAGATE(data_receive((void **) &addr, &addrlen));
     1926                ERROR_PROPAGATE(ip_get_route_req_local(0, IP_GET_PROTOCOL(call),
     1927                    addr, (socklen_t) addrlen, &device_id, &header,
     1928                    &headerlen));
     1929                IPC_SET_DEVICE(answer, device_id);
     1930                IP_SET_HEADERLEN(answer, headerlen);
    19531931               
    19541932                *answer_count = 2;
    1955                
    1956                 rc = data_reply(&headerlen, sizeof(headerlen));
    1957                 if (rc == EOK)
    1958                         rc = data_reply(header, headerlen);
     1933                       
     1934                if (ERROR_NONE(data_reply(&headerlen, sizeof(headerlen))))
     1935                        ERROR_CODE = data_reply(header, headerlen);
    19591936                       
    19601937                free(header);
    1961                 return rc;
    1962        
    1963         case NET_IP_PACKET_SPACE:
    1964                 rc = ip_packet_size_message(IPC_GET_DEVICE(*call), &addrlen,
    1965                     &prefix, &content, &suffix);
    1966                 if (rc != EOK)
    1967                         return rc;
    1968                
    1969                 IPC_SET_ADDR(*answer, addrlen);
    1970                 IPC_SET_PREFIX(*answer, prefix);
    1971                 IPC_SET_CONTENT(*answer, content);
    1972                 IPC_SET_SUFFIX(*answer, suffix);
     1938                return ERROR_CODE;
     1939       
     1940        case NET_IL_PACKET_SPACE:
     1941                ERROR_PROPAGATE(ip_packet_size_message(IPC_GET_DEVICE(call),
     1942                    &addrlen, &prefix, &content, &suffix));
     1943                IPC_SET_ADDR(answer, addrlen);
     1944                IPC_SET_PREFIX(answer, prefix);
     1945                IPC_SET_CONTENT(answer, content);
     1946                IPC_SET_SUFFIX(answer, suffix);
    19731947                *answer_count = 4;
    19741948                return EOK;
    19751949       
    1976         case NET_IP_SEND:
    1977                 rc = packet_translate_remote(ip_globals.net_phone, &packet,
    1978                     IPC_GET_PACKET(*call));
    1979                 if (rc != EOK)
    1980                         return rc;
     1950        case NET_IL_MTU_CHANGED:
     1951                return ip_mtu_changed_message(IPC_GET_DEVICE(call),
     1952                    IPC_GET_MTU(call));
     1953        }
     1954       
     1955        return ENOTSUP;
     1956}
     1957
     1958/** Default thread for new connections.
     1959 *
     1960 * @param[in] iid       The initial message identifier.
     1961 * @param[in] icall     The initial message call structure.
     1962 */
     1963static void il_client_connection(ipc_callid_t iid, ipc_call_t *icall)
     1964{
     1965        /*
     1966         * Accept the connection
     1967         *  - Answer the first IPC_M_CONNECT_ME_TO call.
     1968         */
     1969        ipc_answer_0(iid, EOK);
     1970       
     1971        while (true) {
     1972                ipc_call_t answer;
     1973                int answer_count;
    19811974               
    1982                 return ip_send_msg_local(0, IPC_GET_DEVICE(*call), packet, 0,
    1983                     IPC_GET_ERROR(*call));
    1984         }
    1985        
    1986         return ENOTSUP;
    1987 }
    1988 
     1975                /* Clear the answer structure */
     1976                refresh_answer(&answer, &answer_count);
     1977               
     1978                /* Fetch the next message */
     1979                ipc_call_t call;
     1980                ipc_callid_t callid = async_get_call(&call);
     1981               
     1982                /* Process the message */
     1983                int res = il_module_message_standalone(callid, &call, &answer,
     1984                    &answer_count);
     1985               
     1986                /*
     1987                 * End if told to either by the message or the processing
     1988                 * result.
     1989                 */
     1990                if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) ||
     1991                    (res == EHANGUP)) {
     1992                        return;
     1993                }
     1994               
     1995                /* Answer the message */
     1996                answer_call(callid, res, &answer, answer_count);
     1997        }
     1998}
     1999
     2000/** Starts the module.
     2001 *
     2002 * @returns EOK on success.
     2003 * @returns Other error codes as defined for each specific module start function.
     2004 */
    19892005int main(int argc, char *argv[])
    19902006{
     2007        ERROR_DECLARE;
     2008       
    19912009        /* Start the module */
    1992         return il_module_start(SERVICE_IP);
     2010        ERROR_PROPAGATE(il_module_start_standalone(il_client_connection));
     2011        return EOK;
    19932012}
    19942013
Note: See TracChangeset for help on using the changeset viewer.