Ignore:
File:
1 edited

Legend:

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

    r797b704 r7837101  
    3535 * @see arp.h
    3636 */
     37
     38#include "arp.h"
     39#include "arp_header.h"
     40#include "arp_oc.h"
     41#include "arp_module.h"
    3742
    3843#include <async.h>
     
    4954#include <ipc/arp.h>
    5055#include <ipc/il.h>
    51 #include <ipc/nil.h>
    5256#include <byteorder.h>
    5357#include <errno.h>
     58
    5459#include <net/modules.h>
    5560#include <net/device.h>
    5661#include <net/packet.h>
    57 #include <nil_remote.h>
     62
     63#include <nil_interface.h>
    5864#include <protocol_map.h>
    5965#include <packet_client.h>
    6066#include <packet_remote.h>
    61 #include <il_remote.h>
    62 #include <il_skel.h>
    63 #include "arp.h"
     67#include <il_interface.h>
     68#include <il_local.h>
     69
    6470
    6571/** ARP module name. */
     
    6773
    6874/** Number of microseconds to wait for an ARP reply. */
    69 #define ARP_TRANS_WAIT  1000000
    70 
    71 /** @name ARP operation codes definitions */
    72 /*@{*/
    73 
    74 /** REQUEST operation code. */
    75 #define ARPOP_REQUEST  1
    76 
    77 /** REPLY operation code. */
    78 #define ARPOP_REPLY  2
    79 
    80 /*@}*/
    81 
    82 /** Type definition of an ARP protocol header.
    83  * @see arp_header
    84  */
    85 typedef struct arp_header arp_header_t;
    86 
    87 /** ARP protocol header. */
    88 struct arp_header {
    89         /**
    90          * Hardware type identifier.
    91          * @see hardware.h
    92          */
    93         uint16_t hardware;
    94        
    95         /** Protocol identifier. */
    96         uint16_t protocol;
    97         /** Hardware address length in bytes. */
    98         uint8_t hardware_length;
    99         /** Protocol address length in bytes. */
    100         uint8_t protocol_length;
    101        
    102         /**
    103          * ARP packet type.
    104          * @see arp_oc.h
    105          */
    106         uint16_t operation;
    107 } __attribute__ ((packed));
     75#define ARP_TRANS_WAIT  1000000
    10876
    10977/** ARP global data. */
     
    12088                trans->hw_addr = NULL;
    12189        }
    122        
    12390        fibril_condvar_broadcast(&trans->cv);
    12491}
     
    12794{
    12895        int count;
    129        
     96        arp_trans_t *trans;
     97
    13098        for (count = arp_addr_count(addresses) - 1; count >= 0; count--) {
    131                 arp_trans_t *trans = arp_addr_items_get_index(&addresses->values,
    132                     count);
     99                trans = arp_addr_items_get_index(&addresses->values, count);
    133100                if (trans)
    134101                        arp_clear_trans(trans);
     
    136103}
    137104
    138 /** Clear the device specific data.
    139  *
    140  * @param[in] device Device specific data.
     105
     106/** Clears the device specific data.
     107 *
     108 * @param[in] device    The device specific data.
    141109 */
    142110static void arp_clear_device(arp_device_t *device)
    143111{
    144112        int count;
    145        
     113        arp_proto_t *proto;
     114
    146115        for (count = arp_protos_count(&device->protos) - 1; count >= 0;
    147116            count--) {
    148                 arp_proto_t *proto = arp_protos_get_index(&device->protos,
    149                     count);
    150                
     117                proto = arp_protos_get_index(&device->protos, count);
    151118                if (proto) {
    152119                        if (proto->addr)
    153120                                free(proto->addr);
    154                        
    155121                        if (proto->addr_data)
    156122                                free(proto->addr_data);
    157                        
    158123                        arp_clear_addr(&proto->addresses);
    159124                        arp_addr_destroy(&proto->addresses);
    160125                }
    161126        }
    162        
    163127        arp_protos_clear(&device->protos);
    164128}
     
    167131{
    168132        int count;
    169        
     133        arp_device_t *device;
     134
    170135        fibril_mutex_lock(&arp_globals.lock);
    171136        for (count = arp_cache_count(&arp_globals.cache) - 1; count >= 0;
    172137            count--) {
    173                 arp_device_t *device = arp_cache_get_index(&arp_globals.cache,
    174                     count);
    175                
     138                device = arp_cache_get_index(&arp_globals.cache, count);
    176139                if (device) {
    177140                        arp_clear_device(device);
    178141                        if (device->addr_data)
    179142                                free(device->addr_data);
    180                        
    181143                        if (device->broadcast_data)
    182144                                free(device->broadcast_data);
    183145                }
    184146        }
    185        
    186147        arp_cache_clear(&arp_globals.cache);
    187148        fibril_mutex_unlock(&arp_globals.lock);
    188        
     149        printf("Cache cleaned\n");
    189150        return EOK;
    190151}
     
    193154    services_t protocol, measured_string_t *address)
    194155{
     156        arp_device_t *device;
     157        arp_proto_t *proto;
     158        arp_trans_t *trans;
     159
    195160        fibril_mutex_lock(&arp_globals.lock);
    196        
    197         arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
     161        device = arp_cache_find(&arp_globals.cache, device_id);
    198162        if (!device) {
    199163                fibril_mutex_unlock(&arp_globals.lock);
    200164                return ENOENT;
    201165        }
    202        
    203         arp_proto_t *proto = arp_protos_find(&device->protos, protocol);
     166        proto = arp_protos_find(&device->protos, protocol);
    204167        if (!proto) {
    205168                fibril_mutex_unlock(&arp_globals.lock);
    206169                return ENOENT;
    207170        }
    208        
    209         arp_trans_t *trans = arp_addr_find(&proto->addresses, address->value,
    210             address->length);
     171        trans = arp_addr_find(&proto->addresses, address->value, address->length);
    211172        if (trans)
    212173                arp_clear_trans(trans);
    213        
    214174        arp_addr_exclude(&proto->addresses, address->value, address->length);
    215        
    216175        fibril_mutex_unlock(&arp_globals.lock);
    217176        return EOK;
    218177}
    219178
     179
    220180static int arp_clear_device_req(int arp_phone, device_id_t device_id)
    221181{
     182        arp_device_t *device;
     183
    222184        fibril_mutex_lock(&arp_globals.lock);
    223        
    224         arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
     185        device = arp_cache_find(&arp_globals.cache, device_id);
    225186        if (!device) {
    226187                fibril_mutex_unlock(&arp_globals.lock);
    227188                return ENOENT;
    228189        }
    229        
    230190        arp_clear_device(device);
    231        
     191        printf("Device %d cleared\n", device_id);
    232192        fibril_mutex_unlock(&arp_globals.lock);
    233193        return EOK;
    234194}
    235195
    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  *
     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.
    247205 */
    248206static int arp_proto_create(arp_proto_t **proto, services_t service,
    249207    measured_string_t *address)
    250208{
     209        int rc;
     210
    251211        *proto = (arp_proto_t *) malloc(sizeof(arp_proto_t));
    252212        if (!*proto)
     
    257217        (*proto)->addr_data = address->value;
    258218       
    259         int rc = arp_addr_initialize(&(*proto)->addresses);
     219        rc = arp_addr_initialize(&(*proto)->addresses);
    260220        if (rc != EOK) {
    261221                free(*proto);
     
    266226}
    267227
    268 /** Process the received ARP packet.
    269  *
    270  * 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
    271430 * is targeted to my protocol address.
    272  *
    273  * 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
    274432 * targeted to my address.
    275433 *
    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  *
     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.
    290446 */
    291447static int arp_receive_message(device_id_t device_id, packet_t *packet)
    292448{
     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;
    293458        int rc;
    294        
    295         size_t length = packet_get_data_length(packet);
     459
     460        length = packet_get_data_length(packet);
    296461        if (length <= sizeof(arp_header_t))
    297462                return EINVAL;
    298        
    299         arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
     463
     464        device = arp_cache_find(&arp_globals.cache, device_id);
    300465        if (!device)
    301466                return ENOENT;
    302        
    303         arp_header_t *header = (arp_header_t *) packet_get_data(packet);
     467
     468        header = (arp_header_t *) packet_get_data(packet);
    304469        if ((ntohs(header->hardware) != device->hardware) ||
    305470            (length < sizeof(arp_header_t) + header->hardware_length * 2U +
     
    307472                return EINVAL;
    308473        }
    309        
    310         arp_proto_t *proto = arp_protos_find(&device->protos,
     474
     475        proto = arp_protos_find(&device->protos,
    311476            protocol_unmap(device->service, ntohs(header->protocol)));
    312477        if (!proto)
    313478                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,
     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, (char *) src_proto,
    321485            header->protocol_length);
    322        
    323         if ((trans) && (trans->hw_addr)) {
    324                 /* Translation exists */
     486        /* Exists? */
     487        if (trans && trans->hw_addr) {
    325488                if (trans->hw_addr->length != header->hardware_length)
    326489                        return EINVAL;
    327                
    328490                memcpy(trans->hw_addr->value, src_hw, trans->hw_addr->length);
    329491        }
    330        
    331492        /* Is my protocol address? */
    332493        if (proto->addr->length != header->protocol_length)
    333494                return EINVAL;
    334        
    335         if (!bcmp(proto->addr->value, des_proto, proto->addr->length)) {
     495        if (!str_lcmp(proto->addr->value, (char *) des_proto,
     496            proto->addr->length)) {
     497                /* Not already updated? */
    336498                if (!trans) {
    337                         /* Update the translation */
    338499                        trans = (arp_trans_t *) malloc(sizeof(arp_trans_t));
    339500                        if (!trans)
    340501                                return ENOMEM;
    341                        
    342502                        trans->hw_addr = NULL;
    343503                        fibril_condvar_initialize(&trans->cv);
    344                         rc = arp_addr_add(&proto->addresses, src_proto,
     504                        rc = arp_addr_add(&proto->addresses, (char *) src_proto,
    345505                            header->protocol_length, trans);
    346506                        if (rc != EOK) {
     
    349509                        }
    350510                }
    351                
    352511                if (!trans->hw_addr) {
    353                         trans->hw_addr = measured_string_create_bulk(src_hw,
    354                             header->hardware_length);
     512                        trans->hw_addr = measured_string_create_bulk(
     513                            (char *) src_hw, header->hardware_length);
    355514                        if (!trans->hw_addr)
    356515                                return ENOMEM;
    357                        
     516
    358517                        /* Notify the fibrils that wait for the translation. */
    359518                        fibril_condvar_broadcast(&trans->cv);
    360519                }
    361                
    362520                if (ntohs(header->operation) == ARPOP_REQUEST) {
    363521                        header->operation = htons(ARPOP_REPLY);
     
    380538                }
    381539        }
    382        
     540
    383541        return EOK;
    384542}
    385543
    386 /** Update the device content length according to the new MTU value.
    387  *
    388  * @param[in] device_id Device identifier.
    389  * @param[in] mtu       New MTU value.
    390  *
    391  * @return ENOENT if device is not found.
    392  * @return EOK on success.
    393  *
    394  */
    395 static int arp_mtu_changed_message(device_id_t device_id, size_t mtu)
    396 {
    397         fibril_mutex_lock(&arp_globals.lock);
    398        
    399         arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
    400         if (!device) {
    401                 fibril_mutex_unlock(&arp_globals.lock);
     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)
    402577                return ENOENT;
    403         }
    404        
    405         device->packet_dimension.content = mtu;
    406        
    407         fibril_mutex_unlock(&arp_globals.lock);
    408        
    409         printf("%s: Device %d changed MTU to %zu\n", NAME, device_id, mtu);
    410        
    411         return EOK;
    412 }
    413 
    414 /** Process IPC messages from the registered device driver modules
    415  *
    416  * @param[in]     iid   Message identifier.
    417  * @param[in,out] icall Message parameters.
    418  *
    419  */
    420 static void arp_receiver(ipc_callid_t iid, ipc_call_t *icall)
    421 {
    422         packet_t *packet;
    423         int rc;
    424        
    425         while (true) {
    426                 switch (IPC_GET_IMETHOD(*icall)) {
    427                 case NET_IL_DEVICE_STATE:
    428                         /* Do nothing - keep the cache */
    429                         ipc_answer_0(iid, (sysarg_t) EOK);
    430                         break;
    431                
    432                 case NET_IL_RECEIVED:
    433                         rc = packet_translate_remote(arp_globals.net_phone, &packet,
    434                             IPC_GET_PACKET(*icall));
    435                         if (rc == EOK) {
    436                                 fibril_mutex_lock(&arp_globals.lock);
    437                                 do {
    438                                         packet_t *next = pq_detach(packet);
    439                                         rc = arp_receive_message(IPC_GET_DEVICE(*icall), packet);
    440                                         if (rc != 1) {
    441                                                 pq_release_remote(arp_globals.net_phone,
    442                                                     packet_get_id(packet));
    443                                         }
    444                                        
    445                                         packet = next;
    446                                 } while (packet);
    447                                 fibril_mutex_unlock(&arp_globals.lock);
    448                         }
    449                         ipc_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                         ipc_answer_0(iid, (sysarg_t) rc);
    456                         break;
    457                
    458                 default:
    459                         ipc_answer_0(iid, (sysarg_t) ENOTSUP);
    460                 }
    461                
    462                 iid = async_get_call(icall);
    463         }
    464 }
    465 
    466 /** Register the device.
    467  *
    468  * Create new device entry in the cache or update the protocol address if the
    469  * device with the device identifier and the driver service exists.
    470  *
    471  * @param[in] device_id Device identifier.
    472  * @param[in] service   Device driver service.
    473  * @param[in] protocol  Protocol service.
    474  * @param[in] address   Actual device protocol address.
    475  *
    476  * @return EOK on success.
    477  * @return EEXIST if another device with the same device identifier
    478  *         and different driver service exists.
    479  * @return ENOMEM if there is not enough memory left.
    480  * @return Other error codes as defined for the
    481  *         measured_strings_return() function.
    482  *
    483  */
    484 static int arp_device_message(device_id_t device_id, services_t service,
    485     services_t protocol, measured_string_t *address)
    486 {
    487         int index;
    488         int rc;
    489        
    490         fibril_mutex_lock(&arp_globals.lock);
    491        
    492         /* An existing device? */
    493         arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
    494         if (device) {
    495                 if (device->service != service) {
    496                         printf("%s: Device %d already exists\n", NAME,
    497                             device->device_id);
    498                         fibril_mutex_unlock(&arp_globals.lock);
    499                         return EEXIST;
    500                 }
    501                
    502                 arp_proto_t *proto = arp_protos_find(&device->protos, protocol);
    503                 if (proto) {
    504                         free(proto->addr);
    505                         free(proto->addr_data);
    506                         proto->addr = address;
    507                         proto->addr_data = address->value;
    508                 } else {
    509                         rc = arp_proto_create(&proto, protocol, address);
    510                         if (rc != EOK) {
    511                                 fibril_mutex_unlock(&arp_globals.lock);
    512                                 return rc;
    513                         }
    514                        
    515                         index = arp_protos_add(&device->protos, proto->service,
    516                             proto);
    517                         if (index < 0) {
    518                                 fibril_mutex_unlock(&arp_globals.lock);
    519                                 free(proto);
    520                                 return index;
    521                         }
    522                        
    523                         printf("%s: New protocol added (id: %d, proto: %d)\n", NAME,
    524                             device_id, protocol);
    525                 }
    526         } else {
    527                 hw_type_t hardware = hardware_map(service);
    528                 if (!hardware)
     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)
    529594                        return ENOENT;
    530                
    531                 /* Create new device */
    532                 device = (arp_device_t *) malloc(sizeof(arp_device_t));
    533                 if (!device) {
    534                         fibril_mutex_unlock(&arp_globals.lock);
    535                         return ENOMEM;
    536                 }
    537                
    538                 device->hardware = hardware;
    539                 device->device_id = device_id;
    540                 rc = arp_protos_initialize(&device->protos);
    541                 if (rc != EOK) {
    542                         fibril_mutex_unlock(&arp_globals.lock);
    543                         free(device);
    544                         return rc;
    545                 }
    546                
    547                 arp_proto_t *proto;
    548                 rc = arp_proto_create(&proto, protocol, address);
    549                 if (rc != EOK) {
    550                         fibril_mutex_unlock(&arp_globals.lock);
    551                         free(device);
    552                         return rc;
    553                 }
    554                
    555                 index = arp_protos_add(&device->protos, proto->service, proto);
    556                 if (index < 0) {
    557                         fibril_mutex_unlock(&arp_globals.lock);
    558                         arp_protos_destroy(&device->protos);
    559                         free(device);
    560                         return index;
    561                 }
    562                
    563                 device->service = service;
    564                
    565                 /* Bind */
    566                 device->phone = nil_bind_service(device->service,
    567                     (sysarg_t) device->device_id, SERVICE_ARP,
    568                     arp_receiver);
    569                 if (device->phone < 0) {
    570                         fibril_mutex_unlock(&arp_globals.lock);
    571                         arp_protos_destroy(&device->protos);
    572                         free(device);
    573                         return EREFUSED;
    574                 }
    575                
    576                 /* Get packet dimensions */
    577                 rc = nil_packet_size_req(device->phone, device_id,
    578                     &device->packet_dimension);
    579                 if (rc != EOK) {
    580                         fibril_mutex_unlock(&arp_globals.lock);
    581                         arp_protos_destroy(&device->protos);
    582                         free(device);
    583                         return rc;
    584                 }
    585                
    586                 /* Get hardware address */
    587                 rc = nil_get_addr_req(device->phone, device_id, &device->addr,
    588                     &device->addr_data);
    589                 if (rc != EOK) {
    590                         fibril_mutex_unlock(&arp_globals.lock);
    591                         arp_protos_destroy(&device->protos);
    592                         free(device);
    593                         return rc;
    594                 }
    595                
    596                 /* Get broadcast address */
    597                 rc = nil_get_broadcast_addr_req(device->phone, device_id,
    598                     &device->broadcast_addr, &device->broadcast_data);
    599                 if (rc != EOK) {
    600                         fibril_mutex_unlock(&arp_globals.lock);
    601                         free(device->addr);
    602                         free(device->addr_data);
    603                         arp_protos_destroy(&device->protos);
    604                         free(device);
    605                         return rc;
    606                 }
    607                
    608                 rc = arp_cache_add(&arp_globals.cache, device->device_id,
    609                     device);
    610                 if (rc != EOK) {
    611                         fibril_mutex_unlock(&arp_globals.lock);
    612                         free(device->addr);
    613                         free(device->addr_data);
    614                         free(device->broadcast_addr);
    615                         free(device->broadcast_data);
    616                         arp_protos_destroy(&device->protos);
    617                         free(device);
    618                         return rc;
    619                 }
    620                 printf("%s: Device registered (id: %d, type: 0x%x, service: %d,"
    621                     " proto: %d)\n", NAME, device->device_id, device->hardware,
    622                     device->service, protocol);
    623         }
    624        
    625         fibril_mutex_unlock(&arp_globals.lock);
    626         return EOK;
    627 }
    628 
    629 int il_initialize(int net_phone)
    630 {
    631         fibril_mutex_initialize(&arp_globals.lock);
    632        
    633         fibril_mutex_lock(&arp_globals.lock);
    634         arp_globals.net_phone = net_phone;
    635         int rc = arp_cache_initialize(&arp_globals.cache);
    636         fibril_mutex_unlock(&arp_globals.lock);
    637        
    638         return rc;
    639 }
    640 
    641 static int arp_send_request(device_id_t device_id, services_t protocol,
    642     measured_string_t *target, arp_device_t *device, arp_proto_t *proto)
    643 {
     595                retry = true;
     596                goto restart;
     597        }
     598        if (retry)
     599                return EAGAIN;
     600
    644601        /* ARP packet content size = header + (address + translation) * 2 */
    645         size_t length = 8 + 2 * (proto->addr->length + device->addr->length);
     602        length = 8 + 2 * (proto->addr->length + device->addr->length);
    646603        if (length > device->packet_dimension.content)
    647604                return ELIMIT;
    648        
    649         packet_t *packet = packet_get_4_remote(arp_globals.net_phone,
     605
     606        packet = packet_get_4_remote(arp_globals.net_phone,
    650607            device->packet_dimension.addr_len, device->packet_dimension.prefix,
    651608            length, device->packet_dimension.suffix);
    652609        if (!packet)
    653610                return ENOMEM;
    654        
    655         arp_header_t *header = (arp_header_t *) packet_suffix(packet, length);
     611
     612        header = (arp_header_t *) packet_suffix(packet, length);
    656613        if (!header) {
    657614                pq_release_remote(arp_globals.net_phone, packet_get_id(packet));
    658615                return ENOMEM;
    659616        }
    660        
     617
    661618        header->hardware = htons(device->hardware);
    662619        header->hardware_length = (uint8_t) device->addr->length;
     
    664621        header->protocol_length = (uint8_t) proto->addr->length;
    665622        header->operation = htons(ARPOP_REQUEST);
    666        
    667623        length = sizeof(arp_header_t);
    668        
    669624        memcpy(((uint8_t *) header) + length, device->addr->value,
    670625            device->addr->length);
     
    676631        length += device->addr->length;
    677632        memcpy(((uint8_t *) header) + length, target->value, target->length);
    678        
    679         int rc = packet_set_addr(packet, (uint8_t *) device->addr->value,
     633
     634        rc = packet_set_addr(packet, (uint8_t *) device->addr->value,
    680635            (uint8_t *) device->broadcast_addr->value, device->addr->length);
    681636        if (rc != EOK) {
     
    683638                return rc;
    684639        }
    685        
     640
    686641        nil_send_msg(device->phone, device_id, packet, SERVICE_ARP);
    687         return EOK;
    688 }
    689 
    690 /** Return the hardware address for the given protocol address.
    691  *
    692  * Send the ARP request packet if the hardware address is not found in the
    693  * cache.
    694  *
    695  * @param[in]  device_id   Device identifier.
    696  * @param[in]  protocol    Protocol service.
    697  * @param[in]  target      Target protocol address.
    698  * @param[out] translation Where the hardware address of the target is stored.
    699  *
    700  * @return EOK on success.
    701  * @return EAGAIN if the caller should try again.
    702  * @return Other error codes in case of error.
    703  *
    704  */
    705 static int arp_translate_message(device_id_t device_id, services_t protocol,
    706     measured_string_t *target, measured_string_t **translation)
    707 {
    708         bool retry = false;
    709         int rc;
    710        
    711 restart:
    712         if ((!target) || (!translation))
    713                 return EBADMEM;
    714        
    715         arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
    716         if (!device)
    717                 return ENOENT;
    718        
    719         arp_proto_t *proto = arp_protos_find(&device->protos, protocol);
    720         if ((!proto) || (proto->addr->length != target->length))
    721                 return ENOENT;
    722        
    723         arp_trans_t *trans = arp_addr_find(&proto->addresses, target->value,
    724             target->length);
    725         if (trans) {
    726                 if (trans->hw_addr) {
    727                         *translation = trans->hw_addr;
    728                         return EOK;
    729                 }
    730                
    731                 if (retry) {
    732                         /* Remove the translation from the map */
    733                         arp_clear_trans(trans);
    734                         arp_addr_exclude(&proto->addresses, target->value,
    735                             target->length);
    736                         return EAGAIN;
    737                 }
    738                
    739                 rc = fibril_condvar_wait_timeout(&trans->cv, &arp_globals.lock,
    740                     ARP_TRANS_WAIT);
    741                 if (rc == ETIMEOUT)
    742                         return ENOENT;
    743                
    744                 retry = true;
    745                 goto restart;
    746         }
    747        
    748         if (retry)
    749                 return EAGAIN;
    750        
     642
    751643        trans = (arp_trans_t *) malloc(sizeof(arp_trans_t));
    752644        if (!trans)
    753645                return ENOMEM;
    754        
    755646        trans->hw_addr = NULL;
    756647        fibril_condvar_initialize(&trans->cv);
    757        
    758648        rc = arp_addr_add(&proto->addresses, target->value, target->length,
    759649            trans);
     
    763653        }
    764654       
    765         rc = arp_send_request(device_id, protocol, target, device, proto);
    766         if (rc != EOK)
    767                 return rc;
    768        
    769655        rc = fibril_condvar_wait_timeout(&trans->cv, &arp_globals.lock,
    770656            ARP_TRANS_WAIT);
    771657        if (rc == ETIMEOUT)
    772658                return ENOENT;
    773        
    774659        retry = true;
    775660        goto restart;
    776661}
    777662
    778 /** Process the ARP message.
    779  *
    780  * @param[in]  callid Message identifier.
    781  * @param[in]  call   Message parameters.
    782  * @param[out] answer Answer.
    783  * @param[out] count  Number of arguments of the answer.
    784  *
    785  * @return EOK on success.
    786  * @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.
    787673 *
    788674 * @see arp_interface.h
    789675 * @see IS_NET_ARP_MESSAGE()
    790  *
    791  */
    792 int il_module_message(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer,
    793     size_t *count)
     676 */
     677int
     678arp_message_standalone(ipc_callid_t callid, ipc_call_t *call,
     679    ipc_call_t *answer, int *answer_count)
    794680{
    795681        measured_string_t *address;
    796682        measured_string_t *translation;
    797         uint8_t *data;
     683        char *data;
     684        packet_t *packet;
     685        packet_t *next;
    798686        int rc;
    799687       
    800         *count = 0;
     688        *answer_count = 0;
    801689        switch (IPC_GET_IMETHOD(*call)) {
    802690        case IPC_M_PHONE_HUNGUP:
     
    808696                        return rc;
    809697               
    810                 rc = arp_device_message(IPC_GET_DEVICE(*call),
    811                     IPC_GET_SERVICE(*call), ARP_GET_NETIF(*call), address);
     698                rc = arp_device_message(IPC_GET_DEVICE(call),
     699                    IPC_GET_SERVICE(call), ARP_GET_NETIF(call), address);
    812700                if (rc != EOK) {
    813701                        free(address);
    814702                        free(data);
    815703                }
    816                
    817704                return rc;
    818705       
     
    823710               
    824711                fibril_mutex_lock(&arp_globals.lock);
    825                 rc = arp_translate_message(IPC_GET_DEVICE(*call),
    826                     IPC_GET_SERVICE(*call), address, &translation);
     712                rc = arp_translate_message(IPC_GET_DEVICE(call),
     713                    IPC_GET_SERVICE(call), address, &translation);
    827714                free(address);
    828715                free(data);
    829                
    830716                if (rc != EOK) {
    831717                        fibril_mutex_unlock(&arp_globals.lock);
    832718                        return rc;
    833719                }
    834                
    835720                if (!translation) {
    836721                        fibril_mutex_unlock(&arp_globals.lock);
    837722                        return ENOENT;
    838723                }
    839                
    840724                rc = measured_strings_reply(translation, 1);
    841725                fibril_mutex_unlock(&arp_globals.lock);
    842726                return rc;
    843        
     727
    844728        case NET_ARP_CLEAR_DEVICE:
    845                 return arp_clear_device_req(0, IPC_GET_DEVICE(*call));
    846        
     729                return arp_clear_device_req(0, IPC_GET_DEVICE(call));
     730
    847731        case NET_ARP_CLEAR_ADDRESS:
    848732                rc = measured_strings_receive(&address, &data, 1);
     
    850734                        return rc;
    851735               
    852                 arp_clear_address_req(0, IPC_GET_DEVICE(*call),
    853                     IPC_GET_SERVICE(*call), address);
     736                arp_clear_address_req(0, IPC_GET_DEVICE(call),
     737                    IPC_GET_SERVICE(call), address);
    854738                free(address);
    855739                free(data);
     
    858742        case NET_ARP_CLEAN_CACHE:
    859743                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                rc = packet_translate_remote(arp_globals.net_phone, &packet,
     751                    IPC_GET_PACKET(call));
     752                if (rc != EOK)
     753                        return rc;
     754               
     755                fibril_mutex_lock(&arp_globals.lock);
     756                do {
     757                        next = pq_detach(packet);
     758                        rc = arp_receive_message(IPC_GET_DEVICE(call), packet);
     759                        if (rc != 1) {
     760                                pq_release_remote(arp_globals.net_phone,
     761                                    packet_get_id(packet));
     762                        }
     763                        packet = next;
     764                } while (packet);
     765                fibril_mutex_unlock(&arp_globals.lock);
     766               
     767                return EOK;
     768       
     769        case NET_IL_MTU_CHANGED:
     770                return arp_mtu_changed_message(IPC_GET_DEVICE(call),
     771                    IPC_GET_MTU(call));
    860772        }
    861773       
     
    863775}
    864776
     777/** Default thread for new connections.
     778 *
     779 * @param[in] iid       The initial message identifier.
     780 * @param[in] icall     The initial message call structure.
     781 */
     782static void il_client_connection(ipc_callid_t iid, ipc_call_t *icall)
     783{
     784        /*
     785         * Accept the connection
     786         *  - Answer the first IPC_M_CONNECT_ME_TO call.
     787         */
     788        ipc_answer_0(iid, EOK);
     789       
     790        while (true) {
     791                ipc_call_t answer;
     792                int answer_count;
     793               
     794                /* Clear the answer structure */
     795                refresh_answer(&answer, &answer_count);
     796               
     797                /* Fetch the next message */
     798                ipc_call_t call;
     799                ipc_callid_t callid = async_get_call(&call);
     800               
     801                /* Process the message */
     802                int res = il_module_message_standalone(callid, &call, &answer,
     803                    &answer_count);
     804               
     805                /*
     806                 * End if told to either by the message or the processing
     807                 * result.
     808                 */
     809                if ((IPC_GET_IMETHOD(call) == IPC_M_PHONE_HUNGUP) ||
     810                    (res == EHANGUP))
     811                        return;
     812               
     813                /* Answer the message */
     814                answer_call(callid, res, &answer, answer_count);
     815        }
     816}
     817
     818/** Starts the module.
     819 *
     820 * @return              EOK on success.
     821 * @return              Other error codes as defined for each specific module
     822 *                      start function.
     823 */
    865824int main(int argc, char *argv[])
    866825{
     826        int rc;
     827       
    867828        /* Start the module */
    868         return il_module_start(SERVICE_ARP);
     829        rc = il_module_start_standalone(il_client_connection);
     830        return rc;
    869831}
    870832
    871833/** @}
    872834 */
     835
Note: See TracChangeset for help on using the changeset viewer.