Ignore:
File:
1 edited

Legend:

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

    rfd8e8e1 rccca251  
    3636 */
    3737
    38 #include "ip.h"
    39 #include "ip_module.h"
    40 
    4138#include <async.h>
    4239#include <errno.h>
    43 #include <err.h>
    4440#include <fibril_synch.h>
    4541#include <stdio.h>
    4642#include <str.h>
    47 #include <ipc/ipc.h>
    4843#include <ipc/services.h>
    4944#include <ipc/net.h>
     
    5348#include <sys/types.h>
    5449#include <byteorder.h>
     50#include "ip.h"
    5551
    5652#include <adt/measured_strings.h>
     
    7066#include <net_checksum.h>
    7167#include <icmp_client.h>
    72 #include <icmp_interface.h>
    73 #include <il_interface.h>
     68#include <icmp_remote.h>
    7469#include <ip_client.h>
    7570#include <ip_interface.h>
    7671#include <ip_header.h>
    7772#include <net_interface.h>
    78 #include <nil_interface.h>
    79 #include <tl_interface.h>
     73#include <nil_remote.h>
     74#include <tl_remote.h>
    8075#include <packet_remote.h>
    81 #include <il_local.h>
     76#include <il_remote.h>
     77#include <il_skel.h>
    8278
    8379/** IP module name. */
     
    124120GENERIC_FIELD_IMPLEMENT(ip_routes, ip_route_t);
    125121
     122static void ip_receiver(ipc_callid_t, ipc_call_t *);
     123
    126124/** Releases the packet and returns the result.
    127125 *
     
    130128 * @return              The result parameter.
    131129 */
    132 static int ip_release_and_return(packet_t packet, int result)
     130static int ip_release_and_return(packet_t *packet, int result)
    133131{
    134132        pq_release_remote(ip_globals.net_phone, packet_get_id(packet));
     
    140138 * Searches the registered protocols.
    141139 *
    142  * @returns             The found ICMP phone.
    143  * @returns             ENOENT if the ICMP is not registered.
     140 * @return              The found ICMP phone.
     141 * @return              ENOENT if the ICMP is not registered.
    144142 */
    145143static int ip_get_icmp_phone(void)
    146144{
    147         ip_proto_ref proto;
     145        ip_proto_t *proto;
    148146        int phone;
    149147
     
    161159 * @param[in] packet    The packet or the packet queue to be reported as faulty.
    162160 * @param[in] header    The first packet IP header. May be NULL.
    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
     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
    167165 *                      header.
    168  * @returns             EAFNOSUPPORT if the address family is not supported.
    169  * @returns             EPERM if the protocol is not allowed to send ICMP
     166 * @return              EAFNOSUPPORT if the address family is not supported.
     167 * @return              EPERM if the protocol is not allowed to send ICMP
    170168 *                      notifications. The ICMP protocol itself.
    171  * @returns             Other error codes as defined for the packet_set_addr().
    172  */
    173 static int ip_prepare_icmp(packet_t packet, ip_header_ref header)
    174 {
    175         packet_t next;
     169 * @return              Other error codes as defined for the packet_set_addr().
     170 */
     171static int ip_prepare_icmp(packet_t *packet, ip_header_t *header)
     172{
     173        packet_t *next;
    176174        struct sockaddr *dest;
    177175        struct sockaddr_in dest_in;
    178176        socklen_t addrlen;
    179177
    180         // detach the first packet and release the others
     178        /* Detach the first packet and release the others */
    181179        next = pq_detach(packet);
    182180        if (next)
     
    187185                        return ENOMEM;
    188186
    189                 // get header
    190                 header = (ip_header_ref) packet_get_data(packet);
     187                /* Get header */
     188                header = (ip_header_t *) packet_get_data(packet);
    191189                if (!header)
    192190                        return EINVAL;
     
    194192        }
    195193
    196         // only for the first fragment
     194        /* Only for the first fragment */
    197195        if (IP_FRAGMENT_OFFSET(header))
    198196                return EINVAL;
    199197
    200         // not for the ICMP protocol
     198        /* Not for the ICMP protocol */
    201199        if (header->protocol == IPPROTO_ICMP)
    202200                return EPERM;
    203201
    204         // set the destination address
     202        /* Set the destination address */
    205203        switch (header->version) {
    206204        case IPVERSION:
     
    228226 * @param[in] packet    The packet or the packet queue to be reported as faulty.
    229227 * @param[in] header    The first packet IP header. May be NULL.
    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.
     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.
    234232 */
    235233static int
    236 ip_prepare_icmp_and_get_phone(services_t error, packet_t packet,
    237     ip_header_ref header)
     234ip_prepare_icmp_and_get_phone(services_t error, packet_t *packet,
     235    ip_header_t *header)
    238236{
    239237        int phone;
     
    245243}
    246244
    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  */
    254 int ip_initialize(async_client_conn_t client_connection)
    255 {
    256         ERROR_DECLARE;
    257 
     245int il_initialize(int net_phone)
     246{
    258247        fibril_rwlock_initialize(&ip_globals.lock);
    259248        fibril_rwlock_write_lock(&ip_globals.lock);
    260249        fibril_rwlock_initialize(&ip_globals.protos_lock);
    261250        fibril_rwlock_initialize(&ip_globals.netifs_lock);
     251       
     252        ip_globals.net_phone = net_phone;
    262253        ip_globals.packet_counter = 0;
    263254        ip_globals.gateway.address.s_addr = 0;
     
    265256        ip_globals.gateway.gateway.s_addr = 0;
    266257        ip_globals.gateway.netif = NULL;
    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));
     258       
     259        int rc = ip_netifs_initialize(&ip_globals.netifs);
     260        if (rc != EOK)
     261                goto out;
     262        rc = ip_protos_initialize(&ip_globals.protos);
     263        if (rc != EOK)
     264                goto out;
     265        rc = modules_initialize(&ip_globals.modules);
     266        if (rc != EOK)
     267                goto out;
     268        rc = add_module(NULL, &ip_globals.modules, (uint8_t *) ARP_NAME,
     269            (uint8_t *) ARP_FILENAME, SERVICE_ARP, 0, arp_connect_module);
     270
     271out:
    273272        fibril_rwlock_write_unlock(&ip_globals.lock);
    274273
    275         return EOK;
     274        return rc;
    276275}
    277276
     
    285284 *
    286285 * @param[in,out] ip_netif Network interface specific data.
    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
     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
    294293 *                      net_get_device_conf_req() function.
    295  * @returns             Other error codes as defined for the bind_service()
     294 * @return              Other error codes as defined for the bind_service()
    296295 *                      function.
    297  * @returns             Other error codes as defined for the specific
     296 * @return              Other error codes as defined for the specific
    298297 *                      arp_device_req() function.
    299  * @returns             Other error codes as defined for the
     298 * @return              Other error codes as defined for the
    300299 *                      nil_packet_size_req() function.
    301300 */
    302 static int ip_netif_initialize(ip_netif_ref ip_netif)
    303 {
    304         ERROR_DECLARE;
    305 
     301static int ip_netif_initialize(ip_netif_t *ip_netif)
     302{
    306303        measured_string_t names[] = {
    307304                {
    308                         (char *) "IPV",
     305                        (uint8_t *) "IPV",
    309306                        3
    310307                },
    311308                {
    312                         (char *) "IP_CONFIG",
     309                        (uint8_t *) "IP_CONFIG",
    313310                        9
    314311                },
    315312                {
    316                         (char *) "IP_ADDR",
     313                        (uint8_t *) "IP_ADDR",
    317314                        7
    318315                },
    319316                {
    320                         (char *) "IP_NETMASK",
     317                        (uint8_t *) "IP_NETMASK",
    321318                        10
    322319                },
    323320                {
    324                         (char *) "IP_GATEWAY",
     321                        (uint8_t *) "IP_GATEWAY",
    325322                        10
    326323                },
    327324                {
    328                         (char *) "IP_BROADCAST",
     325                        (uint8_t *) "IP_BROADCAST",
    329326                        12
    330327                },
    331328                {
    332                         (char *) "ARP",
     329                        (uint8_t *) "ARP",
    333330                        3
    334331                },
    335332                {
    336                         (char *) "IP_ROUTING",
     333                        (uint8_t *) "IP_ROUTING",
    337334                        10
    338335                }
    339336        };
    340         measured_string_ref configuration;
     337        measured_string_t *configuration;
    341338        size_t count = sizeof(names) / sizeof(measured_string_t);
    342         char *data;
     339        uint8_t *data;
    343340        measured_string_t address;
     341        ip_route_t *route;
     342        in_addr_t gateway;
    344343        int index;
    345         ip_route_ref route;
    346         in_addr_t gateway;
     344        int rc;
    347345
    348346        ip_netif->arp = NULL;
     
    353351        configuration = &names[0];
    354352
    355         // get configuration
    356         ERROR_PROPAGATE(net_get_device_conf_req(ip_globals.net_phone,
    357             ip_netif->device_id, &configuration, count, &data));
     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       
    358359        if (configuration) {
    359360                if (configuration[0].value)
    360                         ip_netif->ipv = strtol(configuration[0].value, NULL, 0);
    361 
    362                 ip_netif->dhcp = !str_lcmp(configuration[1].value, "dhcp",
     361                        ip_netif->ipv = strtol((char *) configuration[0].value, NULL, 0);
     362               
     363                ip_netif->dhcp = !str_lcmp((char *) configuration[1].value, "dhcp",
    363364                    configuration[1].length);
    364365               
     
    368369                        return ENOTSUP;
    369370                } else if (ip_netif->ipv == IPV4) {
    370                         route = (ip_route_ref) malloc(sizeof(ip_route_t));
     371                        route = (ip_route_t *) malloc(sizeof(ip_route_t));
    371372                        if (!route) {
    372373                                net_free_settings(configuration, data);
     
    383384                                return index;
    384385                        }
    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,
     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,
    392392                            (uint8_t *) &gateway.s_addr) == EINVAL) ||
    393                             (inet_pton(AF_INET, configuration[5].value,
     393                            (inet_pton(AF_INET, (char *) configuration[5].value,
    394394                            (uint8_t *) &ip_netif->broadcast.s_addr) == EINVAL))
    395395                            {
     
    419419        }
    420420
    421         // binds the netif service which also initializes the device
     421        /* Bind netif service which also initializes the device */
    422422        ip_netif->phone = nil_bind_service(ip_netif->service,
    423             (ipcarg_t) ip_netif->device_id, SERVICE_IP,
    424             ip_globals.client_connection);
     423            (sysarg_t) ip_netif->device_id, SERVICE_IP,
     424            ip_receiver);
    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 = (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,
     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,
    437438                            ip_netif->device_id, SERVICE_IP, ip_netif->service,
    438                             &address));
     439                            &address);
     440                        if (rc != EOK)
     441                                return rc;
    439442                } else {
    440443                        ip_netif->arp = 0;
     
    442445        }
    443446
    444         // get packet dimensions
    445         ERROR_PROPAGATE(nil_packet_size_req(ip_netif->phone,
    446             ip_netif->device_id, &ip_netif->packet_dimension));
     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       
    447453        if (ip_netif->packet_dimension.content < IP_MIN_CONTENT) {
    448                 printf("Maximum transmission unit %d bytes is too small, at "
     454                printf("Maximum transmission unit %zu bytes is too small, at "
    449455                    "least %d bytes are needed\n",
    450456                    ip_netif->packet_dimension.content, IP_MIN_CONTENT);
     
    457463       
    458464        if (gateway.s_addr) {
    459                 // the default gateway
     465                /* The default gateway */
    460466                ip_globals.gateway.address.s_addr = 0;
    461467                ip_globals.gateway.netmask.s_addr = 0;
    462468                ip_globals.gateway.gateway.s_addr = gateway.s_addr;
    463469                ip_globals.gateway.netif = ip_netif;
     470               
     471                char defgateway[INET_ADDRSTRLEN];
     472                inet_ntop(AF_INET, (uint8_t *) &gateway.s_addr,
     473                    defgateway, INET_ADDRSTRLEN);
     474                printf("%s: Default gateway (%s)\n", NAME, defgateway);
    464475        }
    465476
     
    467478}
    468479
    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  */
    476 static int ip_mtu_changed_message(device_id_t device_id, size_t mtu)
    477 {
    478         ip_netif_ref netif;
     480static int ip_device_req_local(int il_phone, device_id_t device_id,
     481    services_t netif)
     482{
     483        ip_netif_t *ip_netif;
     484        ip_route_t *route;
     485        int index;
     486        int rc;
     487
     488        ip_netif = (ip_netif_t *) malloc(sizeof(ip_netif_t));
     489        if (!ip_netif)
     490                return ENOMEM;
     491
     492        rc = ip_routes_initialize(&ip_netif->routes);
     493        if (rc != EOK) {
     494                free(ip_netif);
     495                return rc;
     496        }
     497
     498        ip_netif->device_id = device_id;
     499        ip_netif->service = netif;
     500        ip_netif->state = NETIF_STOPPED;
    479501
    480502        fibril_rwlock_write_lock(&ip_globals.netifs_lock);
    481         netif = ip_netifs_find(&ip_globals.netifs, device_id);
    482         if (!netif) {
     503
     504        rc = ip_netif_initialize(ip_netif);
     505        if (rc != EOK) {
    483506                fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
    484                 return ENOENT;
    485         }
    486         netif->packet_dimension.content = mtu;
     507                ip_routes_destroy(&ip_netif->routes, free);
     508                free(ip_netif);
     509                return rc;
     510        }
     511        if (ip_netif->arp)
     512                ip_netif->arp->usage++;
     513
     514        /* Print the settings */
     515        printf("%s: Device registered (id: %d, phone: %d, ipv: %d, conf: %s)\n",
     516            NAME, ip_netif->device_id, ip_netif->phone, ip_netif->ipv,
     517            ip_netif->dhcp ? "dhcp" : "static");
     518       
     519        // TODO ipv6 addresses
     520       
     521        char address[INET_ADDRSTRLEN];
     522        char netmask[INET_ADDRSTRLEN];
     523        char gateway[INET_ADDRSTRLEN];
     524       
     525        for (index = 0; index < ip_routes_count(&ip_netif->routes); index++) {
     526                route = ip_routes_get_index(&ip_netif->routes, index);
     527                if (route) {
     528                        inet_ntop(AF_INET, (uint8_t *) &route->address.s_addr,
     529                            address, INET_ADDRSTRLEN);
     530                        inet_ntop(AF_INET, (uint8_t *) &route->netmask.s_addr,
     531                            netmask, INET_ADDRSTRLEN);
     532                        inet_ntop(AF_INET, (uint8_t *) &route->gateway.s_addr,
     533                            gateway, INET_ADDRSTRLEN);
     534                        printf("%s: Route %d (address: %s, netmask: %s, "
     535                            "gateway: %s)\n", NAME, index, address, netmask,
     536                            gateway);
     537                }
     538        }
     539       
     540        inet_ntop(AF_INET, (uint8_t *) &ip_netif->broadcast.s_addr, address,
     541            INET_ADDRSTRLEN);
    487542        fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
    488543
    489         printf("%s: Device %d changed MTU to %d\n", NAME, device_id, mtu);
     544        printf("%s: Broadcast (%s)\n", NAME, address);
    490545
    491546        return EOK;
    492547}
    493548
    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  */
    501 static 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  */
    529 static ip_header_ref
    530 ip_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)
     549/** Searches the network interfaces if there is a suitable route.
     550 *
     551 * @param[in] netif     The network interface to be searched for routes. May be
     552 *                      NULL.
     553 * @param[in] destination The destination address.
     554 * @return              The found route.
     555 * @return              NULL if no route was found.
     556 */
     557static ip_route_t *ip_netif_find_route(ip_netif_t *netif,
     558    in_addr_t destination)
     559{
     560        int index;
     561        ip_route_t *route;
     562       
     563        if (!netif)
    536564                return NULL;
    537         memcpy(middle, last, IP_HEADER_LENGTH(last));
    538         middle->flags |= IPFLAG_MORE_FRAGMENTS;
    539         return middle;
     565       
     566        /* Start with the first one (the direct route) */
     567        for (index = 0; index < ip_routes_count(&netif->routes); index++) {
     568                route = ip_routes_get_index(&netif->routes, index);
     569                if ((route) &&
     570                    ((route->address.s_addr & route->netmask.s_addr) ==
     571                    (destination.s_addr & route->netmask.s_addr)))
     572                        return route;
     573        }
     574
     575        return NULL;
     576}
     577
     578/** Searches all network interfaces if there is a suitable route.
     579 *
     580 * @param[in] destination The destination address.
     581 * @return              The found route.
     582 * @return              NULL if no route was found.
     583 */
     584static ip_route_t *ip_find_route(in_addr_t destination) {
     585        int index;
     586        ip_route_t *route;
     587        ip_netif_t *netif;
     588
     589        /* Start with the last netif - the newest one */
     590        index = ip_netifs_count(&ip_globals.netifs) - 1;
     591        while (index >= 0) {
     592                netif = ip_netifs_get_index(&ip_globals.netifs, index);
     593                if (netif && (netif->state == NETIF_ACTIVE)) {
     594                        route = ip_netif_find_route(netif, destination);
     595                        if (route)
     596                                return route;
     597                }
     598                index--;
     599        }
     600
     601        return &ip_globals.gateway;
     602}
     603
     604/** Returns the network interface's IP address.
     605 *
     606 * @param[in] netif     The network interface.
     607 * @return              The IP address.
     608 * @return              NULL if no IP address was found.
     609 */
     610static in_addr_t *ip_netif_address(ip_netif_t *netif)
     611{
     612        ip_route_t *route;
     613
     614        route = ip_routes_get_index(&netif->routes, 0);
     615        return route ? &route->address : NULL;
    540616}
    541617
     
    547623 * @param[in] first     The original header to be copied.
    548624 */
    549 static void ip_create_last_header(ip_header_ref last, ip_header_ref first)
    550 {
    551         ip_option_ref option;
     625static void ip_create_last_header(ip_header_t *last, ip_header_t *first)
     626{
     627        ip_option_t *option;
    552628        size_t next;
    553629        size_t length;
    554630
    555         // copy first itself
     631        /* Copy first itself */
    556632        memcpy(last, first, sizeof(ip_header_t));
    557633        length = sizeof(ip_header_t);
    558634        next = sizeof(ip_header_t);
    559635
    560         // process all ip options
     636        /* Process all IP options */
    561637        while (next < first->header_length) {
    562                 option = (ip_option_ref) (((uint8_t *) first) + next);
    563                 // skip end or noop
     638                option = (ip_option_t *) (((uint8_t *) first) + next);
     639                /* Skip end or noop */
    564640                if ((option->type == IPOPT_END) ||
    565641                    (option->type == IPOPT_NOOP)) {
    566642                        next++;
    567643                } else {
    568                         // copy if told so or skip
     644                        /* Copy if told so or skip */
    569645                        if (IPOPT_COPIED(option->type)) {
    570646                                memcpy(((uint8_t *) last) + length,
     
    572648                                length += option->length;
    573649                        }
    574                         // next option
     650                        /* Next option */
    575651                        next += option->length;
    576652                }
    577653        }
    578654
    579         // align 4 byte boundary
     655        /* Align 4 byte boundary */
    580656        if (length % 4) {
    581657                bzero(((uint8_t *) last) + length, 4 - (length % 4));
     
    598674 * @param[in,out] packet The packet to be sent.
    599675 * @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
     676 * @return              EOK on success.
     677 * @return              EINVAL if the packet is too small to contain the IP
    602678 *                      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()
     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()
    606682 *                      function.
    607683 */
    608 static int
    609 ip_prepare_packet(in_addr_t *source, in_addr_t dest, packet_t packet,
    610     measured_string_ref destination)
    611 {
    612         ERROR_DECLARE;
    613 
     684static int ip_prepare_packet(in_addr_t *source, in_addr_t dest,
     685    packet_t *packet, measured_string_t *destination)
     686{
    614687        size_t length;
    615         ip_header_ref header;
    616         ip_header_ref last_header;
    617         ip_header_ref middle_header;
    618         packet_t next;
     688        ip_header_t *header;
     689        ip_header_t *last_header;
     690        ip_header_t *middle_header;
     691        packet_t *next;
     692        int rc;
    619693
    620694        length = packet_get_data_length(packet);
     
    622696                return EINVAL;
    623697
    624         header = (ip_header_ref) packet_get_data(packet);
     698        header = (ip_header_t *) packet_get_data(packet);
    625699        if (destination) {
    626                 ERROR_PROPAGATE(packet_set_addr(packet, NULL,
    627                     (uint8_t *) destination->value,
    628                     CONVERT_SIZE(char, uint8_t, destination->length)));
     700                rc = packet_set_addr(packet, NULL, (uint8_t *) destination->value,
     701                    destination->length);
    629702        } else {
    630                 ERROR_PROPAGATE(packet_set_addr(packet, NULL, NULL, 0));
    631         }
     703                rc = packet_set_addr(packet, NULL, NULL, 0);
     704        }
     705        if (rc != EOK)
     706                return rc;
     707       
    632708        header->version = IPV4;
    633709        header->fragment_offset_high = 0;
     
    644720
    645721        if (pq_next(packet)) {
    646                 last_header = (ip_header_ref) malloc(IP_HEADER_LENGTH(header));
     722                last_header = (ip_header_t *) malloc(IP_HEADER_LENGTH(header));
    647723                if (!last_header)
    648724                        return ENOMEM;
     
    650726                next = pq_next(packet);
    651727                while (pq_next(next)) {
    652                         middle_header = (ip_header_ref) packet_prefix(next,
     728                        middle_header = (ip_header_t *) packet_prefix(next,
    653729                            IP_HEADER_LENGTH(last_header));
    654730                        if (!middle_header) {
     
    669745                            IP_HEADER_CHECKSUM(middle_header);
    670746                        if (destination) {
    671                                 if (ERROR_OCCURRED(packet_set_addr(next, NULL,
     747                                rc = packet_set_addr(next, NULL,
    672748                                    (uint8_t *) destination->value,
    673                                     CONVERT_SIZE(char, uint8_t,
    674                                     destination->length)))) {
     749                                    destination->length);
     750                                if (rc != EOK) {
    675751                                        free(last_header);
    676                                         return ERROR_CODE;
     752                                        return rc;
    677753                                }
    678754                        }
     
    681757                }
    682758
    683                 middle_header = (ip_header_ref) packet_prefix(next,
     759                middle_header = (ip_header_t *) packet_prefix(next,
    684760                    IP_HEADER_LENGTH(last_header));
    685761                if (!middle_header) {
     
    699775                    IP_HEADER_CHECKSUM(middle_header);
    700776                if (destination) {
    701                         if (ERROR_OCCURRED(packet_set_addr(next, NULL,
     777                        rc = packet_set_addr(next, NULL,
    702778                            (uint8_t *) destination->value,
    703                             CONVERT_SIZE(char, uint8_t,
    704                             destination->length)))) {
     779                            destination->length);
     780                        if (rc != EOK) {
    705781                                free(last_header);
    706                                 return ERROR_CODE;
    707                             }
     782                                return rc;
     783                        }
    708784                }
    709785                length += packet_get_data_length(next);
     
    713789
    714790        header->total_length = htons(length);
    715         // unnecessary for all protocols
     791        /* Unnecessary for all protocols */
    716792        header->header_checksum = IP_HEADER_CHECKSUM(header);
    717793
     
    729805 * @param[in] dest      The destiantion address.
    730806 * @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()
     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()
    734810 *                      function.
    735  * @returns             Other error codes as defined for the pq_insert_after()
     811 * @return              Other error codes as defined for the pq_insert_after()
    736812 *                      function.
    737813 */
    738 static int
    739 ip_fragment_packet_data(packet_t packet, packet_t new_packet,
    740     ip_header_ref header, ip_header_ref new_header, size_t length,
     814static int ip_fragment_packet_data(packet_t *packet, packet_t *new_packet,
     815    ip_header_t *header, ip_header_t *new_header, size_t length,
    741816    const struct sockaddr *src, const struct sockaddr *dest, socklen_t addrlen)
    742817{
    743         ERROR_DECLARE;
    744 
    745818        void *data;
    746819        size_t offset;
     820        int rc;
    747821
    748822        data = packet_suffix(new_packet, length);
     
    752826        memcpy(data, ((void *) header) + IP_TOTAL_LENGTH(header) - length,
    753827            length);
    754         ERROR_PROPAGATE(packet_trim(packet, 0, length));
     828       
     829        rc = packet_trim(packet, 0, length);
     830        if (rc != EOK)
     831                return rc;
     832       
    755833        header->total_length = htons(IP_TOTAL_LENGTH(header) - length);
    756834        new_header->total_length = htons(IP_HEADER_LENGTH(new_header) + length);
     
    761839            IP_COMPUTE_FRAGMENT_OFFSET_LOW(offset);
    762840        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));
     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;
    765846
    766847        return pq_insert_after(packet, new_packet);
     848}
     849
     850/** Prefixes a middle fragment header based on the last fragment header to the
     851 * packet.
     852 *
     853 * @param[in] packet    The packet to be prefixed.
     854 * @param[in] last      The last header to be copied.
     855 * @return              The prefixed middle header.
     856 * @return              NULL on error.
     857 */
     858static ip_header_t *ip_create_middle_header(packet_t *packet,
     859    ip_header_t *last)
     860{
     861        ip_header_t *middle;
     862
     863        middle = (ip_header_t *) packet_suffix(packet, IP_HEADER_LENGTH(last));
     864        if (!middle)
     865                return NULL;
     866        memcpy(middle, last, IP_HEADER_LENGTH(last));
     867        middle->flags |= IPFLAG_MORE_FRAGMENTS;
     868        return middle;
    767869}
    768870
     
    776878 * @param[in] suffix    The minimum suffix size.
    777879 * @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
     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
    782884 *                      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
     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
    786888 *                      header.
    787  * @returns             Other error codes as defined for the packet_trim()
     889 * @return              Other error codes as defined for the packet_trim()
    788890 *                      function.
    789  * @returns             Other error codes as defined for the
     891 * @return              Other error codes as defined for the
    790892 *                      ip_create_middle_header() function.
    791  * @returns             Other error codes as defined for the
     893 * @return              Other error codes as defined for the
    792894 *                      ip_fragment_packet_data() function.
    793895 */
    794896static int
    795 ip_fragment_packet(packet_t packet, size_t length, size_t prefix, size_t suffix,
     897ip_fragment_packet(packet_t *packet, size_t length, size_t prefix, size_t suffix,
    796898    socklen_t addr_len)
    797899{
    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;
     900        packet_t *new_packet;
     901        ip_header_t *header;
     902        ip_header_t *middle_header;
     903        ip_header_t *last_header;
    804904        struct sockaddr *src;
    805905        struct sockaddr *dest;
    806906        socklen_t addrlen;
    807907        int result;
     908        int rc;
    808909
    809910        result = packet_get_addr(packet, (uint8_t **) &src, (uint8_t **) &dest);
     
    815916                return ENOMEM;
    816917
    817         // get header
    818         header = (ip_header_ref) packet_get_data(packet);
     918        /* Get header */
     919        header = (ip_header_t *) packet_get_data(packet);
    819920        if (!header)
    820921                return EINVAL;
    821922
    822         // fragmentation forbidden?
     923        /* Fragmentation forbidden? */
    823924        if(header->flags & IPFLAG_DONT_FRAGMENT)
    824925                return EPERM;
    825926
    826         // create the last fragment
     927        /* Create the last fragment */
    827928        new_packet = packet_get_4_remote(ip_globals.net_phone, prefix, length,
    828929            suffix, ((addrlen > addr_len) ? addrlen : addr_len));
     
    830931                return ENOMEM;
    831932
    832         // allocate as much as originally
    833         last_header = (ip_header_ref) packet_suffix(new_packet,
     933        /* Allocate as much as originally */
     934        last_header = (ip_header_t *) packet_suffix(new_packet,
    834935            IP_HEADER_LENGTH(header));
    835936        if (!last_header)
     
    838939        ip_create_last_header(last_header, header);
    839940
    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
     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 */
    847948        // TODO even fragmentation?
    848949        length = length & ~0x7;
    849         if (ERROR_OCCURRED(ip_fragment_packet_data(packet, new_packet, header,
    850             last_header,
     950       
     951        rc = ip_fragment_packet_data(packet, new_packet, header, last_header,
    851952            ((IP_HEADER_DATA_LENGTH(header) -
    852953            ((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
     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 */
    859960        header->flags |= IPFLAG_MORE_FRAGMENTS;
    860961
    861         // create middle framgents
     962        /* Create middle fragments */
    862963        while (IP_TOTAL_LENGTH(header) > length) {
    863964                new_packet = packet_get_4_remote(ip_globals.net_phone, prefix,
     
    872973                        return ip_release_and_return(packet, ENOMEM);
    873974
    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
     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 */
    883984        header->header_checksum = IP_HEADER_CHECKSUM(header);
    884985
     
    897998 * @param[in] addr_len  The minimum address length.
    898999 * @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  */
    902 static packet_t
    903 ip_split_packet(packet_t packet, size_t prefix, size_t content, size_t suffix,
     1000 * @return              The packet or the packet queue of the allowed length.
     1001 * @return              NULL if there are no packets left.
     1002 */
     1003static packet_t *
     1004ip_split_packet(packet_t *packet, size_t prefix, size_t content, size_t suffix,
    9041005    socklen_t addr_len, services_t error)
    9051006{
    9061007        size_t length;
    907         packet_t next;
    908         packet_t new_packet;
     1008        packet_t *next;
     1009        packet_t *new_packet;
    9091010        int result;
    9101011        int phone;
    9111012
    9121013        next = packet;
    913         // check all packets
     1014        /* Check all packets */
    9141015        while (next) {
    9151016                length = packet_get_data_length(next);
     
    9201021                }
    9211022
    922                 // too long
     1023                /* Too long */
    9231024                result = ip_fragment_packet(next, content, prefix,
    9241025                    suffix, addr_len);
     
    9261027                        new_packet = pq_detach(next);
    9271028                        if (next == packet) {
    928                                 // the new first packet of the queue
     1029                                /* The new first packet of the queue */
    9291030                                packet = new_packet;
    9301031                        }
    931                         // fragmentation needed?
     1032                        /* Fragmentation needed? */
    9321033                        if (result == EPERM) {
    9331034                                phone = ip_prepare_icmp_and_get_phone(
    9341035                                    error, next, NULL);
    9351036                                if (phone >= 0) {
    936                                         // fragmentation necessary ICMP
     1037                                        /* Fragmentation necessary ICMP */
    9371038                                        icmp_destination_unreachable_msg(phone,
    9381039                                            ICMP_FRAG_NEEDED, content, next);
     
    9641065 * @param[in] dest      The destination address.
    9651066 * @param[in] error     The error module service.
    966  * @returns             EOK on success.
    967  * @returns             Other error codes as defined for the arp_translate_req()
     1067 * @return              EOK on success.
     1068 * @return              Other error codes as defined for the arp_translate_req()
    9681069 *                      function.
    969  * @returns             Other error codes as defined for the ip_prepare_packet()
     1070 * @return              Other error codes as defined for the ip_prepare_packet()
    9701071 *                      function.
    9711072 */
    972 static int
    973 ip_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 
     1073static int ip_send_route(packet_t *packet, ip_netif_t *netif,
     1074    ip_route_t *route, in_addr_t *src, in_addr_t dest, services_t error)
     1075{
    9781076        measured_string_t destination;
    979         measured_string_ref translation;
    980         char *data;
     1077        measured_string_t *translation;
     1078        uint8_t *data;
    9811079        int phone;
    982 
    983         // get destination hardware address
     1080        int rc;
     1081
     1082        /* Get destination hardware address */
    9841083        if (netif->arp && (route->address.s_addr != dest.s_addr)) {
    9851084                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))) {
     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) {
    9921091                        pq_release_remote(ip_globals.net_phone,
    9931092                            packet_get_id(packet));
    994                         return ERROR_CODE;
     1093                        return rc;
    9951094                }
    9961095
     
    10031102                            NULL);
    10041103                        if (phone >= 0) {
    1005                                 // unreachable ICMP if no routing
     1104                                /* Unreachable ICMP if no routing */
    10061105                                icmp_destination_unreachable_msg(phone,
    10071106                                    ICMP_HOST_UNREACH, 0, packet);
     
    10141113        }
    10151114
    1016         if (ERROR_OCCURRED(ip_prepare_packet(src, dest, packet, translation))) {
     1115        rc = ip_prepare_packet(src, dest, packet, translation);
     1116        if (rc != EOK) {
    10171117                pq_release_remote(ip_globals.net_phone, packet_get_id(packet));
    10181118        } else {
     
    10321132        }
    10331133
    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  */
    1045 static ip_route_ref
    1046 ip_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  */
    1073 static 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  */
    1099 static 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  */
    1123 static int
    1124 ip_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);
    1153 
    1154         return EOK;
    1155 }
    1156 
    1157 static int
    1158 ip_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;
    1164         int index;
    1165 
    1166         ip_netif = (ip_netif_ref) malloc(sizeof(ip_netif_t));
    1167         if (!ip_netif)
    1168                 return ENOMEM;
    1169 
    1170         if (ERROR_OCCURRED(ip_routes_initialize(&ip_netif->routes))) {
    1171                 free(ip_netif);
    1172                 return ERROR_CODE;
    1173         }
    1174 
    1175         ip_netif->device_id = device_id;
    1176         ip_netif->service = netif;
    1177         ip_netif->state = NETIF_STOPPED;
    1178 
    1179         fibril_rwlock_write_lock(&ip_globals.netifs_lock);
    1180         if (ERROR_OCCURRED(ip_netif_initialize(ip_netif))) {
    1181                 fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
    1182                 ip_routes_destroy(&ip_netif->routes);
    1183                 free(ip_netif);
    1184                 return ERROR_CODE;
    1185         }
    1186         if (ip_netif->arp)
    1187                 ip_netif->arp->usage++;
    1188 
    1189         // print the settings
    1190         printf("%s: Device registered (id: %d, phone: %d, ipv: %d, conf: %s)\n",
    1191             NAME, ip_netif->device_id, ip_netif->phone, ip_netif->ipv,
    1192             ip_netif->dhcp ? "dhcp" : "static");
    1193        
    1194         // TODO ipv6 addresses
    1195        
    1196         char address[INET_ADDRSTRLEN];
    1197         char netmask[INET_ADDRSTRLEN];
    1198         char gateway[INET_ADDRSTRLEN];
    1199        
    1200         for (index = 0; index < ip_routes_count(&ip_netif->routes); index++) {
    1201                 route = ip_routes_get_index(&ip_netif->routes, index);
    1202                 if (route) {
    1203                         inet_ntop(AF_INET, (uint8_t *) &route->address.s_addr,
    1204                             address, INET_ADDRSTRLEN);
    1205                         inet_ntop(AF_INET, (uint8_t *) &route->netmask.s_addr,
    1206                             netmask, INET_ADDRSTRLEN);
    1207                         inet_ntop(AF_INET, (uint8_t *) &route->gateway.s_addr,
    1208                             gateway, INET_ADDRSTRLEN);
    1209                         printf("%s: Route %d (address: %s, netmask: %s, "
    1210                             "gateway: %s)\n", NAME, index, address, netmask,
    1211                             gateway);
    1212                 }
    1213         }
    1214        
    1215         inet_ntop(AF_INET, (uint8_t *) &ip_netif->broadcast.s_addr, address,
    1216             INET_ADDRSTRLEN);
    1217         fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
    1218 
    1219         printf("%s: Broadcast (%s)\n", NAME, address);
    1220 
    1221         return EOK;
    1222 }
    1223 
    1224 static int
    1225 ip_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 
     1134        return rc;
     1135}
     1136
     1137static int ip_send_msg_local(int il_phone, device_id_t device_id,
     1138    packet_t *packet, services_t sender, services_t error)
     1139{
    12301140        int addrlen;
    1231         ip_netif_ref netif;
    1232         ip_route_ref route;
     1141        ip_netif_t *netif;
     1142        ip_route_t *route;
    12331143        struct sockaddr *addr;
    12341144        struct sockaddr_in *address_in;
     
    12361146        in_addr_t *src;
    12371147        int phone;
    1238 
    1239         // addresses in the host byte order
    1240         // should be the next hop address or the target destination address
     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         */
    12411154        addrlen = packet_get_addr(packet, NULL, (uint8_t **) &addr);
    12421155        if (addrlen < 0)
     
    12631176        fibril_rwlock_read_lock(&ip_globals.netifs_lock);
    12641177
    1265         // device specified?
     1178        /* Device specified? */
    12661179        if (device_id > 0) {
    12671180                netif = ip_netifs_find(&ip_globals.netifs, device_id);
    1268                 route = ip_netif_find_route(netif, * dest);
     1181                route = ip_netif_find_route(netif, *dest);
    12691182                if (netif && !route && (ip_globals.gateway.netif == netif))
    12701183                        route = &ip_globals.gateway;
     
    12791192                phone = ip_prepare_icmp_and_get_phone(error, packet, NULL);
    12801193                if (phone >= 0) {
    1281                         // unreachable ICMP if no routing
     1194                        /* Unreachable ICMP if no routing */
    12821195                        icmp_destination_unreachable_msg(phone,
    12831196                            ICMP_NET_UNREACH, 0, packet);
     
    12871200
    12881201        if (error) {
    1289                 // do not send for broadcast, anycast packets or network
    1290                 // broadcast
     1202                /*
     1203                 * Do not send for broadcast, anycast packets or network
     1204                 * broadcast.
     1205                 */
    12911206                if (!dest->s_addr || !(~dest->s_addr) ||
    12921207                    !(~((dest->s_addr & ~route->netmask.s_addr) |
     
    12961211                }
    12971212        }
    1298 
    1299         // if the local host is the destination
     1213       
     1214        /* If the local host is the destination */
    13001215        if ((route->address.s_addr == dest->s_addr) &&
    13011216            (dest->s_addr != IPV4_LOCALHOST_ADDRESS)) {
    1302                 // find the loopback device to deliver
     1217                /* Find the loopback device to deliver */
    13031218                dest->s_addr = IPV4_LOCALHOST_ADDRESS;
    13041219                route = ip_find_route(*dest);
     
    13091224                            NULL);
    13101225                        if (phone >= 0) {
    1311                                 // unreachable ICMP if no routing
     1226                                /* Unreachable ICMP if no routing */
    13121227                                icmp_destination_unreachable_msg(phone,
    13131228                                    ICMP_HOST_UNREACH, 0, packet);
     
    13231238        }
    13241239
    1325         ERROR_CODE = ip_send_route(packet, netif, route, src, *dest, error);
     1240        rc = ip_send_route(packet, netif, route, src, *dest, error);
    13261241        fibril_rwlock_read_unlock(&ip_globals.netifs_lock);
    13271242
    1328         return ERROR_CODE;
     1243        return rc;
     1244}
     1245
     1246/** Updates the device state.
     1247 *
     1248 * @param[in] device_id The device identifier.
     1249 * @param[in] state     The new state value.
     1250 * @return              EOK on success.
     1251 * @return              ENOENT if device is not found.
     1252 */
     1253static int ip_device_state_message(device_id_t device_id, device_state_t state)
     1254{
     1255        ip_netif_t *netif;
     1256
     1257        fibril_rwlock_write_lock(&ip_globals.netifs_lock);
     1258        /* Find the device */
     1259        netif = ip_netifs_find(&ip_globals.netifs, device_id);
     1260        if (!netif) {
     1261                fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
     1262                return ENOENT;
     1263        }
     1264        netif->state = state;
     1265        fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
     1266
     1267        printf("%s: Device %d changed state to %d\n", NAME, device_id, state);
     1268
     1269        return EOK;
     1270}
     1271
     1272/** Returns the packet destination address from the IP header.
     1273 *
     1274 * @param[in] header    The packet IP header to be read.
     1275 * @return              The packet destination address.
     1276 */
     1277static in_addr_t ip_get_destination(ip_header_t *header)
     1278{
     1279        in_addr_t destination;
     1280
     1281        // TODO search set ipopt route?
     1282        destination.s_addr = header->destination_address;
     1283        return destination;
     1284}
     1285
     1286/** Delivers the packet to the local host.
     1287 *
     1288 * The packet is either passed to another module or released on error.
     1289 * The ICMP_PROT_UNREACH error notification may be sent if the protocol is not
     1290 * found.
     1291 *
     1292 * @param[in] device_id The source device identifier.
     1293 * @param[in] packet    The packet to be delivered.
     1294 * @param[in] header    The first packet IP header. May be NULL.
     1295 * @param[in] error     The packet error service.
     1296 * @return              EOK on success.
     1297 * @return              ENOTSUP if the packet is a fragment.
     1298 * @return              EAFNOSUPPORT if the address family is not supported.
     1299 * @return              ENOENT if the target protocol is not found.
     1300 * @return              Other error codes as defined for the packet_set_addr()
     1301 *                      function.
     1302 * @return              Other error codes as defined for the packet_trim()
     1303 *                      function.
     1304 * @return              Other error codes as defined for the protocol specific
     1305 *                      tl_received_msg() function.
     1306 */
     1307static int ip_deliver_local(device_id_t device_id, packet_t *packet,
     1308    ip_header_t *header, services_t error)
     1309{
     1310        ip_proto_t *proto;
     1311        int phone;
     1312        services_t service;
     1313        tl_received_msg_t received_msg;
     1314        struct sockaddr *src;
     1315        struct sockaddr *dest;
     1316        struct sockaddr_in src_in;
     1317        struct sockaddr_in dest_in;
     1318        socklen_t addrlen;
     1319        int rc;
     1320
     1321        if ((header->flags & IPFLAG_MORE_FRAGMENTS) ||
     1322            IP_FRAGMENT_OFFSET(header)) {
     1323                // TODO fragmented
     1324                return ENOTSUP;
     1325        }
     1326       
     1327        switch (header->version) {
     1328        case IPVERSION:
     1329                addrlen = sizeof(src_in);
     1330                bzero(&src_in, addrlen);
     1331                src_in.sin_family = AF_INET;
     1332                memcpy(&dest_in, &src_in, addrlen);
     1333                memcpy(&src_in.sin_addr.s_addr, &header->source_address,
     1334                    sizeof(header->source_address));
     1335                memcpy(&dest_in.sin_addr.s_addr, &header->destination_address,
     1336                    sizeof(header->destination_address));
     1337                src = (struct sockaddr *) &src_in;
     1338                dest = (struct sockaddr *) &dest_in;
     1339                break;
     1340
     1341        default:
     1342                return ip_release_and_return(packet, EAFNOSUPPORT);
     1343        }
     1344
     1345        rc = packet_set_addr(packet, (uint8_t *) src, (uint8_t *) dest,
     1346            addrlen);
     1347        if (rc != EOK)
     1348                return ip_release_and_return(packet, rc);
     1349
     1350        /* Trim padding if present */
     1351        if (!error &&
     1352            (IP_TOTAL_LENGTH(header) < packet_get_data_length(packet))) {
     1353                rc = packet_trim(packet, 0,
     1354                    packet_get_data_length(packet) - IP_TOTAL_LENGTH(header));
     1355                if (rc != EOK)
     1356                        return ip_release_and_return(packet, rc);
     1357        }
     1358
     1359        fibril_rwlock_read_lock(&ip_globals.protos_lock);
     1360
     1361        proto = ip_protos_find(&ip_globals.protos, header->protocol);
     1362        if (!proto) {
     1363                fibril_rwlock_read_unlock(&ip_globals.protos_lock);
     1364                phone = ip_prepare_icmp_and_get_phone(error, packet, header);
     1365                if (phone >= 0) {
     1366                        /* Unreachable ICMP */
     1367                        icmp_destination_unreachable_msg(phone,
     1368                            ICMP_PROT_UNREACH, 0, packet);
     1369                }
     1370                return ENOENT;
     1371        }
     1372
     1373        if (proto->received_msg) {
     1374                service = proto->service;
     1375                received_msg = proto->received_msg;
     1376                fibril_rwlock_read_unlock(&ip_globals.protos_lock);
     1377                rc = received_msg(device_id, packet, service, error);
     1378        } else {
     1379                rc = tl_received_msg(proto->phone, device_id, packet,
     1380                    proto->service, error);
     1381                fibril_rwlock_read_unlock(&ip_globals.protos_lock);
     1382        }
     1383
     1384        return rc;
     1385}
     1386
     1387/** Processes the received packet.
     1388 *
     1389 * The packet is either passed to another module or released on error.
     1390 *
     1391 * The ICMP_PARAM_POINTER error notification may be sent if the checksum is
     1392 * invalid.
     1393 * The ICMP_EXC_TTL error notification may be sent if the TTL is less than two.
     1394 * The ICMP_HOST_UNREACH error notification may be sent if no route was found.
     1395 * The ICMP_HOST_UNREACH error notification may be sent if the packet is for
     1396 * another host and the routing is disabled.
     1397 *
     1398 * @param[in] device_id The source device identifier.
     1399 * @param[in] packet    The received packet to be processed.
     1400 * @return              EOK on success.
     1401 * @return              EINVAL if the TTL is less than two.
     1402 * @return              EINVAL if the checksum is invalid.
     1403 * @return              EAFNOSUPPORT if the address family is not supported.
     1404 * @return              ENOENT if no route was found.
     1405 * @return              ENOENT if the packet is for another host and the routing
     1406 *                      is disabled.
     1407 */
     1408static int ip_process_packet(device_id_t device_id, packet_t *packet)
     1409{
     1410        ip_header_t *header;
     1411        in_addr_t dest;
     1412        ip_route_t *route;
     1413        int phone;
     1414        struct sockaddr *addr;
     1415        struct sockaddr_in addr_in;
     1416        socklen_t addrlen;
     1417        int rc;
     1418       
     1419        header = (ip_header_t *) packet_get_data(packet);
     1420        if (!header)
     1421                return ip_release_and_return(packet, ENOMEM);
     1422
     1423        /* Checksum */
     1424        if ((header->header_checksum) &&
     1425            (IP_HEADER_CHECKSUM(header) != IP_CHECKSUM_ZERO)) {
     1426                phone = ip_prepare_icmp_and_get_phone(0, packet, header);
     1427                if (phone >= 0) {
     1428                        /* Checksum error ICMP */
     1429                        icmp_parameter_problem_msg(phone, ICMP_PARAM_POINTER,
     1430                            ((size_t) ((void *) &header->header_checksum)) -
     1431                            ((size_t) ((void *) header)), packet);
     1432                }
     1433                return EINVAL;
     1434        }
     1435
     1436        if (header->ttl <= 1) {
     1437                phone = ip_prepare_icmp_and_get_phone(0, packet, header);
     1438                if (phone >= 0) {
     1439                        /* TTL exceeded ICMP */
     1440                        icmp_time_exceeded_msg(phone, ICMP_EXC_TTL, packet);
     1441                }
     1442                return EINVAL;
     1443        }
     1444       
     1445        /* Process ipopt and get destination */
     1446        dest = ip_get_destination(header);
     1447
     1448        /* Set the destination address */
     1449        switch (header->version) {
     1450        case IPVERSION:
     1451                addrlen = sizeof(addr_in);
     1452                bzero(&addr_in, addrlen);
     1453                addr_in.sin_family = AF_INET;
     1454                memcpy(&addr_in.sin_addr.s_addr, &dest, sizeof(dest));
     1455                addr = (struct sockaddr *) &addr_in;
     1456                break;
     1457
     1458        default:
     1459                return ip_release_and_return(packet, EAFNOSUPPORT);
     1460        }
     1461
     1462        rc = packet_set_addr(packet, NULL, (uint8_t *) &addr, addrlen);
     1463        if (rc != EOK)
     1464                return rc;
     1465       
     1466        route = ip_find_route(dest);
     1467        if (!route) {
     1468                phone = ip_prepare_icmp_and_get_phone(0, packet, header);
     1469                if (phone >= 0) {
     1470                        /* Unreachable ICMP */
     1471                        icmp_destination_unreachable_msg(phone,
     1472                            ICMP_HOST_UNREACH, 0, packet);
     1473                }
     1474                return ENOENT;
     1475        }
     1476
     1477        if (route->address.s_addr == dest.s_addr) {
     1478                /* Local delivery */
     1479                return ip_deliver_local(device_id, packet, header, 0);
     1480        }
     1481
     1482        if (route->netif->routing) {
     1483                header->ttl--;
     1484                return ip_send_route(packet, route->netif, route, NULL, dest,
     1485                    0);
     1486        }
     1487
     1488        phone = ip_prepare_icmp_and_get_phone(0, packet, header);
     1489        if (phone >= 0) {
     1490                /* Unreachable ICMP if no routing */
     1491                icmp_destination_unreachable_msg(phone, ICMP_HOST_UNREACH, 0,
     1492                    packet);
     1493        }
     1494       
     1495        return ENOENT;
    13291496}
    13301497
     
    13381505 * @param[out] content  The maximum content size.
    13391506 * @param[out] suffix   The minimum reserved suffix size.
    1340  * @returns             EOK on success.
    1341  */
    1342 static int
    1343 ip_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;
     1507 * @return              EOK on success.
     1508 */
     1509static int ip_packet_size_message(device_id_t device_id, size_t *addr_len,
     1510    size_t *prefix, size_t *content, size_t *suffix)
     1511{
     1512        ip_netif_t *netif;
    13471513        int index;
    13481514
     
    13921558}
    13931559
    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  */
    1399 static 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  */
    1429 static int
    1430 ip_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  */
    1531 static int
    1532 ip_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 
    1622 static int
    1623 ip_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;
     1560/** Updates the device content length according to the new MTU value.
     1561 *
     1562 * @param[in] device_id The device identifier.
     1563 * @param[in] mtu       The new mtu value.
     1564 * @return              EOK on success.
     1565 * @return              ENOENT if device is not found.
     1566 */
     1567static int ip_mtu_changed_message(device_id_t device_id, size_t mtu)
     1568{
     1569        ip_netif_t *netif;
    16291570
    16301571        fibril_rwlock_write_lock(&ip_globals.netifs_lock);
    1631 
    16321572        netif = ip_netifs_find(&ip_globals.netifs, device_id);
    16331573        if (!netif) {
     
    16351575                return ENOENT;
    16361576        }
    1637 
    1638         route = (ip_route_ref) malloc(sizeof(ip_route_t));
     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 */
     1591static void ip_receiver(ipc_callid_t iid, ipc_call_t *icall)
     1592{
     1593        packet_t *packet;
     1594        int rc;
     1595       
     1596        while (true) {
     1597                switch (IPC_GET_IMETHOD(*icall)) {
     1598                case NET_IL_DEVICE_STATE:
     1599                        rc = ip_device_state_message(IPC_GET_DEVICE(*icall),
     1600                            IPC_GET_STATE(*icall));
     1601                        async_answer_0(iid, (sysarg_t) rc);
     1602                        break;
     1603               
     1604                case NET_IL_RECEIVED:
     1605                        rc = packet_translate_remote(ip_globals.net_phone, &packet,
     1606                            IPC_GET_PACKET(*icall));
     1607                        if (rc == EOK) {
     1608                                do {
     1609                                        packet_t *next = pq_detach(packet);
     1610                                        ip_process_packet(IPC_GET_DEVICE(*icall), packet);
     1611                                        packet = next;
     1612                                } while (packet);
     1613                        }
     1614                       
     1615                        async_answer_0(iid, (sysarg_t) rc);
     1616                        break;
     1617               
     1618                case NET_IL_MTU_CHANGED:
     1619                        rc = ip_mtu_changed_message(IPC_GET_DEVICE(*icall),
     1620                            IPC_GET_MTU(*icall));
     1621                        async_answer_0(iid, (sysarg_t) rc);
     1622                        break;
     1623               
     1624                default:
     1625                        async_answer_0(iid, (sysarg_t) ENOTSUP);
     1626                }
     1627               
     1628                iid = async_get_call(icall);
     1629        }
     1630}
     1631
     1632/** Registers the transport layer protocol.
     1633 *
     1634 * The traffic of this protocol will be supplied using either the receive
     1635 * function or IPC message.
     1636 *
     1637 * @param[in] protocol  The transport layer module protocol.
     1638 * @param[in] service   The transport layer module service.
     1639 * @param[in] phone     The transport layer module phone.
     1640 * @param[in] received_msg The receiving function.
     1641 * @return              EOK on success.
     1642 * @return              EINVAL if the protocol parameter and/or the service
     1643 *                      parameter is zero.
     1644 * @return              EINVAL if the phone parameter is not a positive number
     1645 *                      and the tl_receive_msg is NULL.
     1646 * @return              ENOMEM if there is not enough memory left.
     1647 */
     1648static int
     1649ip_register(int protocol, services_t service, int phone,
     1650    tl_received_msg_t received_msg)
     1651{
     1652        ip_proto_t *proto;
     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
     1683static int
     1684ip_add_route_req_local(int ip_phone, device_id_t device_id, in_addr_t address,
     1685    in_addr_t netmask, in_addr_t gateway)
     1686{
     1687        ip_route_t *route;
     1688        ip_netif_t *netif;
     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));
    16391700        if (!route) {
    16401701                fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
     
    16581719ip_set_gateway_req_local(int ip_phone, device_id_t device_id, in_addr_t gateway)
    16591720{
    1660         ip_netif_ref netif;
     1721        ip_netif_t *netif;
    16611722
    16621723        fibril_rwlock_write_lock(&ip_globals.netifs_lock);
     
    16921753static int
    16931754ip_received_error_msg_local(int ip_phone, device_id_t device_id,
    1694     packet_t packet, services_t target, services_t error)
     1755    packet_t *packet, services_t target, services_t error)
    16951756{
    16961757        uint8_t *data;
     
    16981759        icmp_type_t type;
    16991760        icmp_code_t code;
    1700         ip_netif_ref netif;
     1761        ip_netif_t *netif;
    17011762        measured_string_t address;
    1702         ip_route_ref route;
    1703         ip_header_ref header;
     1763        ip_route_t *route;
     1764        ip_header_t *header;
    17041765
    17051766        switch (error) {
     
    17111772
    17121773                data = packet_get_data(packet);
    1713                 header = (ip_header_ref)(data + offset);
    1714 
    1715                 // destination host unreachable?
     1774                header = (ip_header_t *)(data + offset);
     1775
     1776                /* Destination host unreachable? */
    17161777                if ((type != ICMP_DEST_UNREACH) ||
    17171778                    (code != ICMP_HOST_UNREACH)) {
    1718                         // no, something else
     1779                        /* No, something else */
    17191780                        break;
    17201781                }
     
    17301791                route = ip_routes_get_index(&netif->routes, 0);
    17311792
    1732                 // from the same network?
     1793                /* From the same network? */
    17331794                if (route && ((route->address.s_addr & route->netmask.s_addr) ==
    17341795                    (header->destination_address & route->netmask.s_addr))) {
    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));
     1796                        /* Clear the ARP mapping if any */
     1797                        address.value = (uint8_t *) &header->destination_address;
     1798                        address.length = sizeof(header->destination_address);
    17391799                        arp_clear_address_req(netif->arp->phone,
    17401800                            netif->device_id, SERVICE_IP, &address);
     
    17591819        in_addr_t *dest;
    17601820        in_addr_t *src;
    1761         ip_route_ref route;
    1762         ipv4_pseudo_header_ref header_in;
     1821        ip_route_t *route;
     1822        ipv4_pseudo_header_t *header_in;
    17631823
    17641824        if (!destination || (addrlen <= 0))
     
    17881848        fibril_rwlock_read_lock(&ip_globals.lock);
    17891849        route = ip_find_route(*dest);
    1790         // if the local host is the destination
     1850        /* If the local host is the destination */
    17911851        if (route && (route->address.s_addr == dest->s_addr) &&
    17921852            (dest->s_addr != IPV4_LOCALHOST_ADDRESS)) {
    1793                 // find the loopback device to deliver
     1853                /* Find the loopback device to deliver */
    17941854                dest->s_addr = IPV4_LOCALHOST_ADDRESS;
    17951855                route = ip_find_route(*dest);
     
    18061866
    18071867        *headerlen = sizeof(*header_in);
    1808         header_in = (ipv4_pseudo_header_ref) malloc(*headerlen);
     1868        header_in = (ipv4_pseudo_header_t *) malloc(*headerlen);
    18091869        if (!header_in)
    18101870                return ENOMEM;
     
    18201880}
    18211881
    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  */
    1838 static 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 
    18511882/** Processes the IP message.
    18521883 *
     
    18561887 * @param[out] answer_count The last parameter for the actual answer in the
    18571888 *                      answer parameter.
    1858  * @returns             EOK on success.
    1859  * @returns             ENOTSUP if the message is not known.
     1889 * @return              EOK on success.
     1890 * @return              ENOTSUP if the message is not known.
    18601891 *
    18611892 * @see ip_interface.h
    1862  * @see il_interface.h
     1893 * @see il_remote.h
    18631894 * @see IS_NET_IP_MESSAGE()
    18641895 */
    1865 int
    1866 ip_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;
     1896int il_module_message(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer,
     1897    size_t *answer_count)
     1898{
     1899        packet_t *packet;
    18721900        struct sockaddr *addr;
     1901        void *header;
     1902        size_t headerlen;
    18731903        size_t addrlen;
    18741904        size_t prefix;
    18751905        size_t suffix;
    18761906        size_t content;
    1877         void *header;
    1878         size_t headerlen;
    18791907        device_id_t device_id;
     1908        int rc;
    18801909       
    18811910        *answer_count = 0;
    1882         switch (IPC_GET_METHOD(*call)) {
     1911        switch (IPC_GET_IMETHOD(*call)) {
    18831912        case IPC_M_PHONE_HUNGUP:
    18841913                return EOK;
    18851914       
    18861915        case IPC_M_CONNECT_TO_ME:
    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);
     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));
    19081922       
    19091923        case NET_IP_RECEIVED_ERROR:
    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));
     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));
    19141930       
    19151931        case NET_IP_ADD_ROUTE:
    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));
     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));
    19191935
    19201936        case NET_IP_SET_GATEWAY:
    1921                 return ip_set_gateway_req_local(0, IPC_GET_DEVICE(call),
    1922                     IP_GET_GATEWAY(call));
     1937                return ip_set_gateway_req_local(0, IPC_GET_DEVICE(*call),
     1938                    IP_GET_GATEWAY(*call));
    19231939
    19241940        case NET_IP_GET_ROUTE:
    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);
     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);
    19311953               
    19321954                *answer_count = 2;
    1933                        
    1934                 if (ERROR_NONE(data_reply(&headerlen, sizeof(headerlen))))
    1935                         ERROR_CODE = data_reply(header, headerlen);
     1955               
     1956                rc = data_reply(&headerlen, sizeof(headerlen));
     1957                if (rc == EOK)
     1958                        rc = data_reply(header, headerlen);
    19361959                       
    19371960                free(header);
    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);
     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);
    19471973                *answer_count = 4;
    19481974                return EOK;
    19491975       
    1950         case NET_IL_MTU_CHANGED:
    1951                 return ip_mtu_changed_message(IPC_GET_DEVICE(call),
    1952                     IPC_GET_MTU(call));
     1976        case NET_IP_SEND:
     1977                rc = packet_translate_remote(ip_globals.net_phone, &packet,
     1978                    IPC_GET_PACKET(*call));
     1979                if (rc != EOK)
     1980                        return rc;
     1981               
     1982                return ip_send_msg_local(0, IPC_GET_DEVICE(*call), packet, 0,
     1983                    IPC_GET_ERROR(*call));
    19531984        }
    19541985       
     
    19561987}
    19571988
    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  */
    1963 static 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;
    1974                
    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  */
    20051989int main(int argc, char *argv[])
    20061990{
    2007         ERROR_DECLARE;
    2008        
    20091991        /* Start the module */
    2010         ERROR_PROPAGATE(il_module_start_standalone(il_client_connection));
    2011         return EOK;
     1992        return il_module_start(SERVICE_IP);
    20121993}
    20131994
Note: See TracChangeset for help on using the changeset viewer.