Changeset 069015f2 in mainline


Ignore:
Timestamp:
2010-10-30T19:40:49Z (13 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
5c088975
Parents:
f2d2c604 (diff), fd8e8e1 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge from lp:~jakub/helenos/net.

Location:
uspace
Files:
1 deleted
11 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/net/il/ip_remote.c

    rf2d2c604 r069015f2  
    5757 * The target network is routed using this device.
    5858 *
    59  * @param[in] ip_phone  The IP module phone used for (semi)remote calls.
    60  * @param[in] device_id The device identifier.
    61  * @param[in] address   The target network address.
    62  * @param[in] netmask   The target network mask.
    63  * @param[in] gateway   The target network gateway. Not used if zero.
    64  *
     59 * @param[in] ip_phone  The IP module phone used for (semi)remote calls.
     60 * @param[in] device_id The device identifier.
     61 * @param[in] address   The target network address.
     62 * @param[in] netmask   The target network mask.
     63 * @param[in] gateway   The target network gateway. Not used if zero.
    6564 */
    6665int ip_add_route_req_remote(int ip_phone, device_id_t device_id,
     
    106105 * If the device uses ARP registers also the new ARP device.
    107106 *
    108  * @param[in] ip_phone  The IP module phone used for (semi)remote calls.
    109  * @param[in] device_id The new device identifier.
    110  * @param[in] netif     The underlying device network interface layer service.
    111  *
    112  * @return EOK on success.
    113  * @return ENOMEM if there is not enough memory left.
    114  * @return EINVAL if the device configuration is invalid.
    115  * @return ENOTSUP if the device uses IPv6.
    116  * @return ENOTSUP if the device uses DHCP.
    117  * @return Other error codes as defined for the net_get_device_conf_req()
    118  *         function.
    119  * @return Other error codes as defined for the arp_device_req() function.
    120  *
     107 * @param[in] ip_phone  The IP module phone used for (semi)remote calls.
     108 * @param[in] device_id The new device identifier.
     109 * @param[in] netif     The underlying device network interface layer service.
     110 * @return              EOK on success.
     111 * @return              ENOMEM if there is not enough memory left.
     112 * @return              EINVAL if the device configuration is invalid.
     113 * @return              ENOTSUP if the device uses IPv6.
     114 * @return              ENOTSUP if the device uses DHCP.
     115 * @return              Other error codes as defined for the
     116 *                      net_get_device_conf_req() function.
     117 * @return              Other error codes as defined for the arp_device_req()
     118 *                      function.
    121119 */
    122120int ip_device_req_remote(int ip_phone, device_id_t device_id,
     
    130128 * destination address.
    131129 *
    132  * @param[in]  ip_phone    The IP module phone used for (semi)remote calls.
    133  * @param[in]  protocol    The transport protocol.
    134  * @param[in]  destination The destination address.
    135  * @param[in]  addrlen     The destination address length.
    136  * @param[out] device_id   The device identifier.
    137  * @param[out] header      The constructed IP pseudo header.
    138  * @param[out] headerlen   The IP pseudo header length.
     130 * @param[in] ip_phone  The IP module phone used for (semi)remote calls.
     131 * @param[in] protocol  The transport protocol.
     132 * @param[in] destination The destination address.
     133 * @param[in] addrlen   The destination address length.
     134 * @param[out] device_id The device identifier.
     135 * @param[out] header   The constructed IP pseudo header.
     136 * @param[out] headerlen The IP pseudo header length.
    139137 *
    140138 */
     
    143141    device_id_t *device_id, void **header, size_t *headerlen)
    144142{
    145         if ((!destination) || (addrlen == 0))
     143        if (!destination || (addrlen == 0))
    146144                return EINVAL;
    147145       
    148         if ((!device_id) || (!header) || (!headerlen))
     146        if (!device_id || !header || !headerlen)
    149147                return EBADMEM;
    150148       
     
    169167        async_wait_for(message_id, &result);
    170168       
    171         if ((result != EOK) && (*header))
     169        if ((result != EOK) && *header)
    172170                free(*header);
    173171        else
     
    179177/** Return the device packet dimension for sending.
    180178 *
    181  * @param[in]  ip_phone         The IP module phone used for (semi)remote calls.
    182  * @param[in]  device_id        The device identifier.
     179 * @param[in] ip_phone  The IP module phone used for (semi)remote calls.
     180 * @param[in] device_id The device identifier.
    183181 * @param[out] packet_dimension The packet dimension.
    184  *
    185  * @return EOK on success.
    186  * @return ENOENT if there is no such device.
    187  * @return Other error codes as defined for the
    188  *         generic_packet_size_req_remote() function.
    189  *
     182 * @return              EOK on success.
     183 * @return              ENOENT if there is no such device.
     184 * @return              Other error codes as defined for the
     185 *                      generic_packet_size_req_remote() function.
    190186 */
    191187int ip_packet_size_req_remote(int ip_phone, device_id_t device_id,
     
    198194/** Notify the IP module about the received error notification packet.
    199195 *
    200  * @param[in] ip_phone  The IP module phone used for (semi)remote calls.
    201  * @param[in] device_id The device identifier.
    202  * @param[in] packet    The received packet or the received packet queue.
    203  * @param[in] target    The target internetwork module service to be
    204  *                      delivered to.
    205  * @param[in] error     The packet error reporting service. Prefixes the
    206  *                      received packet.
    207  *
    208  * @return EOK on success.
    209  *
     196 * @param[in] ip_phone  The IP module phone used for (semi)remote calls.
     197 * @param[in] device_id The device identifier.
     198 * @param[in] packet    The received packet or the received packet queue.
     199 * @param[in] target    The target internetwork module service to be
     200 *                      delivered to.
     201 * @param[in] error     The packet error reporting service. Prefixes the
     202 *                      received packet.
     203 * @return              EOK on success.
    210204 */
    211205int ip_received_error_msg_remote(int ip_phone, device_id_t device_id,
     
    220214 * The packets may get fragmented if needed.
    221215 *
    222  * @param[in] ip_phone  The IP module phone used for (semi)remote calls.
    223  * @param[in] device_id The device identifier.
    224  * @param[in] packet    The packet fragments as a packet queue. All the
    225  *                      packets have to have the same destination address.
    226  * @param[in] sender    The sending module service.
    227  * @param[in] error     The packet error reporting service. Prefixes the
    228  *                      received packet.
    229  *
    230  * @return EOK on success.
    231  * @return Other error codes as defined for the generic_send_msg() function.
    232  *
     216 * @param[in] ip_phone  The IP module phone used for (semi)remote calls.
     217 * @param[in] device_id The device identifier.
     218 * @param[in] packet    The packet fragments as a packet queue. All the
     219 *                      packets have to have the same destination address.
     220 * @param[in] sender    The sending module service.
     221 * @param[in] error     The packet error reporting service. Prefixes the
     222 *                      received packet.
     223 * @return              EOK on success.
     224 * @return              Other error codes as defined for the generic_send_msg()
     225 *                      function.
    233226 */
    234227int ip_send_msg_remote(int ip_phone, device_id_t device_id, packet_t packet,
     
    243236 * This gateway is used if no other route is found.
    244237 *
    245  * @param[in] ip_phone  The IP module phone used for (semi)remote calls.
    246  * @param[in] device_id The device identifier.
    247  * @param[in] gateway   The default gateway.
    248  *
     238 * @param[in] ip_phone  The IP module phone used for (semi)remote calls.
     239 * @param[in] device_id The device identifier.
     240 * @param[in] gateway   The default gateway.
    249241 */
    250242int ip_set_gateway_req_remote(int ip_phone, device_id_t device_id,
  • uspace/srv/net/il/arp/arp.c

    rf2d2c604 r069015f2  
    2828
    2929/** @addtogroup arp
    30  *  @{
     30 * @{
    3131 */
    3232
    3333/** @file
    34  *  ARP module implementation.
    35  *  @see arp.h
    36  */
     34 * ARP module implementation.
     35 * @see arp.h
     36 */
     37
     38#include "arp.h"
     39#include "arp_header.h"
     40#include "arp_oc.h"
     41#include "arp_module.h"
    3742
    3843#include <async.h>
     
    4348#include <str.h>
    4449#include <task.h>
     50#include <adt/measured_strings.h>
    4551#include <ipc/ipc.h>
    4652#include <ipc/services.h>
     
    5359#include <net/modules.h>
    5460#include <net/device.h>
    55 #include <arp_interface.h>
     61#include <net/packet.h>
     62
    5663#include <nil_interface.h>
    5764#include <protocol_map.h>
    58 #include <adt/measured_strings.h>
    59 #include <net/packet.h>
    6065#include <packet_client.h>
    6166#include <packet_remote.h>
     
    6368#include <il_local.h>
    6469
    65 #include "arp.h"
    66 #include "arp_header.h"
    67 #include "arp_oc.h"
    68 #include "arp_module.h"
    69 
    70 
    71 /** ARP module name.
    72  */
     70
     71/** ARP module name. */
    7372#define NAME  "arp"
    7473
    75 /** ARP global data.
    76  */
    77 arp_globals_t   arp_globals;
     74/** ARP global data. */
     75arp_globals_t arp_globals;
     76
     77DEVICE_MAP_IMPLEMENT(arp_cache, arp_device_t);
     78INT_MAP_IMPLEMENT(arp_protos, arp_proto_t);
     79GENERIC_CHAR_MAP_IMPLEMENT(arp_addr, measured_string_t);
    7880
    7981/** Clears the device specific data.
    80  *  @param[in] device The device specific data.
    81  */
    82 void arp_clear_device(arp_device_ref device);
    83 
    84 /** Creates new protocol specific data.
    85  *  Allocates and returns the needed memory block as the proto parameter.
    86  *  @param[out] proto The allocated protocol specific data.
    87  *  @param[in] service The protocol module service.
    88  *  @param[in] address The actual protocol device address.
    89  *  @returns EOK on success.
    90  *  @returns ENOMEM if there is not enough memory left.
    91  */
    92 int arp_proto_create(arp_proto_ref * proto, services_t service, measured_string_ref address);
    93 
    94 /** @name Message processing functions
    95  */
    96 /*@{*/
    97 
    98 /** Registers the device.
    99  *  Creates new device entry in the cache or updates the protocol address if the device with the device identifier and the driver service exists.
    100  *  @param[in] device_id The device identifier.
    101  *  @param[in] service The device driver service.
    102  *  @param[in] protocol The protocol service.
    103  *  @param[in] address The actual device protocol address.
    104  *  @returns EOK on success.
    105  *  @returns EEXIST if another device with the same device identifier and different driver service exists.
    106  *  @returns ENOMEM if there is not enough memory left.
    107  *  @returns Other error codes as defined for the measured_strings_return() function.
    108  */
    109 int arp_device_message(device_id_t device_id, services_t service, services_t protocol, measured_string_ref address);
    110 
    111 /** Updates the device content length according to the new MTU value.
    112  *  @param[in] device_id The device identifier.
    113  *  @param[in] mtu The new mtu value.
    114  *  @returns ENOENT if device is not found.
    115  *  @returns EOK on success.
    116  */
    117 int arp_mtu_changed_message(device_id_t device_id, size_t mtu);
    118 
    119 /** Processes the received ARP packet.
    120  *  Updates the source hardware address if the source entry exists or the packet is targeted to my protocol address.
    121  *  Responses to the ARP request if the packet is the ARP request and is targeted to my address.
    122  *  @param[in] device_id The source device identifier.
    123  *  @param[in,out] packet The received packet.
    124  *  @returns EOK on success and the packet is no longer needed.
    125  *  @returns 1 on success and the packet has been reused.
    126  *  @returns EINVAL if the packet is too small to carry an ARP packet.
    127  *  @returns EINVAL if the received address lengths differs from the registered values.
    128  *  @returns ENOENT if the device is not found in the cache.
    129  *  @returns ENOENT if the protocol for the device is not found in the cache.
    130  *  @returns ENOMEM if there is not enough memory left.
    131  */
    132 int arp_receive_message(device_id_t device_id, packet_t packet);
    133 
    134 /** Returns the hardware address for the given protocol address.
    135  *  Sends the ARP request packet if the hardware address is not found in the cache.
    136  *  @param[in] device_id The device identifier.
    137  *  @param[in] protocol The protocol service.
    138  *  @param[in] target The target protocol address.
    139  *  @returns The hardware address of the target.
    140  *  @returns NULL if the target parameter is NULL.
    141  *  @returns NULL if the device is not found.
    142  *  @returns NULL if the device packet is too small to send a&nbsp;request.
    143  *  @returns NULL if the hardware address is not found in the cache.
    144  */
    145 measured_string_ref arp_translate_message(device_id_t device_id, services_t protocol, measured_string_ref target);
    146 
    147 /*@}*/
    148 
    149 DEVICE_MAP_IMPLEMENT(arp_cache, arp_device_t)
    150 
    151 INT_MAP_IMPLEMENT(arp_protos, arp_proto_t)
    152 
    153 GENERIC_CHAR_MAP_IMPLEMENT(arp_addr, measured_string_t)
    154 
    155 int arp_clean_cache_req(int arp_phone){
     82 *
     83 * @param[in] device    The device specific data.
     84 */
     85static void arp_clear_device(arp_device_ref device)
     86{
     87        int count;
     88        arp_proto_ref proto;
     89
     90        for (count = arp_protos_count(&device->protos) - 1; count >= 0;
     91            count--) {
     92                proto = arp_protos_get_index(&device->protos, count);
     93                if (proto) {
     94                        if (proto->addr)
     95                                free(proto->addr);
     96                        if (proto->addr_data)
     97                                free(proto->addr_data);
     98                        arp_addr_destroy(&proto->addresses);
     99                }
     100        }
     101        arp_protos_clear(&device->protos);
     102}
     103
     104static int arp_clean_cache_req(int arp_phone)
     105{
    156106        int count;
    157107        arp_device_ref device;
    158108
    159109        fibril_rwlock_write_lock(&arp_globals.lock);
    160         for(count = arp_cache_count(&arp_globals.cache) - 1; count >= 0; -- count){
     110        for (count = arp_cache_count(&arp_globals.cache) - 1; count >= 0;
     111            count--) {
    161112                device = arp_cache_get_index(&arp_globals.cache, count);
    162                 if(device){
     113                if (device) {
    163114                        arp_clear_device(device);
    164                         if(device->addr_data){
     115                        if (device->addr_data)
    165116                                free(device->addr_data);
    166                         }
    167                         if(device->broadcast_data){
     117                        if (device->broadcast_data)
    168118                                free(device->broadcast_data);
    169                         }
    170119                }
    171120        }
     
    176125}
    177126
    178 int arp_clear_address_req(int arp_phone, device_id_t device_id, services_t protocol, measured_string_ref address){
     127static int
     128arp_clear_address_req(int arp_phone, device_id_t device_id, services_t protocol,
     129    measured_string_ref address)
     130{
    179131        arp_device_ref device;
    180132        arp_proto_ref proto;
     
    182134        fibril_rwlock_write_lock(&arp_globals.lock);
    183135        device = arp_cache_find(&arp_globals.cache, device_id);
    184         if(! device){
     136        if (!device) {
    185137                fibril_rwlock_write_unlock(&arp_globals.lock);
    186138                return ENOENT;
    187139        }
    188140        proto = arp_protos_find(&device->protos, protocol);
    189         if(! proto){
     141        if (!proto) {
    190142                fibril_rwlock_write_unlock(&arp_globals.lock);
    191143                return ENOENT;
     
    196148}
    197149
    198 void arp_clear_device(arp_device_ref device){
    199         int count;
    200         arp_proto_ref proto;
    201 
    202         for(count = arp_protos_count(&device->protos) - 1; count >= 0; -- count){
    203                 proto = arp_protos_get_index(&device->protos, count);
    204                 if(proto){
    205                         if(proto->addr){
    206                                 free(proto->addr);
    207                         }
    208                         if(proto->addr_data){
    209                                 free(proto->addr_data);
    210                         }
    211                         arp_addr_destroy(&proto->addresses);
    212                 }
    213         }
    214         arp_protos_clear(&device->protos);
    215 }
    216 
    217 int arp_clear_device_req(int arp_phone, device_id_t device_id){
     150
     151static int arp_clear_device_req(int arp_phone, device_id_t device_id)
     152{
    218153        arp_device_ref device;
    219154
    220155        fibril_rwlock_write_lock(&arp_globals.lock);
    221156        device = arp_cache_find(&arp_globals.cache, device_id);
    222         if(! device){
     157        if (!device) {
    223158                fibril_rwlock_write_unlock(&arp_globals.lock);
    224159                return ENOENT;
     
    230165}
    231166
    232 int arp_device_message(device_id_t device_id, services_t service, services_t protocol, measured_string_ref address){
     167/** Creates new protocol specific data.
     168 *
     169 * Allocates and returns the needed memory block as the proto parameter.
     170 *
     171 * @param[out] proto    The allocated protocol specific data.
     172 * @param[in] service   The protocol module service.
     173 * @param[in] address   The actual protocol device address.
     174 * @returns             EOK on success.
     175 * @returns             ENOMEM if there is not enough memory left.
     176 */
     177static int
     178arp_proto_create(arp_proto_ref *proto, services_t service,
     179    measured_string_ref address)
     180{
     181        ERROR_DECLARE;
     182
     183        *proto = (arp_proto_ref) malloc(sizeof(arp_proto_t));
     184        if (!*proto)
     185                return ENOMEM;
     186        (*proto)->service = service;
     187        (*proto)->addr = address;
     188        (*proto)->addr_data = address->value;
     189        if (ERROR_OCCURRED(arp_addr_initialize(&(*proto)->addresses))) {
     190                free(*proto);
     191                return ERROR_CODE;
     192        }
     193        return EOK;
     194}
     195
     196/** Registers the device.
     197 *
     198 * Creates new device entry in the cache or updates the protocol address if the
     199 * device with the device identifier and the driver service exists.
     200 *
     201 * @param[in] device_id The device identifier.
     202 * @param[in] service   The device driver service.
     203 * @param[in] protocol  The protocol service.
     204 * @param[in] address   The actual device protocol address.
     205 * @returns             EOK on success.
     206 * @returns             EEXIST if another device with the same device identifier
     207 *                      and different driver service exists.
     208 * @returns             ENOMEM if there is not enough memory left.
     209 * @returns             Other error codes as defined for the
     210 *                      measured_strings_return() function.
     211 */
     212static int
     213arp_device_message(device_id_t device_id, services_t service,
     214    services_t protocol, measured_string_ref address)
     215{
    233216        ERROR_DECLARE;
    234217
     
    241224        // an existing device?
    242225        device = arp_cache_find(&arp_globals.cache, device_id);
    243         if(device){
    244                 if(device->service != service){
     226        if (device) {
     227                if (device->service != service) {
    245228                        printf("Device %d already exists\n", device->device_id);
    246229                        fibril_rwlock_write_unlock(&arp_globals.lock);
     
    248231                }
    249232                proto = arp_protos_find(&device->protos, protocol);
    250                 if(proto){
     233                if (proto) {
    251234                        free(proto->addr);
    252235                        free(proto->addr_data);
    253236                        proto->addr = address;
    254237                        proto->addr_data = address->value;
    255                 }else{
    256                         if(ERROR_OCCURRED(arp_proto_create(&proto, protocol, address))){
     238                } else {
     239                        if (ERROR_OCCURRED(arp_proto_create(&proto, protocol,
     240                            address))) {
    257241                                fibril_rwlock_write_unlock(&arp_globals.lock);
    258242                                return ERROR_CODE;
    259243                        }
    260                         index = arp_protos_add(&device->protos, proto->service, proto);
    261                         if(index < 0){
     244                        index = arp_protos_add(&device->protos, proto->service,
     245                            proto);
     246                        if (index < 0) {
    262247                                fibril_rwlock_write_unlock(&arp_globals.lock);
    263248                                free(proto);
    264249                                return index;
    265250                        }
    266                         printf("New protocol added:\n\tdevice id\t= %d\n\tproto\t= %d", device_id, protocol);
    267                 }
    268         }else{
     251                        printf("New protocol added:\n\tdevice id\t= "
     252                            "%d\n\tproto\t= %d", device_id, protocol);
     253                }
     254        } else {
    269255                hardware = hardware_map(service);
    270                 if(! hardware){
     256                if (!hardware)
    271257                        return ENOENT;
    272                 }
     258               
    273259                // create a new device
    274260                device = (arp_device_ref) malloc(sizeof(arp_device_t));
    275                 if(! device){
     261                if (!device) {
    276262                        fibril_rwlock_write_unlock(&arp_globals.lock);
    277263                        return ENOMEM;
     
    279265                device->hardware = hardware;
    280266                device->device_id = device_id;
    281                 if(ERROR_OCCURRED(arp_protos_initialize(&device->protos))
    282                         || ERROR_OCCURRED(arp_proto_create(&proto, protocol, address))){
     267                if (ERROR_OCCURRED(arp_protos_initialize(&device->protos)) ||
     268                    ERROR_OCCURRED(arp_proto_create(&proto, protocol,
     269                    address))) {
    283270                        fibril_rwlock_write_unlock(&arp_globals.lock);
    284271                        free(device);
     
    286273                }
    287274                index = arp_protos_add(&device->protos, proto->service, proto);
    288                 if(index < 0){
     275                if (index < 0) {
    289276                        fibril_rwlock_write_unlock(&arp_globals.lock);
    290277                        arp_protos_destroy(&device->protos);
     
    293280                }
    294281                device->service = service;
     282               
    295283                // bind the new one
    296                 device->phone = nil_bind_service(device->service, (ipcarg_t) device->device_id, SERVICE_ARP, arp_globals.client_connection);
    297                 if(device->phone < 0){
     284                device->phone = nil_bind_service(device->service,
     285                    (ipcarg_t) device->device_id, SERVICE_ARP,
     286                    arp_globals.client_connection);
     287                if (device->phone < 0) {
    298288                        fibril_rwlock_write_unlock(&arp_globals.lock);
    299289                        arp_protos_destroy(&device->protos);
     
    301291                        return EREFUSED;
    302292                }
     293               
    303294                // get packet dimensions
    304                 if(ERROR_OCCURRED(nil_packet_size_req(device->phone, device_id, &device->packet_dimension))){
     295                if (ERROR_OCCURRED(nil_packet_size_req(device->phone, device_id,
     296                    &device->packet_dimension))) {
    305297                        fibril_rwlock_write_unlock(&arp_globals.lock);
    306298                        arp_protos_destroy(&device->protos);
     
    308300                        return ERROR_CODE;
    309301                }
     302               
    310303                // get hardware address
    311                 if(ERROR_OCCURRED(nil_get_addr_req(device->phone, device_id, &device->addr, &device->addr_data))){
     304                if (ERROR_OCCURRED(nil_get_addr_req(device->phone, device_id,
     305                    &device->addr, &device->addr_data))) {
    312306                        fibril_rwlock_write_unlock(&arp_globals.lock);
    313307                        arp_protos_destroy(&device->protos);
     
    315309                        return ERROR_CODE;
    316310                }
     311               
    317312                // get broadcast address
    318                 if(ERROR_OCCURRED(nil_get_broadcast_addr_req(device->phone, device_id, &device->broadcast_addr, &device->broadcast_data))){
     313                if (ERROR_OCCURRED(nil_get_broadcast_addr_req(device->phone,
     314                    device_id, &device->broadcast_addr,
     315                    &device->broadcast_data))) {
    319316                        fibril_rwlock_write_unlock(&arp_globals.lock);
    320317                        free(device->addr);
     
    324321                        return ERROR_CODE;
    325322                }
    326                 if(ERROR_OCCURRED(arp_cache_add(&arp_globals.cache, device->device_id, device))){
     323               
     324                if (ERROR_OCCURRED(arp_cache_add(&arp_globals.cache,
     325                    device->device_id, device))) {
    327326                        fibril_rwlock_write_unlock(&arp_globals.lock);
    328327                        free(device->addr);
     
    334333                        return ERROR_CODE;
    335334                }
    336                 printf("%s: Device registered (id: %d, type: 0x%x, service: %d, proto: %d)\n",
    337                     NAME, device->device_id, device->hardware, device->service, protocol);
     335                printf("%s: Device registered (id: %d, type: 0x%x, service: %d,"
     336                    " proto: %d)\n", NAME, device->device_id, device->hardware,
     337                    device->service, protocol);
    338338        }
    339339        fibril_rwlock_write_unlock(&arp_globals.lock);
    340         return EOK;
    341 }
    342 
    343 int arp_device_req(int arp_phone, device_id_t device_id, services_t protocol, services_t netif, measured_string_ref address){
    344         ERROR_DECLARE;
    345 
    346         measured_string_ref tmp;
    347 
    348         // copy the given address for exclusive use
    349         tmp = measured_string_copy(address);
    350         if(ERROR_OCCURRED(arp_device_message(device_id, netif, protocol, tmp))){
    351                 free(tmp->value);
    352                 free(tmp);
    353         }
    354         return ERROR_CODE;
    355 }
    356 
    357 int arp_initialize(async_client_conn_t client_connection){
     340       
     341        return EOK;
     342}
     343
     344/** Initializes the ARP module.
     345 *
     346 *  @param[in] client_connection The client connection processing function.
     347 *                      The module skeleton propagates its own one.
     348 *  @returns            EOK on success.
     349 *  @returns            ENOMEM if there is not enough memory left.
     350 */
     351int arp_initialize(async_client_conn_t client_connection)
     352{
    358353        ERROR_DECLARE;
    359354
     
    366361}
    367362
    368 int arp_message_standalone(ipc_callid_t callid, ipc_call_t *call,
    369     ipc_call_t *answer, int *answer_count)
    370 {
    371         ERROR_DECLARE;
    372        
    373         measured_string_ref address;
    374         measured_string_ref translation;
    375         char * data;
    376         packet_t packet;
    377         packet_t next;
    378        
    379         *answer_count = 0;
    380         switch (IPC_GET_METHOD(*call)) {
    381                 case IPC_M_PHONE_HUNGUP:
    382                         return EOK;
    383                 case NET_ARP_DEVICE:
    384                         ERROR_PROPAGATE(measured_strings_receive(&address, &data, 1));
    385                         if(ERROR_OCCURRED(arp_device_message(IPC_GET_DEVICE(call), IPC_GET_SERVICE(call), ARP_GET_NETIF(call), address))){
    386                                 free(address);
    387                                 free(data);
    388                         }
    389                         return ERROR_CODE;
    390                 case NET_ARP_TRANSLATE:
    391                         ERROR_PROPAGATE(measured_strings_receive(&address, &data, 1));
    392                         fibril_rwlock_read_lock(&arp_globals.lock);
    393                         translation = arp_translate_message(IPC_GET_DEVICE(call), IPC_GET_SERVICE(call), address);
    394                         free(address);
    395                         free(data);
    396                         if(! translation){
    397                                 fibril_rwlock_read_unlock(&arp_globals.lock);
    398                                 return ENOENT;
    399                         }
    400                         ERROR_CODE = measured_strings_reply(translation, 1);
    401                         fibril_rwlock_read_unlock(&arp_globals.lock);
    402                         return ERROR_CODE;
    403                 case NET_ARP_CLEAR_DEVICE:
    404                         return arp_clear_device_req(0, IPC_GET_DEVICE(call));
    405                 case NET_ARP_CLEAR_ADDRESS:
    406                         ERROR_PROPAGATE(measured_strings_receive(&address, &data, 1));
    407                         arp_clear_address_req(0, IPC_GET_DEVICE(call), IPC_GET_SERVICE(call), address);
    408                         free(address);
    409                         free(data);
    410                         return EOK;
    411                 case NET_ARP_CLEAN_CACHE:
    412                         return arp_clean_cache_req(0);
    413                 case NET_IL_DEVICE_STATE:
    414                         // do nothing - keep the cache
    415                         return EOK;
    416                 case NET_IL_RECEIVED:
    417                         if(! ERROR_OCCURRED(packet_translate_remote(arp_globals.net_phone, &packet, IPC_GET_PACKET(call)))){
    418                                 fibril_rwlock_read_lock(&arp_globals.lock);
    419                                 do{
    420                                         next = pq_detach(packet);
    421                                         ERROR_CODE = arp_receive_message(IPC_GET_DEVICE(call), packet);
    422                                         if(ERROR_CODE != 1){
    423                                                 pq_release_remote(arp_globals.net_phone, packet_get_id(packet));
    424                                         }
    425                                         packet = next;
    426                                 }while(packet);
    427                                 fibril_rwlock_read_unlock(&arp_globals.lock);
    428                         }
    429                         return ERROR_CODE;
    430                 case NET_IL_MTU_CHANGED:
    431                         return arp_mtu_changed_message(IPC_GET_DEVICE(call), IPC_GET_MTU(call));
    432         }
    433        
    434         return ENOTSUP;
    435 }
    436 
    437 int arp_mtu_changed_message(device_id_t device_id, size_t mtu){
     363/** Updates the device content length according to the new MTU value.
     364 *
     365 * @param[in] device_id The device identifier.
     366 * @param[in] mtu       The new mtu value.
     367 * @returns             ENOENT if device is not found.
     368 * @returns             EOK on success.
     369 */
     370static int arp_mtu_changed_message(device_id_t device_id, size_t mtu)
     371{
    438372        arp_device_ref device;
    439373
    440374        fibril_rwlock_write_lock(&arp_globals.lock);
    441375        device = arp_cache_find(&arp_globals.cache, device_id);
    442         if(! device){
     376        if (!device) {
    443377                fibril_rwlock_write_unlock(&arp_globals.lock);
    444378                return ENOENT;
    445379        }
    446380        device->packet_dimension.content = mtu;
     381        fibril_rwlock_write_unlock(&arp_globals.lock);
    447382        printf("arp - device %d changed mtu to %d\n\n", device_id, mtu);
    448         fibril_rwlock_write_unlock(&arp_globals.lock);
    449         return EOK;
    450 }
    451 
    452 int arp_proto_create(arp_proto_ref * proto, services_t service, measured_string_ref address){
    453         ERROR_DECLARE;
    454 
    455         *proto = (arp_proto_ref) malloc(sizeof(arp_proto_t));
    456         if(!(*proto)){
    457                 return ENOMEM;
    458         }
    459         (** proto).service = service;
    460         (** proto).addr = address;
    461         (** proto).addr_data = address->value;
    462         if(ERROR_OCCURRED(arp_addr_initialize(&(** proto).addresses))){
    463                 free(*proto);
    464                 return ERROR_CODE;
    465         }
    466         return EOK;
    467 }
    468 
    469 int arp_receive_message(device_id_t device_id, packet_t packet){
     383        return EOK;
     384}
     385
     386/** Processes the received ARP packet.
     387 *
     388 * Updates the source hardware address if the source entry exists or the packet
     389 * is targeted to my protocol address.
     390 * Responses to the ARP request if the packet is the ARP request and is
     391 * targeted to my address.
     392 *
     393 * @param[in] device_id The source device identifier.
     394 * @param[in,out] packet The received packet.
     395 * @returns             EOK on success and the packet is no longer needed.
     396 * @returns             One on success and the packet has been reused.
     397 * @returns             EINVAL if the packet is too small to carry an ARP
     398 *                      packet.
     399 * @returns             EINVAL if the received address lengths differs from
     400 *                      the registered values.
     401 * @returns             ENOENT if the device is not found in the cache.
     402 * @returns             ENOENT if the protocol for the device is not found in
     403 *                      the cache.
     404 * @returns             ENOMEM if there is not enough memory left.
     405 */
     406static int arp_receive_message(device_id_t device_id, packet_t packet)
     407{
    470408        ERROR_DECLARE;
    471409
     
    475413        arp_proto_ref proto;
    476414        measured_string_ref hw_source;
    477         uint8_t * src_hw;
    478         uint8_t * src_proto;
    479         uint8_t * des_hw;
    480         uint8_t * des_proto;
     415        uint8_t *src_hw;
     416        uint8_t *src_proto;
     417        uint8_t *des_hw;
     418        uint8_t *des_proto;
    481419
    482420        length = packet_get_data_length(packet);
    483         if(length <= sizeof(arp_header_t)){
     421        if (length <= sizeof(arp_header_t))
    484422                return EINVAL;
    485         }
     423
    486424        device = arp_cache_find(&arp_globals.cache, device_id);
    487         if(! device){
     425        if (!device)
    488426                return ENOENT;
    489         }
     427
    490428        header = (arp_header_ref) packet_get_data(packet);
    491         if((ntohs(header->hardware) != device->hardware)
    492                 || (length < sizeof(arp_header_t) + header->hardware_length * 2u + header->protocol_length * 2u)){
     429        if ((ntohs(header->hardware) != device->hardware) ||
     430            (length < sizeof(arp_header_t) + header->hardware_length * 2U +
     431            header->protocol_length * 2U)) {
    493432                return EINVAL;
    494433        }
    495         proto = arp_protos_find(&device->protos, protocol_unmap(device->service, ntohs(header->protocol)));
    496         if(! proto){
     434
     435        proto = arp_protos_find(&device->protos,
     436            protocol_unmap(device->service, ntohs(header->protocol)));
     437        if (!proto)
    497438                return ENOENT;
    498         }
     439
    499440        src_hw = ((uint8_t *) header) + sizeof(arp_header_t);
    500441        src_proto = src_hw + header->hardware_length;
    501442        des_hw = src_proto + header->protocol_length;
    502443        des_proto = des_hw + header->hardware_length;
    503         hw_source = arp_addr_find(&proto->addresses, (char *) src_proto, CONVERT_SIZE(uint8_t, char, header->protocol_length));
     444        hw_source = arp_addr_find(&proto->addresses, (char *) src_proto,
     445            CONVERT_SIZE(uint8_t, char, header->protocol_length));
    504446        // exists?
    505         if(hw_source){
    506                 if(hw_source->length != CONVERT_SIZE(uint8_t, char, header->hardware_length)){
     447        if (hw_source) {
     448                if (hw_source->length != CONVERT_SIZE(uint8_t, char,
     449                    header->hardware_length)) {
    507450                        return EINVAL;
    508451                }
     
    510453        }
    511454        // is my protocol address?
    512         if(proto->addr->length != CONVERT_SIZE(uint8_t, char, header->protocol_length)){
     455        if (proto->addr->length != CONVERT_SIZE(uint8_t, char,
     456            header->protocol_length)) {
    513457                return EINVAL;
    514458        }
    515         if(! str_lcmp(proto->addr->value, (char *) des_proto, proto->addr->length)){
     459        if (!str_lcmp(proto->addr->value, (char *) des_proto,
     460            proto->addr->length)) {
    516461                // not already upadted?
    517                 if(! hw_source){
    518                         hw_source = measured_string_create_bulk((char *) src_hw, CONVERT_SIZE(uint8_t, char, header->hardware_length));
    519                         if(! hw_source){
     462                if (!hw_source) {
     463                        hw_source = measured_string_create_bulk((char *) src_hw,
     464                            CONVERT_SIZE(uint8_t, char,
     465                            header->hardware_length));
     466                        if (!hw_source)
    520467                                return ENOMEM;
    521                         }
    522                         ERROR_PROPAGATE(arp_addr_add(&proto->addresses, (char *) src_proto, CONVERT_SIZE(uint8_t, char, header->protocol_length), hw_source));
    523                 }
    524                 if(ntohs(header->operation) == ARPOP_REQUEST){
     468
     469                        ERROR_PROPAGATE(arp_addr_add(&proto->addresses,
     470                            (char *) src_proto, CONVERT_SIZE(uint8_t, char,
     471                            header->protocol_length), hw_source));
     472                }
     473                if (ntohs(header->operation) == ARPOP_REQUEST) {
    525474                        header->operation = htons(ARPOP_REPLY);
    526475                        memcpy(des_proto, src_proto, header->protocol_length);
    527                         memcpy(src_proto, proto->addr->value, header->protocol_length);
    528                         memcpy(src_hw, device->addr->value, device->packet_dimension.addr_len);
    529                         memcpy(des_hw, hw_source->value, header->hardware_length);
    530                         ERROR_PROPAGATE(packet_set_addr(packet, src_hw, des_hw, header->hardware_length));
    531                         nil_send_msg(device->phone, device_id, packet, SERVICE_ARP);
     476                        memcpy(src_proto, proto->addr->value,
     477                            header->protocol_length);
     478                        memcpy(src_hw, device->addr->value,
     479                            device->packet_dimension.addr_len);
     480                        memcpy(des_hw, hw_source->value,
     481                            header->hardware_length);
     482                        ERROR_PROPAGATE(packet_set_addr(packet, src_hw, des_hw,
     483                            header->hardware_length));
     484                        nil_send_msg(device->phone, device_id, packet,
     485                            SERVICE_ARP);
    532486                        return 1;
    533487                }
    534488        }
    535         return EOK;
    536 }
    537 
    538 measured_string_ref arp_translate_message(device_id_t device_id, services_t protocol, measured_string_ref target){
     489
     490        return EOK;
     491}
     492
     493
     494/** Returns the hardware address for the given protocol address.
     495 *
     496 * Sends the ARP request packet if the hardware address is not found in the
     497 * cache.
     498 *
     499 * @param[in] device_id The device identifier.
     500 * @param[in] protocol  The protocol service.
     501 * @param[in] target    The target protocol address.
     502 * @returns             The hardware address of the target.
     503 * @returns             NULL if the target parameter is NULL.
     504 * @returns             NULL if the device is not found.
     505 * @returns             NULL if the device packet is too small to send a
     506 *                      request.
     507 * @returns             NULL if the hardware address is not found in the cache.
     508 */
     509static measured_string_ref
     510arp_translate_message(device_id_t device_id, services_t protocol,
     511    measured_string_ref target)
     512{
    539513        arp_device_ref device;
    540514        arp_proto_ref proto;
     
    544518        arp_header_ref header;
    545519
    546         if(! target){
     520        if (!target)
    547521                return NULL;
    548         }
     522
    549523        device = arp_cache_find(&arp_globals.cache, device_id);
    550         if(! device){
     524        if (!device)
    551525                return NULL;
    552         }
     526
    553527        proto = arp_protos_find(&device->protos, protocol);
    554         if((! proto) || (proto->addr->length != target->length)){
     528        if (!proto || (proto->addr->length != target->length))
    555529                return NULL;
    556         }
     530
    557531        addr = arp_addr_find(&proto->addresses, target->value, target->length);
    558         if(addr){
     532        if (addr)
    559533                return addr;
    560         }
     534
    561535        // ARP packet content size = header + (address + translation) * 2
    562         length = 8 + (CONVERT_SIZE(char, uint8_t, proto->addr->length) + CONVERT_SIZE(char, uint8_t, device->addr->length)) * 2;
    563         if(length > device->packet_dimension.content){
     536        length = 8 + 2 * (CONVERT_SIZE(char, uint8_t, proto->addr->length) +
     537            CONVERT_SIZE(char, uint8_t, device->addr->length));
     538        if (length > device->packet_dimension.content)
    564539                return NULL;
    565         }
    566         packet = packet_get_4_remote(arp_globals.net_phone, device->packet_dimension.addr_len, device->packet_dimension.prefix, length, device->packet_dimension.suffix);
    567         if(! packet){
     540
     541        packet = packet_get_4_remote(arp_globals.net_phone,
     542            device->packet_dimension.addr_len, device->packet_dimension.prefix,
     543            length, device->packet_dimension.suffix);
     544        if (!packet)
    568545                return NULL;
    569         }
     546
    570547        header = (arp_header_ref) packet_suffix(packet, length);
    571         if(! header){
     548        if (!header) {
    572549                pq_release_remote(arp_globals.net_phone, packet_get_id(packet));
    573550                return NULL;
    574551        }
     552
    575553        header->hardware = htons(device->hardware);
    576554        header->hardware_length = (uint8_t) device->addr->length;
     
    579557        header->operation = htons(ARPOP_REQUEST);
    580558        length = sizeof(arp_header_t);
    581         memcpy(((uint8_t *) header) + length, device->addr->value, device->addr->length);
     559        memcpy(((uint8_t *) header) + length, device->addr->value,
     560            device->addr->length);
    582561        length += device->addr->length;
    583         memcpy(((uint8_t *) header) + length, proto->addr->value, proto->addr->length);
     562        memcpy(((uint8_t *) header) + length, proto->addr->value,
     563            proto->addr->length);
    584564        length += proto->addr->length;
    585565        bzero(((uint8_t *) header) + length, device->addr->length);
    586566        length += device->addr->length;
    587567        memcpy(((uint8_t *) header) + length, target->value, target->length);
    588         if(packet_set_addr(packet, (uint8_t *) device->addr->value, (uint8_t *) device->broadcast_addr->value, CONVERT_SIZE(char, uint8_t, device->addr->length)) != EOK){
     568
     569        if (packet_set_addr(packet, (uint8_t *) device->addr->value,
     570            (uint8_t *) device->broadcast_addr->value,
     571            CONVERT_SIZE(char, uint8_t, device->addr->length)) != EOK) {
    589572                pq_release_remote(arp_globals.net_phone, packet_get_id(packet));
    590573                return NULL;
    591574        }
     575
    592576        nil_send_msg(device->phone, device_id, packet, SERVICE_ARP);
    593577        return NULL;
    594578}
    595579
     580
     581/** Processes the ARP message.
     582 *
     583 * @param[in] callid    The message identifier.
     584 * @param[in] call      The message parameters.
     585 * @param[out] answer   The message answer parameters.
     586 * @param[out] answer_count The last parameter for the actual answer in the
     587 *                      answer parameter.
     588 * @returns             EOK on success.
     589 * @returns             ENOTSUP if the message is not known.
     590 *
     591 * @see arp_interface.h
     592 * @see IS_NET_ARP_MESSAGE()
     593 */
     594int
     595arp_message_standalone(ipc_callid_t callid, ipc_call_t *call,
     596    ipc_call_t *answer, int *answer_count)
     597{
     598        ERROR_DECLARE;
     599       
     600        measured_string_ref address;
     601        measured_string_ref translation;
     602        char *data;
     603        packet_t packet;
     604        packet_t next;
     605       
     606        *answer_count = 0;
     607        switch (IPC_GET_METHOD(*call)) {
     608        case IPC_M_PHONE_HUNGUP:
     609                return EOK;
     610       
     611        case NET_ARP_DEVICE:
     612                ERROR_PROPAGATE(measured_strings_receive(&address, &data, 1));
     613                if (ERROR_OCCURRED(arp_device_message(IPC_GET_DEVICE(call),
     614                    IPC_GET_SERVICE(call), ARP_GET_NETIF(call), address))) {
     615                        free(address);
     616                        free(data);
     617                }
     618                return ERROR_CODE;
     619       
     620        case NET_ARP_TRANSLATE:
     621                ERROR_PROPAGATE(measured_strings_receive(&address, &data, 1));
     622                fibril_rwlock_read_lock(&arp_globals.lock);
     623                translation = arp_translate_message(IPC_GET_DEVICE(call),
     624                    IPC_GET_SERVICE(call), address);
     625                free(address);
     626                free(data);
     627                if (!translation) {
     628                        fibril_rwlock_read_unlock(&arp_globals.lock);
     629                        return ENOENT;
     630                }
     631                ERROR_CODE = measured_strings_reply(translation, 1);
     632                fibril_rwlock_read_unlock(&arp_globals.lock);
     633                return ERROR_CODE;
     634
     635        case NET_ARP_CLEAR_DEVICE:
     636                return arp_clear_device_req(0, IPC_GET_DEVICE(call));
     637
     638        case NET_ARP_CLEAR_ADDRESS:
     639                ERROR_PROPAGATE(measured_strings_receive(&address, &data, 1));
     640                arp_clear_address_req(0, IPC_GET_DEVICE(call),
     641                    IPC_GET_SERVICE(call), address);
     642                free(address);
     643                free(data);
     644                return EOK;
     645       
     646        case NET_ARP_CLEAN_CACHE:
     647                return arp_clean_cache_req(0);
     648       
     649        case NET_IL_DEVICE_STATE:
     650                // do nothing - keep the cache
     651                return EOK;
     652       
     653        case NET_IL_RECEIVED:
     654                if (ERROR_NONE(packet_translate_remote(arp_globals.net_phone,
     655                    &packet, IPC_GET_PACKET(call)))) {
     656                        fibril_rwlock_read_lock(&arp_globals.lock);
     657                        do {
     658                                next = pq_detach(packet);
     659                                ERROR_CODE =
     660                                    arp_receive_message(IPC_GET_DEVICE(call),
     661                                    packet);
     662                                if (ERROR_CODE != 1) {
     663                                        pq_release_remote(arp_globals.net_phone,
     664                                            packet_get_id(packet));
     665                                }
     666                                packet = next;
     667                        } while (packet);
     668                        fibril_rwlock_read_unlock(&arp_globals.lock);
     669                }
     670                return ERROR_CODE;
     671       
     672        case NET_IL_MTU_CHANGED:
     673                return arp_mtu_changed_message(IPC_GET_DEVICE(call),
     674                    IPC_GET_MTU(call));
     675        }
     676       
     677        return ENOTSUP;
     678}
     679
    596680/** Default thread for new connections.
    597681 *
    598  *  @param[in] iid The initial message identifier.
    599  *  @param[in] icall The initial message call structure.
    600  *
    601  */
    602 static void il_client_connection(ipc_callid_t iid, ipc_call_t * icall)
     682 * @param[in] iid       The initial message identifier.
     683 * @param[in] icall     The initial message call structure.
     684 */
     685static void il_client_connection(ipc_callid_t iid, ipc_call_t *icall)
    603686{
    604687        /*
     
    608691        ipc_answer_0(iid, EOK);
    609692       
    610         while(true) {
     693        while (true) {
    611694                ipc_call_t answer;
    612695                int answer_count;
     
    623706                    &answer_count);
    624707               
    625                 /* End if said to either by the message or the processing result */
    626                 if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) || (res == EHANGUP))
     708                /*
     709                 * End if told to either by the message or the processing
     710                 * result.
     711                 */
     712                if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) ||
     713                    (res == EHANGUP))
    627714                        return;
    628715               
     
    634721/** Starts the module.
    635722 *
    636  *  @param argc The count of the command line arguments. Ignored parameter.
    637  *  @param argv The command line parameters. Ignored parameter.
    638  *
    639  *  @returns EOK on success.
    640  *  @returns Other error codes as defined for each specific module start function.
    641  *
     723 * @returns             EOK on success.
     724 * @returns             Other error codes as defined for each specific module
     725 *                      start function.
    642726 */
    643727int main(int argc, char *argv[])
     
    646730       
    647731        /* Start the module */
    648         if (ERROR_OCCURRED(il_module_start_standalone(il_client_connection)))
    649                 return ERROR_CODE;
    650        
     732        ERROR_PROPAGATE(il_module_start_standalone(il_client_connection));
    651733        return EOK;
    652734}
     
    654736/** @}
    655737 */
     738
  • uspace/srv/net/il/arp/arp.h

    rf2d2c604 r069015f2  
    2828
    2929/** @addtogroup arp
    30  *  @{
     30 * @{
    3131 */
    3232
    3333/** @file
    34  *  ARP module.
     34 * ARP module.
    3535 */
    3636
    37 #ifndef __NET_ARP_H__
    38 #define __NET_ARP_H__
     37#ifndef NET_ARP_H_
     38#define NET_ARP_H_
    3939
    4040#include <fibril_synch.h>
     
    4444
    4545#include <net/device.h>
     46#include <net/packet.h>
    4647#include <net_hardware.h>
    4748#include <adt/generic_char_map.h>
     
    4950#include <adt/measured_strings.h>
    5051
    51 
    5252/** Type definition of the ARP device specific data.
    53  *  @see arp_device
     53 * @see arp_device
    5454 */
    55 typedef struct arp_device       arp_device_t;
     55typedef struct arp_device arp_device_t;
    5656
    5757/** Type definition of the ARP device specific data pointer.
    58  *  @see arp_device
     58 * @see arp_device
    5959 */
    60 typedef arp_device_t *          arp_device_ref;
     60typedef arp_device_t *arp_device_ref;
    6161
    6262/** Type definition of the ARP global data.
    63  *  @see arp_globals
     63 * @see arp_globals
    6464 */
    65 typedef struct arp_globals      arp_globals_t;
     65typedef struct arp_globals arp_globals_t;
    6666
    6767/** Type definition of the ARP protocol specific data.
    68  *  @see arp_proto
     68 * @see arp_proto
    6969 */
    70 typedef struct arp_proto        arp_proto_t;
     70typedef struct arp_proto arp_proto_t;
    7171
    7272/** Type definition of the ARP protocol specific data pointer.
    73  *  @see arp_proto
     73 * @see arp_proto
    7474 */
    75 typedef arp_proto_t *           arp_proto_ref;
     75typedef arp_proto_t *arp_proto_ref;
    7676
    7777/** ARP address map.
    78  *  Translates addresses.
    79  *  @see generic_char_map.h
     78 *
     79 * Translates addresses.
     80 * @see generic_char_map.h
    8081 */
    81 GENERIC_CHAR_MAP_DECLARE(arp_addr, measured_string_t)
     82GENERIC_CHAR_MAP_DECLARE(arp_addr, measured_string_t);
    8283
    8384/** ARP address cache.
    84  *  Maps devices to the ARP device specific data.
    85  *  @see device.h
     85 *
     86 * Maps devices to the ARP device specific data.
     87 * @see device.h
    8688 */
    87 DEVICE_MAP_DECLARE(arp_cache, arp_device_t)
     89DEVICE_MAP_DECLARE(arp_cache, arp_device_t);
    8890
    8991/** ARP protocol map.
    90  *  Maps protocol identifiers to the ARP protocol specific data.
    91  *  @see int_map.h
     92 *
     93 * Maps protocol identifiers to the ARP protocol specific data.
     94 * @see int_map.h
    9295 */
    93 INT_MAP_DECLARE(arp_protos, arp_proto_t)
     96INT_MAP_DECLARE(arp_protos, arp_proto_t);
    9497
    95 /** ARP device specific data.
    96  */
    97 struct arp_device{
    98         /** Actual device hardware address.
    99          */
     98/** ARP device specific data. */
     99struct arp_device {
     100        /** Actual device hardware address. */
    100101        measured_string_ref addr;
    101         /** Actual device hardware address data.
    102          */
    103         char * addr_data;
    104         /** Broadcast device hardware address.
    105          */
     102        /** Actual device hardware address data. */
     103        char *addr_data;
     104        /** Broadcast device hardware address. */
    106105        measured_string_ref broadcast_addr;
    107         /** Broadcast device hardware address data.
    108          */
    109         char * broadcast_data;
    110         /** Device identifier.
    111          */
     106        /** Broadcast device hardware address data. */
     107        char *broadcast_data;
     108        /** Device identifier. */
    112109        device_id_t device_id;
    113         /** Hardware type.
    114          */
     110        /** Hardware type. */
    115111        hw_type_t hardware;
    116         /** Packet dimension.
    117          */
     112        /** Packet dimension. */
    118113        packet_dimension_t packet_dimension;
    119         /** Device module phone.
    120          */
     114        /** Device module phone. */
    121115        int phone;
    122         /** Protocol map.
    123          *  Address map for each protocol.
     116       
     117        /**
     118         * Protocol map.
     119         * Address map for each protocol.
    124120         */
    125121        arp_protos_t protos;
    126         /** Device module service.
    127         */
     122       
     123        /** Device module service. */
    128124        services_t service;
    129125};
    130126
    131 /** ARP global data.
    132  */
    133 struct  arp_globals{
    134         /** ARP address cache.
    135          */
     127/** ARP global data. */
     128struct arp_globals {
     129        /** ARP address cache. */
    136130        arp_cache_t cache;
    137         /** The client connection processing function.
    138          *  The module skeleton propagates its own one.
     131       
     132        /**
     133         * The client connection processing function.
     134         * The module skeleton propagates its own one.
    139135         */
    140136        async_client_conn_t client_connection;
    141         /** Networking module phone.
    142         */
     137       
     138        /** Networking module phone. */
    143139        int net_phone;
    144         /** Safety lock.
    145          */
     140        /** Safety lock. */
    146141        fibril_rwlock_t lock;
    147142};
    148143
    149 /** ARP protocol specific data.
    150  */
    151 struct arp_proto{
    152         /** Actual device protocol address.
    153          */
     144/** ARP protocol specific data. */
     145struct arp_proto {
     146        /** Actual device protocol address. */
    154147        measured_string_ref addr;
    155         /** Actual device protocol address data.
    156          */
    157         char * addr_data;
    158         /** Address map.
    159          */
     148        /** Actual device protocol address data. */
     149        char *addr_data;
     150        /** Address map. */
    160151        arp_addr_t addresses;
    161         /** Protocol service.
    162          */
     152        /** Protocol service. */
    163153        services_t service;
    164154};
  • uspace/srv/net/il/arp/arp_header.h

    rf2d2c604 r069015f2  
    3232
    3333/** @file
    34  *  ARP protocol header.
    35  *  Based on the RFC~826.
     34 * ARP protocol header.
     35 * Based on the RFC 826.
    3636 */
    3737
    38 #ifndef __NET_ARP_HEADER_H__
    39 #define __NET_ARP_HEADER_H__
     38#ifndef NET_ARP_HEADER_H_
     39#define NET_ARP_HEADER_H_
    4040
    4141#include <sys/types.h>
    4242
    4343/** Type definition of an ARP protocol header.
    44  *  @see arp_header
     44 * @see arp_header
    4545 */
    46 typedef struct arp_header       arp_header_t;
     46typedef struct arp_header arp_header_t;
    4747
    4848/** Type definition of an ARP protocol header pointer.
    49  *  @see arp_header
     49 * @see arp_header
    5050 */
    51 typedef arp_header_t *          arp_header_ref;
     51typedef arp_header_t *arp_header_ref;
    5252
    53 /** ARP protocol header.
    54  */
    55 struct arp_header{
    56         /** Hardware type identifier.
    57          *  @see hardware.h
     53/** ARP protocol header. */
     54struct arp_header {
     55        /**
     56         * Hardware type identifier.
     57         * @see hardware.h
    5858         */
    5959        uint16_t hardware;
    60         /** Protocol identifier.
    61         */
     60       
     61        /** Protocol identifier. */
    6262        uint16_t protocol;
    63         /** Hardware address length in bytes.
    64          */
     63        /** Hardware address length in bytes. */
    6564        uint8_t hardware_length;
    66         /** Protocol address length in bytes.
    67          */
     65        /** Protocol address length in bytes. */
    6866        uint8_t protocol_length;
    69         /** ARP packet type.
    70          *  @see arp_oc.h
     67       
     68        /**
     69         * ARP packet type.
     70         * @see arp_oc.h
    7171         */
    7272        uint16_t operation;
  • uspace/srv/net/il/arp/arp_module.c

    rf2d2c604 r069015f2  
    3232
    3333/** @file
    34  *  ARP standalone module implementation.
    35  *  Contains skeleton module functions mapping.
    36  *  The functions are used by the module skeleton as module specific entry points.
    37  *  @see module.c
     34 * ARP standalone module implementation.
     35 * Contains skeleton module functions mapping.
     36 * The functions are used by the module skeleton as module specific entry
     37 * points.
     38 * @see module.c
    3839 */
    3940
     
    5354#include "arp_module.h"
    5455
    55 /** ARP module global data.
    56  */
    57 extern arp_globals_t    arp_globals;
     56/** ARP module global data. */
     57extern arp_globals_t arp_globals;
    5858
    59 int il_module_message_standalone(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count){
     59int
     60il_module_message_standalone(ipc_callid_t callid, ipc_call_t *call,
     61    ipc_call_t *answer, int *answer_count)
     62{
    6063        return arp_message_standalone(callid, call, answer, answer_count);
    6164}
    6265
    63 int il_module_start_standalone(async_client_conn_t client_connection){
     66int il_module_start_standalone(async_client_conn_t client_connection)
     67{
    6468        ERROR_DECLARE;
    6569       
     
    6973       
    7074        ipcarg_t phonehash;
    71         if (ERROR_OCCURRED(arp_initialize(client_connection))
    72             || ERROR_OCCURRED(REGISTER_ME(SERVICE_ARP, &phonehash))) {
     75        if (ERROR_OCCURRED(arp_initialize(client_connection)) ||
     76            ERROR_OCCURRED(REGISTER_ME(SERVICE_ARP, &phonehash))) {
    7377                pm_destroy();
    7478                return ERROR_CODE;
  • uspace/srv/net/il/arp/arp_module.h

    rf2d2c604 r069015f2  
    2828
    2929/** @addtogroup arp
    30  *  @{
     30 * @{
    3131 */
    3232
    3333/** @file
    34  *  ARP module functions.
    35  *  The functions are used as ARP module entry points.
     34 * ARP module functions.
     35 * The functions are used as ARP module entry points.
    3636 */
    3737
    38 #ifndef __NET_ARP_MODULE_H__
    39 #define __NET_ARP_MODULE_H__
     38#ifndef NET_ARP_MODULE_H_
     39#define NET_ARP_MODULE_H_
    4040
    4141#include <ipc/ipc.h>
     42#include <async.h>
    4243
    43 /** Initializes the ARP module.
    44  *  @param[in] client_connection The client connection processing function. The module skeleton propagates its own one.
    45  *  @returns EOK on success.
    46  *  @returns ENOMEM if there is not enough memory left.
    47  */
    48 int arp_initialize(async_client_conn_t client_connection);
    49 
    50 /** Processes the ARP message.
    51  *  @param[in] callid The message identifier.
    52  *  @param[in] call The message parameters.
    53  *  @param[out] answer The message answer parameters.
    54  *  @param[out] answer_count The last parameter for the actual answer in the answer parameter.
    55  *  @returns EOK on success.
    56  *  @returns ENOTSUP if the message is not known.
    57  *  @see arp_interface.h
    58  *  @see IS_NET_ARP_MESSAGE()
    59  */
    60 int arp_message_standalone(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count);
     44extern int arp_initialize(async_client_conn_t);
     45extern int arp_message_standalone(ipc_callid_t, ipc_call_t *, ipc_call_t *,
     46    int *);
    6147
    6248#endif
  • uspace/srv/net/il/arp/arp_oc.h

    rf2d2c604 r069015f2  
    3232
    3333/** @file
    34  *  ARP operation codes according to the on-line IANA - Address Resolution Protocol (ARP) Parameters - <http://www.iana.org/assignments/arp-parameters/arp-parameters.xml>, cited January 14 2009.
     34 * ARP operation codes according to the on-line IANA - Address Resolution
     35 * Protocol (ARP) Parameters
     36 * http://www.iana.org/assignments/arp-parameters/arp-parameters.xml
     37 * cited January 14 2009.
    3538 */
    3639
    37 #ifndef __NET_ARP_ARPOP_H__
    38 #define __NET_ARP_ARPOP_H__
     40#ifndef NET_ARP_ARPOP_H_
     41#define NET_ARP_ARPOP_H_
    3942
    40 /** @name ARP operation codes definitions
    41  */
     43/** @name ARP operation codes definitions */
    4244/*@{*/
    4345
    44 /** REQUEST operation code.
    45  */
    46 #define ARPOP_REQUEST                                   1
     46/** REQUEST operation code. */
     47#define ARPOP_REQUEST   1
    4748
    48 /** REPLY operation code.
    49  */
    50 #define ARPOP_REPLY                                             2
    51 
    52 /** Reverse request operation code.
    53  */
    54 #define ARPOP_RREQUEST                                  3
    55 
    56 /** Reverse reply operation code.
    57  */
    58 #define ARPOP_RREPLY                                    4
    59 
    60 /** DRARP-Request operation code.
    61  */
    62 #define ARPOP_DRARP_Request                             5
    63 
    64 /** DRARP-Reply operation code.
    65  */
    66 #define ARPOP_DRARP_Reply                               6
    67 
    68 /** DRARP-Error operation code.
    69  */
    70 #define ARPOP_DRARP_Error                               7
    71 
    72 /** InARP-Request operation code.
    73  */
    74 #define ARPOP_InREQUEST                                 8
    75 
    76 /** InARP-Reply operation code.
    77  */
    78 #define ARPOP_InREPLY                                   9
    79 
    80 /** ARP-NAK operation code.
    81  */
    82 #define ARPOP_NAK                                               10
    83 
    84 /** MARS-Request operation code.
    85  */
    86 #define ARPOP_MARS_Request                              11
    87 
    88 /** MARS-Multi operation code.
    89  */
    90 #define ARPOP_MARS_Multi                                12
    91 
    92 /** MARS-MServ operation code.
    93  */
    94 #define ARPOP_MARS_MServ                                13
    95 
    96 /** MARS-Join operation code.
    97  */
    98 #define ARPOP_MARS_Join                                 14
    99 
    100 /** MARS-Leave operation code.
    101  */
    102 #define ARPOP_MARS_Leave                                15
    103 
    104 /** MARS-NAK operation code.
    105  */
    106 #define ARPOP_MARS_NAK                                  16
    107 
    108 /** MARS-Unserv operation code.
    109  */
    110 #define ARPOP_MARS_Unserv                               17
    111 
    112 /** MARS-SJoin operation code.
    113  */
    114 #define ARPOP_MARS_SJoin                                18
    115 
    116 /** MARS-SLeave operation code.
    117  */
    118 #define ARPOP_MARS_SLeave                               19
    119 
    120 /** MARS-Grouplist-Request operation code.
    121  */
    122 #define ARPOP_MARS_Grouplist_Request    20
    123 
    124 /** MARS-Grouplist-Reply operation code.
    125  */
    126 #define ARPOP_MARS_Grouplist_Reply              21
    127 
    128 /** MARS-Redirect-Map operation code.
    129  */
    130 #define ARPOP_MARS_Redirect_Map                 22
    131 
    132 /** MAPOS-UNARP operation code.
    133  */
    134 #define ARPOP_MAPOS_UNARP                               23
     49/** REPLY operation code. */
     50#define ARPOP_REPLY     2
    13551
    13652/*@}*/
  • uspace/srv/net/il/ip/ip.c

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

    rf2d2c604 r069015f2  
    2828
    2929/** @addtogroup ip
    30  *  @{
     30 * @{
    3131 */
    3232
    3333/** @file
    34  *  IP module.
     34 * IP module.
    3535 */
    3636
    37 #ifndef __NET_IP_H__
    38 #define __NET_IP_H__
     37#ifndef NET_IP_H_
     38#define NET_IP_H_
    3939
    4040#include <fibril_synch.h>
     
    5050
    5151/** Type definition of the IP global data.
    52  *  @see ip_globals
     52 * @see ip_globals
    5353 */
    54 typedef struct ip_globals       ip_globals_t;
     54typedef struct ip_globals ip_globals_t;
    5555
    5656/** Type definition of the IP network interface specific data.
    57  *  @see ip_netif
     57 * @see ip_netif
    5858 */
    59 typedef struct ip_netif ip_netif_t;
     59typedef struct ip_netif ip_netif_t;
    6060
    6161/** Type definition of the IP network interface specific data pointer.
    62  *  @see ip_netif
     62 * @see ip_netif
    6363 */
    64 typedef ip_netif_t *    ip_netif_ref;
     64typedef ip_netif_t *ip_netif_ref;
    6565
    6666/** Type definition of the IP protocol specific data.
    67  *  @see ip_proto
     67 * @see ip_proto
    6868 */
    69 typedef struct ip_proto ip_proto_t;
     69typedef struct ip_proto ip_proto_t;
    7070
    7171/** Type definition of the IP protocol specific data pointer.
    72  *  @see ip_proto
     72 * @see ip_proto
    7373 */
    74 typedef ip_proto_t *    ip_proto_ref;
     74typedef ip_proto_t *ip_proto_ref;
    7575
    7676/** Type definition of the IP route specific data.
     
    8282 *  @see ip_route
    8383 */
    84 typedef ip_route_t *    ip_route_ref;
     84typedef ip_route_t *ip_route_ref;
    8585
    8686/** IP network interfaces.
    87  *  Maps devices to the IP network interface specific data.
    88  *  @see device.h
     87 * Maps devices to the IP network interface specific data.
     88 * @see device.h
    8989 */
    90 DEVICE_MAP_DECLARE(ip_netifs, ip_netif_t)
     90DEVICE_MAP_DECLARE(ip_netifs, ip_netif_t);
    9191
    9292/** IP registered protocols.
    93  *  Maps protocols to the IP protocol specific data.
    94  *  @see int_map.h
     93 * Maps protocols to the IP protocol specific data.
     94 * @see int_map.h
    9595 */
    96 INT_MAP_DECLARE(ip_protos, ip_proto_t)
     96INT_MAP_DECLARE(ip_protos, ip_proto_t);
    9797
    9898/** IP routing table.
    99  *  @see generic_field.h
     99 * @see generic_field.h
    100100 */
    101 GENERIC_FIELD_DECLARE(ip_routes, ip_route_t)
     101GENERIC_FIELD_DECLARE(ip_routes, ip_route_t);
    102102
    103 /** IP network interface specific data.
    104  */
    105 struct  ip_netif{
    106         /** ARP module.
    107          *  Assigned if using ARP.
    108          */
     103/** IP network interface specific data. */
     104struct ip_netif {
     105        /** ARP module. Assigned if using ARP. */
    109106        module_ref arp;
    110         /** Broadcast address.
    111          */
     107        /** Broadcast address. */
    112108        in_addr_t broadcast;
    113         /** Device identifier.
    114          */
     109        /** Device identifier. */
    115110        device_id_t device_id;
    116         /** Indicates whether using DHCP.
    117          */
     111        /** Indicates whether using DHCP. */
    118112        int dhcp;
    119         /** IP version.
    120          */
     113        /** IP version. */
    121114        int ipv;
    122         /** Packet dimension.
    123          */
     115        /** Packet dimension. */
    124116        packet_dimension_t packet_dimension;
    125         /** Netif module phone.
    126          */
     117        /** Netif module phone. */
    127118        int phone;
    128         /** Routing table.
    129          */
     119        /** Routing table. */
    130120        ip_routes_t routes;
    131         /** Indicates whether IP routing is enabled.
    132          */
     121        /** Indicates whether IP routing is enabled. */
    133122        int routing;
    134         /** Netif module service.
    135          */
     123        /** Netif module service. */
    136124        services_t service;
    137         /** Device state.
    138          */
     125        /** Device state. */
    139126        device_state_t state;
    140127};
    141128
    142 /** IP protocol specific data.
    143  */
    144 struct ip_proto{
    145         /** Protocol module phone.
    146          */
     129/** IP protocol specific data. */
     130struct ip_proto {
     131        /** Protocol module phone. */
    147132        int phone;
    148         /** Protocol number.
    149          */
     133        /** Protocol number. */
    150134        int protocol;
    151         /** Protocol packet receiving function.
    152          */
     135        /** Protocol packet receiving function. */
    153136        tl_received_msg_t received_msg;
    154         /** Protocol module service.
    155          */
     137        /** Protocol module service. */
    156138        services_t service;
    157139};
    158140
    159 /** IP route specific data.
    160  */
    161 struct ip_route{
    162         /** Target address.
    163          */
     141/** IP route specific data. */
     142struct ip_route {
     143        /** Target address. */
    164144        in_addr_t address;
    165         /** Gateway.
    166          */
     145        /** Gateway. */
    167146        in_addr_t gateway;
    168         /** Parent netif.
    169          */
     147        /** Parent netif. */
    170148        ip_netif_ref netif;
    171         /** Target network mask.
    172          */
     149        /** Target network mask. */
    173150        in_addr_t netmask;
    174151};
    175152
    176 /** IP global data.
    177  */
    178 struct  ip_globals{
    179         /** Default client connection function for support modules.
    180          */
     153/** IP global data. */
     154struct ip_globals {
     155        /** Default client connection function for support modules. */
    181156        async_client_conn_t client_connection;
    182         /** Default gateway.
    183          */
     157        /** Default gateway. */
    184158        ip_route_t gateway;
    185         /** Safety lock.
    186          */
     159        /** Safety lock. */
    187160        fibril_rwlock_t lock;
    188         /** Known support modules.
    189          */
     161        /** Known support modules. */
    190162        modules_t modules;
    191         /** Networking module phone.
    192          */
     163        /** Networking module phone. */
    193164        int net_phone;
    194         /** Registered network interfaces.
    195          */
     165        /** Registered network interfaces. */
    196166        ip_netifs_t netifs;
    197         /** Netifs safeyt lock.
    198          */
     167        /** Netifs safeyt lock. */
    199168        fibril_rwlock_t netifs_lock;
    200         /** Packet counter.
    201          */
     169        /** Packet counter. */
    202170        uint16_t packet_counter;
    203         /** Registered protocols.
    204          */
     171        /** Registered protocols. */
    205172        ip_protos_t protos;
    206         /** Protocols safety lock.
    207          */
     173        /** Protocols safety lock. */
    208174        fibril_rwlock_t protos_lock;
    209175};
  • uspace/srv/net/il/ip/ip_module.c

    rf2d2c604 r069015f2  
    3232
    3333/** @file
    34  *  IP standalone module implementation.
    35  *  Contains skeleton module functions mapping.
    36  *  The functions are used by the module skeleton as module specific entry points.
    37  *  @see module.c
     34 * IP standalone module implementation.
     35 * Contains skeleton module functions mapping.
     36 * The functions are used by the module skeleton as module specific entry
     37 * points.
     38 *
     39 * @see module.c
    3840 */
    3941
     
    5254#include "ip_module.h"
    5355
    54 /** IP module global data.
    55  */
     56/** IP module global data. */
    5657extern ip_globals_t ip_globals;
    5758
    58 int il_module_message_standalone(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count){
     59int
     60il_module_message_standalone(ipc_callid_t callid, ipc_call_t *call,
     61    ipc_call_t *answer, int *answer_count)
     62{
    5963        return ip_message_standalone(callid, call, answer, answer_count);
    6064}
    6165
    62 int il_module_start_standalone(async_client_conn_t client_connection){
     66int il_module_start_standalone(async_client_conn_t client_connection)
     67{
    6368        ERROR_DECLARE;
    6469       
     
    6873       
    6974        ipcarg_t phonehash;
    70         if (ERROR_OCCURRED(ip_initialize(client_connection))
    71             || ERROR_OCCURRED(REGISTER_ME(SERVICE_IP, &phonehash))) {
     75        if (ERROR_OCCURRED(ip_initialize(client_connection)) ||
     76            ERROR_OCCURRED(REGISTER_ME(SERVICE_IP, &phonehash))) {
    7277                pm_destroy();
    7378                return ERROR_CODE;
  • uspace/srv/net/il/ip/ip_module.h

    rf2d2c604 r069015f2  
    2828
    2929/** @addtogroup ip
    30  *  @{
     30 * @{
    3131 */
    3232
    3333/** @file
    34  *  IP module functions.
    35  *  The functions are used as IP module entry points.
     34 * IP module functions.
     35 * The functions are used as IP module entry points.
    3636 */
    3737
    38 #ifndef __NET_IP_MODULE_H__
    39 #define __NET_IP_MODULE_H__
     38#ifndef NET_IP_MODULE_H_
     39#define NET_IP_MODULE_H_
    4040
    4141#include <ipc/ipc.h>
    4242
    43 /** Initializes the IP module.
    44  *  @param[in] client_connection The client connection processing function. The module skeleton propagates its own one.
    45  *  @returns EOK on success.
    46  *  @returns ENOMEM if there is not enough memory left.
    47  */
    48 int ip_initialize(async_client_conn_t client_connection);
    49 
    50 /** Processes the IP message.
    51  *  @param[in] callid The message identifier.
    52  *  @param[in] call The message parameters.
    53  *  @param[out] answer The message answer parameters.
    54  *  @param[out] answer_count The last parameter for the actual answer in the answer parameter.
    55  *  @returns EOK on success.
    56  *  @returns ENOTSUP if the message is not known.
    57  *  @see ip_interface.h
    58  *  @see il_interface.h
    59  *  @see IS_NET_IP_MESSAGE()
    60  */
    61 int ip_message_standalone(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count);
     43extern int ip_initialize(async_client_conn_t);
     44extern int ip_message_standalone(ipc_callid_t, ipc_call_t *, ipc_call_t *,
     45    int *);
    6246
    6347#endif
Note: See TracChangeset for help on using the changeset viewer.