Ignore:
File:
1 edited

Legend:

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

    r7e752b2 rffa2c8ef  
    3636 */
    3737
    38 #include "arp.h"
    39 #include "arp_header.h"
    40 #include "arp_oc.h"
    41 #include "arp_module.h"
    42 
    4338#include <async.h>
    4439#include <malloc.h>
    4540#include <mem.h>
    4641#include <fibril_synch.h>
     42#include <assert.h>
    4743#include <stdio.h>
    4844#include <str.h>
    4945#include <task.h>
    5046#include <adt/measured_strings.h>
    51 #include <ipc/ipc.h>
    5247#include <ipc/services.h>
    5348#include <ipc/net.h>
    5449#include <ipc/arp.h>
    5550#include <ipc/il.h>
     51#include <ipc/nil.h>
    5652#include <byteorder.h>
    5753#include <errno.h>
    58 
    5954#include <net/modules.h>
    6055#include <net/device.h>
    6156#include <net/packet.h>
    62 
    63 #include <nil_interface.h>
     57#include <nil_remote.h>
    6458#include <protocol_map.h>
    6559#include <packet_client.h>
    6660#include <packet_remote.h>
    67 #include <il_interface.h>
    68 #include <il_local.h>
    69 
     61#include <il_remote.h>
     62#include <il_skel.h>
     63#include "arp.h"
    7064
    7165/** ARP module name. */
    7266#define NAME  "arp"
    7367
     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 */
     85typedef struct arp_header arp_header_t;
     86
     87/** ARP protocol header. */
     88struct arp_header {
     89        /**
     90         * Hardware type identifier.
     91         * @see hardware.h
     92         */
     93        uint16_t hardware;
     94       
     95        /** Protocol identifier. */
     96        uint16_t protocol;
     97        /** Hardware address length in bytes. */
     98        uint8_t hardware_length;
     99        /** Protocol address length in bytes. */
     100        uint8_t protocol_length;
     101       
     102        /**
     103         * ARP packet type.
     104         * @see arp_oc.h
     105         */
     106        uint16_t operation;
     107} __attribute__ ((packed));
     108
    74109/** ARP global data. */
    75110arp_globals_t arp_globals;
     
    77112DEVICE_MAP_IMPLEMENT(arp_cache, arp_device_t);
    78113INT_MAP_IMPLEMENT(arp_protos, arp_proto_t);
    79 GENERIC_CHAR_MAP_IMPLEMENT(arp_addr, measured_string_t);
    80 
    81 /** Clears the device specific data.
    82  *
    83  * @param[in] device    The device specific data.
     114GENERIC_CHAR_MAP_IMPLEMENT(arp_addr, arp_trans_t);
     115
     116static void arp_clear_trans(arp_trans_t *trans)
     117{
     118        if (trans->hw_addr) {
     119                free(trans->hw_addr);
     120                trans->hw_addr = NULL;
     121        }
     122       
     123        fibril_condvar_broadcast(&trans->cv);
     124}
     125
     126static void arp_clear_addr(arp_addr_t *addresses)
     127{
     128        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.
    84141 */
    85142static void arp_clear_device(arp_device_t *device)
    86143{
    87144        int count;
    88         arp_proto_t *proto;
    89 
     145       
    90146        for (count = arp_protos_count(&device->protos) - 1; count >= 0;
    91147            count--) {
    92                 proto = arp_protos_get_index(&device->protos, count);
     148                arp_proto_t *proto = arp_protos_get_index(&device->protos,
     149                    count);
     150               
    93151                if (proto) {
    94152                        if (proto->addr)
    95153                                free(proto->addr);
     154                       
    96155                        if (proto->addr_data)
    97156                                free(proto->addr_data);
     157                       
     158                        arp_clear_addr(&proto->addresses);
    98159                        arp_addr_destroy(&proto->addresses);
    99160                }
    100161        }
     162       
    101163        arp_protos_clear(&device->protos);
    102164}
     
    105167{
    106168        int count;
    107         arp_device_t *device;
    108 
    109         fibril_rwlock_write_lock(&arp_globals.lock);
     169       
     170        fibril_mutex_lock(&arp_globals.lock);
    110171        for (count = arp_cache_count(&arp_globals.cache) - 1; count >= 0;
    111172            count--) {
    112                 device = arp_cache_get_index(&arp_globals.cache, count);
     173                arp_device_t *device = arp_cache_get_index(&arp_globals.cache,
     174                    count);
     175               
    113176                if (device) {
    114177                        arp_clear_device(device);
    115178                        if (device->addr_data)
    116179                                free(device->addr_data);
     180                       
    117181                        if (device->broadcast_data)
    118182                                free(device->broadcast_data);
    119183                }
    120184        }
     185       
    121186        arp_cache_clear(&arp_globals.cache);
    122         fibril_rwlock_write_unlock(&arp_globals.lock);
    123         printf("Cache cleaned\n");
     187        fibril_mutex_unlock(&arp_globals.lock);
     188       
    124189        return EOK;
    125190}
     
    128193    services_t protocol, measured_string_t *address)
    129194{
    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);
     195        fibril_mutex_lock(&arp_globals.lock);
     196       
     197        arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
    135198        if (!device) {
    136                 fibril_rwlock_write_unlock(&arp_globals.lock);
     199                fibril_mutex_unlock(&arp_globals.lock);
    137200                return ENOENT;
    138201        }
    139         proto = arp_protos_find(&device->protos, protocol);
     202       
     203        arp_proto_t *proto = arp_protos_find(&device->protos, protocol);
    140204        if (!proto) {
    141                 fibril_rwlock_write_unlock(&arp_globals.lock);
     205                fibril_mutex_unlock(&arp_globals.lock);
    142206                return ENOENT;
    143207        }
     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       
    144214        arp_addr_exclude(&proto->addresses, address->value, address->length);
    145         fibril_rwlock_write_unlock(&arp_globals.lock);
     215       
     216        fibril_mutex_unlock(&arp_globals.lock);
    146217        return EOK;
    147218}
    148219
    149 
    150220static int arp_clear_device_req(int arp_phone, device_id_t device_id)
    151221{
    152         arp_device_t *device;
    153 
    154         fibril_rwlock_write_lock(&arp_globals.lock);
    155         device = arp_cache_find(&arp_globals.cache, device_id);
     222        fibril_mutex_lock(&arp_globals.lock);
     223       
     224        arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
    156225        if (!device) {
    157                 fibril_rwlock_write_unlock(&arp_globals.lock);
     226                fibril_mutex_unlock(&arp_globals.lock);
    158227                return ENOENT;
    159228        }
     229       
    160230        arp_clear_device(device);
    161         printf("Device %d cleared\n", device_id);
    162         fibril_rwlock_write_unlock(&arp_globals.lock);
     231       
     232        fibril_mutex_unlock(&arp_globals.lock);
    163233        return EOK;
    164234}
    165235
    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.
     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 *
    175247 */
    176248static int arp_proto_create(arp_proto_t **proto, services_t service,
    177249    measured_string_t *address)
    178250{
    179         int rc;
    180 
    181251        *proto = (arp_proto_t *) malloc(sizeof(arp_proto_t));
    182252        if (!*proto)
     
    187257        (*proto)->addr_data = address->value;
    188258       
    189         rc = arp_addr_initialize(&(*proto)->addresses);
     259        int rc = arp_addr_initialize(&(*proto)->addresses);
    190260        if (rc != EOK) {
    191261                free(*proto);
     
    196266}
    197267
    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  */
    214 static 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;
     268/** Process the received ARP packet.
     269 *
     270 * Update the source hardware address if the source entry exists or the packet
     271 * is targeted to my protocol address.
     272 *
     273 * Respond to the ARP request if the packet is the ARP request and is
     274 * targeted to my address.
     275 *
     276 * @param[in]     device_id Source device identifier.
     277 * @param[in,out] packet    Received packet.
     278 *
     279 * @return EOK on success and the packet is no longer needed.
     280 * @return One on success and the packet has been reused.
     281 * @return EINVAL if the packet is too small to carry an ARP
     282 *         packet.
     283 * @return EINVAL if the received address lengths differs from
     284 *         the registered values.
     285 * @return ENOENT if the device is not found in the cache.
     286 * @return ENOENT if the protocol for the device is not found in
     287 *         the cache.
     288 * @return ENOMEM if there is not enough memory left.
     289 *
     290 */
     291static int arp_receive_message(device_id_t device_id, packet_t *packet)
     292{
    221293        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  */
    361 int 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  */
    381 static 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
    400  * is targeted to my protocol address.
    401  * Responses to the ARP request if the packet is the ARP request and is
    402  * targeted to my address.
    403  *
    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.
    416  */
    417 static int arp_receive_message(device_id_t device_id, packet_t *packet)
    418 {
    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;
    428         int rc;
    429 
    430         length = packet_get_data_length(packet);
     294       
     295        size_t length = packet_get_data_length(packet);
    431296        if (length <= sizeof(arp_header_t))
    432297                return EINVAL;
    433 
    434         device = arp_cache_find(&arp_globals.cache, device_id);
     298       
     299        arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
    435300        if (!device)
    436301                return ENOENT;
    437 
    438         header = (arp_header_t *) packet_get_data(packet);
     302       
     303        arp_header_t *header = (arp_header_t *) packet_get_data(packet);
    439304        if ((ntohs(header->hardware) != device->hardware) ||
    440305            (length < sizeof(arp_header_t) + header->hardware_length * 2U +
     
    442307                return EINVAL;
    443308        }
    444 
    445         proto = arp_protos_find(&device->protos,
     309       
     310        arp_proto_t *proto = arp_protos_find(&device->protos,
    446311            protocol_unmap(device->service, ntohs(header->protocol)));
    447312        if (!proto)
    448313                return ENOENT;
    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)) {
     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)
    460326                        return EINVAL;
    461                 }
    462                 memcpy(hw_source->value, src_hw, hw_source->length);
    463         }
     327               
     328                memcpy(trans->hw_addr->value, src_hw, trans->hw_addr->length);
     329        }
     330       
    464331        /* Is my protocol address? */
    465         if (proto->addr->length != CONVERT_SIZE(uint8_t, char,
    466             header->protocol_length)) {
     332        if (proto->addr->length != header->protocol_length)
    467333                return EINVAL;
    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)
     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)
    477340                                return ENOMEM;
    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)
     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! */
    483348                                return rc;
    484                 }
     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               
    485362                if (ntohs(header->operation) == ARPOP_REQUEST) {
    486363                        header->operation = htons(ARPOP_REPLY);
     
    490367                        memcpy(src_hw, device->addr->value,
    491368                            device->packet_dimension.addr_len);
    492                         memcpy(des_hw, hw_source->value,
     369                        memcpy(des_hw, trans->hw_addr->value,
    493370                            header->hardware_length);
    494371                       
     
    503380                }
    504381        }
    505 
     382       
    506383        return EOK;
    507384}
    508385
    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  */
    525 static measured_string_t *
    526 arp_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;
     386/** Update the device content length according to the new MTU value.
     387 *
     388 * @param[in] device_id Device identifier.
     389 * @param[in] mtu       New MTU value.
     390 *
     391 * @return ENOENT if device is not found.
     392 * @return EOK on success.
     393 *
     394 */
     395static int arp_mtu_changed_message(device_id_t device_id, size_t mtu)
     396{
     397        fibril_mutex_lock(&arp_globals.lock);
     398       
     399        arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
     400        if (!device) {
     401                fibril_mutex_unlock(&arp_globals.lock);
     402                return ENOENT;
     403        }
     404       
     405        device->packet_dimension.content = mtu;
     406       
     407        fibril_mutex_unlock(&arp_globals.lock);
     408       
     409        printf("%s: Device %d changed MTU to %zu\n", NAME, device_id, mtu);
     410       
     411        return EOK;
     412}
     413
     414/** Process IPC messages from the registered device driver modules
     415 *
     416 * @param[in]     iid   Message identifier.
     417 * @param[in,out] icall Message parameters.
     418 *
     419 */
     420static void arp_receiver(ipc_callid_t iid, ipc_call_t *icall)
     421{
    533422        packet_t *packet;
    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 
     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 */
     484static 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
     629int il_initialize(int net_phone)
     630{
     631        fibril_mutex_initialize(&arp_globals.lock);
     632       
     633        fibril_mutex_lock(&arp_globals.lock);
     634        arp_globals.net_phone = net_phone;
     635        int rc = arp_cache_initialize(&arp_globals.cache);
     636        fibril_mutex_unlock(&arp_globals.lock);
     637       
     638        return rc;
     639}
     640
     641static int arp_send_request(device_id_t device_id, services_t protocol,
     642    measured_string_t *target, arp_device_t *device, arp_proto_t *proto)
     643{
    551644        /* ARP packet content size = header + (address + translation) * 2 */
    552         length = 8 + 2 * (CONVERT_SIZE(char, uint8_t, proto->addr->length) +
    553             CONVERT_SIZE(char, uint8_t, device->addr->length));
     645        size_t length = 8 + 2 * (proto->addr->length + device->addr->length);
    554646        if (length > device->packet_dimension.content)
    555                 return NULL;
    556 
    557         packet = packet_get_4_remote(arp_globals.net_phone,
     647                return ELIMIT;
     648       
     649        packet_t *packet = packet_get_4_remote(arp_globals.net_phone,
    558650            device->packet_dimension.addr_len, device->packet_dimension.prefix,
    559651            length, device->packet_dimension.suffix);
    560652        if (!packet)
    561                 return NULL;
    562 
    563         header = (arp_header_t *) packet_suffix(packet, length);
     653                return ENOMEM;
     654       
     655        arp_header_t *header = (arp_header_t *) packet_suffix(packet, length);
    564656        if (!header) {
    565657                pq_release_remote(arp_globals.net_phone, packet_get_id(packet));
    566                 return NULL;
    567         }
    568 
     658                return ENOMEM;
     659        }
     660       
    569661        header->hardware = htons(device->hardware);
    570662        header->hardware_length = (uint8_t) device->addr->length;
     
    572664        header->protocol_length = (uint8_t) proto->addr->length;
    573665        header->operation = htons(ARPOP_REQUEST);
     666       
    574667        length = sizeof(arp_header_t);
     668       
    575669        memcpy(((uint8_t *) header) + length, device->addr->value,
    576670            device->addr->length);
     
    582676        length += device->addr->length;
    583677        memcpy(((uint8_t *) header) + length, target->value, target->length);
    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) {
     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) {
    588682                pq_release_remote(arp_globals.net_phone, packet_get_id(packet));
    589                 return NULL;
    590         }
    591 
     683                return rc;
     684        }
     685       
    592686        nil_send_msg(device->phone, device_id, packet, SERVICE_ARP);
    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.
     687        return EOK;
     688}
     689
     690/** Return the hardware address for the given protocol address.
     691 *
     692 * Send the ARP request packet if the hardware address is not found in the
     693 * cache.
     694 *
     695 * @param[in]  device_id   Device identifier.
     696 * @param[in]  protocol    Protocol service.
     697 * @param[in]  target      Target protocol address.
     698 * @param[out] translation Where the hardware address of the target is stored.
     699 *
     700 * @return EOK on success.
     701 * @return EAGAIN if the caller should try again.
     702 * @return Other error codes in case of error.
     703 *
     704 */
     705static int arp_translate_message(device_id_t device_id, services_t protocol,
     706    measured_string_t *target, measured_string_t **translation)
     707{
     708        bool retry = false;
     709        int rc;
     710
     711        assert(fibril_mutex_is_locked(&arp_globals.lock));
     712       
     713restart:
     714        if ((!target) || (!translation))
     715                return EBADMEM;
     716       
     717        arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
     718        if (!device)
     719                return ENOENT;
     720       
     721        arp_proto_t *proto = arp_protos_find(&device->protos, protocol);
     722        if ((!proto) || (proto->addr->length != target->length))
     723                return ENOENT;
     724       
     725        arp_trans_t *trans = arp_addr_find(&proto->addresses, target->value,
     726            target->length);
     727        if (trans) {
     728                if (trans->hw_addr) {
     729                        /* The translation is in place. */
     730                        *translation = trans->hw_addr;
     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.
    606833 *
    607834 * @see arp_interface.h
    608835 * @see IS_NET_ARP_MESSAGE()
    609  */
    610 int
    611 arp_message_standalone(ipc_callid_t callid, ipc_call_t *call,
    612     ipc_call_t *answer, int *answer_count)
     836 *
     837 */
     838int il_module_message(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer,
     839    size_t *count)
    613840{
    614841        measured_string_t *address;
    615842        measured_string_t *translation;
    616         char *data;
    617         packet_t *packet;
    618         packet_t *next;
     843        uint8_t *data;
    619844        int rc;
    620845       
    621         *answer_count = 0;
    622         switch (IPC_GET_METHOD(*call)) {
     846        *count = 0;
     847        switch (IPC_GET_IMETHOD(*call)) {
    623848        case IPC_M_PHONE_HUNGUP:
    624849                return EOK;
     
    629854                        return rc;
    630855               
    631                 rc = arp_device_message(IPC_GET_DEVICE(call),
    632                     IPC_GET_SERVICE(call), ARP_GET_NETIF(call), address);
     856                rc = arp_device_message(IPC_GET_DEVICE(*call),
     857                    IPC_GET_SERVICE(*call), ARP_GET_NETIF(*call), address);
    633858                if (rc != EOK) {
    634859                        free(address);
    635860                        free(data);
    636861                }
     862               
    637863                return rc;
    638864       
     
    642868                        return rc;
    643869               
    644                 fibril_rwlock_read_lock(&arp_globals.lock);
    645                 translation = arp_translate_message(IPC_GET_DEVICE(call),
    646                     IPC_GET_SERVICE(call), address);
     870                fibril_mutex_lock(&arp_globals.lock);
     871                rc = arp_translate_message(IPC_GET_DEVICE(*call),
     872                    IPC_GET_SERVICE(*call), address, &translation);
    647873                free(address);
    648874                free(data);
     875               
     876                if (rc != EOK) {
     877                        fibril_mutex_unlock(&arp_globals.lock);
     878                        return rc;
     879                }
     880               
    649881                if (!translation) {
    650                         fibril_rwlock_read_unlock(&arp_globals.lock);
     882                        fibril_mutex_unlock(&arp_globals.lock);
    651883                        return ENOENT;
    652884                }
     885               
    653886                rc = measured_strings_reply(translation, 1);
    654                 fibril_rwlock_read_unlock(&arp_globals.lock);
     887                fibril_mutex_unlock(&arp_globals.lock);
    655888                return rc;
    656 
     889       
    657890        case NET_ARP_CLEAR_DEVICE:
    658                 return arp_clear_device_req(0, IPC_GET_DEVICE(call));
    659 
     891                return arp_clear_device_req(0, IPC_GET_DEVICE(*call));
     892       
    660893        case NET_ARP_CLEAR_ADDRESS:
    661894                rc = measured_strings_receive(&address, &data, 1);
     
    663896                        return rc;
    664897               
    665                 arp_clear_address_req(0, IPC_GET_DEVICE(call),
    666                     IPC_GET_SERVICE(call), address);
     898                arp_clear_address_req(0, IPC_GET_DEVICE(*call),
     899                    IPC_GET_SERVICE(*call), address);
    667900                free(address);
    668901                free(data);
     
    671904        case NET_ARP_CLEAN_CACHE:
    672905                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));
    701906        }
    702907       
     
    704909}
    705910
    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  */
    711 static 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  */
    753911int main(int argc, char *argv[])
    754912{
    755         int rc;
    756        
    757913        /* Start the module */
    758         rc = il_module_start_standalone(il_client_connection);
    759         return rc;
     914        return il_module_start(SERVICE_ARP);
    760915}
    761916
    762917/** @}
    763918 */
    764 
Note: See TracChangeset for help on using the changeset viewer.