Ignore:
File:
1 edited

Legend:

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

    r5fe7692 re9caf47  
    3636 */
    3737
     38#include "arp.h"
     39#include "arp_header.h"
     40#include "arp_oc.h"
     41#include "arp_module.h"
     42
    3843#include <async.h>
    3944#include <malloc.h>
    4045#include <mem.h>
    4146#include <fibril_synch.h>
    42 #include <assert.h>
    4347#include <stdio.h>
    4448#include <str.h>
    4549#include <task.h>
    4650#include <adt/measured_strings.h>
     51#include <ipc/ipc.h>
    4752#include <ipc/services.h>
    4853#include <ipc/net.h>
    4954#include <ipc/arp.h>
    5055#include <ipc/il.h>
    51 #include <ipc/nil.h>
    5256#include <byteorder.h>
    53 #include <errno.h>
     57#include <err.h>
     58
    5459#include <net/modules.h>
    5560#include <net/device.h>
    5661#include <net/packet.h>
    57 #include <nil_remote.h>
     62
     63#include <nil_interface.h>
    5864#include <protocol_map.h>
    5965#include <packet_client.h>
    6066#include <packet_remote.h>
    61 #include <il_remote.h>
    62 #include <il_skel.h>
    63 #include "arp.h"
     67#include <il_interface.h>
     68#include <il_local.h>
     69
    6470
    6571/** ARP module name. */
    6672#define NAME  "arp"
    6773
    68 /** Number of microseconds to wait for an ARP reply. */
    69 #define ARP_TRANS_WAIT  1000000
    70 
    71 /** @name ARP operation codes definitions */
    72 /*@{*/
    73 
    74 /** REQUEST operation code. */
    75 #define ARPOP_REQUEST  1
    76 
    77 /** REPLY operation code. */
    78 #define ARPOP_REPLY  2
    79 
    80 /*@}*/
    81 
    82 /** Type definition of an ARP protocol header.
    83  * @see arp_header
    84  */
    85 typedef struct arp_header arp_header_t;
    86 
    87 /** ARP protocol header. */
    88 struct arp_header {
    89         /**
    90          * Hardware type identifier.
    91          * @see hardware.h
    92          */
    93         uint16_t hardware;
    94        
    95         /** Protocol identifier. */
    96         uint16_t protocol;
    97         /** Hardware address length in bytes. */
    98         uint8_t hardware_length;
    99         /** Protocol address length in bytes. */
    100         uint8_t protocol_length;
    101        
    102         /**
    103          * ARP packet type.
    104          * @see arp_oc.h
    105          */
    106         uint16_t operation;
    107 } __attribute__ ((packed));
    108 
    10974/** ARP global data. */
    11075arp_globals_t arp_globals;
     
    11277DEVICE_MAP_IMPLEMENT(arp_cache, arp_device_t);
    11378INT_MAP_IMPLEMENT(arp_protos, arp_proto_t);
    114 GENERIC_CHAR_MAP_IMPLEMENT(arp_addr, arp_trans_t);
    115 
    116 static void arp_clear_trans(arp_trans_t *trans)
    117 {
    118         if (trans->hw_addr) {
    119                 free(trans->hw_addr);
    120                 trans->hw_addr = NULL;
    121         }
    122        
    123         fibril_condvar_broadcast(&trans->cv);
    124 }
    125 
    126 static void arp_clear_addr(arp_addr_t *addresses)
     79GENERIC_CHAR_MAP_IMPLEMENT(arp_addr, measured_string_t);
     80
     81/** Clears the device specific data.
     82 *
     83 * @param[in] device    The device specific data.
     84 */
     85static void arp_clear_device(arp_device_ref device)
    12786{
    12887        int count;
    129        
    130         for (count = arp_addr_count(addresses) - 1; count >= 0; count--) {
    131                 arp_trans_t *trans = arp_addr_items_get_index(&addresses->values,
    132                     count);
    133                 if (trans)
    134                         arp_clear_trans(trans);
    135         }
    136 }
    137 
    138 /** Clear the device specific data.
    139  *
    140  * @param[in] device Device specific data.
    141  */
    142 static void arp_clear_device(arp_device_t *device)
    143 {
    144         int count;
    145        
     88        arp_proto_ref proto;
     89
    14690        for (count = arp_protos_count(&device->protos) - 1; count >= 0;
    14791            count--) {
    148                 arp_proto_t *proto = arp_protos_get_index(&device->protos,
    149                     count);
    150                
     92                proto = arp_protos_get_index(&device->protos, count);
    15193                if (proto) {
    15294                        if (proto->addr)
    15395                                free(proto->addr);
    154                        
    15596                        if (proto->addr_data)
    15697                                free(proto->addr_data);
    157                        
    158                         arp_clear_addr(&proto->addresses);
    159                         arp_addr_destroy(&proto->addresses, free);
    160                 }
    161         }
    162        
    163         arp_protos_clear(&device->protos, free);
     98                        arp_addr_destroy(&proto->addresses);
     99                }
     100        }
     101        arp_protos_clear(&device->protos);
    164102}
    165103
     
    167105{
    168106        int count;
    169        
    170         fibril_mutex_lock(&arp_globals.lock);
     107        arp_device_ref device;
     108
     109        fibril_rwlock_write_lock(&arp_globals.lock);
    171110        for (count = arp_cache_count(&arp_globals.cache) - 1; count >= 0;
    172111            count--) {
    173                 arp_device_t *device = arp_cache_get_index(&arp_globals.cache,
    174                     count);
    175                
     112                device = arp_cache_get_index(&arp_globals.cache, count);
    176113                if (device) {
    177114                        arp_clear_device(device);
    178115                        if (device->addr_data)
    179116                                free(device->addr_data);
    180                        
    181117                        if (device->broadcast_data)
    182118                                free(device->broadcast_data);
    183119                }
    184120        }
    185        
    186         arp_cache_clear(&arp_globals.cache, free);
    187         fibril_mutex_unlock(&arp_globals.lock);
    188        
    189         return EOK;
    190 }
    191 
    192 static int arp_clear_address_req(int arp_phone, device_id_t device_id,
    193     services_t protocol, measured_string_t *address)
    194 {
    195         fibril_mutex_lock(&arp_globals.lock);
    196        
    197         arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
     121        arp_cache_clear(&arp_globals.cache);
     122        fibril_rwlock_write_unlock(&arp_globals.lock);
     123        printf("Cache cleaned\n");
     124        return EOK;
     125}
     126
     127static int
     128arp_clear_address_req(int arp_phone, device_id_t device_id, services_t protocol,
     129    measured_string_ref address)
     130{
     131        arp_device_ref device;
     132        arp_proto_ref proto;
     133
     134        fibril_rwlock_write_lock(&arp_globals.lock);
     135        device = arp_cache_find(&arp_globals.cache, device_id);
    198136        if (!device) {
    199                 fibril_mutex_unlock(&arp_globals.lock);
     137                fibril_rwlock_write_unlock(&arp_globals.lock);
    200138                return ENOENT;
    201139        }
    202        
    203         arp_proto_t *proto = arp_protos_find(&device->protos, protocol);
     140        proto = arp_protos_find(&device->protos, protocol);
    204141        if (!proto) {
    205                 fibril_mutex_unlock(&arp_globals.lock);
     142                fibril_rwlock_write_unlock(&arp_globals.lock);
    206143                return ENOENT;
    207144        }
    208        
    209         arp_trans_t *trans = arp_addr_find(&proto->addresses, address->value,
    210             address->length);
    211         if (trans)
    212                 arp_clear_trans(trans);
    213        
    214         arp_addr_exclude(&proto->addresses, address->value, address->length, free);
    215        
    216         fibril_mutex_unlock(&arp_globals.lock);
    217         return EOK;
    218 }
     145        arp_addr_exclude(&proto->addresses, address->value, address->length);
     146        fibril_rwlock_write_unlock(&arp_globals.lock);
     147        return EOK;
     148}
     149
    219150
    220151static int arp_clear_device_req(int arp_phone, device_id_t device_id)
    221152{
    222         fibril_mutex_lock(&arp_globals.lock);
    223        
    224         arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
     153        arp_device_ref device;
     154
     155        fibril_rwlock_write_lock(&arp_globals.lock);
     156        device = arp_cache_find(&arp_globals.cache, device_id);
    225157        if (!device) {
    226                 fibril_mutex_unlock(&arp_globals.lock);
     158                fibril_rwlock_write_unlock(&arp_globals.lock);
    227159                return ENOENT;
    228160        }
    229        
    230161        arp_clear_device(device);
    231        
    232         fibril_mutex_unlock(&arp_globals.lock);
    233         return EOK;
    234 }
    235 
    236 /** Create new protocol specific data.
    237  *
    238  * Allocate and return the needed memory block as the proto parameter.
    239  *
    240  * @param[out] proto   Allocated protocol specific data.
    241  * @param[in]  service Protocol module service.
    242  * @param[in]  address Actual protocol device address.
    243  *
    244  * @return EOK on success.
    245  * @return ENOMEM if there is not enough memory left.
    246  *
    247  */
    248 static int arp_proto_create(arp_proto_t **proto, services_t service,
    249     measured_string_t *address)
    250 {
    251         *proto = (arp_proto_t *) malloc(sizeof(arp_proto_t));
     162        printf("Device %d cleared\n", device_id);
     163        fibril_rwlock_write_unlock(&arp_globals.lock);
     164        return EOK;
     165}
     166
     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));
    252184        if (!*proto)
    253185                return ENOMEM;
    254        
    255186        (*proto)->service = service;
    256187        (*proto)->addr = address;
    257188        (*proto)->addr_data = address->value;
    258        
    259         int rc = arp_addr_initialize(&(*proto)->addresses);
    260         if (rc != EOK) {
     189        if (ERROR_OCCURRED(arp_addr_initialize(&(*proto)->addresses))) {
    261190                free(*proto);
    262                 return rc;
    263         }
    264        
    265         return EOK;
    266 }
    267 
    268 /** Process the received ARP packet.
    269  *
    270  * Update the source hardware address if the source entry exists or the packet
     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{
     216        ERROR_DECLARE;
     217
     218        arp_device_ref device;
     219        arp_proto_ref proto;
     220        int index;
     221        hw_type_t hardware;
     222
     223        fibril_rwlock_write_lock(&arp_globals.lock);
     224        // an existing device?
     225        device = arp_cache_find(&arp_globals.cache, device_id);
     226        if (device) {
     227                if (device->service != service) {
     228                        printf("Device %d already exists\n", device->device_id);
     229                        fibril_rwlock_write_unlock(&arp_globals.lock);
     230                        return EEXIST;
     231                }
     232                proto = arp_protos_find(&device->protos, protocol);
     233                if (proto) {
     234                        free(proto->addr);
     235                        free(proto->addr_data);
     236                        proto->addr = address;
     237                        proto->addr_data = address->value;
     238                } else {
     239                        if (ERROR_OCCURRED(arp_proto_create(&proto, protocol,
     240                            address))) {
     241                                fibril_rwlock_write_unlock(&arp_globals.lock);
     242                                return ERROR_CODE;
     243                        }
     244                        index = arp_protos_add(&device->protos, proto->service,
     245                            proto);
     246                        if (index < 0) {
     247                                fibril_rwlock_write_unlock(&arp_globals.lock);
     248                                free(proto);
     249                                return index;
     250                        }
     251                        printf("New protocol added:\n\tdevice id\t= "
     252                            "%d\n\tproto\t= %d", device_id, protocol);
     253                }
     254        } else {
     255                hardware = hardware_map(service);
     256                if (!hardware)
     257                        return ENOENT;
     258               
     259                // create a new device
     260                device = (arp_device_ref) malloc(sizeof(arp_device_t));
     261                if (!device) {
     262                        fibril_rwlock_write_unlock(&arp_globals.lock);
     263                        return ENOMEM;
     264                }
     265                device->hardware = hardware;
     266                device->device_id = device_id;
     267                if (ERROR_OCCURRED(arp_protos_initialize(&device->protos)) ||
     268                    ERROR_OCCURRED(arp_proto_create(&proto, protocol,
     269                    address))) {
     270                        fibril_rwlock_write_unlock(&arp_globals.lock);
     271                        free(device);
     272                        return ERROR_CODE;
     273                }
     274                index = arp_protos_add(&device->protos, proto->service, proto);
     275                if (index < 0) {
     276                        fibril_rwlock_write_unlock(&arp_globals.lock);
     277                        arp_protos_destroy(&device->protos);
     278                        free(device);
     279                        return index;
     280                }
     281                device->service = service;
     282               
     283                // bind the new one
     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) {
     288                        fibril_rwlock_write_unlock(&arp_globals.lock);
     289                        arp_protos_destroy(&device->protos);
     290                        free(device);
     291                        return EREFUSED;
     292                }
     293               
     294                // get packet dimensions
     295                if (ERROR_OCCURRED(nil_packet_size_req(device->phone, device_id,
     296                    &device->packet_dimension))) {
     297                        fibril_rwlock_write_unlock(&arp_globals.lock);
     298                        arp_protos_destroy(&device->protos);
     299                        free(device);
     300                        return ERROR_CODE;
     301                }
     302               
     303                // get hardware address
     304                if (ERROR_OCCURRED(nil_get_addr_req(device->phone, device_id,
     305                    &device->addr, &device->addr_data))) {
     306                        fibril_rwlock_write_unlock(&arp_globals.lock);
     307                        arp_protos_destroy(&device->protos);
     308                        free(device);
     309                        return ERROR_CODE;
     310                }
     311               
     312                // get broadcast address
     313                if (ERROR_OCCURRED(nil_get_broadcast_addr_req(device->phone,
     314                    device_id, &device->broadcast_addr,
     315                    &device->broadcast_data))) {
     316                        fibril_rwlock_write_unlock(&arp_globals.lock);
     317                        free(device->addr);
     318                        free(device->addr_data);
     319                        arp_protos_destroy(&device->protos);
     320                        free(device);
     321                        return ERROR_CODE;
     322                }
     323               
     324                if (ERROR_OCCURRED(arp_cache_add(&arp_globals.cache,
     325                    device->device_id, device))) {
     326                        fibril_rwlock_write_unlock(&arp_globals.lock);
     327                        free(device->addr);
     328                        free(device->addr_data);
     329                        free(device->broadcast_addr);
     330                        free(device->broadcast_data);
     331                        arp_protos_destroy(&device->protos);
     332                        free(device);
     333                        return ERROR_CODE;
     334                }
     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);
     338        }
     339        fibril_rwlock_write_unlock(&arp_globals.lock);
     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{
     353        ERROR_DECLARE;
     354
     355        fibril_rwlock_initialize(&arp_globals.lock);
     356        fibril_rwlock_write_lock(&arp_globals.lock);
     357        arp_globals.client_connection = client_connection;
     358        ERROR_PROPAGATE(arp_cache_initialize(&arp_globals.cache));
     359        fibril_rwlock_write_unlock(&arp_globals.lock);
     360        return EOK;
     361}
     362
     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{
     372        arp_device_ref device;
     373
     374        fibril_rwlock_write_lock(&arp_globals.lock);
     375        device = arp_cache_find(&arp_globals.cache, device_id);
     376        if (!device) {
     377                fibril_rwlock_write_unlock(&arp_globals.lock);
     378                return ENOENT;
     379        }
     380        device->packet_dimension.content = mtu;
     381        fibril_rwlock_write_unlock(&arp_globals.lock);
     382        printf("arp - device %d changed mtu to %d\n\n", device_id, mtu);
     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
    271389 * is targeted to my protocol address.
    272  *
    273  * Respond to the ARP request if the packet is the ARP request and is
     390 * Responses to the ARP request if the packet is the ARP request and is
    274391 * targeted to my address.
    275392 *
    276  * @param[in]     device_id Source device identifier.
    277  * @param[in,out] packet    Received packet.
    278  *
    279  * @return EOK on success and the packet is no longer needed.
    280  * @return One on success and the packet has been reused.
    281  * @return EINVAL if the packet is too small to carry an ARP
    282  *         packet.
    283  * @return EINVAL if the received address lengths differs from
    284  *         the registered values.
    285  * @return ENOENT if the device is not found in the cache.
    286  * @return ENOENT if the protocol for the device is not found in
    287  *         the cache.
    288  * @return ENOMEM if there is not enough memory left.
    289  *
    290  */
    291 static int arp_receive_message(device_id_t device_id, packet_t *packet)
    292 {
    293         int rc;
    294        
    295         size_t length = packet_get_data_length(packet);
     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{
     408        ERROR_DECLARE;
     409
     410        size_t length;
     411        arp_header_ref header;
     412        arp_device_ref device;
     413        arp_proto_ref proto;
     414        measured_string_ref hw_source;
     415        uint8_t *src_hw;
     416        uint8_t *src_proto;
     417        uint8_t *des_hw;
     418        uint8_t *des_proto;
     419
     420        length = packet_get_data_length(packet);
    296421        if (length <= sizeof(arp_header_t))
    297422                return EINVAL;
    298        
    299         arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
     423
     424        device = arp_cache_find(&arp_globals.cache, device_id);
    300425        if (!device)
    301426                return ENOENT;
    302        
    303         arp_header_t *header = (arp_header_t *) packet_get_data(packet);
     427
     428        header = (arp_header_ref) packet_get_data(packet);
    304429        if ((ntohs(header->hardware) != device->hardware) ||
    305430            (length < sizeof(arp_header_t) + header->hardware_length * 2U +
     
    307432                return EINVAL;
    308433        }
    309        
    310         arp_proto_t *proto = arp_protos_find(&device->protos,
     434
     435        proto = arp_protos_find(&device->protos,
    311436            protocol_unmap(device->service, ntohs(header->protocol)));
    312437        if (!proto)
    313438                return ENOENT;
    314        
    315         uint8_t *src_hw = ((uint8_t *) header) + sizeof(arp_header_t);
    316         uint8_t *src_proto = src_hw + header->hardware_length;
    317         uint8_t *des_hw = src_proto + header->protocol_length;
    318         uint8_t *des_proto = des_hw + header->hardware_length;
    319        
    320         arp_trans_t *trans = arp_addr_find(&proto->addresses, src_proto,
    321             header->protocol_length);
    322        
    323         if ((trans) && (trans->hw_addr)) {
    324                 /* Translation exists */
    325                 if (trans->hw_addr->length != header->hardware_length)
     439
     440        src_hw = ((uint8_t *) header) + sizeof(arp_header_t);
     441        src_proto = src_hw + header->hardware_length;
     442        des_hw = src_proto + header->protocol_length;
     443        des_proto = des_hw + header->hardware_length;
     444        hw_source = arp_addr_find(&proto->addresses, (char *) src_proto,
     445            CONVERT_SIZE(uint8_t, char, header->protocol_length));
     446        // exists?
     447        if (hw_source) {
     448                if (hw_source->length != CONVERT_SIZE(uint8_t, char,
     449                    header->hardware_length)) {
    326450                        return EINVAL;
    327                
    328                 memcpy(trans->hw_addr->value, src_hw, trans->hw_addr->length);
    329         }
    330        
    331         /* Is my protocol address? */
    332         if (proto->addr->length != header->protocol_length)
     451                }
     452                memcpy(hw_source->value, src_hw, hw_source->length);
     453        }
     454        // is my protocol address?
     455        if (proto->addr->length != CONVERT_SIZE(uint8_t, char,
     456            header->protocol_length)) {
    333457                return EINVAL;
    334        
    335         if (!bcmp(proto->addr->value, des_proto, proto->addr->length)) {
    336                 if (!trans) {
    337                         /* Update the translation */
    338                         trans = (arp_trans_t *) malloc(sizeof(arp_trans_t));
    339                         if (!trans)
     458        }
     459        if (!str_lcmp(proto->addr->value, (char *) des_proto,
     460            proto->addr->length)) {
     461                // not already upadted?
     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)
    340467                                return ENOMEM;
    341                        
    342                         trans->hw_addr = NULL;
    343                         fibril_condvar_initialize(&trans->cv);
    344                         rc = arp_addr_add(&proto->addresses, src_proto,
    345                             header->protocol_length, trans);
    346                         if (rc != EOK) {
    347                                 free(trans);
    348                                 return rc;
    349                         }
    350                 }
    351                
    352                 if (!trans->hw_addr) {
    353                         trans->hw_addr = measured_string_create_bulk(src_hw,
    354                             header->hardware_length);
    355                         if (!trans->hw_addr)
    356                                 return ENOMEM;
    357                        
    358                         /* Notify the fibrils that wait for the translation. */
    359                         fibril_condvar_broadcast(&trans->cv);
    360                 }
    361                
     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                }
    362473                if (ntohs(header->operation) == ARPOP_REQUEST) {
    363474                        header->operation = htons(ARPOP_REPLY);
     
    367478                        memcpy(src_hw, device->addr->value,
    368479                            device->packet_dimension.addr_len);
    369                         memcpy(des_hw, trans->hw_addr->value,
     480                        memcpy(des_hw, hw_source->value,
    370481                            header->hardware_length);
    371                        
    372                         rc = packet_set_addr(packet, src_hw, des_hw,
    373                             header->hardware_length);
    374                         if (rc != EOK)
    375                                 return rc;
    376                        
     482                        ERROR_PROPAGATE(packet_set_addr(packet, src_hw, des_hw,
     483                            header->hardware_length));
    377484                        nil_send_msg(device->phone, device_id, packet,
    378485                            SERVICE_ARP);
     
    380487                }
    381488        }
    382        
    383         return EOK;
    384 }
    385 
    386 /** Update the device content length according to the new MTU value.
    387  *
    388  * @param[in] device_id Device identifier.
    389  * @param[in] mtu       New MTU value.
    390  *
    391  * @return ENOENT if device is not found.
    392  * @return EOK on success.
    393  *
    394  */
    395 static int arp_mtu_changed_message(device_id_t device_id, size_t mtu)
    396 {
    397         fibril_mutex_lock(&arp_globals.lock);
    398        
    399         arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
    400         if (!device) {
    401                 fibril_mutex_unlock(&arp_globals.lock);
    402                 return ENOENT;
    403         }
    404        
    405         device->packet_dimension.content = mtu;
    406        
    407         fibril_mutex_unlock(&arp_globals.lock);
    408        
    409         printf("%s: Device %d changed MTU to %zu\n", NAME, device_id, mtu);
    410        
    411         return EOK;
    412 }
    413 
    414 /** Process IPC messages from the registered device driver modules
    415  *
    416  * @param[in]     iid   Message identifier.
    417  * @param[in,out] icall Message parameters.
    418  *
    419  */
    420 static void arp_receiver(ipc_callid_t iid, ipc_call_t *icall)
    421 {
    422         packet_t *packet;
    423         int rc;
    424        
    425         while (true) {
    426                 switch (IPC_GET_IMETHOD(*icall)) {
    427                 case NET_IL_DEVICE_STATE:
    428                         /* Do nothing - keep the cache */
    429                         async_answer_0(iid, (sysarg_t) EOK);
    430                         break;
    431                
    432                 case NET_IL_RECEIVED:
    433                         rc = packet_translate_remote(arp_globals.net_phone, &packet,
    434                             IPC_GET_PACKET(*icall));
    435                         if (rc == EOK) {
    436                                 fibril_mutex_lock(&arp_globals.lock);
    437                                 do {
    438                                         packet_t *next = pq_detach(packet);
    439                                         rc = arp_receive_message(IPC_GET_DEVICE(*icall), packet);
    440                                         if (rc != 1) {
    441                                                 pq_release_remote(arp_globals.net_phone,
    442                                                     packet_get_id(packet));
    443                                         }
    444                                        
    445                                         packet = next;
    446                                 } while (packet);
    447                                 fibril_mutex_unlock(&arp_globals.lock);
    448                         }
    449                         async_answer_0(iid, (sysarg_t) rc);
    450                         break;
    451                
    452                 case NET_IL_MTU_CHANGED:
    453                         rc = arp_mtu_changed_message(IPC_GET_DEVICE(*icall),
    454                             IPC_GET_MTU(*icall));
    455                         async_answer_0(iid, (sysarg_t) rc);
    456                         break;
    457                
    458                 default:
    459                         async_answer_0(iid, (sysarg_t) ENOTSUP);
    460                 }
    461                
    462                 iid = async_get_call(icall);
    463         }
    464 }
    465 
    466 /** Register the device.
    467  *
    468  * Create new device entry in the cache or update the protocol address if the
    469  * device with the device identifier and the driver service exists.
    470  *
    471  * @param[in] device_id Device identifier.
    472  * @param[in] service   Device driver service.
    473  * @param[in] protocol  Protocol service.
    474  * @param[in] address   Actual device protocol address.
    475  *
    476  * @return EOK on success.
    477  * @return EEXIST if another device with the same device identifier
    478  *         and different driver service exists.
    479  * @return ENOMEM if there is not enough memory left.
    480  * @return Other error codes as defined for the
    481  *         measured_strings_return() function.
    482  *
    483  */
    484 static int arp_device_message(device_id_t device_id, services_t service,
    485     services_t protocol, measured_string_t *address)
    486 {
    487         int index;
    488         int rc;
    489        
    490         fibril_mutex_lock(&arp_globals.lock);
    491        
    492         /* An existing device? */
    493         arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
    494         if (device) {
    495                 if (device->service != service) {
    496                         printf("%s: Device %d already exists\n", NAME,
    497                             device->device_id);
    498                         fibril_mutex_unlock(&arp_globals.lock);
    499                         return EEXIST;
    500                 }
    501                
    502                 arp_proto_t *proto = arp_protos_find(&device->protos, protocol);
    503                 if (proto) {
    504                         free(proto->addr);
    505                         free(proto->addr_data);
    506                         proto->addr = address;
    507                         proto->addr_data = address->value;
    508                 } else {
    509                         rc = arp_proto_create(&proto, protocol, address);
    510                         if (rc != EOK) {
    511                                 fibril_mutex_unlock(&arp_globals.lock);
    512                                 return rc;
    513                         }
    514                        
    515                         index = arp_protos_add(&device->protos, proto->service,
    516                             proto);
    517                         if (index < 0) {
    518                                 fibril_mutex_unlock(&arp_globals.lock);
    519                                 free(proto);
    520                                 return index;
    521                         }
    522                        
    523                         printf("%s: New protocol added (id: %d, proto: %d)\n", NAME,
    524                             device_id, protocol);
    525                 }
    526         } else {
    527                 hw_type_t hardware = hardware_map(service);
    528                 if (!hardware)
    529                         return ENOENT;
    530                
    531                 /* Create new device */
    532                 device = (arp_device_t *) malloc(sizeof(arp_device_t));
    533                 if (!device) {
    534                         fibril_mutex_unlock(&arp_globals.lock);
    535                         return ENOMEM;
    536                 }
    537                
    538                 device->hardware = hardware;
    539                 device->device_id = device_id;
    540                 rc = arp_protos_initialize(&device->protos);
    541                 if (rc != EOK) {
    542                         fibril_mutex_unlock(&arp_globals.lock);
    543                         free(device);
    544                         return rc;
    545                 }
    546                
    547                 arp_proto_t *proto;
    548                 rc = arp_proto_create(&proto, protocol, address);
    549                 if (rc != EOK) {
    550                         fibril_mutex_unlock(&arp_globals.lock);
    551                         free(device);
    552                         return rc;
    553                 }
    554                
    555                 index = arp_protos_add(&device->protos, proto->service, proto);
    556                 if (index < 0) {
    557                         fibril_mutex_unlock(&arp_globals.lock);
    558                         arp_protos_destroy(&device->protos, free);
    559                         free(device);
    560                         return index;
    561                 }
    562                
    563                 device->service = service;
    564                
    565                 /* Bind */
    566                 device->phone = nil_bind_service(device->service,
    567                     (sysarg_t) device->device_id, SERVICE_ARP,
    568                     arp_receiver);
    569                 if (device->phone < 0) {
    570                         fibril_mutex_unlock(&arp_globals.lock);
    571                         arp_protos_destroy(&device->protos, free);
    572                         free(device);
    573                         return EREFUSED;
    574                 }
    575                
    576                 /* Get packet dimensions */
    577                 rc = nil_packet_size_req(device->phone, device_id,
    578                     &device->packet_dimension);
    579                 if (rc != EOK) {
    580                         fibril_mutex_unlock(&arp_globals.lock);
    581                         arp_protos_destroy(&device->protos, free);
    582                         free(device);
    583                         return rc;
    584                 }
    585                
    586                 /* Get hardware address */
    587                 rc = nil_get_addr_req(device->phone, device_id, &device->addr,
    588                     &device->addr_data);
    589                 if (rc != EOK) {
    590                         fibril_mutex_unlock(&arp_globals.lock);
    591                         arp_protos_destroy(&device->protos, free);
    592                         free(device);
    593                         return rc;
    594                 }
    595                
    596                 /* Get broadcast address */
    597                 rc = nil_get_broadcast_addr_req(device->phone, device_id,
    598                     &device->broadcast_addr, &device->broadcast_data);
    599                 if (rc != EOK) {
    600                         fibril_mutex_unlock(&arp_globals.lock);
    601                         free(device->addr);
    602                         free(device->addr_data);
    603                         arp_protos_destroy(&device->protos, free);
    604                         free(device);
    605                         return rc;
    606                 }
    607                
    608                 rc = arp_cache_add(&arp_globals.cache, device->device_id,
    609                     device);
    610                 if (rc != EOK) {
    611                         fibril_mutex_unlock(&arp_globals.lock);
    612                         free(device->addr);
    613                         free(device->addr_data);
    614                         free(device->broadcast_addr);
    615                         free(device->broadcast_data);
    616                         arp_protos_destroy(&device->protos, free);
    617                         free(device);
    618                         return rc;
    619                 }
    620                 printf("%s: Device registered (id: %d, type: 0x%x, service: %d,"
    621                     " proto: %d)\n", NAME, device->device_id, device->hardware,
    622                     device->service, protocol);
    623         }
    624        
    625         fibril_mutex_unlock(&arp_globals.lock);
    626         return EOK;
    627 }
    628 
    629 int il_initialize(int net_phone)
    630 {
    631         fibril_mutex_initialize(&arp_globals.lock);
    632        
    633         fibril_mutex_lock(&arp_globals.lock);
    634         arp_globals.net_phone = net_phone;
    635         int rc = arp_cache_initialize(&arp_globals.cache);
    636         fibril_mutex_unlock(&arp_globals.lock);
    637        
    638         return rc;
    639 }
    640 
    641 static int arp_send_request(device_id_t device_id, services_t protocol,
    642     measured_string_t *target, arp_device_t *device, arp_proto_t *proto)
    643 {
    644         /* ARP packet content size = header + (address + translation) * 2 */
    645         size_t length = 8 + 2 * (proto->addr->length + device->addr->length);
     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{
     513        arp_device_ref device;
     514        arp_proto_ref proto;
     515        measured_string_ref addr;
     516        size_t length;
     517        packet_t packet;
     518        arp_header_ref header;
     519
     520        if (!target)
     521                return NULL;
     522
     523        device = arp_cache_find(&arp_globals.cache, device_id);
     524        if (!device)
     525                return NULL;
     526
     527        proto = arp_protos_find(&device->protos, protocol);
     528        if (!proto || (proto->addr->length != target->length))
     529                return NULL;
     530
     531        addr = arp_addr_find(&proto->addresses, target->value, target->length);
     532        if (addr)
     533                return addr;
     534
     535        // ARP packet content size = header + (address + translation) * 2
     536        length = 8 + 2 * (CONVERT_SIZE(char, uint8_t, proto->addr->length) +
     537            CONVERT_SIZE(char, uint8_t, device->addr->length));
    646538        if (length > device->packet_dimension.content)
    647                 return ELIMIT;
    648        
    649         packet_t *packet = packet_get_4_remote(arp_globals.net_phone,
     539                return NULL;
     540
     541        packet = packet_get_4_remote(arp_globals.net_phone,
    650542            device->packet_dimension.addr_len, device->packet_dimension.prefix,
    651543            length, device->packet_dimension.suffix);
    652544        if (!packet)
    653                 return ENOMEM;
    654        
    655         arp_header_t *header = (arp_header_t *) packet_suffix(packet, length);
     545                return NULL;
     546
     547        header = (arp_header_ref) packet_suffix(packet, length);
    656548        if (!header) {
    657549                pq_release_remote(arp_globals.net_phone, packet_get_id(packet));
    658                 return ENOMEM;
    659         }
    660        
     550                return NULL;
     551        }
     552
    661553        header->hardware = htons(device->hardware);
    662554        header->hardware_length = (uint8_t) device->addr->length;
     
    664556        header->protocol_length = (uint8_t) proto->addr->length;
    665557        header->operation = htons(ARPOP_REQUEST);
    666        
    667558        length = sizeof(arp_header_t);
    668        
    669559        memcpy(((uint8_t *) header) + length, device->addr->value,
    670560            device->addr->length);
     
    676566        length += device->addr->length;
    677567        memcpy(((uint8_t *) header) + length, target->value, target->length);
    678        
    679         int rc = packet_set_addr(packet, (uint8_t *) device->addr->value,
    680             (uint8_t *) device->broadcast_addr->value, device->addr->length);
    681         if (rc != 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) {
    682572                pq_release_remote(arp_globals.net_phone, packet_get_id(packet));
    683                 return rc;
    684         }
    685        
     573                return NULL;
     574        }
     575
    686576        nil_send_msg(device->phone, device_id, packet, SERVICE_ARP);
    687         return EOK;
    688 }
    689 
    690 /** Return the hardware address for the given protocol address.
    691  *
    692  * Send the ARP request packet if the hardware address is not found in the
    693  * cache.
    694  *
    695  * @param[in]  device_id   Device identifier.
    696  * @param[in]  protocol    Protocol service.
    697  * @param[in]  target      Target protocol address.
    698  * @param[out] translation Where the hardware address of the target is stored.
    699  *
    700  * @return EOK on success.
    701  * @return EAGAIN if the caller should try again.
    702  * @return Other error codes in case of error.
    703  *
    704  */
    705 static int arp_translate_message(device_id_t device_id, services_t protocol,
    706     measured_string_t *target, measured_string_t **translation)
    707 {
    708         bool retry = false;
    709         int rc;
    710 
    711         assert(fibril_mutex_is_locked(&arp_globals.lock));
    712        
    713 restart:
    714         if ((!target) || (!translation))
    715                 return EBADMEM;
    716        
    717         arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
    718         if (!device)
    719                 return ENOENT;
    720        
    721         arp_proto_t *proto = arp_protos_find(&device->protos, protocol);
    722         if ((!proto) || (proto->addr->length != target->length))
    723                 return ENOENT;
    724        
    725         arp_trans_t *trans = arp_addr_find(&proto->addresses, target->value,
    726             target->length);
    727         if (trans) {
    728                 if (trans->hw_addr) {
    729                         /* The translation is in place. */
    730                         *translation = trans->hw_addr;
    731                         return EOK;
    732                 }
    733                
    734                 if (retry) {
    735                         /*
    736                          * We may get here as a result of being signalled for
    737                          * some reason while waiting for the translation (e.g.
    738                          * translation becoming available, record being removed
    739                          * from the table) and then losing the race for
    740                          * the arp_globals.lock with someone else who modified
    741                          * the table.
    742                          *
    743                          * Remove the incomplete record so that it is possible
    744                          * to make new ARP requests.
    745                          */
    746                         arp_clear_trans(trans);
    747                         arp_addr_exclude(&proto->addresses, target->value,
    748                             target->length, free);
    749                         return EAGAIN;
    750                 }
    751                
    752                 /*
    753                  * We are a random passer-by who merely joins an already waiting
    754                  * fibril in waiting for the translation.
    755                  */
    756                 rc = fibril_condvar_wait_timeout(&trans->cv, &arp_globals.lock,
    757                     ARP_TRANS_WAIT);
    758                 if (rc == ETIMEOUT)
    759                         return ENOENT;
    760                
    761                 /*
    762                  * Need to recheck because we did not hold the lock while
    763                  * sleeping on the condition variable.
    764                  */
    765                 retry = true;
    766                 goto restart;
    767         }
    768        
    769         if (retry)
    770                 return EAGAIN;
    771 
    772         /*
    773          * We are under the protection of arp_globals.lock, so we can afford to
    774          * first send the ARP request and then insert an incomplete ARP record.
    775          * The incomplete record is used to tell any other potential waiter
    776          * that this fibril has already sent the request and that it is waiting
    777          * for the answer. Lastly, any fibril which sees the incomplete request
    778          * can perform a timed wait on its condition variable to wait for the
    779          * ARP reply to arrive.
    780          */
    781 
    782         rc = arp_send_request(device_id, protocol, target, device, proto);
    783         if (rc != EOK)
    784                 return rc;
    785        
    786         trans = (arp_trans_t *) malloc(sizeof(arp_trans_t));
    787         if (!trans)
    788                 return ENOMEM;
    789        
    790         trans->hw_addr = NULL;
    791         fibril_condvar_initialize(&trans->cv);
    792        
    793         rc = arp_addr_add(&proto->addresses, target->value, target->length,
    794             trans);
    795         if (rc != EOK) {
    796                 free(trans);
    797                 return rc;
    798         }
    799        
    800         rc = fibril_condvar_wait_timeout(&trans->cv, &arp_globals.lock,
    801             ARP_TRANS_WAIT);
    802         if (rc == ETIMEOUT) {
    803                 /*
    804                  * Remove the incomplete record so that it is possible to make
    805                  * new ARP requests.
    806                  */
    807                 arp_clear_trans(trans);
    808                 arp_addr_exclude(&proto->addresses, target->value,
    809                     target->length, free);
    810                 return ENOENT;
    811         }
    812        
    813         /*
    814          * We need to recheck that the translation has indeed become available,
    815          * because we dropped the arp_globals.lock while sleeping on the
    816          * condition variable and someone else might have e.g. removed the
    817          * translation before we managed to lock arp_globals.lock again.
    818          */
    819 
    820         retry = true;
    821         goto restart;
    822 }
    823 
    824 /** Process the ARP message.
    825  *
    826  * @param[in]  callid Message identifier.
    827  * @param[in]  call   Message parameters.
    828  * @param[out] answer Answer.
    829  * @param[out] count  Number of arguments of the answer.
    830  *
    831  * @return EOK on success.
    832  * @return ENOTSUP if the message is not known.
     577        return NULL;
     578}
     579
     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.
    833590 *
    834591 * @see arp_interface.h
    835592 * @see IS_NET_ARP_MESSAGE()
    836  *
    837  */
    838 int il_module_message(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer,
    839     size_t *count)
    840 {
    841         measured_string_t *address;
    842         measured_string_t *translation;
    843         uint8_t *data;
    844         int rc;
    845        
    846         *count = 0;
    847         switch (IPC_GET_IMETHOD(*call)) {
     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)) {
    848608        case IPC_M_PHONE_HUNGUP:
    849609                return EOK;
    850610       
    851611        case NET_ARP_DEVICE:
    852                 rc = measured_strings_receive(&address, &data, 1);
    853                 if (rc != EOK)
    854                         return rc;
    855                
    856                 rc = arp_device_message(IPC_GET_DEVICE(*call),
    857                     IPC_GET_SERVICE(*call), ARP_GET_NETIF(*call), address);
    858                 if (rc != EOK) {
     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))) {
    859615                        free(address);
    860616                        free(data);
    861617                }
    862                
    863                 return rc;
     618                return ERROR_CODE;
    864619       
    865620        case NET_ARP_TRANSLATE:
    866                 rc = measured_strings_receive(&address, &data, 1);
    867                 if (rc != EOK)
    868                         return rc;
    869                
    870                 fibril_mutex_lock(&arp_globals.lock);
    871                 rc = arp_translate_message(IPC_GET_DEVICE(*call),
    872                     IPC_GET_SERVICE(*call), address, &translation);
     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);
    873625                free(address);
    874626                free(data);
    875                
    876                 if (rc != EOK) {
    877                         fibril_mutex_unlock(&arp_globals.lock);
    878                         return rc;
    879                 }
    880                
    881627                if (!translation) {
    882                         fibril_mutex_unlock(&arp_globals.lock);
     628                        fibril_rwlock_read_unlock(&arp_globals.lock);
    883629                        return ENOENT;
    884630                }
    885                
    886                 rc = measured_strings_reply(translation, 1);
    887                 fibril_mutex_unlock(&arp_globals.lock);
    888                 return rc;
    889        
     631                ERROR_CODE = measured_strings_reply(translation, 1);
     632                fibril_rwlock_read_unlock(&arp_globals.lock);
     633                return ERROR_CODE;
     634
    890635        case NET_ARP_CLEAR_DEVICE:
    891                 return arp_clear_device_req(0, IPC_GET_DEVICE(*call));
    892        
     636                return arp_clear_device_req(0, IPC_GET_DEVICE(call));
     637
    893638        case NET_ARP_CLEAR_ADDRESS:
    894                 rc = measured_strings_receive(&address, &data, 1);
    895                 if (rc != EOK)
    896                         return rc;
    897                
    898                 arp_clear_address_req(0, IPC_GET_DEVICE(*call),
    899                     IPC_GET_SERVICE(*call), 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);
    900642                free(address);
    901643                free(data);
     
    904646        case NET_ARP_CLEAN_CACHE:
    905647                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));
    906675        }
    907676       
     
    909678}
    910679
     680/** Default thread for new connections.
     681 *
     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)
     686{
     687        /*
     688         * Accept the connection
     689         *  - Answer the first IPC_M_CONNECT_ME_TO call.
     690         */
     691        ipc_answer_0(iid, EOK);
     692       
     693        while (true) {
     694                ipc_call_t answer;
     695                int answer_count;
     696               
     697                /* Clear the answer structure */
     698                refresh_answer(&answer, &answer_count);
     699               
     700                /* Fetch the next message */
     701                ipc_call_t call;
     702                ipc_callid_t callid = async_get_call(&call);
     703               
     704                /* Process the message */
     705                int res = il_module_message_standalone(callid, &call, &answer,
     706                    &answer_count);
     707               
     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))
     714                        return;
     715               
     716                /* Answer the message */
     717                answer_call(callid, res, &answer, answer_count);
     718        }
     719}
     720
     721/** Starts the module.
     722 *
     723 * @returns             EOK on success.
     724 * @returns             Other error codes as defined for each specific module
     725 *                      start function.
     726 */
    911727int main(int argc, char *argv[])
    912728{
     729        ERROR_DECLARE;
     730       
    913731        /* Start the module */
    914         return il_module_start(SERVICE_ARP);
     732        ERROR_PROPAGATE(il_module_start_standalone(il_client_connection));
     733        return EOK;
    915734}
    916735
    917736/** @}
    918737 */
     738
Note: See TracChangeset for help on using the changeset viewer.