Ignore:
File:
1 edited

Legend:

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

    rffa2c8ef r7e752b2  
    3636 */
    3737
     38#include "arp.h"
     39#include "arp_header.h"
     40#include "arp_oc.h"
     41#include "arp_module.h"
     42
    3843#include <async.h>
    3944#include <malloc.h>
    4045#include <mem.h>
    4146#include <fibril_synch.h>
    42 #include <assert.h>
    4347#include <stdio.h>
    4448#include <str.h>
    4549#include <task.h>
    4650#include <adt/measured_strings.h>
     51#include <ipc/ipc.h>
    4752#include <ipc/services.h>
    4853#include <ipc/net.h>
    4954#include <ipc/arp.h>
    5055#include <ipc/il.h>
    51 #include <ipc/nil.h>
    5256#include <byteorder.h>
    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. */
    6672#define NAME  "arp"
    6773
    68 /** Number of microseconds to wait for an ARP reply. */
    69 #define ARP_TRANS_WAIT  1000000
    70 
    71 /** @name ARP operation codes definitions */
    72 /*@{*/
    73 
    74 /** REQUEST operation code. */
    75 #define ARPOP_REQUEST  1
    76 
    77 /** REPLY operation code. */
    78 #define ARPOP_REPLY  2
    79 
    80 /*@}*/
    81 
    82 /** Type definition of an ARP protocol header.
    83  * @see arp_header
    84  */
    85 typedef struct arp_header arp_header_t;
    86 
    87 /** ARP protocol header. */
    88 struct arp_header {
    89         /**
    90          * Hardware type identifier.
    91          * @see hardware.h
    92          */
    93         uint16_t hardware;
    94        
    95         /** Protocol identifier. */
    96         uint16_t protocol;
    97         /** Hardware address length in bytes. */
    98         uint8_t hardware_length;
    99         /** Protocol address length in bytes. */
    100         uint8_t protocol_length;
    101        
    102         /**
    103          * ARP packet type.
    104          * @see arp_oc.h
    105          */
    106         uint16_t operation;
    107 } __attribute__ ((packed));
    108 
    10974/** ARP global data. */
    11075arp_globals_t arp_globals;
     
    11277DEVICE_MAP_IMPLEMENT(arp_cache, arp_device_t);
    11378INT_MAP_IMPLEMENT(arp_protos, arp_proto_t);
    114 GENERIC_CHAR_MAP_IMPLEMENT(arp_addr, arp_trans_t);
    115 
    116 static void arp_clear_trans(arp_trans_t *trans)
    117 {
    118         if (trans->hw_addr) {
    119                 free(trans->hw_addr);
    120                 trans->hw_addr = NULL;
    121         }
    122        
    123         fibril_condvar_broadcast(&trans->cv);
    124 }
    125 
    126 static void arp_clear_addr(arp_addr_t *addresses)
     79GENERIC_CHAR_MAP_IMPLEMENT(arp_addr, measured_string_t);
     80
     81/** Clears the device specific data.
     82 *
     83 * @param[in] device    The device specific data.
     84 */
     85static void arp_clear_device(arp_device_t *device)
    12786{
    12887        int count;
    129        
    130         for (count = arp_addr_count(addresses) - 1; count >= 0; count--) {
    131                 arp_trans_t *trans = arp_addr_items_get_index(&addresses->values,
    132                     count);
    133                 if (trans)
    134                         arp_clear_trans(trans);
    135         }
    136 }
    137 
    138 /** Clear the device specific data.
    139  *
    140  * @param[in] device Device specific data.
    141  */
    142 static void arp_clear_device(arp_device_t *device)
    143 {
    144         int count;
    145        
     88        arp_proto_t *proto;
     89
    14690        for (count = arp_protos_count(&device->protos) - 1; count >= 0;
    14791            count--) {
    148                 arp_proto_t *proto = arp_protos_get_index(&device->protos,
    149                     count);
    150                
     92                proto = arp_protos_get_index(&device->protos, count);
    15193                if (proto) {
    15294                        if (proto->addr)
    15395                                free(proto->addr);
    154                        
    15596                        if (proto->addr_data)
    15697                                free(proto->addr_data);
    157                        
    158                         arp_clear_addr(&proto->addresses);
    15998                        arp_addr_destroy(&proto->addresses);
    16099                }
    161100        }
    162        
    163101        arp_protos_clear(&device->protos);
    164102}
     
    167105{
    168106        int count;
    169        
    170         fibril_mutex_lock(&arp_globals.lock);
     107        arp_device_t *device;
     108
     109        fibril_rwlock_write_lock(&arp_globals.lock);
    171110        for (count = arp_cache_count(&arp_globals.cache) - 1; count >= 0;
    172111            count--) {
    173                 arp_device_t *device = arp_cache_get_index(&arp_globals.cache,
    174                     count);
    175                
     112                device = arp_cache_get_index(&arp_globals.cache, count);
    176113                if (device) {
    177114                        arp_clear_device(device);
    178115                        if (device->addr_data)
    179116                                free(device->addr_data);
    180                        
    181117                        if (device->broadcast_data)
    182118                                free(device->broadcast_data);
    183119                }
    184120        }
    185        
    186121        arp_cache_clear(&arp_globals.cache);
    187         fibril_mutex_unlock(&arp_globals.lock);
    188        
     122        fibril_rwlock_write_unlock(&arp_globals.lock);
     123        printf("Cache cleaned\n");
    189124        return EOK;
    190125}
     
    193128    services_t protocol, measured_string_t *address)
    194129{
    195         fibril_mutex_lock(&arp_globals.lock);
    196        
    197         arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
     130        arp_device_t *device;
     131        arp_proto_t *proto;
     132
     133        fibril_rwlock_write_lock(&arp_globals.lock);
     134        device = arp_cache_find(&arp_globals.cache, device_id);
    198135        if (!device) {
    199                 fibril_mutex_unlock(&arp_globals.lock);
     136                fibril_rwlock_write_unlock(&arp_globals.lock);
    200137                return ENOENT;
    201138        }
    202        
    203         arp_proto_t *proto = arp_protos_find(&device->protos, protocol);
     139        proto = arp_protos_find(&device->protos, protocol);
    204140        if (!proto) {
    205                 fibril_mutex_unlock(&arp_globals.lock);
     141                fibril_rwlock_write_unlock(&arp_globals.lock);
    206142                return ENOENT;
    207143        }
    208        
    209         arp_trans_t *trans = arp_addr_find(&proto->addresses, address->value,
    210             address->length);
    211         if (trans)
    212                 arp_clear_trans(trans);
    213        
    214144        arp_addr_exclude(&proto->addresses, address->value, address->length);
    215        
    216         fibril_mutex_unlock(&arp_globals.lock);
     145        fibril_rwlock_write_unlock(&arp_globals.lock);
    217146        return EOK;
    218147}
    219148
     149
    220150static int arp_clear_device_req(int arp_phone, device_id_t device_id)
    221151{
    222         fibril_mutex_lock(&arp_globals.lock);
    223        
    224         arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
     152        arp_device_t *device;
     153
     154        fibril_rwlock_write_lock(&arp_globals.lock);
     155        device = arp_cache_find(&arp_globals.cache, device_id);
    225156        if (!device) {
    226                 fibril_mutex_unlock(&arp_globals.lock);
     157                fibril_rwlock_write_unlock(&arp_globals.lock);
    227158                return ENOENT;
    228159        }
    229        
    230160        arp_clear_device(device);
    231        
    232         fibril_mutex_unlock(&arp_globals.lock);
     161        printf("Device %d cleared\n", device_id);
     162        fibril_rwlock_write_unlock(&arp_globals.lock);
    233163        return EOK;
    234164}
    235165
    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  *
     166/** Creates new protocol specific data.
     167 *
     168 * Allocates and returns the needed memory block as the proto parameter.
     169 *
     170 * @param[out] proto    The allocated protocol specific data.
     171 * @param[in] service   The protocol module service.
     172 * @param[in] address   The actual protocol device address.
     173 * @return              EOK on success.
     174 * @return              ENOMEM if there is not enough memory left.
    247175 */
    248176static int arp_proto_create(arp_proto_t **proto, services_t service,
    249177    measured_string_t *address)
    250178{
     179        int rc;
     180
    251181        *proto = (arp_proto_t *) malloc(sizeof(arp_proto_t));
    252182        if (!*proto)
     
    257187        (*proto)->addr_data = address->value;
    258188       
    259         int rc = arp_addr_initialize(&(*proto)->addresses);
     189        rc = arp_addr_initialize(&(*proto)->addresses);
    260190        if (rc != EOK) {
    261191                free(*proto);
     
    266196}
    267197
    268 /** Process the received ARP packet.
    269  *
    270  * Update the source hardware address if the source entry exists or the packet
     198/** Registers the device.
     199 *
     200 * Creates new device entry in the cache or updates the protocol address if the
     201 * device with the device identifier and the driver service exists.
     202 *
     203 * @param[in] device_id The device identifier.
     204 * @param[in] service   The device driver service.
     205 * @param[in] protocol  The protocol service.
     206 * @param[in] address   The actual device protocol address.
     207 * @return              EOK on success.
     208 * @return              EEXIST if another device with the same device identifier
     209 *                      and different driver service exists.
     210 * @return              ENOMEM if there is not enough memory left.
     211 * @return              Other error codes as defined for the
     212 *                      measured_strings_return() function.
     213 */
     214static int arp_device_message(device_id_t device_id, services_t service,
     215    services_t protocol, measured_string_t *address)
     216{
     217        arp_device_t *device;
     218        arp_proto_t *proto;
     219        hw_type_t hardware;
     220        int index;
     221        int rc;
     222
     223        fibril_rwlock_write_lock(&arp_globals.lock);
     224
     225        /* An existing device? */
     226        device = arp_cache_find(&arp_globals.cache, device_id);
     227
     228        if (device) {
     229                if (device->service != service) {
     230                        printf("Device %d already exists\n", device->device_id);
     231                        fibril_rwlock_write_unlock(&arp_globals.lock);
     232                        return EEXIST;
     233                }
     234                proto = arp_protos_find(&device->protos, protocol);
     235                if (proto) {
     236                        free(proto->addr);
     237                        free(proto->addr_data);
     238                        proto->addr = address;
     239                        proto->addr_data = address->value;
     240                } else {
     241                        rc = arp_proto_create(&proto, protocol, address);
     242                        if (rc != EOK) {
     243                                fibril_rwlock_write_unlock(&arp_globals.lock);
     244                                return rc;
     245                        }
     246                        index = arp_protos_add(&device->protos, proto->service,
     247                            proto);
     248                        if (index < 0) {
     249                                fibril_rwlock_write_unlock(&arp_globals.lock);
     250                                free(proto);
     251                                return index;
     252                        }
     253                        printf("New protocol added:\n\tdevice id\t= "
     254                            "%d\n\tproto\t= %d", device_id, protocol);
     255                }
     256        } else {
     257                hardware = hardware_map(service);
     258                if (!hardware)
     259                        return ENOENT;
     260               
     261                /* Create a new device */
     262                device = (arp_device_t *) malloc(sizeof(arp_device_t));
     263                if (!device) {
     264                        fibril_rwlock_write_unlock(&arp_globals.lock);
     265                        return ENOMEM;
     266                }
     267                device->hardware = hardware;
     268                device->device_id = device_id;
     269                rc = arp_protos_initialize(&device->protos);
     270                if (rc != EOK) {
     271                        fibril_rwlock_write_unlock(&arp_globals.lock);
     272                        free(device);
     273                        return rc;
     274                }
     275                rc = arp_proto_create(&proto, protocol, address);
     276                if (rc != EOK) {
     277                        fibril_rwlock_write_unlock(&arp_globals.lock);
     278                        free(device);
     279                        return rc;
     280                }
     281                index = arp_protos_add(&device->protos, proto->service, proto);
     282                if (index < 0) {
     283                        fibril_rwlock_write_unlock(&arp_globals.lock);
     284                        arp_protos_destroy(&device->protos);
     285                        free(device);
     286                        return index;
     287                }
     288                device->service = service;
     289               
     290                /* Bind the new one */
     291                device->phone = nil_bind_service(device->service,
     292                    (ipcarg_t) device->device_id, SERVICE_ARP,
     293                    arp_globals.client_connection);
     294                if (device->phone < 0) {
     295                        fibril_rwlock_write_unlock(&arp_globals.lock);
     296                        arp_protos_destroy(&device->protos);
     297                        free(device);
     298                        return EREFUSED;
     299                }
     300               
     301                /* Get packet dimensions */
     302                rc = nil_packet_size_req(device->phone, device_id,
     303                    &device->packet_dimension);
     304                if (rc != EOK) {
     305                        fibril_rwlock_write_unlock(&arp_globals.lock);
     306                        arp_protos_destroy(&device->protos);
     307                        free(device);
     308                        return rc;
     309                }
     310               
     311                /* Get hardware address */
     312                rc = nil_get_addr_req(device->phone, device_id, &device->addr,
     313                    &device->addr_data);
     314                if (rc != EOK) {
     315                        fibril_rwlock_write_unlock(&arp_globals.lock);
     316                        arp_protos_destroy(&device->protos);
     317                        free(device);
     318                        return rc;
     319                }
     320               
     321                /* Get broadcast address */
     322                rc = nil_get_broadcast_addr_req(device->phone, device_id,
     323                    &device->broadcast_addr, &device->broadcast_data);
     324                if (rc != EOK) {
     325                        fibril_rwlock_write_unlock(&arp_globals.lock);
     326                        free(device->addr);
     327                        free(device->addr_data);
     328                        arp_protos_destroy(&device->protos);
     329                        free(device);
     330                        return rc;
     331                }
     332               
     333                rc = arp_cache_add(&arp_globals.cache, device->device_id,
     334                    device);
     335                if (rc != EOK) {
     336                        fibril_rwlock_write_unlock(&arp_globals.lock);
     337                        free(device->addr);
     338                        free(device->addr_data);
     339                        free(device->broadcast_addr);
     340                        free(device->broadcast_data);
     341                        arp_protos_destroy(&device->protos);
     342                        free(device);
     343                        return rc;
     344                }
     345                printf("%s: Device registered (id: %d, type: 0x%x, service: %d,"
     346                    " proto: %d)\n", NAME, device->device_id, device->hardware,
     347                    device->service, protocol);
     348        }
     349        fibril_rwlock_write_unlock(&arp_globals.lock);
     350       
     351        return EOK;
     352}
     353
     354/** Initializes the ARP module.
     355 *
     356 *  @param[in] client_connection The client connection processing function.
     357 *                      The module skeleton propagates its own one.
     358 *  @return             EOK on success.
     359 *  @return             ENOMEM if there is not enough memory left.
     360 */
     361int arp_initialize(async_client_conn_t client_connection)
     362{
     363        int rc;
     364
     365        fibril_rwlock_initialize(&arp_globals.lock);
     366        fibril_rwlock_write_lock(&arp_globals.lock);
     367        arp_globals.client_connection = client_connection;
     368        rc = arp_cache_initialize(&arp_globals.cache);
     369        fibril_rwlock_write_unlock(&arp_globals.lock);
     370       
     371        return rc;
     372}
     373
     374/** Updates the device content length according to the new MTU value.
     375 *
     376 * @param[in] device_id The device identifier.
     377 * @param[in] mtu       The new mtu value.
     378 * @return              ENOENT if device is not found.
     379 * @return              EOK on success.
     380 */
     381static int arp_mtu_changed_message(device_id_t device_id, size_t mtu)
     382{
     383        arp_device_t *device;
     384
     385        fibril_rwlock_write_lock(&arp_globals.lock);
     386        device = arp_cache_find(&arp_globals.cache, device_id);
     387        if (!device) {
     388                fibril_rwlock_write_unlock(&arp_globals.lock);
     389                return ENOENT;
     390        }
     391        device->packet_dimension.content = mtu;
     392        fibril_rwlock_write_unlock(&arp_globals.lock);
     393        printf("arp - device %d changed mtu to %zu\n\n", device_id, mtu);
     394        return EOK;
     395}
     396
     397/** Processes the received ARP packet.
     398 *
     399 * Updates the source hardware address if the source entry exists or the packet
    271400 * is targeted to my protocol address.
    272  *
    273  * Respond to the ARP request if the packet is the ARP request and is
     401 * Responses to the ARP request if the packet is the ARP request and is
    274402 * targeted to my address.
    275403 *
    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  *
     404 * @param[in] device_id The source device identifier.
     405 * @param[in,out] packet The received packet.
     406 * @return              EOK on success and the packet is no longer needed.
     407 * @return              One on success and the packet has been reused.
     408 * @return              EINVAL if the packet is too small to carry an ARP
     409 *                      packet.
     410 * @return              EINVAL if the received address lengths differs from
     411 *                      the registered values.
     412 * @return              ENOENT if the device is not found in the cache.
     413 * @return              ENOENT if the protocol for the device is not found in
     414 *                      the cache.
     415 * @return              ENOMEM if there is not enough memory left.
    290416 */
    291417static int arp_receive_message(device_id_t device_id, packet_t *packet)
    292418{
     419        size_t length;
     420        arp_header_t *header;
     421        arp_device_t *device;
     422        arp_proto_t *proto;
     423        measured_string_t *hw_source;
     424        uint8_t *src_hw;
     425        uint8_t *src_proto;
     426        uint8_t *des_hw;
     427        uint8_t *des_proto;
    293428        int rc;
    294        
    295         size_t length = packet_get_data_length(packet);
     429
     430        length = packet_get_data_length(packet);
    296431        if (length <= sizeof(arp_header_t))
    297432                return EINVAL;
    298        
    299         arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
     433
     434        device = arp_cache_find(&arp_globals.cache, device_id);
    300435        if (!device)
    301436                return ENOENT;
    302        
    303         arp_header_t *header = (arp_header_t *) packet_get_data(packet);
     437
     438        header = (arp_header_t *) packet_get_data(packet);
    304439        if ((ntohs(header->hardware) != device->hardware) ||
    305440            (length < sizeof(arp_header_t) + header->hardware_length * 2U +
     
    307442                return EINVAL;
    308443        }
    309        
    310         arp_proto_t *proto = arp_protos_find(&device->protos,
     444
     445        proto = arp_protos_find(&device->protos,
    311446            protocol_unmap(device->service, ntohs(header->protocol)));
    312447        if (!proto)
    313448                return ENOENT;
    314        
    315         uint8_t *src_hw = ((uint8_t *) header) + sizeof(arp_header_t);
    316         uint8_t *src_proto = src_hw + header->hardware_length;
    317         uint8_t *des_hw = src_proto + header->protocol_length;
    318         uint8_t *des_proto = des_hw + header->hardware_length;
    319        
    320         arp_trans_t *trans = arp_addr_find(&proto->addresses, src_proto,
    321             header->protocol_length);
    322        
    323         if ((trans) && (trans->hw_addr)) {
    324                 /* Translation exists */
    325                 if (trans->hw_addr->length != header->hardware_length)
     449
     450        src_hw = ((uint8_t *) header) + sizeof(arp_header_t);
     451        src_proto = src_hw + header->hardware_length;
     452        des_hw = src_proto + header->protocol_length;
     453        des_proto = des_hw + header->hardware_length;
     454        hw_source = arp_addr_find(&proto->addresses, (char *) src_proto,
     455            CONVERT_SIZE(uint8_t, char, header->protocol_length));
     456        /* Exists? */
     457        if (hw_source) {
     458                if (hw_source->length != CONVERT_SIZE(uint8_t, char,
     459                    header->hardware_length)) {
    326460                        return EINVAL;
    327                
    328                 memcpy(trans->hw_addr->value, src_hw, trans->hw_addr->length);
    329         }
    330        
     461                }
     462                memcpy(hw_source->value, src_hw, hw_source->length);
     463        }
    331464        /* Is my protocol address? */
    332         if (proto->addr->length != header->protocol_length)
     465        if (proto->addr->length != CONVERT_SIZE(uint8_t, char,
     466            header->protocol_length)) {
    333467                return EINVAL;
    334        
    335         if (!bcmp(proto->addr->value, des_proto, proto->addr->length)) {
    336                 if (!trans) {
    337                         /* Update the translation */
    338                         trans = (arp_trans_t *) malloc(sizeof(arp_trans_t));
    339                         if (!trans)
     468        }
     469        if (!str_lcmp(proto->addr->value, (char *) des_proto,
     470            proto->addr->length)) {
     471                /* Not already updated? */
     472                if (!hw_source) {
     473                        hw_source = measured_string_create_bulk((char *) src_hw,
     474                            CONVERT_SIZE(uint8_t, char,
     475                            header->hardware_length));
     476                        if (!hw_source)
    340477                                return ENOMEM;
    341                        
    342                         trans->hw_addr = NULL;
    343                         fibril_condvar_initialize(&trans->cv);
    344                         rc = arp_addr_add(&proto->addresses, src_proto,
    345                             header->protocol_length, trans);
    346                         if (rc != EOK) {
    347                                 /* The generic char map has already freed trans! */
     478
     479                        rc = arp_addr_add(&proto->addresses, (char *) src_proto,
     480                            CONVERT_SIZE(uint8_t, char,
     481                            header->protocol_length), hw_source);
     482                        if (rc != EOK)
    348483                                return rc;
    349                         }
    350                 }
    351                
    352                 if (!trans->hw_addr) {
    353                         trans->hw_addr = measured_string_create_bulk(src_hw,
    354                             header->hardware_length);
    355                         if (!trans->hw_addr)
    356                                 return ENOMEM;
    357                        
    358                         /* Notify the fibrils that wait for the translation. */
    359                         fibril_condvar_broadcast(&trans->cv);
    360                 }
    361                
     484                }
    362485                if (ntohs(header->operation) == ARPOP_REQUEST) {
    363486                        header->operation = htons(ARPOP_REPLY);
     
    367490                        memcpy(src_hw, device->addr->value,
    368491                            device->packet_dimension.addr_len);
    369                         memcpy(des_hw, trans->hw_addr->value,
     492                        memcpy(des_hw, hw_source->value,
    370493                            header->hardware_length);
    371494                       
     
    380503                }
    381504        }
    382        
     505
    383506        return EOK;
    384507}
    385508
    386 /** Update the device content length according to the new MTU value.
    387  *
    388  * @param[in] device_id Device identifier.
    389  * @param[in] mtu       New MTU value.
    390  *
    391  * @return ENOENT if device is not found.
    392  * @return EOK on success.
    393  *
    394  */
    395 static int arp_mtu_changed_message(device_id_t device_id, size_t mtu)
    396 {
    397         fibril_mutex_lock(&arp_globals.lock);
    398        
    399         arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
    400         if (!device) {
    401                 fibril_mutex_unlock(&arp_globals.lock);
    402                 return ENOENT;
    403         }
    404        
    405         device->packet_dimension.content = mtu;
    406        
    407         fibril_mutex_unlock(&arp_globals.lock);
    408        
    409         printf("%s: Device %d changed MTU to %zu\n", NAME, device_id, mtu);
    410        
    411         return EOK;
    412 }
    413 
    414 /** Process IPC messages from the registered device driver modules
    415  *
    416  * @param[in]     iid   Message identifier.
    417  * @param[in,out] icall Message parameters.
    418  *
    419  */
    420 static void arp_receiver(ipc_callid_t iid, ipc_call_t *icall)
    421 {
     509
     510/** Returns the hardware address for the given protocol address.
     511 *
     512 * Sends the ARP request packet if the hardware address is not found in the
     513 * cache.
     514 *
     515 * @param[in] device_id The device identifier.
     516 * @param[in] protocol  The protocol service.
     517 * @param[in] target    The target protocol address.
     518 * @return              The hardware address of the target.
     519 * @return              NULL if the target parameter is NULL.
     520 * @return              NULL if the device is not found.
     521 * @return              NULL if the device packet is too small to send a
     522 *                      request.
     523 * @return              NULL if the hardware address is not found in the cache.
     524 */
     525static measured_string_t *
     526arp_translate_message(device_id_t device_id, services_t protocol,
     527    measured_string_t *target)
     528{
     529        arp_device_t *device;
     530        arp_proto_t *proto;
     531        measured_string_t *addr;
     532        size_t length;
    422533        packet_t *packet;
    423         int rc;
    424        
    425         while (true) {
    426                 switch (IPC_GET_IMETHOD(*icall)) {
    427                 case NET_IL_DEVICE_STATE:
    428                         /* Do nothing - keep the cache */
    429                         async_answer_0(iid, (sysarg_t) EOK);
    430                         break;
    431                
    432                 case NET_IL_RECEIVED:
    433                         rc = packet_translate_remote(arp_globals.net_phone, &packet,
    434                             IPC_GET_PACKET(*icall));
    435                         if (rc == EOK) {
    436                                 fibril_mutex_lock(&arp_globals.lock);
    437                                 do {
    438                                         packet_t *next = pq_detach(packet);
    439                                         rc = arp_receive_message(IPC_GET_DEVICE(*icall), packet);
    440                                         if (rc != 1) {
    441                                                 pq_release_remote(arp_globals.net_phone,
    442                                                     packet_get_id(packet));
    443                                         }
    444                                        
    445                                         packet = next;
    446                                 } while (packet);
    447                                 fibril_mutex_unlock(&arp_globals.lock);
    448                         }
    449                         async_answer_0(iid, (sysarg_t) rc);
    450                         break;
    451                
    452                 case NET_IL_MTU_CHANGED:
    453                         rc = arp_mtu_changed_message(IPC_GET_DEVICE(*icall),
    454                             IPC_GET_MTU(*icall));
    455                         async_answer_0(iid, (sysarg_t) rc);
    456                         break;
    457                
    458                 default:
    459                         async_answer_0(iid, (sysarg_t) ENOTSUP);
    460                 }
    461                
    462                 iid = async_get_call(icall);
    463         }
    464 }
    465 
    466 /** Register the device.
    467  *
    468  * Create new device entry in the cache or update the protocol address if the
    469  * device with the device identifier and the driver service exists.
    470  *
    471  * @param[in] device_id Device identifier.
    472  * @param[in] service   Device driver service.
    473  * @param[in] protocol  Protocol service.
    474  * @param[in] address   Actual device protocol address.
    475  *
    476  * @return EOK on success.
    477  * @return EEXIST if another device with the same device identifier
    478  *         and different driver service exists.
    479  * @return ENOMEM if there is not enough memory left.
    480  * @return Other error codes as defined for the
    481  *         measured_strings_return() function.
    482  *
    483  */
    484 static int arp_device_message(device_id_t device_id, services_t service,
    485     services_t protocol, measured_string_t *address)
    486 {
    487         int index;
    488         int rc;
    489        
    490         fibril_mutex_lock(&arp_globals.lock);
    491        
    492         /* An existing device? */
    493         arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
    494         if (device) {
    495                 if (device->service != service) {
    496                         printf("%s: Device %d already exists\n", NAME,
    497                             device->device_id);
    498                         fibril_mutex_unlock(&arp_globals.lock);
    499                         return EEXIST;
    500                 }
    501                
    502                 arp_proto_t *proto = arp_protos_find(&device->protos, protocol);
    503                 if (proto) {
    504                         free(proto->addr);
    505                         free(proto->addr_data);
    506                         proto->addr = address;
    507                         proto->addr_data = address->value;
    508                 } else {
    509                         rc = arp_proto_create(&proto, protocol, address);
    510                         if (rc != EOK) {
    511                                 fibril_mutex_unlock(&arp_globals.lock);
    512                                 return rc;
    513                         }
    514                        
    515                         index = arp_protos_add(&device->protos, proto->service,
    516                             proto);
    517                         if (index < 0) {
    518                                 fibril_mutex_unlock(&arp_globals.lock);
    519                                 free(proto);
    520                                 return index;
    521                         }
    522                        
    523                         printf("%s: New protocol added (id: %d, proto: %d)\n", NAME,
    524                             device_id, protocol);
    525                 }
    526         } else {
    527                 hw_type_t hardware = hardware_map(service);
    528                 if (!hardware)
    529                         return ENOENT;
    530                
    531                 /* Create new device */
    532                 device = (arp_device_t *) malloc(sizeof(arp_device_t));
    533                 if (!device) {
    534                         fibril_mutex_unlock(&arp_globals.lock);
    535                         return ENOMEM;
    536                 }
    537                
    538                 device->hardware = hardware;
    539                 device->device_id = device_id;
    540                 rc = arp_protos_initialize(&device->protos);
    541                 if (rc != EOK) {
    542                         fibril_mutex_unlock(&arp_globals.lock);
    543                         free(device);
    544                         return rc;
    545                 }
    546                
    547                 arp_proto_t *proto;
    548                 rc = arp_proto_create(&proto, protocol, address);
    549                 if (rc != EOK) {
    550                         fibril_mutex_unlock(&arp_globals.lock);
    551                         free(device);
    552                         return rc;
    553                 }
    554                
    555                 index = arp_protos_add(&device->protos, proto->service, proto);
    556                 if (index < 0) {
    557                         fibril_mutex_unlock(&arp_globals.lock);
    558                         arp_protos_destroy(&device->protos);
    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 {
     534        arp_header_t *header;
     535
     536        if (!target)
     537                return NULL;
     538
     539        device = arp_cache_find(&arp_globals.cache, device_id);
     540        if (!device)
     541                return NULL;
     542
     543        proto = arp_protos_find(&device->protos, protocol);
     544        if (!proto || (proto->addr->length != target->length))
     545                return NULL;
     546
     547        addr = arp_addr_find(&proto->addresses, target->value, target->length);
     548        if (addr)
     549                return addr;
     550
    644551        /* ARP packet content size = header + (address + translation) * 2 */
    645         size_t length = 8 + 2 * (proto->addr->length + device->addr->length);
     552        length = 8 + 2 * (CONVERT_SIZE(char, uint8_t, proto->addr->length) +
     553            CONVERT_SIZE(char, uint8_t, device->addr->length));
    646554        if (length > device->packet_dimension.content)
    647                 return ELIMIT;
    648        
    649         packet_t *packet = packet_get_4_remote(arp_globals.net_phone,
     555                return NULL;
     556
     557        packet = packet_get_4_remote(arp_globals.net_phone,
    650558            device->packet_dimension.addr_len, device->packet_dimension.prefix,
    651559            length, device->packet_dimension.suffix);
    652560        if (!packet)
    653                 return ENOMEM;
    654        
    655         arp_header_t *header = (arp_header_t *) packet_suffix(packet, length);
     561                return NULL;
     562
     563        header = (arp_header_t *) packet_suffix(packet, length);
    656564        if (!header) {
    657565                pq_release_remote(arp_globals.net_phone, packet_get_id(packet));
    658                 return ENOMEM;
    659         }
    660        
     566                return NULL;
     567        }
     568
    661569        header->hardware = htons(device->hardware);
    662570        header->hardware_length = (uint8_t) device->addr->length;
     
    664572        header->protocol_length = (uint8_t) proto->addr->length;
    665573        header->operation = htons(ARPOP_REQUEST);
    666        
    667574        length = sizeof(arp_header_t);
    668        
    669575        memcpy(((uint8_t *) header) + length, device->addr->value,
    670576            device->addr->length);
     
    676582        length += device->addr->length;
    677583        memcpy(((uint8_t *) header) + length, target->value, target->length);
    678        
    679         int rc = packet_set_addr(packet, (uint8_t *) device->addr->value,
    680             (uint8_t *) device->broadcast_addr->value, device->addr->length);
    681         if (rc != EOK) {
     584
     585        if (packet_set_addr(packet, (uint8_t *) device->addr->value,
     586            (uint8_t *) device->broadcast_addr->value,
     587            CONVERT_SIZE(char, uint8_t, device->addr->length)) != EOK) {
    682588                pq_release_remote(arp_globals.net_phone, packet_get_id(packet));
    683                 return rc;
    684         }
    685        
     589                return NULL;
     590        }
     591
    686592        nil_send_msg(device->phone, device_id, packet, SERVICE_ARP);
    687         return EOK;
    688 }
    689 
    690 /** Return the hardware address for the given protocol address.
    691  *
    692  * Send the ARP request packet if the hardware address is not found in the
    693  * cache.
    694  *
    695  * @param[in]  device_id   Device identifier.
    696  * @param[in]  protocol    Protocol service.
    697  * @param[in]  target      Target protocol address.
    698  * @param[out] translation Where the hardware address of the target is stored.
    699  *
    700  * @return EOK on success.
    701  * @return EAGAIN if the caller should try again.
    702  * @return Other error codes in case of error.
    703  *
    704  */
    705 static int arp_translate_message(device_id_t device_id, services_t protocol,
    706     measured_string_t *target, measured_string_t **translation)
    707 {
    708         bool retry = false;
    709         int rc;
    710 
    711         assert(fibril_mutex_is_locked(&arp_globals.lock));
    712        
    713 restart:
    714         if ((!target) || (!translation))
    715                 return EBADMEM;
    716        
    717         arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
    718         if (!device)
    719                 return ENOENT;
    720        
    721         arp_proto_t *proto = arp_protos_find(&device->protos, protocol);
    722         if ((!proto) || (proto->addr->length != target->length))
    723                 return ENOENT;
    724        
    725         arp_trans_t *trans = arp_addr_find(&proto->addresses, target->value,
    726             target->length);
    727         if (trans) {
    728                 if (trans->hw_addr) {
    729                         /* The translation is in place. */
    730                         *translation = trans->hw_addr;
    731                         return EOK;
    732                 }
    733                
    734                 if (retry) {
    735                         /*
    736                          * We may get here as a result of being signalled for
    737                          * some reason while waiting for the translation (e.g.
    738                          * translation becoming available, record being removed
    739                          * from the table) and then losing the race for
    740                          * the arp_globals.lock with someone else who modified
    741                          * the table.
    742                          *
    743                          * Remove the incomplete record so that it is possible
    744                          * to make new ARP requests.
    745                          */
    746                         arp_clear_trans(trans);
    747                         arp_addr_exclude(&proto->addresses, target->value,
    748                             target->length);
    749                         return EAGAIN;
    750                 }
    751                
    752                 /*
    753                  * We are a random passer-by who merely joins an already waiting
    754                  * fibril in waiting for the translation.
    755                  */
    756                 rc = fibril_condvar_wait_timeout(&trans->cv, &arp_globals.lock,
    757                     ARP_TRANS_WAIT);
    758                 if (rc == ETIMEOUT)
    759                         return ENOENT;
    760                
    761                 /*
    762                  * Need to recheck because we did not hold the lock while
    763                  * sleeping on the condition variable.
    764                  */
    765                 retry = true;
    766                 goto restart;
    767         }
    768        
    769         if (retry)
    770                 return EAGAIN;
    771 
    772         /*
    773          * We are under the protection of arp_globals.lock, so we can afford to
    774          * first send the ARP request and then insert an incomplete ARP record.
    775          * The incomplete record is used to tell any other potential waiter
    776          * that this fibril has already sent the request and that it is waiting
    777          * for the answer. Lastly, any fibril which sees the incomplete request
    778          * can perform a timed wait on its condition variable to wait for the
    779          * ARP reply to arrive.
    780          */
    781 
    782         rc = arp_send_request(device_id, protocol, target, device, proto);
    783         if (rc != EOK)
    784                 return rc;
    785        
    786         trans = (arp_trans_t *) malloc(sizeof(arp_trans_t));
    787         if (!trans)
    788                 return ENOMEM;
    789        
    790         trans->hw_addr = NULL;
    791         fibril_condvar_initialize(&trans->cv);
    792        
    793         rc = arp_addr_add(&proto->addresses, target->value, target->length,
    794             trans);
    795         if (rc != EOK) {
    796                 /* The generic char map has already freed trans! */
    797                 return rc;
    798         }
    799        
    800         rc = fibril_condvar_wait_timeout(&trans->cv, &arp_globals.lock,
    801             ARP_TRANS_WAIT);
    802         if (rc == ETIMEOUT) {
    803                 /*
    804                  * Remove the incomplete record so that it is possible to make
    805                  * new ARP requests.
    806                  */
    807                 arp_clear_trans(trans);
    808                 arp_addr_exclude(&proto->addresses, target->value,
    809                     target->length);
    810                 return ENOENT;
    811         }
    812        
    813         /*
    814          * We need to recheck that the translation has indeed become available,
    815          * because we dropped the arp_globals.lock while sleeping on the
    816          * condition variable and someone else might have e.g. removed the
    817          * translation before we managed to lock arp_globals.lock again.
    818          */
    819 
    820         retry = true;
    821         goto restart;
    822 }
    823 
    824 /** Process the ARP message.
    825  *
    826  * @param[in]  callid Message identifier.
    827  * @param[in]  call   Message parameters.
    828  * @param[out] answer Answer.
    829  * @param[out] count  Number of arguments of the answer.
    830  *
    831  * @return EOK on success.
    832  * @return ENOTSUP if the message is not known.
     593        return NULL;
     594}
     595
     596
     597/** Processes the ARP message.
     598 *
     599 * @param[in] callid    The message identifier.
     600 * @param[in] call      The message parameters.
     601 * @param[out] answer   The message answer parameters.
     602 * @param[out] answer_count The last parameter for the actual answer in the
     603 *                      answer parameter.
     604 * @return              EOK on success.
     605 * @return              ENOTSUP if the message is not known.
    833606 *
    834607 * @see arp_interface.h
    835608 * @see IS_NET_ARP_MESSAGE()
    836  *
    837  */
    838 int il_module_message(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer,
    839     size_t *count)
     609 */
     610int
     611arp_message_standalone(ipc_callid_t callid, ipc_call_t *call,
     612    ipc_call_t *answer, int *answer_count)
    840613{
    841614        measured_string_t *address;
    842615        measured_string_t *translation;
    843         uint8_t *data;
     616        char *data;
     617        packet_t *packet;
     618        packet_t *next;
    844619        int rc;
    845620       
    846         *count = 0;
    847         switch (IPC_GET_IMETHOD(*call)) {
     621        *answer_count = 0;
     622        switch (IPC_GET_METHOD(*call)) {
    848623        case IPC_M_PHONE_HUNGUP:
    849624                return EOK;
     
    854629                        return rc;
    855630               
    856                 rc = arp_device_message(IPC_GET_DEVICE(*call),
    857                     IPC_GET_SERVICE(*call), ARP_GET_NETIF(*call), address);
     631                rc = arp_device_message(IPC_GET_DEVICE(call),
     632                    IPC_GET_SERVICE(call), ARP_GET_NETIF(call), address);
    858633                if (rc != EOK) {
    859634                        free(address);
    860635                        free(data);
    861636                }
    862                
    863637                return rc;
    864638       
     
    868642                        return rc;
    869643               
    870                 fibril_mutex_lock(&arp_globals.lock);
    871                 rc = arp_translate_message(IPC_GET_DEVICE(*call),
    872                     IPC_GET_SERVICE(*call), address, &translation);
     644                fibril_rwlock_read_lock(&arp_globals.lock);
     645                translation = arp_translate_message(IPC_GET_DEVICE(call),
     646                    IPC_GET_SERVICE(call), address);
    873647                free(address);
    874648                free(data);
    875                
    876                 if (rc != EOK) {
    877                         fibril_mutex_unlock(&arp_globals.lock);
    878                         return rc;
    879                 }
    880                
    881649                if (!translation) {
    882                         fibril_mutex_unlock(&arp_globals.lock);
     650                        fibril_rwlock_read_unlock(&arp_globals.lock);
    883651                        return ENOENT;
    884652                }
    885                
    886653                rc = measured_strings_reply(translation, 1);
    887                 fibril_mutex_unlock(&arp_globals.lock);
     654                fibril_rwlock_read_unlock(&arp_globals.lock);
    888655                return rc;
    889        
     656
    890657        case NET_ARP_CLEAR_DEVICE:
    891                 return arp_clear_device_req(0, IPC_GET_DEVICE(*call));
    892        
     658                return arp_clear_device_req(0, IPC_GET_DEVICE(call));
     659
    893660        case NET_ARP_CLEAR_ADDRESS:
    894661                rc = measured_strings_receive(&address, &data, 1);
     
    896663                        return rc;
    897664               
    898                 arp_clear_address_req(0, IPC_GET_DEVICE(*call),
    899                     IPC_GET_SERVICE(*call), address);
     665                arp_clear_address_req(0, IPC_GET_DEVICE(call),
     666                    IPC_GET_SERVICE(call), address);
    900667                free(address);
    901668                free(data);
     
    904671        case NET_ARP_CLEAN_CACHE:
    905672                return arp_clean_cache_req(0);
     673       
     674        case NET_IL_DEVICE_STATE:
     675                /* Do nothing - keep the cache */
     676                return EOK;
     677       
     678        case NET_IL_RECEIVED:
     679                rc = packet_translate_remote(arp_globals.net_phone, &packet,
     680                    IPC_GET_PACKET(call));
     681                if (rc != EOK)
     682                        return rc;
     683               
     684                fibril_rwlock_read_lock(&arp_globals.lock);
     685                do {
     686                        next = pq_detach(packet);
     687                        rc = arp_receive_message(IPC_GET_DEVICE(call), packet);
     688                        if (rc != 1) {
     689                                pq_release_remote(arp_globals.net_phone,
     690                                    packet_get_id(packet));
     691                        }
     692                        packet = next;
     693                } while (packet);
     694                fibril_rwlock_read_unlock(&arp_globals.lock);
     695               
     696                return EOK;
     697       
     698        case NET_IL_MTU_CHANGED:
     699                return arp_mtu_changed_message(IPC_GET_DEVICE(call),
     700                    IPC_GET_MTU(call));
    906701        }
    907702       
     
    909704}
    910705
     706/** Default thread for new connections.
     707 *
     708 * @param[in] iid       The initial message identifier.
     709 * @param[in] icall     The initial message call structure.
     710 */
     711static void il_client_connection(ipc_callid_t iid, ipc_call_t *icall)
     712{
     713        /*
     714         * Accept the connection
     715         *  - Answer the first IPC_M_CONNECT_ME_TO call.
     716         */
     717        ipc_answer_0(iid, EOK);
     718       
     719        while (true) {
     720                ipc_call_t answer;
     721                int answer_count;
     722               
     723                /* Clear the answer structure */
     724                refresh_answer(&answer, &answer_count);
     725               
     726                /* Fetch the next message */
     727                ipc_call_t call;
     728                ipc_callid_t callid = async_get_call(&call);
     729               
     730                /* Process the message */
     731                int res = il_module_message_standalone(callid, &call, &answer,
     732                    &answer_count);
     733               
     734                /*
     735                 * End if told to either by the message or the processing
     736                 * result.
     737                 */
     738                if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) ||
     739                    (res == EHANGUP))
     740                        return;
     741               
     742                /* Answer the message */
     743                answer_call(callid, res, &answer, answer_count);
     744        }
     745}
     746
     747/** Starts the module.
     748 *
     749 * @return              EOK on success.
     750 * @return              Other error codes as defined for each specific module
     751 *                      start function.
     752 */
    911753int main(int argc, char *argv[])
    912754{
     755        int rc;
     756       
    913757        /* Start the module */
    914         return il_module_start(SERVICE_ARP);
     758        rc = il_module_start_standalone(il_client_connection);
     759        return rc;
    915760}
    916761
    917762/** @}
    918763 */
     764
Note: See TracChangeset for help on using the changeset viewer.