Ignore:
File:
1 edited

Legend:

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

    r87e373b r774e6d1a  
    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>
     
    5054#include <ipc/arp.h>
    5155#include <ipc/il.h>
    52 #include <ipc/nil.h>
    5356#include <byteorder.h>
    5457#include <errno.h>
     58
    5559#include <net/modules.h>
    5660#include <net/device.h>
    5761#include <net/packet.h>
    58 #include <nil_remote.h>
     62
     63#include <nil_interface.h>
    5964#include <protocol_map.h>
    6065#include <packet_client.h>
    6166#include <packet_remote.h>
    62 #include <il_remote.h>
    63 #include <il_skel.h>
    64 #include "arp.h"
     67#include <il_interface.h>
     68#include <il_local.h>
     69
    6570
    6671/** ARP module name. */
     
    6873
    6974/** Number of microseconds to wait for an ARP reply. */
    70 #define ARP_TRANS_WAIT  1000000
    71 
    72 /** @name ARP operation codes definitions */
    73 /*@{*/
    74 
    75 /** REQUEST operation code. */
    76 #define ARPOP_REQUEST  1
    77 
    78 /** REPLY operation code. */
    79 #define ARPOP_REPLY  2
    80 
    81 /*@}*/
    82 
    83 /** Type definition of an ARP protocol header.
    84  * @see arp_header
    85  */
    86 typedef struct arp_header arp_header_t;
    87 
    88 /** ARP protocol header. */
    89 struct arp_header {
    90         /**
    91          * Hardware type identifier.
    92          * @see hardware.h
    93          */
    94         uint16_t hardware;
    95        
    96         /** Protocol identifier. */
    97         uint16_t protocol;
    98         /** Hardware address length in bytes. */
    99         uint8_t hardware_length;
    100         /** Protocol address length in bytes. */
    101         uint8_t protocol_length;
    102        
    103         /**
    104          * ARP packet type.
    105          * @see arp_oc.h
    106          */
    107         uint16_t operation;
    108 } __attribute__ ((packed));
     75#define ARP_TRANS_WAIT  1000000
    10976
    11077/** ARP global data. */
     
    12188                trans->hw_addr = NULL;
    12289        }
    123        
    12490        fibril_condvar_broadcast(&trans->cv);
    12591}
     
    12894{
    12995        int count;
    130        
     96        arp_trans_t *trans;
     97
    13198        for (count = arp_addr_count(addresses) - 1; count >= 0; count--) {
    132                 arp_trans_t *trans = arp_addr_items_get_index(&addresses->values,
    133                     count);
     99                trans = arp_addr_items_get_index(&addresses->values, count);
    134100                if (trans)
    135101                        arp_clear_trans(trans);
     
    137103}
    138104
    139 /** Clear the device specific data.
    140  *
    141  * @param[in] device Device specific data.
     105
     106/** Clears the device specific data.
     107 *
     108 * @param[in] device    The device specific data.
    142109 */
    143110static void arp_clear_device(arp_device_t *device)
    144111{
    145112        int count;
    146        
     113        arp_proto_t *proto;
     114
    147115        for (count = arp_protos_count(&device->protos) - 1; count >= 0;
    148116            count--) {
    149                 arp_proto_t *proto = arp_protos_get_index(&device->protos,
    150                     count);
    151                
     117                proto = arp_protos_get_index(&device->protos, count);
    152118                if (proto) {
    153119                        if (proto->addr)
    154120                                free(proto->addr);
    155                        
    156121                        if (proto->addr_data)
    157122                                free(proto->addr_data);
    158                        
    159123                        arp_clear_addr(&proto->addresses);
    160124                        arp_addr_destroy(&proto->addresses);
    161125                }
    162126        }
    163        
    164127        arp_protos_clear(&device->protos);
    165128}
     
    168131{
    169132        int count;
    170        
     133        arp_device_t *device;
     134
    171135        fibril_mutex_lock(&arp_globals.lock);
    172136        for (count = arp_cache_count(&arp_globals.cache) - 1; count >= 0;
    173137            count--) {
    174                 arp_device_t *device = arp_cache_get_index(&arp_globals.cache,
    175                     count);
    176                
     138                device = arp_cache_get_index(&arp_globals.cache, count);
    177139                if (device) {
    178140                        arp_clear_device(device);
    179141                        if (device->addr_data)
    180142                                free(device->addr_data);
    181                        
    182143                        if (device->broadcast_data)
    183144                                free(device->broadcast_data);
    184145                }
    185146        }
    186        
    187147        arp_cache_clear(&arp_globals.cache);
    188148        fibril_mutex_unlock(&arp_globals.lock);
    189        
     149        printf("Cache cleaned\n");
    190150        return EOK;
    191151}
     
    194154    services_t protocol, measured_string_t *address)
    195155{
     156        arp_device_t *device;
     157        arp_proto_t *proto;
     158        arp_trans_t *trans;
     159
    196160        fibril_mutex_lock(&arp_globals.lock);
    197        
    198         arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
     161        device = arp_cache_find(&arp_globals.cache, device_id);
    199162        if (!device) {
    200163                fibril_mutex_unlock(&arp_globals.lock);
    201164                return ENOENT;
    202165        }
    203        
    204         arp_proto_t *proto = arp_protos_find(&device->protos, protocol);
     166        proto = arp_protos_find(&device->protos, protocol);
    205167        if (!proto) {
    206168                fibril_mutex_unlock(&arp_globals.lock);
    207169                return ENOENT;
    208170        }
    209        
    210         arp_trans_t *trans = arp_addr_find(&proto->addresses, address->value,
    211             address->length);
     171        trans = arp_addr_find(&proto->addresses, address->value, address->length);
    212172        if (trans)
    213173                arp_clear_trans(trans);
    214        
    215174        arp_addr_exclude(&proto->addresses, address->value, address->length);
    216        
    217175        fibril_mutex_unlock(&arp_globals.lock);
    218176        return EOK;
    219177}
    220178
     179
    221180static int arp_clear_device_req(int arp_phone, device_id_t device_id)
    222181{
     182        arp_device_t *device;
     183
    223184        fibril_mutex_lock(&arp_globals.lock);
    224        
    225         arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
     185        device = arp_cache_find(&arp_globals.cache, device_id);
    226186        if (!device) {
    227187                fibril_mutex_unlock(&arp_globals.lock);
    228188                return ENOENT;
    229189        }
    230        
    231190        arp_clear_device(device);
    232        
     191        printf("Device %d cleared\n", device_id);
    233192        fibril_mutex_unlock(&arp_globals.lock);
    234193        return EOK;
    235194}
    236195
    237 /** Create new protocol specific data.
    238  *
    239  * Allocate and return the needed memory block as the proto parameter.
    240  *
    241  * @param[out] proto   Allocated protocol specific data.
    242  * @param[in]  service Protocol module service.
    243  * @param[in]  address Actual protocol device address.
    244  *
    245  * @return EOK on success.
    246  * @return ENOMEM if there is not enough memory left.
    247  *
     196/** Creates new protocol specific data.
     197 *
     198 * Allocates and returns the needed memory block as the proto parameter.
     199 *
     200 * @param[out] proto    The allocated protocol specific data.
     201 * @param[in] service   The protocol module service.
     202 * @param[in] address   The actual protocol device address.
     203 * @return              EOK on success.
     204 * @return              ENOMEM if there is not enough memory left.
    248205 */
    249206static int arp_proto_create(arp_proto_t **proto, services_t service,
    250207    measured_string_t *address)
    251208{
     209        int rc;
     210
    252211        *proto = (arp_proto_t *) malloc(sizeof(arp_proto_t));
    253212        if (!*proto)
     
    258217        (*proto)->addr_data = address->value;
    259218       
    260         int rc = arp_addr_initialize(&(*proto)->addresses);
     219        rc = arp_addr_initialize(&(*proto)->addresses);
    261220        if (rc != EOK) {
    262221                free(*proto);
     
    267226}
    268227
    269 /** Process the received ARP packet.
    270  *
    271  * Update the source hardware address if the source entry exists or the packet
     228/** Registers the device.
     229 *
     230 * Creates new device entry in the cache or updates the protocol address if the
     231 * device with the device identifier and the driver service exists.
     232 *
     233 * @param[in] device_id The device identifier.
     234 * @param[in] service   The device driver service.
     235 * @param[in] protocol  The protocol service.
     236 * @param[in] address   The actual device protocol address.
     237 * @return              EOK on success.
     238 * @return              EEXIST if another device with the same device identifier
     239 *                      and different driver service exists.
     240 * @return              ENOMEM if there is not enough memory left.
     241 * @return              Other error codes as defined for the
     242 *                      measured_strings_return() function.
     243 */
     244static int arp_device_message(device_id_t device_id, services_t service,
     245    services_t protocol, measured_string_t *address)
     246{
     247        arp_device_t *device;
     248        arp_proto_t *proto;
     249        hw_type_t hardware;
     250        int index;
     251        int rc;
     252
     253        fibril_mutex_lock(&arp_globals.lock);
     254
     255        /* An existing device? */
     256        device = arp_cache_find(&arp_globals.cache, device_id);
     257
     258        if (device) {
     259                if (device->service != service) {
     260                        printf("Device %d already exists\n", device->device_id);
     261                        fibril_mutex_unlock(&arp_globals.lock);
     262                        return EEXIST;
     263                }
     264                proto = arp_protos_find(&device->protos, protocol);
     265                if (proto) {
     266                        free(proto->addr);
     267                        free(proto->addr_data);
     268                        proto->addr = address;
     269                        proto->addr_data = address->value;
     270                } else {
     271                        rc = arp_proto_create(&proto, protocol, address);
     272                        if (rc != EOK) {
     273                                fibril_mutex_unlock(&arp_globals.lock);
     274                                return rc;
     275                        }
     276                        index = arp_protos_add(&device->protos, proto->service,
     277                            proto);
     278                        if (index < 0) {
     279                                fibril_mutex_unlock(&arp_globals.lock);
     280                                free(proto);
     281                                return index;
     282                        }
     283                        printf("New protocol added:\n\tdevice id\t= "
     284                            "%d\n\tproto\t= %d", device_id, protocol);
     285                }
     286        } else {
     287                hardware = hardware_map(service);
     288                if (!hardware)
     289                        return ENOENT;
     290               
     291                /* Create a new device */
     292                device = (arp_device_t *) malloc(sizeof(arp_device_t));
     293                if (!device) {
     294                        fibril_mutex_unlock(&arp_globals.lock);
     295                        return ENOMEM;
     296                }
     297                device->hardware = hardware;
     298                device->device_id = device_id;
     299                rc = arp_protos_initialize(&device->protos);
     300                if (rc != EOK) {
     301                        fibril_mutex_unlock(&arp_globals.lock);
     302                        free(device);
     303                        return rc;
     304                }
     305                rc = arp_proto_create(&proto, protocol, address);
     306                if (rc != EOK) {
     307                        fibril_mutex_unlock(&arp_globals.lock);
     308                        free(device);
     309                        return rc;
     310                }
     311                index = arp_protos_add(&device->protos, proto->service, proto);
     312                if (index < 0) {
     313                        fibril_mutex_unlock(&arp_globals.lock);
     314                        arp_protos_destroy(&device->protos);
     315                        free(device);
     316                        return index;
     317                }
     318                device->service = service;
     319               
     320                /* Bind the new one */
     321                device->phone = nil_bind_service(device->service,
     322                    (sysarg_t) device->device_id, SERVICE_ARP,
     323                    arp_globals.client_connection);
     324                if (device->phone < 0) {
     325                        fibril_mutex_unlock(&arp_globals.lock);
     326                        arp_protos_destroy(&device->protos);
     327                        free(device);
     328                        return EREFUSED;
     329                }
     330               
     331                /* Get packet dimensions */
     332                rc = nil_packet_size_req(device->phone, device_id,
     333                    &device->packet_dimension);
     334                if (rc != EOK) {
     335                        fibril_mutex_unlock(&arp_globals.lock);
     336                        arp_protos_destroy(&device->protos);
     337                        free(device);
     338                        return rc;
     339                }
     340               
     341                /* Get hardware address */
     342                rc = nil_get_addr_req(device->phone, device_id, &device->addr,
     343                    &device->addr_data);
     344                if (rc != EOK) {
     345                        fibril_mutex_unlock(&arp_globals.lock);
     346                        arp_protos_destroy(&device->protos);
     347                        free(device);
     348                        return rc;
     349                }
     350               
     351                /* Get broadcast address */
     352                rc = nil_get_broadcast_addr_req(device->phone, device_id,
     353                    &device->broadcast_addr, &device->broadcast_data);
     354                if (rc != EOK) {
     355                        fibril_mutex_unlock(&arp_globals.lock);
     356                        free(device->addr);
     357                        free(device->addr_data);
     358                        arp_protos_destroy(&device->protos);
     359                        free(device);
     360                        return rc;
     361                }
     362               
     363                rc = arp_cache_add(&arp_globals.cache, device->device_id,
     364                    device);
     365                if (rc != EOK) {
     366                        fibril_mutex_unlock(&arp_globals.lock);
     367                        free(device->addr);
     368                        free(device->addr_data);
     369                        free(device->broadcast_addr);
     370                        free(device->broadcast_data);
     371                        arp_protos_destroy(&device->protos);
     372                        free(device);
     373                        return rc;
     374                }
     375                printf("%s: Device registered (id: %d, type: 0x%x, service: %d,"
     376                    " proto: %d)\n", NAME, device->device_id, device->hardware,
     377                    device->service, protocol);
     378        }
     379        fibril_mutex_unlock(&arp_globals.lock);
     380       
     381        return EOK;
     382}
     383
     384/** Initializes the ARP module.
     385 *
     386 *  @param[in] client_connection The client connection processing function.
     387 *                      The module skeleton propagates its own one.
     388 *  @return             EOK on success.
     389 *  @return             ENOMEM if there is not enough memory left.
     390 */
     391int arp_initialize(async_client_conn_t client_connection)
     392{
     393        int rc;
     394
     395        fibril_mutex_initialize(&arp_globals.lock);
     396        fibril_mutex_lock(&arp_globals.lock);
     397        arp_globals.client_connection = client_connection;
     398        rc = arp_cache_initialize(&arp_globals.cache);
     399        fibril_mutex_unlock(&arp_globals.lock);
     400       
     401        return rc;
     402}
     403
     404/** Updates the device content length according to the new MTU value.
     405 *
     406 * @param[in] device_id The device identifier.
     407 * @param[in] mtu       The new mtu value.
     408 * @return              ENOENT if device is not found.
     409 * @return              EOK on success.
     410 */
     411static int arp_mtu_changed_message(device_id_t device_id, size_t mtu)
     412{
     413        arp_device_t *device;
     414
     415        fibril_mutex_lock(&arp_globals.lock);
     416        device = arp_cache_find(&arp_globals.cache, device_id);
     417        if (!device) {
     418                fibril_mutex_unlock(&arp_globals.lock);
     419                return ENOENT;
     420        }
     421        device->packet_dimension.content = mtu;
     422        fibril_mutex_unlock(&arp_globals.lock);
     423        printf("arp - device %d changed mtu to %zu\n\n", device_id, mtu);
     424        return EOK;
     425}
     426
     427/** Processes the received ARP packet.
     428 *
     429 * Updates the source hardware address if the source entry exists or the packet
    272430 * is targeted to my protocol address.
    273  *
    274  * Respond to the ARP request if the packet is the ARP request and is
     431 * Responses to the ARP request if the packet is the ARP request and is
    275432 * targeted to my address.
    276433 *
    277  * @param[in]     device_id Source device identifier.
    278  * @param[in,out] packet    Received packet.
    279  *
    280  * @return EOK on success and the packet is no longer needed.
    281  * @return One on success and the packet has been reused.
    282  * @return EINVAL if the packet is too small to carry an ARP
    283  *         packet.
    284  * @return EINVAL if the received address lengths differs from
    285  *         the registered values.
    286  * @return ENOENT if the device is not found in the cache.
    287  * @return ENOENT if the protocol for the device is not found in
    288  *         the cache.
    289  * @return ENOMEM if there is not enough memory left.
    290  *
     434 * @param[in] device_id The source device identifier.
     435 * @param[in,out] packet The received packet.
     436 * @return              EOK on success and the packet is no longer needed.
     437 * @return              One on success and the packet has been reused.
     438 * @return              EINVAL if the packet is too small to carry an ARP
     439 *                      packet.
     440 * @return              EINVAL if the received address lengths differs from
     441 *                      the registered values.
     442 * @return              ENOENT if the device is not found in the cache.
     443 * @return              ENOENT if the protocol for the device is not found in
     444 *                      the cache.
     445 * @return              ENOMEM if there is not enough memory left.
    291446 */
    292447static int arp_receive_message(device_id_t device_id, packet_t *packet)
    293448{
     449        size_t length;
     450        arp_header_t *header;
     451        arp_device_t *device;
     452        arp_proto_t *proto;
     453        arp_trans_t *trans;
     454        uint8_t *src_hw;
     455        uint8_t *src_proto;
     456        uint8_t *des_hw;
     457        uint8_t *des_proto;
    294458        int rc;
    295459       
    296         size_t length = packet_get_data_length(packet);
     460        length = packet_get_data_length(packet);
    297461        if (length <= sizeof(arp_header_t))
    298462                return EINVAL;
    299        
    300         arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
     463
     464        device = arp_cache_find(&arp_globals.cache, device_id);
    301465        if (!device)
    302466                return ENOENT;
    303        
    304         arp_header_t *header = (arp_header_t *) packet_get_data(packet);
     467
     468        header = (arp_header_t *) packet_get_data(packet);
    305469        if ((ntohs(header->hardware) != device->hardware) ||
    306470            (length < sizeof(arp_header_t) + header->hardware_length * 2U +
     
    308472                return EINVAL;
    309473        }
    310        
    311         arp_proto_t *proto = arp_protos_find(&device->protos,
     474
     475        proto = arp_protos_find(&device->protos,
    312476            protocol_unmap(device->service, ntohs(header->protocol)));
    313477        if (!proto)
    314478                return ENOENT;
    315        
    316         uint8_t *src_hw = ((uint8_t *) header) + sizeof(arp_header_t);
    317         uint8_t *src_proto = src_hw + header->hardware_length;
    318         uint8_t *des_hw = src_proto + header->protocol_length;
    319         uint8_t *des_proto = des_hw + header->hardware_length;
    320        
    321         arp_trans_t *trans = arp_addr_find(&proto->addresses, src_proto,
     479
     480        src_hw = ((uint8_t *) header) + sizeof(arp_header_t);
     481        src_proto = src_hw + header->hardware_length;
     482        des_hw = src_proto + header->protocol_length;
     483        des_proto = des_hw + header->hardware_length;
     484        trans = arp_addr_find(&proto->addresses, src_proto,
    322485            header->protocol_length);
    323        
    324         if ((trans) && (trans->hw_addr)) {
    325                 /* Translation exists */
     486        /* Exists? */
     487        if (trans && trans->hw_addr) {
    326488                if (trans->hw_addr->length != header->hardware_length)
    327489                        return EINVAL;
    328                
    329490                memcpy(trans->hw_addr->value, src_hw, trans->hw_addr->length);
    330491        }
    331        
    332492        /* Is my protocol address? */
    333493        if (proto->addr->length != header->protocol_length)
     
    335495       
    336496        if (!bcmp(proto->addr->value, des_proto, proto->addr->length)) {
     497                /* Not already updated? */
    337498                if (!trans) {
    338                         /* Update the translation */
    339499                        trans = (arp_trans_t *) malloc(sizeof(arp_trans_t));
    340500                        if (!trans)
    341501                                return ENOMEM;
    342                        
    343502                        trans->hw_addr = NULL;
    344503                        fibril_condvar_initialize(&trans->cv);
     
    350509                        }
    351510                }
    352                
    353511                if (!trans->hw_addr) {
    354512                        trans->hw_addr = measured_string_create_bulk(src_hw,
     
    360518                        fibril_condvar_broadcast(&trans->cv);
    361519                }
    362                
    363520                if (ntohs(header->operation) == ARPOP_REQUEST) {
    364521                        header->operation = htons(ARPOP_REPLY);
     
    381538                }
    382539        }
    383        
     540
    384541        return EOK;
    385542}
    386543
    387 /** Update the device content length according to the new MTU value.
    388  *
    389  * @param[in] device_id Device identifier.
    390  * @param[in] mtu       New MTU value.
    391  *
    392  * @return ENOENT if device is not found.
    393  * @return EOK on success.
    394  *
    395  */
    396 static int arp_mtu_changed_message(device_id_t device_id, size_t mtu)
    397 {
    398         fibril_mutex_lock(&arp_globals.lock);
    399        
    400         arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
    401         if (!device) {
    402                 fibril_mutex_unlock(&arp_globals.lock);
     544
     545/** Returns the hardware address for the given protocol address.
     546 *
     547 * Sends the ARP request packet if the hardware address is not found in the
     548 * cache.
     549 *
     550 * @param[in] device_id The device identifier.
     551 * @param[in] protocol  The protocol service.
     552 * @param[in] target    The target protocol address.
     553 * @param[out] translation Where the hardware address of the target is stored.
     554 * @return              EOK on success.
     555 * @return              EAGAIN if the caller should try again.
     556 * @return              Other error codes in case of error.
     557 */
     558static int
     559arp_translate_message(device_id_t device_id, services_t protocol,
     560    measured_string_t *target, measured_string_t **translation)
     561{
     562        arp_device_t *device;
     563        arp_proto_t *proto;
     564        arp_trans_t *trans;
     565        size_t length;
     566        packet_t *packet;
     567        arp_header_t *header;
     568        bool retry = false;
     569        int rc;
     570
     571restart:
     572        if (!target || !translation)
     573                return EBADMEM;
     574
     575        device = arp_cache_find(&arp_globals.cache, device_id);
     576        if (!device)
    403577                return ENOENT;
    404         }
    405        
    406         device->packet_dimension.content = mtu;
    407        
    408         fibril_mutex_unlock(&arp_globals.lock);
    409        
    410         printf("%s: Device %d changed MTU to %zu\n", NAME, device_id, mtu);
    411        
    412         return EOK;
    413 }
    414 
    415 /** Process IPC messages from the registered device driver modules
    416  *
    417  * @param[in]     iid   Message identifier.
    418  * @param[in,out] icall Message parameters.
    419  *
    420  */
    421 static void arp_receiver(ipc_callid_t iid, ipc_call_t *icall)
    422 {
    423         packet_t *packet;
    424         int rc;
    425        
    426         while (true) {
    427                 switch (IPC_GET_IMETHOD(*icall)) {
    428                 case NET_IL_DEVICE_STATE:
    429                         /* Do nothing - keep the cache */
    430                         ipc_answer_0(iid, (sysarg_t) EOK);
    431                         break;
    432                
    433                 case NET_IL_RECEIVED:
    434                         rc = packet_translate_remote(arp_globals.net_phone, &packet,
    435                             IPC_GET_PACKET(*icall));
    436                         if (rc == EOK) {
    437                                 fibril_mutex_lock(&arp_globals.lock);
    438                                 do {
    439                                         packet_t *next = pq_detach(packet);
    440                                         rc = arp_receive_message(IPC_GET_DEVICE(*icall), packet);
    441                                         if (rc != 1) {
    442                                                 pq_release_remote(arp_globals.net_phone,
    443                                                     packet_get_id(packet));
    444                                         }
    445                                        
    446                                         packet = next;
    447                                 } while (packet);
    448                                 fibril_mutex_unlock(&arp_globals.lock);
    449                         }
    450                         ipc_answer_0(iid, (sysarg_t) rc);
    451                         break;
    452                
    453                 case NET_IL_MTU_CHANGED:
    454                         rc = arp_mtu_changed_message(IPC_GET_DEVICE(*icall),
    455                             IPC_GET_MTU(*icall));
    456                         ipc_answer_0(iid, (sysarg_t) rc);
    457                         break;
    458                
    459                 default:
    460                         ipc_answer_0(iid, (sysarg_t) ENOTSUP);
    461                 }
    462                
    463                 iid = async_get_call(icall);
    464         }
    465 }
    466 
    467 /** Register the device.
    468  *
    469  * Create new device entry in the cache or update the protocol address if the
    470  * device with the device identifier and the driver service exists.
    471  *
    472  * @param[in] device_id Device identifier.
    473  * @param[in] service   Device driver service.
    474  * @param[in] protocol  Protocol service.
    475  * @param[in] address   Actual device protocol address.
    476  *
    477  * @return EOK on success.
    478  * @return EEXIST if another device with the same device identifier
    479  *         and different driver service exists.
    480  * @return ENOMEM if there is not enough memory left.
    481  * @return Other error codes as defined for the
    482  *         measured_strings_return() function.
    483  *
    484  */
    485 static int arp_device_message(device_id_t device_id, services_t service,
    486     services_t protocol, measured_string_t *address)
    487 {
    488         int index;
    489         int rc;
    490        
    491         fibril_mutex_lock(&arp_globals.lock);
    492        
    493         /* An existing device? */
    494         arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
    495         if (device) {
    496                 if (device->service != service) {
    497                         printf("%s: Device %d already exists\n", NAME,
    498                             device->device_id);
    499                         fibril_mutex_unlock(&arp_globals.lock);
    500                         return EEXIST;
    501                 }
    502                
    503                 arp_proto_t *proto = arp_protos_find(&device->protos, protocol);
    504                 if (proto) {
    505                         free(proto->addr);
    506                         free(proto->addr_data);
    507                         proto->addr = address;
    508                         proto->addr_data = address->value;
    509                 } else {
    510                         rc = arp_proto_create(&proto, protocol, address);
    511                         if (rc != EOK) {
    512                                 fibril_mutex_unlock(&arp_globals.lock);
    513                                 return rc;
    514                         }
    515                        
    516                         index = arp_protos_add(&device->protos, proto->service,
    517                             proto);
    518                         if (index < 0) {
    519                                 fibril_mutex_unlock(&arp_globals.lock);
    520                                 free(proto);
    521                                 return index;
    522                         }
    523                        
    524                         printf("%s: New protocol added (id: %d, proto: %d)\n", NAME,
    525                             device_id, protocol);
    526                 }
    527         } else {
    528                 hw_type_t hardware = hardware_map(service);
    529                 if (!hardware)
     578
     579        proto = arp_protos_find(&device->protos, protocol);
     580        if (!proto || (proto->addr->length != target->length))
     581                return ENOENT;
     582
     583        trans = arp_addr_find(&proto->addresses, target->value, target->length);
     584        if (trans) {
     585                if (trans->hw_addr) {
     586                        *translation = trans->hw_addr;
     587                        return EOK;
     588                }
     589                if (retry)
     590                        return EAGAIN;
     591                rc = fibril_condvar_wait_timeout(&trans->cv, &arp_globals.lock,
     592                    ARP_TRANS_WAIT);
     593                if (rc == ETIMEOUT)
    530594                        return ENOENT;
    531                
    532                 /* Create new device */
    533                 device = (arp_device_t *) malloc(sizeof(arp_device_t));
    534                 if (!device) {
    535                         fibril_mutex_unlock(&arp_globals.lock);
    536                         return ENOMEM;
    537                 }
    538                
    539                 device->hardware = hardware;
    540                 device->device_id = device_id;
    541                 rc = arp_protos_initialize(&device->protos);
    542                 if (rc != EOK) {
    543                         fibril_mutex_unlock(&arp_globals.lock);
    544                         free(device);
    545                         return rc;
    546                 }
    547                
    548                 arp_proto_t *proto;
    549                 rc = arp_proto_create(&proto, protocol, address);
    550                 if (rc != EOK) {
    551                         fibril_mutex_unlock(&arp_globals.lock);
    552                         free(device);
    553                         return rc;
    554                 }
    555                
    556                 index = arp_protos_add(&device->protos, proto->service, proto);
    557                 if (index < 0) {
    558                         fibril_mutex_unlock(&arp_globals.lock);
    559                         arp_protos_destroy(&device->protos);
    560                         free(device);
    561                         return index;
    562                 }
    563                
    564                 device->service = service;
    565                
    566                 /* Bind */
    567                 device->phone = nil_bind_service(device->service,
    568                     (sysarg_t) device->device_id, SERVICE_ARP,
    569                     arp_receiver);
    570                 if (device->phone < 0) {
    571                         fibril_mutex_unlock(&arp_globals.lock);
    572                         arp_protos_destroy(&device->protos);
    573                         free(device);
    574                         return EREFUSED;
    575                 }
    576                
    577                 /* Get packet dimensions */
    578                 rc = nil_packet_size_req(device->phone, device_id,
    579                     &device->packet_dimension);
    580                 if (rc != EOK) {
    581                         fibril_mutex_unlock(&arp_globals.lock);
    582                         arp_protos_destroy(&device->protos);
    583                         free(device);
    584                         return rc;
    585                 }
    586                
    587                 /* Get hardware address */
    588                 rc = nil_get_addr_req(device->phone, device_id, &device->addr,
    589                     &device->addr_data);
    590                 if (rc != EOK) {
    591                         fibril_mutex_unlock(&arp_globals.lock);
    592                         arp_protos_destroy(&device->protos);
    593                         free(device);
    594                         return rc;
    595                 }
    596                
    597                 /* Get broadcast address */
    598                 rc = nil_get_broadcast_addr_req(device->phone, device_id,
    599                     &device->broadcast_addr, &device->broadcast_data);
    600                 if (rc != EOK) {
    601                         fibril_mutex_unlock(&arp_globals.lock);
    602                         free(device->addr);
    603                         free(device->addr_data);
    604                         arp_protos_destroy(&device->protos);
    605                         free(device);
    606                         return rc;
    607                 }
    608                
    609                 rc = arp_cache_add(&arp_globals.cache, device->device_id,
    610                     device);
    611                 if (rc != EOK) {
    612                         fibril_mutex_unlock(&arp_globals.lock);
    613                         free(device->addr);
    614                         free(device->addr_data);
    615                         free(device->broadcast_addr);
    616                         free(device->broadcast_data);
    617                         arp_protos_destroy(&device->protos);
    618                         free(device);
    619                         return rc;
    620                 }
    621                 printf("%s: Device registered (id: %d, type: 0x%x, service: %d,"
    622                     " proto: %d)\n", NAME, device->device_id, device->hardware,
    623                     device->service, protocol);
    624         }
    625        
    626         fibril_mutex_unlock(&arp_globals.lock);
    627         return EOK;
    628 }
    629 
    630 int il_initialize(int net_phone)
    631 {
    632         fibril_mutex_initialize(&arp_globals.lock);
    633        
    634         fibril_mutex_lock(&arp_globals.lock);
    635         arp_globals.net_phone = net_phone;
    636         int rc = arp_cache_initialize(&arp_globals.cache);
    637         fibril_mutex_unlock(&arp_globals.lock);
    638        
    639         return rc;
    640 }
    641 
    642 static int arp_send_request(device_id_t device_id, services_t protocol,
    643     measured_string_t *target, arp_device_t *device, arp_proto_t *proto)
    644 {
     595                retry = true;
     596                goto restart;
     597        }
     598        if (retry)
     599                return EAGAIN;
     600
    645601        /* ARP packet content size = header + (address + translation) * 2 */
    646         size_t length = 8 + 2 * (proto->addr->length + device->addr->length);
     602        length = 8 + 2 * (proto->addr->length + device->addr->length);
    647603        if (length > device->packet_dimension.content)
    648604                return ELIMIT;
    649        
    650         packet_t *packet = packet_get_4_remote(arp_globals.net_phone,
     605
     606        packet = packet_get_4_remote(arp_globals.net_phone,
    651607            device->packet_dimension.addr_len, device->packet_dimension.prefix,
    652608            length, device->packet_dimension.suffix);
    653609        if (!packet)
    654610                return ENOMEM;
    655        
    656         arp_header_t *header = (arp_header_t *) packet_suffix(packet, length);
     611
     612        header = (arp_header_t *) packet_suffix(packet, length);
    657613        if (!header) {
    658614                pq_release_remote(arp_globals.net_phone, packet_get_id(packet));
    659615                return ENOMEM;
    660616        }
    661        
     617
    662618        header->hardware = htons(device->hardware);
    663619        header->hardware_length = (uint8_t) device->addr->length;
     
    665621        header->protocol_length = (uint8_t) proto->addr->length;
    666622        header->operation = htons(ARPOP_REQUEST);
    667        
    668623        length = sizeof(arp_header_t);
    669        
    670624        memcpy(((uint8_t *) header) + length, device->addr->value,
    671625            device->addr->length);
     
    677631        length += device->addr->length;
    678632        memcpy(((uint8_t *) header) + length, target->value, target->length);
    679        
    680         int rc = packet_set_addr(packet, (uint8_t *) device->addr->value,
     633
     634        rc = packet_set_addr(packet, (uint8_t *) device->addr->value,
    681635            (uint8_t *) device->broadcast_addr->value, device->addr->length);
    682636        if (rc != EOK) {
     
    684638                return rc;
    685639        }
    686        
     640
    687641        nil_send_msg(device->phone, device_id, packet, SERVICE_ARP);
    688         return EOK;
    689 }
    690 
    691 /** Return the hardware address for the given protocol address.
    692  *
    693  * Send the ARP request packet if the hardware address is not found in the
    694  * cache.
    695  *
    696  * @param[in]  device_id   Device identifier.
    697  * @param[in]  protocol    Protocol service.
    698  * @param[in]  target      Target protocol address.
    699  * @param[out] translation Where the hardware address of the target is stored.
    700  *
    701  * @return EOK on success.
    702  * @return EAGAIN if the caller should try again.
    703  * @return Other error codes in case of error.
    704  *
    705  */
    706 static int arp_translate_message(device_id_t device_id, services_t protocol,
    707     measured_string_t *target, measured_string_t **translation)
    708 {
    709         bool retry = false;
    710         int rc;
    711 
    712         assert(fibril_mutex_is_locked(&arp_globals.lock));
    713        
    714 restart:
    715         if ((!target) || (!translation))
    716                 return EBADMEM;
    717        
    718         arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
    719         if (!device)
    720                 return ENOENT;
    721        
    722         arp_proto_t *proto = arp_protos_find(&device->protos, protocol);
    723         if ((!proto) || (proto->addr->length != target->length))
    724                 return ENOENT;
    725        
    726         arp_trans_t *trans = arp_addr_find(&proto->addresses, target->value,
    727             target->length);
    728         if (trans) {
    729                 if (trans->hw_addr) {
    730                         /* The translation is in place. */
    731                         *translation = trans->hw_addr;
    732                         return EOK;
    733                 }
    734                
    735                 if (retry) {
    736                         /*
    737                          * We may get here as a result of being signalled for
    738                          * some reason while waiting for the translation (e.g.
    739                          * translation becoming available, record being removed
    740                          * from the table) and then losing the race for
    741                          * the arp_globals.lock with someone else who modified
    742                          * the table.
    743                          *
    744                          * Remove the incomplete record so that it is possible
    745                          * to make new ARP requests.
    746                          */
    747                         arp_clear_trans(trans);
    748                         arp_addr_exclude(&proto->addresses, target->value,
    749                             target->length);
    750                         return EAGAIN;
    751                 }
    752                
    753                 /*
    754                  * We are a random passer-by who merely joins an already waiting
    755                  * fibril in waiting for the translation.
    756                  */
    757                 rc = fibril_condvar_wait_timeout(&trans->cv, &arp_globals.lock,
    758                     ARP_TRANS_WAIT);
    759                 if (rc == ETIMEOUT)
    760                         return ENOENT;
    761                
    762                 /*
    763                  * Need to recheck because we did not hold the lock while
    764                  * sleeping on the condition variable.
    765                  */
    766                 retry = true;
    767                 goto restart;
    768         }
    769        
    770         if (retry)
    771                 return EAGAIN;
    772 
    773         /*
    774          * We are under the protection of arp_globals.lock, so we can afford to
    775          * first send the ARP request and then insert an incomplete ARP record.
    776          * The incomplete record is used to tell any other potential waiter
    777          * that this fibril has already sent the request and that it is waiting
    778          * for the answer. Lastly, any fibril which sees the incomplete request
    779          * can perform a timed wait on its condition variable to wait for the
    780          * ARP reply to arrive.
    781          */
    782 
    783         rc = arp_send_request(device_id, protocol, target, device, proto);
    784         if (rc != EOK)
    785                 return rc;
    786        
     642
    787643        trans = (arp_trans_t *) malloc(sizeof(arp_trans_t));
    788644        if (!trans)
    789645                return ENOMEM;
    790        
    791646        trans->hw_addr = NULL;
    792647        fibril_condvar_initialize(&trans->cv);
    793        
    794648        rc = arp_addr_add(&proto->addresses, target->value, target->length,
    795649            trans);
     
    801655        rc = fibril_condvar_wait_timeout(&trans->cv, &arp_globals.lock,
    802656            ARP_TRANS_WAIT);
    803         if (rc == ETIMEOUT) {
    804                 /*
    805                  * Remove the incomplete record so that it is possible to make
    806                  * new ARP requests.
    807                  */
    808                 arp_clear_trans(trans);
    809                 arp_addr_exclude(&proto->addresses, target->value,
    810                     target->length);
     657        if (rc == ETIMEOUT)
    811658                return ENOENT;
    812         }
    813        
    814         /*
    815          * We need to recheck that the translation has indeed become available,
    816          * because we dropped the arp_globals.lock while sleeping on the
    817          * condition variable and someone else might have e.g. removed the
    818          * translation before we managed to lock arp_globals.lock again.
    819          */
    820 
    821659        retry = true;
    822660        goto restart;
    823661}
    824662
    825 /** Process the ARP message.
    826  *
    827  * @param[in]  callid Message identifier.
    828  * @param[in]  call   Message parameters.
    829  * @param[out] answer Answer.
    830  * @param[out] count  Number of arguments of the answer.
    831  *
    832  * @return EOK on success.
    833  * @return ENOTSUP if the message is not known.
     663
     664/** Processes the ARP message.
     665 *
     666 * @param[in] callid    The message identifier.
     667 * @param[in] call      The message parameters.
     668 * @param[out] answer   The message answer parameters.
     669 * @param[out] answer_count The last parameter for the actual answer in the
     670 *                      answer parameter.
     671 * @return              EOK on success.
     672 * @return              ENOTSUP if the message is not known.
    834673 *
    835674 * @see arp_interface.h
    836675 * @see IS_NET_ARP_MESSAGE()
    837  *
    838  */
    839 int il_module_message(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer,
    840     size_t *count)
     676 */
     677int
     678arp_message_standalone(ipc_callid_t callid, ipc_call_t *call,
     679    ipc_call_t *answer, size_t *answer_count)
    841680{
    842681        measured_string_t *address;
    843682        measured_string_t *translation;
    844683        uint8_t *data;
     684        packet_t *packet;
     685        packet_t *next;
    845686        int rc;
    846687       
    847         *count = 0;
     688        *answer_count = 0;
    848689        switch (IPC_GET_IMETHOD(*call)) {
    849690        case IPC_M_PHONE_HUNGUP:
     
    861702                        free(data);
    862703                }
    863                
    864704                return rc;
    865705       
     
    874714                free(address);
    875715                free(data);
    876                
    877716                if (rc != EOK) {
    878717                        fibril_mutex_unlock(&arp_globals.lock);
    879718                        return rc;
    880719                }
    881                
    882720                if (!translation) {
    883721                        fibril_mutex_unlock(&arp_globals.lock);
    884722                        return ENOENT;
    885723                }
    886                
    887724                rc = measured_strings_reply(translation, 1);
    888725                fibril_mutex_unlock(&arp_globals.lock);
    889726                return rc;
    890        
     727
    891728        case NET_ARP_CLEAR_DEVICE:
    892729                return arp_clear_device_req(0, IPC_GET_DEVICE(*call));
    893        
     730
    894731        case NET_ARP_CLEAR_ADDRESS:
    895732                rc = measured_strings_receive(&address, &data, 1);
     
    905742        case NET_ARP_CLEAN_CACHE:
    906743                return arp_clean_cache_req(0);
     744       
     745        case NET_IL_DEVICE_STATE:
     746                /* Do nothing - keep the cache */
     747                return EOK;
     748       
     749        case NET_IL_RECEIVED:
     750               
     751                rc = packet_translate_remote(arp_globals.net_phone, &packet,
     752                    IPC_GET_PACKET(*call));
     753                if (rc != EOK)
     754                        return rc;
     755               
     756                fibril_mutex_lock(&arp_globals.lock);
     757                do {
     758                        next = pq_detach(packet);
     759                        rc = arp_receive_message(IPC_GET_DEVICE(*call), packet);
     760                        if (rc != 1) {
     761                                pq_release_remote(arp_globals.net_phone,
     762                                    packet_get_id(packet));
     763                        }
     764                        packet = next;
     765                } while (packet);
     766                fibril_mutex_unlock(&arp_globals.lock);
     767               
     768                return EOK;
     769       
     770        case NET_IL_MTU_CHANGED:
     771                return arp_mtu_changed_message(IPC_GET_DEVICE(*call),
     772                    IPC_GET_MTU(*call));
    907773        }
    908774       
     
    910776}
    911777
     778/** Default thread for new connections.
     779 *
     780 * @param[in] iid       The initial message identifier.
     781 * @param[in] icall     The initial message call structure.
     782 */
     783static void il_client_connection(ipc_callid_t iid, ipc_call_t *icall)
     784{
     785        /*
     786         * Accept the connection
     787         *  - Answer the first IPC_M_CONNECT_ME_TO call.
     788         */
     789        ipc_answer_0(iid, EOK);
     790       
     791        while (true) {
     792                ipc_call_t answer;
     793                size_t count;
     794               
     795                /* Clear the answer structure */
     796                refresh_answer(&answer, &count);
     797               
     798                /* Fetch the next message */
     799                ipc_call_t call;
     800                ipc_callid_t callid = async_get_call(&call);
     801               
     802                /* Process the message */
     803                int res = il_module_message_standalone(callid, &call, &answer,
     804                    &count);
     805               
     806                /*
     807                 * End if told to either by the message or the processing
     808                 * result.
     809                 */
     810                if ((IPC_GET_IMETHOD(call) == IPC_M_PHONE_HUNGUP) ||
     811                    (res == EHANGUP))
     812                        return;
     813               
     814                /* Answer the message */
     815                answer_call(callid, res, &answer, count);
     816        }
     817}
     818
     819/** Starts the module.
     820 *
     821 * @return              EOK on success.
     822 * @return              Other error codes as defined for each specific module
     823 *                      start function.
     824 */
    912825int main(int argc, char *argv[])
    913826{
     827        int rc;
     828       
    914829        /* Start the module */
    915         return il_module_start(SERVICE_ARP);
     830        rc = il_module_start_standalone(il_client_connection);
     831        return rc;
    916832}
    917833
    918834/** @}
    919835 */
     836
Note: See TracChangeset for help on using the changeset viewer.