Changeset 89c57b6 in mainline for uspace/srv/net/il/arp/arp.c


Ignore:
Timestamp:
2011-04-13T14:45:41Z (14 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
88634420
Parents:
cefb126 (diff), 17279ead (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 mainline changes.

File:
1 edited

Legend:

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

    rcefb126 r89c57b6  
    2828
    2929/** @addtogroup arp
    30  *  @{
     30 * @{
    3131 */
    3232
    3333/** @file
    34  *  ARP module implementation.
    35  *  @see arp.h
     34 * ARP module implementation.
     35 * @see arp.h
    3636 */
    3737
     
    4040#include <mem.h>
    4141#include <fibril_synch.h>
     42#include <assert.h>
    4243#include <stdio.h>
    4344#include <str.h>
    4445#include <task.h>
    45 #include <ipc/ipc.h>
     46#include <adt/measured_strings.h>
    4647#include <ipc/services.h>
    47 
    48 #include <net_err.h>
    49 #include <net_messages.h>
    50 #include <net_modules.h>
    51 #include <net_byteorder.h>
    52 #include <net_device.h>
    53 #include <arp_interface.h>
    54 #include <nil_interface.h>
     48#include <ipc/net.h>
     49#include <ipc/arp.h>
     50#include <ipc/il.h>
     51#include <ipc/nil.h>
     52#include <byteorder.h>
     53#include <errno.h>
     54#include <net/modules.h>
     55#include <net/device.h>
     56#include <net/packet.h>
     57#include <nil_remote.h>
    5558#include <protocol_map.h>
    56 #include <adt/measured_strings.h>
    57 #include <packet/packet.h>
    58 #include <packet/packet_client.h>
     59#include <packet_client.h>
    5960#include <packet_remote.h>
    60 #include <il_messages.h>
    61 #include <il_interface.h>
    62 #include <il_local.h>
    63 #include <arp_messages.h>
    64 
     61#include <il_remote.h>
     62#include <il_skel.h>
    6563#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  */
     64
     65/** ARP module name. */
    7366#define NAME  "arp"
    7467
    75 /** ARP global data.
    76  */
    77 arp_globals_t   arp_globals;
    78 
    79 /** 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  */
     68/** Number of microseconds to wait for an ARP reply. */
     69#define ARP_TRANS_WAIT  1000000
     70
     71/** @name ARP operation codes definitions */
    9672/*@{*/
    9773
    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);
     74/** REQUEST operation code. */
     75#define ARPOP_REQUEST  1
     76
     77/** REPLY operation code. */
     78#define ARPOP_REPLY  2
    14679
    14780/*@}*/
    14881
    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/** Type definition of an ARP protocol header.
     83 * @see arp_header
     84 */
     85typedef struct arp_header arp_header_t;
     86
     87/** ARP protocol header. */
     88struct 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
     109/** ARP global data. */
     110arp_globals_t arp_globals;
     111
     112DEVICE_MAP_IMPLEMENT(arp_cache, arp_device_t);
     113INT_MAP_IMPLEMENT(arp_protos, arp_proto_t);
     114GENERIC_CHAR_MAP_IMPLEMENT(arp_addr, arp_trans_t);
     115
     116static 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
     126static void arp_clear_addr(arp_addr_t *addresses)
     127{
    156128        int count;
    157         arp_device_ref device;
    158 
    159         fibril_rwlock_write_lock(&arp_globals.lock);
    160         for(count = arp_cache_count(&arp_globals.cache) - 1; count >= 0; -- count){
    161                 device = arp_cache_get_index(&arp_globals.cache, count);
    162                 if(device){
     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 */
     142static void arp_clear_device(arp_device_t *device)
     143{
     144        int count;
     145       
     146        for (count = arp_protos_count(&device->protos) - 1; count >= 0;
     147            count--) {
     148                arp_proto_t *proto = arp_protos_get_index(&device->protos,
     149                    count);
     150               
     151                if (proto) {
     152                        if (proto->addr)
     153                                free(proto->addr);
     154                       
     155                        if (proto->addr_data)
     156                                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);
     164}
     165
     166static int arp_clean_cache_req(int arp_phone)
     167{
     168        int count;
     169       
     170        fibril_mutex_lock(&arp_globals.lock);
     171        for (count = arp_cache_count(&arp_globals.cache) - 1; count >= 0;
     172            count--) {
     173                arp_device_t *device = arp_cache_get_index(&arp_globals.cache,
     174                    count);
     175               
     176                if (device) {
    163177                        arp_clear_device(device);
    164                         if(device->addr_data){
     178                        if (device->addr_data)
    165179                                free(device->addr_data);
     180                       
     181                        if (device->broadcast_data)
     182                                free(device->broadcast_data);
     183                }
     184        }
     185       
     186        arp_cache_clear(&arp_globals.cache, free);
     187        fibril_mutex_unlock(&arp_globals.lock);
     188       
     189        return EOK;
     190}
     191
     192static 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);
     198        if (!device) {
     199                fibril_mutex_unlock(&arp_globals.lock);
     200                return ENOENT;
     201        }
     202       
     203        arp_proto_t *proto = arp_protos_find(&device->protos, protocol);
     204        if (!proto) {
     205                fibril_mutex_unlock(&arp_globals.lock);
     206                return ENOENT;
     207        }
     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}
     219
     220static int arp_clear_device_req(int arp_phone, device_id_t device_id)
     221{
     222        fibril_mutex_lock(&arp_globals.lock);
     223       
     224        arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
     225        if (!device) {
     226                fibril_mutex_unlock(&arp_globals.lock);
     227                return ENOENT;
     228        }
     229       
     230        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 */
     248static 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));
     252        if (!*proto)
     253                return ENOMEM;
     254       
     255        (*proto)->service = service;
     256        (*proto)->addr = address;
     257        (*proto)->addr_data = address->value;
     258       
     259        int rc = arp_addr_initialize(&(*proto)->addresses);
     260        if (rc != EOK) {
     261                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
     271 * is targeted to my protocol address.
     272 *
     273 * Respond to the ARP request if the packet is the ARP request and is
     274 * targeted to my address.
     275 *
     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 */
     291static 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);
     296        if (length <= sizeof(arp_header_t))
     297                return EINVAL;
     298       
     299        arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
     300        if (!device)
     301                return ENOENT;
     302       
     303        arp_header_t *header = (arp_header_t *) packet_get_data(packet);
     304        if ((ntohs(header->hardware) != device->hardware) ||
     305            (length < sizeof(arp_header_t) + header->hardware_length * 2U +
     306            header->protocol_length * 2U)) {
     307                return EINVAL;
     308        }
     309       
     310        arp_proto_t *proto = arp_protos_find(&device->protos,
     311            protocol_unmap(device->service, ntohs(header->protocol)));
     312        if (!proto)
     313                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)
     326                        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)
     333                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)
     340                                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;
    166349                        }
    167                         if(device->broadcast_data){
    168                                 free(device->broadcast_data);
     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               
     362                if (ntohs(header->operation) == ARPOP_REQUEST) {
     363                        header->operation = htons(ARPOP_REPLY);
     364                        memcpy(des_proto, src_proto, header->protocol_length);
     365                        memcpy(src_proto, proto->addr->value,
     366                            header->protocol_length);
     367                        memcpy(src_hw, device->addr->value,
     368                            device->packet_dimension.addr_len);
     369                        memcpy(des_hw, trans->hw_addr->value,
     370                            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                       
     377                        nil_send_msg(device->phone, device_id, packet,
     378                            SERVICE_ARP);
     379                        return 1;
     380                }
     381        }
     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 */
     395static 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 */
     420static 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);
    169448                        }
    170                 }
    171         }
    172         arp_cache_clear(&arp_globals.cache);
    173         fibril_rwlock_write_unlock(&arp_globals.lock);
    174         printf("Cache cleaned\n");
    175         return EOK;
    176 }
    177 
    178 int arp_clear_address_req(int arp_phone, device_id_t device_id, services_t protocol, measured_string_ref address){
    179         arp_device_ref device;
    180         arp_proto_ref proto;
    181 
    182         fibril_rwlock_write_lock(&arp_globals.lock);
    183         device = arp_cache_find(&arp_globals.cache, device_id);
    184         if(! device){
    185                 fibril_rwlock_write_unlock(&arp_globals.lock);
    186                 return ENOENT;
    187         }
    188         proto = arp_protos_find(&device->protos, protocol);
    189         if(! proto){
    190                 fibril_rwlock_write_unlock(&arp_globals.lock);
    191                 return ENOENT;
    192         }
    193         arp_addr_exclude(&proto->addresses, address->value, address->length);
    194         fibril_rwlock_write_unlock(&arp_globals.lock);
    195         return EOK;
    196 }
    197 
    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){
    218         arp_device_ref device;
    219 
    220         fibril_rwlock_write_lock(&arp_globals.lock);
    221         device = arp_cache_find(&arp_globals.cache, device_id);
    222         if(! device){
    223                 fibril_rwlock_write_unlock(&arp_globals.lock);
    224                 return ENOENT;
    225         }
    226         arp_clear_device(device);
    227         printf("Device %d cleared\n", device_id);
    228         fibril_rwlock_write_unlock(&arp_globals.lock);
    229         return EOK;
    230 }
    231 
    232 int arp_connect_module(services_t service){
    233         if(service != SERVICE_ARP){
    234                 return EINVAL;
    235         }
    236         return EOK;
    237 }
    238 
    239 int arp_device_message(device_id_t device_id, services_t service, services_t protocol, measured_string_ref address){
    240         ERROR_DECLARE;
    241 
    242         arp_device_ref device;
    243         arp_proto_ref proto;
     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 */
     484static int arp_device_message(device_id_t device_id, services_t service,
     485    services_t protocol, measured_string_t *address)
     486{
    244487        int index;
    245         hw_type_t hardware;
    246 
    247         fibril_rwlock_write_lock(&arp_globals.lock);
    248         // an existing device?
    249         device = arp_cache_find(&arp_globals.cache, device_id);
    250         if(device){
    251                 if(device->service != service){
    252                         printf("Device %d already exists\n", device->device_id);
    253                         fibril_rwlock_write_unlock(&arp_globals.lock);
     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);
    254499                        return EEXIST;
    255500                }
    256                 proto = arp_protos_find(&device->protos, protocol);
    257                 if(proto){
     501               
     502                arp_proto_t *proto = arp_protos_find(&device->protos, protocol);
     503                if (proto) {
    258504                        free(proto->addr);
    259505                        free(proto->addr_data);
    260506                        proto->addr = address;
    261507                        proto->addr_data = address->value;
    262                 }else{
    263                         if(ERROR_OCCURRED(arp_proto_create(&proto, protocol, address))){
    264                                 fibril_rwlock_write_unlock(&arp_globals.lock);
    265                                 return ERROR_CODE;
     508                } else {
     509                        rc = arp_proto_create(&proto, protocol, address);
     510                        if (rc != EOK) {
     511                                fibril_mutex_unlock(&arp_globals.lock);
     512                                return rc;
    266513                        }
    267                         index = arp_protos_add(&device->protos, proto->service, proto);
    268                         if(index < 0){
    269                                 fibril_rwlock_write_unlock(&arp_globals.lock);
     514                       
     515                        index = arp_protos_add(&device->protos, proto->service,
     516                            proto);
     517                        if (index < 0) {
     518                                fibril_mutex_unlock(&arp_globals.lock);
    270519                                free(proto);
    271520                                return index;
    272521                        }
    273                         printf("New protocol added:\n\tdevice id\t= %d\n\tproto\t= %d", device_id, protocol);
    274                 }
    275         }else{
    276                 hardware = hardware_map(service);
    277                 if(! hardware){
     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)
    278529                        return ENOENT;
    279                 }
    280                 // create a new device
    281                 device = (arp_device_ref) malloc(sizeof(arp_device_t));
    282                 if(! device){
    283                         fibril_rwlock_write_unlock(&arp_globals.lock);
     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);
    284535                        return ENOMEM;
    285536                }
     537               
    286538                device->hardware = hardware;
    287539                device->device_id = device_id;
    288                 if(ERROR_OCCURRED(arp_protos_initialize(&device->protos))
    289                         || ERROR_OCCURRED(arp_proto_create(&proto, protocol, address))){
    290                         fibril_rwlock_write_unlock(&arp_globals.lock);
     540                rc = arp_protos_initialize(&device->protos);
     541                if (rc != EOK) {
     542                        fibril_mutex_unlock(&arp_globals.lock);
    291543                        free(device);
    292                         return ERROR_CODE;
    293                 }
     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               
    294555                index = arp_protos_add(&device->protos, proto->service, proto);
    295                 if(index < 0){
    296                         fibril_rwlock_write_unlock(&arp_globals.lock);
    297                         arp_protos_destroy(&device->protos);
     556                if (index < 0) {
     557                        fibril_mutex_unlock(&arp_globals.lock);
     558                        arp_protos_destroy(&device->protos, free);
    298559                        free(device);
    299560                        return index;
    300561                }
     562               
    301563                device->service = service;
    302                 // bind the new one
    303                 device->phone = nil_bind_service(device->service, (ipcarg_t) device->device_id, SERVICE_ARP, arp_globals.client_connection);
    304                 if(device->phone < 0){
    305                         fibril_rwlock_write_unlock(&arp_globals.lock);
    306                         arp_protos_destroy(&device->protos);
     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);
    307572                        free(device);
    308573                        return EREFUSED;
    309574                }
    310                 // get packet dimensions
    311                 if(ERROR_OCCURRED(nil_packet_size_req(device->phone, device_id, &device->packet_dimension))){
    312                         fibril_rwlock_write_unlock(&arp_globals.lock);
    313                         arp_protos_destroy(&device->protos);
     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);
    314582                        free(device);
    315                         return ERROR_CODE;
    316                 }
    317                 // get hardware address
    318                 if(ERROR_OCCURRED(nil_get_addr_req(device->phone, device_id, &device->addr, &device->addr_data))){
    319                         fibril_rwlock_write_unlock(&arp_globals.lock);
    320                         arp_protos_destroy(&device->protos);
     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);
    321592                        free(device);
    322                         return ERROR_CODE;
    323                 }
    324                 // get broadcast address
    325                 if(ERROR_OCCURRED(nil_get_broadcast_addr_req(device->phone, device_id, &device->broadcast_addr, &device->broadcast_data))){
    326                         fibril_rwlock_write_unlock(&arp_globals.lock);
     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);
    327601                        free(device->addr);
    328602                        free(device->addr_data);
    329                         arp_protos_destroy(&device->protos);
     603                        arp_protos_destroy(&device->protos, free);
    330604                        free(device);
    331                         return ERROR_CODE;
    332                 }
    333                 if(ERROR_OCCURRED(arp_cache_add(&arp_globals.cache, device->device_id, device))){
    334                         fibril_rwlock_write_unlock(&arp_globals.lock);
     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);
    335612                        free(device->addr);
    336613                        free(device->addr_data);
    337614                        free(device->broadcast_addr);
    338615                        free(device->broadcast_data);
    339                         arp_protos_destroy(&device->protos);
     616                        arp_protos_destroy(&device->protos, free);
    340617                        free(device);
    341                         return ERROR_CODE;
    342                 }
    343                 printf("%s: Device registered (id: %d, type: 0x%x, service: %d, proto: %d)\n",
    344                     NAME, device->device_id, device->hardware, device->service, protocol);
    345         }
    346         fibril_rwlock_write_unlock(&arp_globals.lock);
     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);
    347626        return EOK;
    348627}
    349628
    350 int arp_device_req(int arp_phone, device_id_t device_id, services_t protocol, services_t netif, measured_string_ref address){
    351         ERROR_DECLARE;
    352 
    353         measured_string_ref tmp;
    354 
    355         // copy the given address for exclusive use
    356         tmp = measured_string_copy(address);
    357         if(ERROR_OCCURRED(arp_device_message(device_id, netif, protocol, tmp))){
    358                 free(tmp->value);
    359                 free(tmp);
    360         }
    361         return ERROR_CODE;
    362 }
    363 
    364 int arp_initialize(async_client_conn_t client_connection){
    365         ERROR_DECLARE;
    366 
    367         fibril_rwlock_initialize(&arp_globals.lock);
    368         fibril_rwlock_write_lock(&arp_globals.lock);
    369         arp_globals.client_connection = client_connection;
    370         ERROR_PROPAGATE(arp_cache_initialize(&arp_globals.cache));
    371         fibril_rwlock_write_unlock(&arp_globals.lock);
    372         return EOK;
    373 }
    374 
    375 int arp_message_standalone(ipc_callid_t callid, ipc_call_t *call,
    376     ipc_call_t *answer, int *answer_count)
    377 {
    378         ERROR_DECLARE;
    379        
    380         measured_string_ref address;
    381         measured_string_ref translation;
    382         char * data;
    383         packet_t packet;
    384         packet_t next;
    385        
    386         *answer_count = 0;
    387         switch (IPC_GET_METHOD(*call)) {
    388                 case IPC_M_PHONE_HUNGUP:
    389                         return EOK;
    390                 case NET_ARP_DEVICE:
    391                         ERROR_PROPAGATE(measured_strings_receive(&address, &data, 1));
    392                         if(ERROR_OCCURRED(arp_device_message(IPC_GET_DEVICE(call), IPC_GET_SERVICE(call), ARP_GET_NETIF(call), address))){
    393                                 free(address);
    394                                 free(data);
    395                         }
    396                         return ERROR_CODE;
    397                 case NET_ARP_TRANSLATE:
    398                         ERROR_PROPAGATE(measured_strings_receive(&address, &data, 1));
    399                         fibril_rwlock_read_lock(&arp_globals.lock);
    400                         translation = arp_translate_message(IPC_GET_DEVICE(call), IPC_GET_SERVICE(call), address);
    401                         free(address);
    402                         free(data);
    403                         if(! translation){
    404                                 fibril_rwlock_read_unlock(&arp_globals.lock);
    405                                 return ENOENT;
    406                         }
    407                         ERROR_CODE = measured_strings_reply(translation, 1);
    408                         fibril_rwlock_read_unlock(&arp_globals.lock);
    409                         return ERROR_CODE;
    410                 case NET_ARP_CLEAR_DEVICE:
    411                         return arp_clear_device_req(0, IPC_GET_DEVICE(call));
    412                 case NET_ARP_CLEAR_ADDRESS:
    413                         ERROR_PROPAGATE(measured_strings_receive(&address, &data, 1));
    414                         arp_clear_address_req(0, IPC_GET_DEVICE(call), IPC_GET_SERVICE(call), address);
    415                         free(address);
    416                         free(data);
    417                         return EOK;
    418                 case NET_ARP_CLEAN_CACHE:
    419                         return arp_clean_cache_req(0);
    420                 case NET_IL_DEVICE_STATE:
    421                         // do nothing - keep the cache
    422                         return EOK;
    423                 case NET_IL_RECEIVED:
    424                         if(! ERROR_OCCURRED(packet_translate_remote(arp_globals.net_phone, &packet, IPC_GET_PACKET(call)))){
    425                                 fibril_rwlock_read_lock(&arp_globals.lock);
    426                                 do{
    427                                         next = pq_detach(packet);
    428                                         ERROR_CODE = arp_receive_message(IPC_GET_DEVICE(call), packet);
    429                                         if(ERROR_CODE != 1){
    430                                                 pq_release_remote(arp_globals.net_phone, packet_get_id(packet));
    431                                         }
    432                                         packet = next;
    433                                 }while(packet);
    434                                 fibril_rwlock_read_unlock(&arp_globals.lock);
    435                         }
    436                         return ERROR_CODE;
    437                 case NET_IL_MTU_CHANGED:
    438                         return arp_mtu_changed_message(IPC_GET_DEVICE(call), IPC_GET_MTU(call));
    439         }
    440        
    441         return ENOTSUP;
    442 }
    443 
    444 int arp_mtu_changed_message(device_id_t device_id, size_t mtu){
    445         arp_device_ref device;
    446 
    447         fibril_rwlock_write_lock(&arp_globals.lock);
    448         device = arp_cache_find(&arp_globals.cache, device_id);
    449         if(! device){
    450                 fibril_rwlock_write_unlock(&arp_globals.lock);
    451                 return ENOENT;
    452         }
    453         device->packet_dimension.content = mtu;
    454         printf("arp - device %d changed mtu to %d\n\n", device_id, mtu);
    455         fibril_rwlock_write_unlock(&arp_globals.lock);
    456         return EOK;
    457 }
    458 
    459 int arp_proto_create(arp_proto_ref * proto, services_t service, measured_string_ref address){
    460         ERROR_DECLARE;
    461 
    462         *proto = (arp_proto_ref) malloc(sizeof(arp_proto_t));
    463         if(!(*proto)){
     629int 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
     641static 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);
     646        if (length > device->packet_dimension.content)
     647                return ELIMIT;
     648       
     649        packet_t *packet = packet_get_4_remote(arp_globals.net_phone,
     650            device->packet_dimension.addr_len, device->packet_dimension.prefix,
     651            length, device->packet_dimension.suffix);
     652        if (!packet)
    464653                return ENOMEM;
    465         }
    466         (** proto).service = service;
    467         (** proto).addr = address;
    468         (** proto).addr_data = address->value;
    469         if(ERROR_OCCURRED(arp_addr_initialize(&(** proto).addresses))){
    470                 free(*proto);
    471                 return ERROR_CODE;
    472         }
    473         return EOK;
    474 }
    475 
    476 int arp_receive_message(device_id_t device_id, packet_t packet){
    477         ERROR_DECLARE;
    478 
    479         size_t length;
    480         arp_header_ref header;
    481         arp_device_ref device;
    482         arp_proto_ref proto;
    483         measured_string_ref hw_source;
    484         uint8_t * src_hw;
    485         uint8_t * src_proto;
    486         uint8_t * des_hw;
    487         uint8_t * des_proto;
    488 
    489         length = packet_get_data_length(packet);
    490         if(length <= sizeof(arp_header_t)){
    491                 return EINVAL;
    492         }
    493         device = arp_cache_find(&arp_globals.cache, device_id);
    494         if(! device){
    495                 return ENOENT;
    496         }
    497         header = (arp_header_ref) packet_get_data(packet);
    498         if((ntohs(header->hardware) != device->hardware)
    499                 || (length < sizeof(arp_header_t) + header->hardware_length * 2u + header->protocol_length * 2u)){
    500                 return EINVAL;
    501         }
    502         proto = arp_protos_find(&device->protos, protocol_unmap(device->service, ntohs(header->protocol)));
    503         if(! proto){
    504                 return ENOENT;
    505         }
    506         src_hw = ((uint8_t *) header) + sizeof(arp_header_t);
    507         src_proto = src_hw + header->hardware_length;
    508         des_hw = src_proto + header->protocol_length;
    509         des_proto = des_hw + header->hardware_length;
    510         hw_source = arp_addr_find(&proto->addresses, (char *) src_proto, CONVERT_SIZE(uint8_t, char, header->protocol_length));
    511         // exists?
    512         if(hw_source){
    513                 if(hw_source->length != CONVERT_SIZE(uint8_t, char, header->hardware_length)){
    514                         return EINVAL;
    515                 }
    516                 memcpy(hw_source->value, src_hw, hw_source->length);
    517         }
    518         // is my protocol address?
    519         if(proto->addr->length != CONVERT_SIZE(uint8_t, char, header->protocol_length)){
    520                 return EINVAL;
    521         }
    522         if(! str_lcmp(proto->addr->value, (char *) des_proto, proto->addr->length)){
    523                 // not already upadted?
    524                 if(! hw_source){
    525                         hw_source = measured_string_create_bulk((char *) src_hw, CONVERT_SIZE(uint8_t, char, header->hardware_length));
    526                         if(! hw_source){
    527                                 return ENOMEM;
    528                         }
    529                         ERROR_PROPAGATE(arp_addr_add(&proto->addresses, (char *) src_proto, CONVERT_SIZE(uint8_t, char, header->protocol_length), hw_source));
    530                 }
    531                 if(ntohs(header->operation) == ARPOP_REQUEST){
    532                         header->operation = htons(ARPOP_REPLY);
    533                         memcpy(des_proto, src_proto, header->protocol_length);
    534                         memcpy(src_proto, proto->addr->value, header->protocol_length);
    535                         memcpy(src_hw, device->addr->value, device->packet_dimension.addr_len);
    536                         memcpy(des_hw, hw_source->value, header->hardware_length);
    537                         ERROR_PROPAGATE(packet_set_addr(packet, src_hw, des_hw, header->hardware_length));
    538                         nil_send_msg(device->phone, device_id, packet, SERVICE_ARP);
    539                         return 1;
    540                 }
    541         }
    542         return EOK;
    543 }
    544 
    545 task_id_t arp_task_get_id(void){
    546         return task_get_id();
    547 }
    548 
    549 measured_string_ref arp_translate_message(device_id_t device_id, services_t protocol, measured_string_ref target){
    550         arp_device_ref device;
    551         arp_proto_ref proto;
    552         measured_string_ref addr;
    553         size_t length;
    554         packet_t packet;
    555         arp_header_ref header;
    556 
    557         if(! target){
    558                 return NULL;
    559         }
    560         device = arp_cache_find(&arp_globals.cache, device_id);
    561         if(! device){
    562                 return NULL;
    563         }
    564         proto = arp_protos_find(&device->protos, protocol);
    565         if((! proto) || (proto->addr->length != target->length)){
    566                 return NULL;
    567         }
    568         addr = arp_addr_find(&proto->addresses, target->value, target->length);
    569         if(addr){
    570                 return addr;
    571         }
    572         // ARP packet content size = header + (address + translation) * 2
    573         length = 8 + (CONVERT_SIZE(char, uint8_t, proto->addr->length) + CONVERT_SIZE(char, uint8_t, device->addr->length)) * 2;
    574         if(length > device->packet_dimension.content){
    575                 return NULL;
    576         }
    577         packet = packet_get_4_remote(arp_globals.net_phone, device->packet_dimension.addr_len, device->packet_dimension.prefix, length, device->packet_dimension.suffix);
    578         if(! packet){
    579                 return NULL;
    580         }
    581         header = (arp_header_ref) packet_suffix(packet, length);
    582         if(! header){
     654       
     655        arp_header_t *header = (arp_header_t *) packet_suffix(packet, length);
     656        if (!header) {
    583657                pq_release_remote(arp_globals.net_phone, packet_get_id(packet));
    584                 return NULL;
    585         }
     658                return ENOMEM;
     659        }
     660       
    586661        header->hardware = htons(device->hardware);
    587662        header->hardware_length = (uint8_t) device->addr->length;
     
    589664        header->protocol_length = (uint8_t) proto->addr->length;
    590665        header->operation = htons(ARPOP_REQUEST);
     666       
    591667        length = sizeof(arp_header_t);
    592         memcpy(((uint8_t *) header) + length, device->addr->value, device->addr->length);
     668       
     669        memcpy(((uint8_t *) header) + length, device->addr->value,
     670            device->addr->length);
    593671        length += device->addr->length;
    594         memcpy(((uint8_t *) header) + length, proto->addr->value, proto->addr->length);
     672        memcpy(((uint8_t *) header) + length, proto->addr->value,
     673            proto->addr->length);
    595674        length += proto->addr->length;
    596675        bzero(((uint8_t *) header) + length, device->addr->length);
    597676        length += device->addr->length;
    598677        memcpy(((uint8_t *) header) + length, target->value, target->length);
    599         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){
     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) {
    600682                pq_release_remote(arp_globals.net_phone, packet_get_id(packet));
    601                 return NULL;
    602         }
     683                return rc;
     684        }
     685       
    603686        nil_send_msg(device->phone, device_id, packet, SERVICE_ARP);
    604         return NULL;
    605 }
    606 
    607 int arp_translate_req(int arp_phone, device_id_t device_id, services_t protocol, measured_string_ref address, measured_string_ref * translation, char ** data){
    608         measured_string_ref tmp;
    609 
    610         fibril_rwlock_read_lock(&arp_globals.lock);
    611         tmp = arp_translate_message(device_id, protocol, address);
    612         if(tmp){
    613                 *translation = measured_string_copy(tmp);
    614                 fibril_rwlock_read_unlock(&arp_globals.lock);
    615                 if(*translation){
    616                         *data = (** translation).value;
     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 */
     705static 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       
     713restart:
     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;
    617731                        return EOK;
    618                 }else{
    619                         return ENOMEM;
    620                 }
    621         }else{
    622                 fibril_rwlock_read_unlock(&arp_globals.lock);
     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);
    623810                return ENOENT;
    624811        }
    625 }
    626 
    627 /** Default thread for new connections.
    628  *
    629  *  @param[in] iid The initial message identifier.
    630  *  @param[in] icall The initial message call structure.
    631  *
    632  */
    633 static void il_client_connection(ipc_callid_t iid, ipc_call_t * icall)
    634 {
     812       
    635813        /*
    636          * Accept the connection
    637          *  - Answer the first IPC_M_CONNECT_ME_TO call.
     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.
    638818         */
    639         ipc_answer_0(iid, EOK);
    640        
    641         while(true) {
    642                 ipc_call_t answer;
    643                 int answer_count;
    644                
    645                 /* Clear the answer structure */
    646                 refresh_answer(&answer, &answer_count);
    647                
    648                 /* Fetch the next message */
    649                 ipc_call_t call;
    650                 ipc_callid_t callid = async_get_call(&call);
    651                
    652                 /* Process the message */
    653                 int res = il_module_message_standalone(callid, &call, &answer,
    654                     &answer_count);
    655                
    656                 /* End if said to either by the message or the processing result */
    657                 if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) || (res == EHANGUP))
    658                         return;
    659                
    660                 /* Answer the message */
    661                 answer_call(callid, res, &answer, answer_count);
    662         }
    663 }
    664 
    665 /** Starts the module.
    666  *
    667  *  @param argc The count of the command line arguments. Ignored parameter.
    668  *  @param argv The command line parameters. Ignored parameter.
    669  *
    670  *  @returns EOK on success.
    671  *  @returns Other error codes as defined for each specific module start function.
    672  *
    673  */
     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.
     833 *
     834 * @see arp_interface.h
     835 * @see IS_NET_ARP_MESSAGE()
     836 *
     837 */
     838int 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)) {
     848        case IPC_M_PHONE_HUNGUP:
     849                return EOK;
     850       
     851        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) {
     859                        free(address);
     860                        free(data);
     861                }
     862               
     863                return rc;
     864       
     865        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);
     873                free(address);
     874                free(data);
     875               
     876                if (rc != EOK) {
     877                        fibril_mutex_unlock(&arp_globals.lock);
     878                        return rc;
     879                }
     880               
     881                if (!translation) {
     882                        fibril_mutex_unlock(&arp_globals.lock);
     883                        return ENOENT;
     884                }
     885               
     886                rc = measured_strings_reply(translation, 1);
     887                fibril_mutex_unlock(&arp_globals.lock);
     888                return rc;
     889       
     890        case NET_ARP_CLEAR_DEVICE:
     891                return arp_clear_device_req(0, IPC_GET_DEVICE(*call));
     892       
     893        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);
     900                free(address);
     901                free(data);
     902                return EOK;
     903       
     904        case NET_ARP_CLEAN_CACHE:
     905                return arp_clean_cache_req(0);
     906        }
     907       
     908        return ENOTSUP;
     909}
     910
    674911int main(int argc, char *argv[])
    675912{
    676         ERROR_DECLARE;
    677        
    678913        /* Start the module */
    679         if (ERROR_OCCURRED(il_module_start_standalone(il_client_connection)))
    680                 return ERROR_CODE;
    681        
    682         return EOK;
     914        return il_module_start(SERVICE_ARP);
    683915}
    684916
Note: See TracChangeset for help on using the changeset viewer.