Changeset 357b5f5 in mainline for uspace/srv/net


Ignore:
Timestamp:
2011-01-23T20:09:13Z (15 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
fdb9982c
Parents:
cead2aa (diff), 7e36c8d (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge mainline changes.

Location:
uspace/srv/net
Files:
14 deleted
23 edited
2 moved

Legend:

Unmodified
Added
Removed
  • uspace/srv/net/cfg/ne2k

    rcead2aa r357b5f5  
    33NAME=ne2k
    44
    5 NETIF=dp8390
     5NETIF=ne2000
    66NIL=eth
    77IL=ip
    88
    9 IRQ=9
     9IRQ=5
    1010IO=300
    1111
     
    1717IP_ADDR=10.0.2.15
    1818IP_ROUTING=yes
    19 IP_NETMASK=255.255.255.240
     19IP_NETMASK=255.255.255.0
    2020IP_BROADCAST=10.0.2.255
    2121IP_GATEWAY=10.0.2.2
    2222ARP=arp
    2323
    24 MTU=1492
     24MTU=1500
  • uspace/srv/net/il/arp/Makefile

    rcead2aa r357b5f5  
    3434
    3535SOURCES = \
    36         arp.c \
    37         arp_module.c
     36        arp.c
    3837
    3938include $(USPACE_PREFIX)/Makefile.common
  • uspace/srv/net/il/arp/arp.c

    rcead2aa r357b5f5  
    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>
     
    5450#include <ipc/arp.h>
    5551#include <ipc/il.h>
     52#include <ipc/nil.h>
    5653#include <byteorder.h>
    5754#include <errno.h>
    58 
    5955#include <net/modules.h>
    6056#include <net/device.h>
    6157#include <net/packet.h>
    62 
    63 #include <nil_interface.h>
     58#include <nil_remote.h>
    6459#include <protocol_map.h>
    6560#include <packet_client.h>
    6661#include <packet_remote.h>
    67 #include <il_interface.h>
    68 #include <il_local.h>
    69 
     62#include <il_remote.h>
     63#include <il_skel.h>
     64#include "arp.h"
    7065
    7166/** ARP module name. */
    7267#define NAME  "arp"
    7368
     69/** Number of microseconds to wait for an ARP reply. */
     70#define ARP_TRANS_WAIT  1000000
     71
     72/** @name ARP operation codes definitions */
     73/*@{*/
     74
     75/** REQUEST operation code. */
     76#define ARPOP_REQUEST  1
     77
     78/** REPLY operation code. */
     79#define ARPOP_REPLY  2
     80
     81/*@}*/
     82
     83/** Type definition of an ARP protocol header.
     84 * @see arp_header
     85 */
     86typedef struct arp_header arp_header_t;
     87
     88/** ARP protocol header. */
     89struct arp_header {
     90        /**
     91         * Hardware type identifier.
     92         * @see hardware.h
     93         */
     94        uint16_t hardware;
     95       
     96        /** Protocol identifier. */
     97        uint16_t protocol;
     98        /** Hardware address length in bytes. */
     99        uint8_t hardware_length;
     100        /** Protocol address length in bytes. */
     101        uint8_t protocol_length;
     102       
     103        /**
     104         * ARP packet type.
     105         * @see arp_oc.h
     106         */
     107        uint16_t operation;
     108} __attribute__ ((packed));
     109
    74110/** ARP global data. */
    75111arp_globals_t arp_globals;
     
    77113DEVICE_MAP_IMPLEMENT(arp_cache, arp_device_t);
    78114INT_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.
     115GENERIC_CHAR_MAP_IMPLEMENT(arp_addr, arp_trans_t);
     116
     117static void arp_clear_trans(arp_trans_t *trans)
     118{
     119        if (trans->hw_addr) {
     120                free(trans->hw_addr);
     121                trans->hw_addr = NULL;
     122        }
     123       
     124        fibril_condvar_broadcast(&trans->cv);
     125}
     126
     127static void arp_clear_addr(arp_addr_t *addresses)
     128{
     129        int count;
     130       
     131        for (count = arp_addr_count(addresses) - 1; count >= 0; count--) {
     132                arp_trans_t *trans = arp_addr_items_get_index(&addresses->values,
     133                    count);
     134                if (trans)
     135                        arp_clear_trans(trans);
     136        }
     137}
     138
     139/** Clear the device specific data.
     140 *
     141 * @param[in] device Device specific data.
    84142 */
    85143static void arp_clear_device(arp_device_t *device)
    86144{
    87145        int count;
    88         arp_proto_t *proto;
    89 
     146       
    90147        for (count = arp_protos_count(&device->protos) - 1; count >= 0;
    91148            count--) {
    92                 proto = arp_protos_get_index(&device->protos, count);
     149                arp_proto_t *proto = arp_protos_get_index(&device->protos,
     150                    count);
     151               
    93152                if (proto) {
    94153                        if (proto->addr)
    95154                                free(proto->addr);
     155                       
    96156                        if (proto->addr_data)
    97157                                free(proto->addr_data);
     158                       
     159                        arp_clear_addr(&proto->addresses);
    98160                        arp_addr_destroy(&proto->addresses);
    99161                }
    100162        }
     163       
    101164        arp_protos_clear(&device->protos);
    102165}
     
    105168{
    106169        int count;
    107         arp_device_t *device;
    108 
    109         fibril_rwlock_write_lock(&arp_globals.lock);
     170       
     171        fibril_mutex_lock(&arp_globals.lock);
    110172        for (count = arp_cache_count(&arp_globals.cache) - 1; count >= 0;
    111173            count--) {
    112                 device = arp_cache_get_index(&arp_globals.cache, count);
     174                arp_device_t *device = arp_cache_get_index(&arp_globals.cache,
     175                    count);
     176               
    113177                if (device) {
    114178                        arp_clear_device(device);
    115179                        if (device->addr_data)
    116180                                free(device->addr_data);
     181                       
    117182                        if (device->broadcast_data)
    118183                                free(device->broadcast_data);
    119184                }
    120185        }
     186       
    121187        arp_cache_clear(&arp_globals.cache);
    122         fibril_rwlock_write_unlock(&arp_globals.lock);
    123         printf("Cache cleaned\n");
     188        fibril_mutex_unlock(&arp_globals.lock);
     189       
    124190        return EOK;
    125191}
     
    128194    services_t protocol, measured_string_t *address)
    129195{
    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);
     196        fibril_mutex_lock(&arp_globals.lock);
     197       
     198        arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
    135199        if (!device) {
    136                 fibril_rwlock_write_unlock(&arp_globals.lock);
     200                fibril_mutex_unlock(&arp_globals.lock);
    137201                return ENOENT;
    138202        }
    139         proto = arp_protos_find(&device->protos, protocol);
     203       
     204        arp_proto_t *proto = arp_protos_find(&device->protos, protocol);
    140205        if (!proto) {
    141                 fibril_rwlock_write_unlock(&arp_globals.lock);
     206                fibril_mutex_unlock(&arp_globals.lock);
    142207                return ENOENT;
    143208        }
     209       
     210        arp_trans_t *trans = arp_addr_find(&proto->addresses, address->value,
     211            address->length);
     212        if (trans)
     213                arp_clear_trans(trans);
     214       
    144215        arp_addr_exclude(&proto->addresses, address->value, address->length);
    145         fibril_rwlock_write_unlock(&arp_globals.lock);
     216       
     217        fibril_mutex_unlock(&arp_globals.lock);
    146218        return EOK;
    147219}
    148220
    149 
    150221static int arp_clear_device_req(int arp_phone, device_id_t device_id)
    151222{
    152         arp_device_t *device;
    153 
    154         fibril_rwlock_write_lock(&arp_globals.lock);
    155         device = arp_cache_find(&arp_globals.cache, device_id);
     223        fibril_mutex_lock(&arp_globals.lock);
     224       
     225        arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
    156226        if (!device) {
    157                 fibril_rwlock_write_unlock(&arp_globals.lock);
     227                fibril_mutex_unlock(&arp_globals.lock);
    158228                return ENOENT;
    159229        }
     230       
    160231        arp_clear_device(device);
    161         printf("Device %d cleared\n", device_id);
    162         fibril_rwlock_write_unlock(&arp_globals.lock);
     232       
     233        fibril_mutex_unlock(&arp_globals.lock);
    163234        return EOK;
    164235}
    165236
    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.
     237/** Create new protocol specific data.
     238 *
     239 * Allocate and return the needed memory block as the proto parameter.
     240 *
     241 * @param[out] proto   Allocated protocol specific data.
     242 * @param[in]  service Protocol module service.
     243 * @param[in]  address Actual protocol device address.
     244 *
     245 * @return EOK on success.
     246 * @return ENOMEM if there is not enough memory left.
     247 *
    175248 */
    176249static int arp_proto_create(arp_proto_t **proto, services_t service,
    177250    measured_string_t *address)
    178251{
    179         int rc;
    180 
    181252        *proto = (arp_proto_t *) malloc(sizeof(arp_proto_t));
    182253        if (!*proto)
     
    187258        (*proto)->addr_data = address->value;
    188259       
    189         rc = arp_addr_initialize(&(*proto)->addresses);
     260        int rc = arp_addr_initialize(&(*proto)->addresses);
    190261        if (rc != EOK) {
    191262                free(*proto);
     
    196267}
    197268
    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;
     269/** Process the received ARP packet.
     270 *
     271 * Update the source hardware address if the source entry exists or the packet
     272 * is targeted to my protocol address.
     273 *
     274 * Respond to the ARP request if the packet is the ARP request and is
     275 * targeted to my address.
     276 *
     277 * @param[in]     device_id Source device identifier.
     278 * @param[in,out] packet    Received packet.
     279 *
     280 * @return EOK on success and the packet is no longer needed.
     281 * @return One on success and the packet has been reused.
     282 * @return EINVAL if the packet is too small to carry an ARP
     283 *         packet.
     284 * @return EINVAL if the received address lengths differs from
     285 *         the registered values.
     286 * @return ENOENT if the device is not found in the cache.
     287 * @return ENOENT if the protocol for the device is not found in
     288 *         the cache.
     289 * @return ENOMEM if there is not enough memory left.
     290 *
     291 */
     292static int arp_receive_message(device_id_t device_id, packet_t *packet)
     293{
    221294        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);
     295       
     296        size_t length = packet_get_data_length(packet);
    431297        if (length <= sizeof(arp_header_t))
    432298                return EINVAL;
    433 
    434         device = arp_cache_find(&arp_globals.cache, device_id);
     299       
     300        arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
    435301        if (!device)
    436302                return ENOENT;
    437 
    438         header = (arp_header_t *) packet_get_data(packet);
     303       
     304        arp_header_t *header = (arp_header_t *) packet_get_data(packet);
    439305        if ((ntohs(header->hardware) != device->hardware) ||
    440306            (length < sizeof(arp_header_t) + header->hardware_length * 2U +
     
    442308                return EINVAL;
    443309        }
    444 
    445         proto = arp_protos_find(&device->protos,
     310       
     311        arp_proto_t *proto = arp_protos_find(&device->protos,
    446312            protocol_unmap(device->service, ntohs(header->protocol)));
    447313        if (!proto)
    448314                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)) {
     315       
     316        uint8_t *src_hw = ((uint8_t *) header) + sizeof(arp_header_t);
     317        uint8_t *src_proto = src_hw + header->hardware_length;
     318        uint8_t *des_hw = src_proto + header->protocol_length;
     319        uint8_t *des_proto = des_hw + header->hardware_length;
     320       
     321        arp_trans_t *trans = arp_addr_find(&proto->addresses, src_proto,
     322            header->protocol_length);
     323       
     324        if ((trans) && (trans->hw_addr)) {
     325                /* Translation exists */
     326                if (trans->hw_addr->length != header->hardware_length)
    460327                        return EINVAL;
    461                 }
    462                 memcpy(hw_source->value, src_hw, hw_source->length);
    463         }
     328               
     329                memcpy(trans->hw_addr->value, src_hw, trans->hw_addr->length);
     330        }
     331       
    464332        /* Is my protocol address? */
    465         if (proto->addr->length != CONVERT_SIZE(uint8_t, char,
    466             header->protocol_length)) {
     333        if (proto->addr->length != header->protocol_length)
    467334                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)
     335       
     336        if (!bcmp(proto->addr->value, des_proto, proto->addr->length)) {
     337                if (!trans) {
     338                        /* Update the translation */
     339                        trans = (arp_trans_t *) malloc(sizeof(arp_trans_t));
     340                        if (!trans)
    477341                                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)
     342                       
     343                        trans->hw_addr = NULL;
     344                        fibril_condvar_initialize(&trans->cv);
     345                        rc = arp_addr_add(&proto->addresses, src_proto,
     346                            header->protocol_length, trans);
     347                        if (rc != EOK) {
     348                                /* The generic char map has already freed trans! */
    483349                                return rc;
    484                 }
     350                        }
     351                }
     352               
     353                if (!trans->hw_addr) {
     354                        trans->hw_addr = measured_string_create_bulk(src_hw,
     355                            header->hardware_length);
     356                        if (!trans->hw_addr)
     357                                return ENOMEM;
     358                       
     359                        /* Notify the fibrils that wait for the translation. */
     360                        fibril_condvar_broadcast(&trans->cv);
     361                }
     362               
    485363                if (ntohs(header->operation) == ARPOP_REQUEST) {
    486364                        header->operation = htons(ARPOP_REPLY);
     
    490368                        memcpy(src_hw, device->addr->value,
    491369                            device->packet_dimension.addr_len);
    492                         memcpy(des_hw, hw_source->value,
     370                        memcpy(des_hw, trans->hw_addr->value,
    493371                            header->hardware_length);
    494372                       
     
    503381                }
    504382        }
    505 
     383       
    506384        return EOK;
    507385}
    508386
    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;
     387/** Update the device content length according to the new MTU value.
     388 *
     389 * @param[in] device_id Device identifier.
     390 * @param[in] mtu       New MTU value.
     391 *
     392 * @return ENOENT if device is not found.
     393 * @return EOK on success.
     394 *
     395 */
     396static int arp_mtu_changed_message(device_id_t device_id, size_t mtu)
     397{
     398        fibril_mutex_lock(&arp_globals.lock);
     399       
     400        arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
     401        if (!device) {
     402                fibril_mutex_unlock(&arp_globals.lock);
     403                return ENOENT;
     404        }
     405       
     406        device->packet_dimension.content = mtu;
     407       
     408        fibril_mutex_unlock(&arp_globals.lock);
     409       
     410        printf("%s: Device %d changed MTU to %zu\n", NAME, device_id, mtu);
     411       
     412        return EOK;
     413}
     414
     415/** Process IPC messages from the registered device driver modules
     416 *
     417 * @param[in]     iid   Message identifier.
     418 * @param[in,out] icall Message parameters.
     419 *
     420 */
     421static void arp_receiver(ipc_callid_t iid, ipc_call_t *icall)
     422{
    533423        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 
     424        int rc;
     425       
     426        while (true) {
     427                switch (IPC_GET_IMETHOD(*icall)) {
     428                case NET_IL_DEVICE_STATE:
     429                        /* Do nothing - keep the cache */
     430                        ipc_answer_0(iid, (sysarg_t) EOK);
     431                        break;
     432               
     433                case NET_IL_RECEIVED:
     434                        rc = packet_translate_remote(arp_globals.net_phone, &packet,
     435                            IPC_GET_PACKET(*icall));
     436                        if (rc == EOK) {
     437                                fibril_mutex_lock(&arp_globals.lock);
     438                                do {
     439                                        packet_t *next = pq_detach(packet);
     440                                        rc = arp_receive_message(IPC_GET_DEVICE(*icall), packet);
     441                                        if (rc != 1) {
     442                                                pq_release_remote(arp_globals.net_phone,
     443                                                    packet_get_id(packet));
     444                                        }
     445                                       
     446                                        packet = next;
     447                                } while (packet);
     448                                fibril_mutex_unlock(&arp_globals.lock);
     449                        }
     450                        ipc_answer_0(iid, (sysarg_t) rc);
     451                        break;
     452               
     453                case NET_IL_MTU_CHANGED:
     454                        rc = arp_mtu_changed_message(IPC_GET_DEVICE(*icall),
     455                            IPC_GET_MTU(*icall));
     456                        ipc_answer_0(iid, (sysarg_t) rc);
     457                        break;
     458               
     459                default:
     460                        ipc_answer_0(iid, (sysarg_t) ENOTSUP);
     461                }
     462               
     463                iid = async_get_call(icall);
     464        }
     465}
     466
     467/** Register the device.
     468 *
     469 * Create new device entry in the cache or update the protocol address if the
     470 * device with the device identifier and the driver service exists.
     471 *
     472 * @param[in] device_id Device identifier.
     473 * @param[in] service   Device driver service.
     474 * @param[in] protocol  Protocol service.
     475 * @param[in] address   Actual device protocol address.
     476 *
     477 * @return EOK on success.
     478 * @return EEXIST if another device with the same device identifier
     479 *         and different driver service exists.
     480 * @return ENOMEM if there is not enough memory left.
     481 * @return Other error codes as defined for the
     482 *         measured_strings_return() function.
     483 *
     484 */
     485static int arp_device_message(device_id_t device_id, services_t service,
     486    services_t protocol, measured_string_t *address)
     487{
     488        int index;
     489        int rc;
     490       
     491        fibril_mutex_lock(&arp_globals.lock);
     492       
     493        /* An existing device? */
     494        arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
     495        if (device) {
     496                if (device->service != service) {
     497                        printf("%s: Device %d already exists\n", NAME,
     498                            device->device_id);
     499                        fibril_mutex_unlock(&arp_globals.lock);
     500                        return EEXIST;
     501                }
     502               
     503                arp_proto_t *proto = arp_protos_find(&device->protos, protocol);
     504                if (proto) {
     505                        free(proto->addr);
     506                        free(proto->addr_data);
     507                        proto->addr = address;
     508                        proto->addr_data = address->value;
     509                } else {
     510                        rc = arp_proto_create(&proto, protocol, address);
     511                        if (rc != EOK) {
     512                                fibril_mutex_unlock(&arp_globals.lock);
     513                                return rc;
     514                        }
     515                       
     516                        index = arp_protos_add(&device->protos, proto->service,
     517                            proto);
     518                        if (index < 0) {
     519                                fibril_mutex_unlock(&arp_globals.lock);
     520                                free(proto);
     521                                return index;
     522                        }
     523                       
     524                        printf("%s: New protocol added (id: %d, proto: %d)\n", NAME,
     525                            device_id, protocol);
     526                }
     527        } else {
     528                hw_type_t hardware = hardware_map(service);
     529                if (!hardware)
     530                        return ENOENT;
     531               
     532                /* Create new device */
     533                device = (arp_device_t *) malloc(sizeof(arp_device_t));
     534                if (!device) {
     535                        fibril_mutex_unlock(&arp_globals.lock);
     536                        return ENOMEM;
     537                }
     538               
     539                device->hardware = hardware;
     540                device->device_id = device_id;
     541                rc = arp_protos_initialize(&device->protos);
     542                if (rc != EOK) {
     543                        fibril_mutex_unlock(&arp_globals.lock);
     544                        free(device);
     545                        return rc;
     546                }
     547               
     548                arp_proto_t *proto;
     549                rc = arp_proto_create(&proto, protocol, address);
     550                if (rc != EOK) {
     551                        fibril_mutex_unlock(&arp_globals.lock);
     552                        free(device);
     553                        return rc;
     554                }
     555               
     556                index = arp_protos_add(&device->protos, proto->service, proto);
     557                if (index < 0) {
     558                        fibril_mutex_unlock(&arp_globals.lock);
     559                        arp_protos_destroy(&device->protos);
     560                        free(device);
     561                        return index;
     562                }
     563               
     564                device->service = service;
     565               
     566                /* Bind */
     567                device->phone = nil_bind_service(device->service,
     568                    (sysarg_t) device->device_id, SERVICE_ARP,
     569                    arp_receiver);
     570                if (device->phone < 0) {
     571                        fibril_mutex_unlock(&arp_globals.lock);
     572                        arp_protos_destroy(&device->protos);
     573                        free(device);
     574                        return EREFUSED;
     575                }
     576               
     577                /* Get packet dimensions */
     578                rc = nil_packet_size_req(device->phone, device_id,
     579                    &device->packet_dimension);
     580                if (rc != EOK) {
     581                        fibril_mutex_unlock(&arp_globals.lock);
     582                        arp_protos_destroy(&device->protos);
     583                        free(device);
     584                        return rc;
     585                }
     586               
     587                /* Get hardware address */
     588                rc = nil_get_addr_req(device->phone, device_id, &device->addr,
     589                    &device->addr_data);
     590                if (rc != EOK) {
     591                        fibril_mutex_unlock(&arp_globals.lock);
     592                        arp_protos_destroy(&device->protos);
     593                        free(device);
     594                        return rc;
     595                }
     596               
     597                /* Get broadcast address */
     598                rc = nil_get_broadcast_addr_req(device->phone, device_id,
     599                    &device->broadcast_addr, &device->broadcast_data);
     600                if (rc != EOK) {
     601                        fibril_mutex_unlock(&arp_globals.lock);
     602                        free(device->addr);
     603                        free(device->addr_data);
     604                        arp_protos_destroy(&device->protos);
     605                        free(device);
     606                        return rc;
     607                }
     608               
     609                rc = arp_cache_add(&arp_globals.cache, device->device_id,
     610                    device);
     611                if (rc != EOK) {
     612                        fibril_mutex_unlock(&arp_globals.lock);
     613                        free(device->addr);
     614                        free(device->addr_data);
     615                        free(device->broadcast_addr);
     616                        free(device->broadcast_data);
     617                        arp_protos_destroy(&device->protos);
     618                        free(device);
     619                        return rc;
     620                }
     621                printf("%s: Device registered (id: %d, type: 0x%x, service: %d,"
     622                    " proto: %d)\n", NAME, device->device_id, device->hardware,
     623                    device->service, protocol);
     624        }
     625       
     626        fibril_mutex_unlock(&arp_globals.lock);
     627        return EOK;
     628}
     629
     630int il_initialize(int net_phone)
     631{
     632        fibril_mutex_initialize(&arp_globals.lock);
     633       
     634        fibril_mutex_lock(&arp_globals.lock);
     635        arp_globals.net_phone = net_phone;
     636        int rc = arp_cache_initialize(&arp_globals.cache);
     637        fibril_mutex_unlock(&arp_globals.lock);
     638       
     639        return rc;
     640}
     641
     642static int arp_send_request(device_id_t device_id, services_t protocol,
     643    measured_string_t *target, arp_device_t *device, arp_proto_t *proto)
     644{
    551645        /* 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));
     646        size_t length = 8 + 2 * (proto->addr->length + device->addr->length);
    554647        if (length > device->packet_dimension.content)
    555                 return NULL;
    556 
    557         packet = packet_get_4_remote(arp_globals.net_phone,
     648                return ELIMIT;
     649       
     650        packet_t *packet = packet_get_4_remote(arp_globals.net_phone,
    558651            device->packet_dimension.addr_len, device->packet_dimension.prefix,
    559652            length, device->packet_dimension.suffix);
    560653        if (!packet)
    561                 return NULL;
    562 
    563         header = (arp_header_t *) packet_suffix(packet, length);
     654                return ENOMEM;
     655       
     656        arp_header_t *header = (arp_header_t *) packet_suffix(packet, length);
    564657        if (!header) {
    565658                pq_release_remote(arp_globals.net_phone, packet_get_id(packet));
    566                 return NULL;
    567         }
    568 
     659                return ENOMEM;
     660        }
     661       
    569662        header->hardware = htons(device->hardware);
    570663        header->hardware_length = (uint8_t) device->addr->length;
     
    572665        header->protocol_length = (uint8_t) proto->addr->length;
    573666        header->operation = htons(ARPOP_REQUEST);
     667       
    574668        length = sizeof(arp_header_t);
     669       
    575670        memcpy(((uint8_t *) header) + length, device->addr->value,
    576671            device->addr->length);
     
    582677        length += device->addr->length;
    583678        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) {
     679       
     680        int rc = packet_set_addr(packet, (uint8_t *) device->addr->value,
     681            (uint8_t *) device->broadcast_addr->value, device->addr->length);
     682        if (rc != EOK) {
    588683                pq_release_remote(arp_globals.net_phone, packet_get_id(packet));
    589                 return NULL;
    590         }
    591 
     684                return rc;
     685        }
     686       
    592687        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.
     688        return EOK;
     689}
     690
     691/** Return the hardware address for the given protocol address.
     692 *
     693 * Send the ARP request packet if the hardware address is not found in the
     694 * cache.
     695 *
     696 * @param[in]  device_id   Device identifier.
     697 * @param[in]  protocol    Protocol service.
     698 * @param[in]  target      Target protocol address.
     699 * @param[out] translation Where the hardware address of the target is stored.
     700 *
     701 * @return EOK on success.
     702 * @return EAGAIN if the caller should try again.
     703 * @return Other error codes in case of error.
     704 *
     705 */
     706static int arp_translate_message(device_id_t device_id, services_t protocol,
     707    measured_string_t *target, measured_string_t **translation)
     708{
     709        bool retry = false;
     710        int rc;
     711
     712        assert(fibril_mutex_is_locked(&arp_globals.lock));
     713       
     714restart:
     715        if ((!target) || (!translation))
     716                return EBADMEM;
     717       
     718        arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
     719        if (!device)
     720                return ENOENT;
     721       
     722        arp_proto_t *proto = arp_protos_find(&device->protos, protocol);
     723        if ((!proto) || (proto->addr->length != target->length))
     724                return ENOENT;
     725       
     726        arp_trans_t *trans = arp_addr_find(&proto->addresses, target->value,
     727            target->length);
     728        if (trans) {
     729                if (trans->hw_addr) {
     730                        /* The translation is in place. */
     731                        *translation = trans->hw_addr;
     732                        return EOK;
     733                }
     734               
     735                if (retry) {
     736                        /*
     737                         * We may get here as a result of being signalled for
     738                         * some reason while waiting for the translation (e.g.
     739                         * translation becoming available, record being removed
     740                         * from the table) and then losing the race for
     741                         * the arp_globals.lock with someone else who modified
     742                         * the table.
     743                         *
     744                         * Remove the incomplete record so that it is possible
     745                         * to make new ARP requests.
     746                         */
     747                        arp_clear_trans(trans);
     748                        arp_addr_exclude(&proto->addresses, target->value,
     749                            target->length);
     750                        return EAGAIN;
     751                }
     752               
     753                /*
     754                 * We are a random passer-by who merely joins an already waiting
     755                 * fibril in waiting for the translation.
     756                 */
     757                rc = fibril_condvar_wait_timeout(&trans->cv, &arp_globals.lock,
     758                    ARP_TRANS_WAIT);
     759                if (rc == ETIMEOUT)
     760                        return ENOENT;
     761               
     762                /*
     763                 * Need to recheck because we did not hold the lock while
     764                 * sleeping on the condition variable.
     765                 */
     766                retry = true;
     767                goto restart;
     768        }
     769       
     770        if (retry)
     771                return EAGAIN;
     772
     773        /*
     774         * We are under the protection of arp_globals.lock, so we can afford to
     775         * first send the ARP request and then insert an incomplete ARP record.
     776         * The incomplete record is used to tell any other potential waiter
     777         * that this fibril has already sent the request and that it is waiting
     778         * for the answer. Lastly, any fibril which sees the incomplete request
     779         * can perform a timed wait on its condition variable to wait for the
     780         * ARP reply to arrive.
     781         */
     782
     783        rc = arp_send_request(device_id, protocol, target, device, proto);
     784        if (rc != EOK)
     785                return rc;
     786       
     787        trans = (arp_trans_t *) malloc(sizeof(arp_trans_t));
     788        if (!trans)
     789                return ENOMEM;
     790       
     791        trans->hw_addr = NULL;
     792        fibril_condvar_initialize(&trans->cv);
     793       
     794        rc = arp_addr_add(&proto->addresses, target->value, target->length,
     795            trans);
     796        if (rc != EOK) {
     797                /* The generic char map has already freed trans! */
     798                return rc;
     799        }
     800       
     801        rc = fibril_condvar_wait_timeout(&trans->cv, &arp_globals.lock,
     802            ARP_TRANS_WAIT);
     803        if (rc == ETIMEOUT) {
     804                /*
     805                 * Remove the incomplete record so that it is possible to make
     806                 * new ARP requests.
     807                 */
     808                arp_clear_trans(trans);
     809                arp_addr_exclude(&proto->addresses, target->value,
     810                    target->length);
     811                return ENOENT;
     812        }
     813       
     814        /*
     815         * We need to recheck that the translation has indeed become available,
     816         * because we dropped the arp_globals.lock while sleeping on the
     817         * condition variable and someone else might have e.g. removed the
     818         * translation before we managed to lock arp_globals.lock again.
     819         */
     820
     821        retry = true;
     822        goto restart;
     823}
     824
     825/** Process the ARP message.
     826 *
     827 * @param[in]  callid Message identifier.
     828 * @param[in]  call   Message parameters.
     829 * @param[out] answer Answer.
     830 * @param[out] count  Number of arguments of the answer.
     831 *
     832 * @return EOK on success.
     833 * @return ENOTSUP if the message is not known.
    606834 *
    607835 * @see arp_interface.h
    608836 * @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)
     837 *
     838 */
     839int il_module_message(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer,
     840    size_t *count)
    613841{
    614842        measured_string_t *address;
    615843        measured_string_t *translation;
    616         char *data;
    617         packet_t *packet;
    618         packet_t *next;
     844        uint8_t *data;
    619845        int rc;
    620846       
    621         *answer_count = 0;
    622         switch (IPC_GET_METHOD(*call)) {
     847        *count = 0;
     848        switch (IPC_GET_IMETHOD(*call)) {
    623849        case IPC_M_PHONE_HUNGUP:
    624850                return EOK;
     
    629855                        return rc;
    630856               
    631                 rc = arp_device_message(IPC_GET_DEVICE(call),
    632                     IPC_GET_SERVICE(call), ARP_GET_NETIF(call), address);
     857                rc = arp_device_message(IPC_GET_DEVICE(*call),
     858                    IPC_GET_SERVICE(*call), ARP_GET_NETIF(*call), address);
    633859                if (rc != EOK) {
    634860                        free(address);
    635861                        free(data);
    636862                }
     863               
    637864                return rc;
    638865       
     
    642869                        return rc;
    643870               
    644                 fibril_rwlock_read_lock(&arp_globals.lock);
    645                 translation = arp_translate_message(IPC_GET_DEVICE(call),
    646                     IPC_GET_SERVICE(call), address);
     871                fibril_mutex_lock(&arp_globals.lock);
     872                rc = arp_translate_message(IPC_GET_DEVICE(*call),
     873                    IPC_GET_SERVICE(*call), address, &translation);
    647874                free(address);
    648875                free(data);
     876               
     877                if (rc != EOK) {
     878                        fibril_mutex_unlock(&arp_globals.lock);
     879                        return rc;
     880                }
     881               
    649882                if (!translation) {
    650                         fibril_rwlock_read_unlock(&arp_globals.lock);
     883                        fibril_mutex_unlock(&arp_globals.lock);
    651884                        return ENOENT;
    652885                }
     886               
    653887                rc = measured_strings_reply(translation, 1);
    654                 fibril_rwlock_read_unlock(&arp_globals.lock);
     888                fibril_mutex_unlock(&arp_globals.lock);
    655889                return rc;
    656 
     890       
    657891        case NET_ARP_CLEAR_DEVICE:
    658                 return arp_clear_device_req(0, IPC_GET_DEVICE(call));
    659 
     892                return arp_clear_device_req(0, IPC_GET_DEVICE(*call));
     893       
    660894        case NET_ARP_CLEAR_ADDRESS:
    661895                rc = measured_strings_receive(&address, &data, 1);
     
    663897                        return rc;
    664898               
    665                 arp_clear_address_req(0, IPC_GET_DEVICE(call),
    666                     IPC_GET_SERVICE(call), address);
     899                arp_clear_address_req(0, IPC_GET_DEVICE(*call),
     900                    IPC_GET_SERVICE(*call), address);
    667901                free(address);
    668902                free(data);
     
    671905        case NET_ARP_CLEAN_CACHE:
    672906                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));
    701907        }
    702908       
     
    704910}
    705911
    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  */
    753912int main(int argc, char *argv[])
    754913{
    755         int rc;
    756        
    757914        /* Start the module */
    758         rc = il_module_start_standalone(il_client_connection);
    759         return rc;
     915        return il_module_start(SERVICE_ARP);
    760916}
    761917
    762918/** @}
    763919 */
    764 
  • uspace/srv/net/il/arp/arp.h

    rcead2aa r357b5f5  
    6565typedef struct arp_proto arp_proto_t;
    6666
     67/** Type definition of the ARP address translation record.
     68 * @see arp_trans
     69 */
     70typedef struct arp_trans arp_trans_t;
     71
    6772/** ARP address map.
    6873 *
     
    7075 * @see generic_char_map.h
    7176 */
    72 GENERIC_CHAR_MAP_DECLARE(arp_addr, measured_string_t);
     77GENERIC_CHAR_MAP_DECLARE(arp_addr, arp_trans_t);
    7378
    7479/** ARP address cache.
     
    8994struct arp_device {
    9095        /** Actual device hardware address. */
    91         measured_string_t * addr;
     96        measured_string_t *addr;
    9297        /** Actual device hardware address data. */
    93         char *addr_data;
     98        uint8_t *addr_data;
    9499        /** Broadcast device hardware address. */
    95         measured_string_t * broadcast_addr;
     100        measured_string_t *broadcast_addr;
    96101        /** Broadcast device hardware address data. */
    97         char *broadcast_data;
     102        uint8_t *broadcast_data;
    98103        /** Device identifier. */
    99104        device_id_t device_id;
     
    120125        arp_cache_t cache;
    121126       
    122         /**
    123          * The client connection processing function.
    124          * The module skeleton propagates its own one.
    125          */
    126         async_client_conn_t client_connection;
    127        
    128127        /** Networking module phone. */
    129128        int net_phone;
    130129        /** Safety lock. */
    131         fibril_rwlock_t lock;
     130        fibril_mutex_t lock;
    132131};
    133132
     
    137136        measured_string_t *addr;
    138137        /** Actual device protocol address data. */
    139         char *addr_data;
     138        uint8_t *addr_data;
    140139        /** Address map. */
    141140        arp_addr_t addresses;
     
    144143};
    145144
     145/** ARP address translation record. */
     146struct arp_trans {
     147        /**
     148         * Hardware address for the translation. NULL denotes an incomplete
     149         * record with possible waiters.
     150         */
     151        measured_string_t *hw_addr;
     152        /** Condition variable used for waiting for completion of the record. */
     153        fibril_condvar_t cv;
     154};
     155
    146156#endif
    147157
    148158/** @}
    149159 */
     160
  • uspace/srv/net/il/ip/Makefile

    rcead2aa r357b5f5  
    3434
    3535SOURCES = \
    36         ip.c \
    37         ip_module.c
     36        ip.c
    3837
    3938include $(USPACE_PREFIX)/Makefile.common
  • uspace/srv/net/il/ip/ip.c

    rcead2aa r357b5f5  
    3535 * @see arp.h
    3636 */
    37 
    38 #include "ip.h"
    39 #include "ip_module.h"
    4037
    4138#include <async.h>
     
    5249#include <sys/types.h>
    5350#include <byteorder.h>
     51#include "ip.h"
    5452
    5553#include <adt/measured_strings.h>
     
    6967#include <net_checksum.h>
    7068#include <icmp_client.h>
    71 #include <icmp_interface.h>
    72 #include <il_interface.h>
     69#include <icmp_remote.h>
    7370#include <ip_client.h>
    7471#include <ip_interface.h>
    7572#include <ip_header.h>
    7673#include <net_interface.h>
    77 #include <nil_interface.h>
    78 #include <tl_interface.h>
     74#include <nil_remote.h>
     75#include <tl_remote.h>
    7976#include <packet_remote.h>
    80 #include <il_local.h>
     77#include <il_remote.h>
     78#include <il_skel.h>
    8179
    8280/** IP module name. */
     
    122120INT_MAP_IMPLEMENT(ip_protos, ip_proto_t);
    123121GENERIC_FIELD_IMPLEMENT(ip_routes, ip_route_t);
     122
     123static void ip_receiver(ipc_callid_t, ipc_call_t *);
    124124
    125125/** Releases the packet and returns the result.
     
    244244}
    245245
    246 /** Initializes the IP module.
    247  *
    248  * @param[in] client_connection The client connection processing function. The
    249  *                      module skeleton propagates its own one.
    250  * @return              EOK on success.
    251  * @return              ENOMEM if there is not enough memory left.
    252  */
    253 int ip_initialize(async_client_conn_t client_connection)
    254 {
    255         int rc;
    256 
     246int il_initialize(int net_phone)
     247{
    257248        fibril_rwlock_initialize(&ip_globals.lock);
    258249        fibril_rwlock_write_lock(&ip_globals.lock);
    259250        fibril_rwlock_initialize(&ip_globals.protos_lock);
    260251        fibril_rwlock_initialize(&ip_globals.netifs_lock);
     252       
     253        ip_globals.net_phone = net_phone;
    261254        ip_globals.packet_counter = 0;
    262255        ip_globals.gateway.address.s_addr = 0;
     
    264257        ip_globals.gateway.gateway.s_addr = 0;
    265258        ip_globals.gateway.netif = NULL;
    266         ip_globals.client_connection = client_connection;
    267        
    268         rc = ip_netifs_initialize(&ip_globals.netifs);
     259       
     260        int rc = ip_netifs_initialize(&ip_globals.netifs);
    269261        if (rc != EOK)
    270262                goto out;
     
    275267        if (rc != EOK)
    276268                goto out;
    277         rc = add_module(NULL, &ip_globals.modules, ARP_NAME, ARP_FILENAME,
    278             SERVICE_ARP, 0, arp_connect_module);
     269        rc = add_module(NULL, &ip_globals.modules, (uint8_t *) ARP_NAME,
     270            (uint8_t *) ARP_FILENAME, SERVICE_ARP, 0, arp_connect_module);
    279271
    280272out:
     
    312304        measured_string_t names[] = {
    313305                {
    314                         (char *) "IPV",
     306                        (uint8_t *) "IPV",
    315307                        3
    316308                },
    317309                {
    318                         (char *) "IP_CONFIG",
     310                        (uint8_t *) "IP_CONFIG",
    319311                        9
    320312                },
    321313                {
    322                         (char *) "IP_ADDR",
     314                        (uint8_t *) "IP_ADDR",
    323315                        7
    324316                },
    325317                {
    326                         (char *) "IP_NETMASK",
     318                        (uint8_t *) "IP_NETMASK",
    327319                        10
    328320                },
    329321                {
    330                         (char *) "IP_GATEWAY",
     322                        (uint8_t *) "IP_GATEWAY",
    331323                        10
    332324                },
    333325                {
    334                         (char *) "IP_BROADCAST",
     326                        (uint8_t *) "IP_BROADCAST",
    335327                        12
    336328                },
    337329                {
    338                         (char *) "ARP",
     330                        (uint8_t *) "ARP",
    339331                        3
    340332                },
    341333                {
    342                         (char *) "IP_ROUTING",
     334                        (uint8_t *) "IP_ROUTING",
    343335                        10
    344336                }
     
    346338        measured_string_t *configuration;
    347339        size_t count = sizeof(names) / sizeof(measured_string_t);
    348         char *data;
     340        uint8_t *data;
    349341        measured_string_t address;
    350342        ip_route_t *route;
     
    368360        if (configuration) {
    369361                if (configuration[0].value)
    370                         ip_netif->ipv = strtol(configuration[0].value, NULL, 0);
    371 
    372                 ip_netif->dhcp = !str_lcmp(configuration[1].value, "dhcp",
     362                        ip_netif->ipv = strtol((char *) configuration[0].value, NULL, 0);
     363               
     364                ip_netif->dhcp = !str_lcmp((char *) configuration[1].value, "dhcp",
    373365                    configuration[1].length);
    374366               
     
    394386                        }
    395387                       
    396                         if ((inet_pton(AF_INET, configuration[2].value,
     388                        if ((inet_pton(AF_INET, (char *) configuration[2].value,
    397389                            (uint8_t *) &route->address.s_addr) != EOK) ||
    398                             (inet_pton(AF_INET, configuration[3].value,
     390                            (inet_pton(AF_INET, (char *) configuration[3].value,
    399391                            (uint8_t *) &route->netmask.s_addr) != EOK) ||
    400                             (inet_pton(AF_INET, configuration[4].value,
     392                            (inet_pton(AF_INET, (char *) configuration[4].value,
    401393                            (uint8_t *) &gateway.s_addr) == EINVAL) ||
    402                             (inet_pton(AF_INET, configuration[5].value,
     394                            (inet_pton(AF_INET, (char *) configuration[5].value,
    403395                            (uint8_t *) &ip_netif->broadcast.s_addr) == EINVAL))
    404396                            {
     
    430422        // binds the netif service which also initializes the device
    431423        ip_netif->phone = nil_bind_service(ip_netif->service,
    432             (ipcarg_t) ip_netif->device_id, SERVICE_IP,
    433             ip_globals.client_connection);
     424            (sysarg_t) ip_netif->device_id, SERVICE_IP,
     425            ip_receiver);
    434426        if (ip_netif->phone < 0) {
    435427                printf("Failed to contact the nil service %d\n",
     
    441433        if (ip_netif->arp) {
    442434                if (route) {
    443                         address.value = (char *) &route->address.s_addr;
    444                         address.length = CONVERT_SIZE(in_addr_t, char, 1);
     435                        address.value = (uint8_t *) &route->address.s_addr;
     436                        address.length = sizeof(in_addr_t);
    445437                       
    446438                        rc = arp_device_req(ip_netif->arp->phone,
     
    477469                ip_globals.gateway.gateway.s_addr = gateway.s_addr;
    478470                ip_globals.gateway.netif = ip_netif;
     471               
     472                char defgateway[INET_ADDRSTRLEN];
     473                inet_ntop(AF_INET, (uint8_t *) &gateway.s_addr,
     474                    defgateway, INET_ADDRSTRLEN);
     475                printf("%s: Default gateway (%s)\n", NAME, defgateway);
    479476        }
    480477
     
    482479}
    483480
    484 /** Updates the device content length according to the new MTU value.
    485  *
    486  * @param[in] device_id The device identifier.
    487  * @param[in] mtu       The new mtu value.
    488  * @return              EOK on success.
    489  * @return              ENOENT if device is not found.
    490  */
    491 static int ip_mtu_changed_message(device_id_t device_id, size_t mtu)
    492 {
     481static int ip_device_req_local(int il_phone, device_id_t device_id,
     482    services_t netif)
     483{
     484        ip_netif_t *ip_netif;
     485        ip_route_t *route;
     486        int index;
     487        int rc;
     488
     489        ip_netif = (ip_netif_t *) malloc(sizeof(ip_netif_t));
     490        if (!ip_netif)
     491                return ENOMEM;
     492
     493        rc = ip_routes_initialize(&ip_netif->routes);
     494        if (rc != EOK) {
     495                free(ip_netif);
     496                return rc;
     497        }
     498
     499        ip_netif->device_id = device_id;
     500        ip_netif->service = netif;
     501        ip_netif->state = NETIF_STOPPED;
     502
     503        fibril_rwlock_write_lock(&ip_globals.netifs_lock);
     504
     505        rc = ip_netif_initialize(ip_netif);
     506        if (rc != EOK) {
     507                fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
     508                ip_routes_destroy(&ip_netif->routes);
     509                free(ip_netif);
     510                return rc;
     511        }
     512        if (ip_netif->arp)
     513                ip_netif->arp->usage++;
     514
     515        // print the settings
     516        printf("%s: Device registered (id: %d, phone: %d, ipv: %d, conf: %s)\n",
     517            NAME, ip_netif->device_id, ip_netif->phone, ip_netif->ipv,
     518            ip_netif->dhcp ? "dhcp" : "static");
     519       
     520        // TODO ipv6 addresses
     521       
     522        char address[INET_ADDRSTRLEN];
     523        char netmask[INET_ADDRSTRLEN];
     524        char gateway[INET_ADDRSTRLEN];
     525       
     526        for (index = 0; index < ip_routes_count(&ip_netif->routes); index++) {
     527                route = ip_routes_get_index(&ip_netif->routes, index);
     528                if (route) {
     529                        inet_ntop(AF_INET, (uint8_t *) &route->address.s_addr,
     530                            address, INET_ADDRSTRLEN);
     531                        inet_ntop(AF_INET, (uint8_t *) &route->netmask.s_addr,
     532                            netmask, INET_ADDRSTRLEN);
     533                        inet_ntop(AF_INET, (uint8_t *) &route->gateway.s_addr,
     534                            gateway, INET_ADDRSTRLEN);
     535                        printf("%s: Route %d (address: %s, netmask: %s, "
     536                            "gateway: %s)\n", NAME, index, address, netmask,
     537                            gateway);
     538                }
     539        }
     540       
     541        inet_ntop(AF_INET, (uint8_t *) &ip_netif->broadcast.s_addr, address,
     542            INET_ADDRSTRLEN);
     543        fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
     544
     545        printf("%s: Broadcast (%s)\n", NAME, address);
     546
     547        return EOK;
     548}
     549
     550/** Searches the network interfaces if there is a suitable route.
     551 *
     552 * @param[in] netif     The network interface to be searched for routes. May be
     553 *                      NULL.
     554 * @param[in] destination The destination address.
     555 * @return              The found route.
     556 * @return              NULL if no route was found.
     557 */
     558static ip_route_t *ip_netif_find_route(ip_netif_t *netif,
     559    in_addr_t destination)
     560{
     561        int index;
     562        ip_route_t *route;
     563       
     564        if (!netif)
     565                return NULL;
     566       
     567        /* Start with the first one (the direct route) */
     568        for (index = 0; index < ip_routes_count(&netif->routes); index++) {
     569                route = ip_routes_get_index(&netif->routes, index);
     570                if ((route) &&
     571                    ((route->address.s_addr & route->netmask.s_addr) ==
     572                    (destination.s_addr & route->netmask.s_addr)))
     573                        return route;
     574        }
     575
     576        return NULL;
     577}
     578
     579/** Searches all network interfaces if there is a suitable route.
     580 *
     581 * @param[in] destination The destination address.
     582 * @return              The found route.
     583 * @return              NULL if no route was found.
     584 */
     585static ip_route_t *ip_find_route(in_addr_t destination) {
     586        int index;
     587        ip_route_t *route;
    493588        ip_netif_t *netif;
    494589
    495         fibril_rwlock_write_lock(&ip_globals.netifs_lock);
    496         netif = ip_netifs_find(&ip_globals.netifs, device_id);
    497         if (!netif) {
    498                 fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
    499                 return ENOENT;
    500         }
    501         netif->packet_dimension.content = mtu;
    502         fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
    503 
    504         printf("%s: Device %d changed MTU to %zu\n", NAME, device_id, mtu);
    505 
    506         return EOK;
    507 }
    508 
    509 /** Updates the device state.
    510  *
    511  * @param[in] device_id The device identifier.
    512  * @param[in] state     The new state value.
    513  * @return              EOK on success.
    514  * @return              ENOENT if device is not found.
    515  */
    516 static int ip_device_state_message(device_id_t device_id, device_state_t state)
    517 {
    518         ip_netif_t *netif;
    519 
    520         fibril_rwlock_write_lock(&ip_globals.netifs_lock);
    521         // find the device
    522         netif = ip_netifs_find(&ip_globals.netifs, device_id);
    523         if (!netif) {
    524                 fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
    525                 return ENOENT;
    526         }
    527         netif->state = state;
    528         fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
    529 
    530         printf("%s: Device %d changed state to %d\n", NAME, device_id, state);
    531 
    532         return EOK;
    533 }
    534 
    535 
    536 /** Prefixes a middle fragment header based on the last fragment header to the
    537  * packet.
    538  *
    539  * @param[in] packet    The packet to be prefixed.
    540  * @param[in] last      The last header to be copied.
    541  * @return              The prefixed middle header.
    542  * @return              NULL on error.
    543  */
    544 static ip_header_t *
    545 ip_create_middle_header(packet_t *packet, ip_header_t *last)
    546 {
    547         ip_header_t *middle;
    548 
    549         middle = (ip_header_t *) packet_suffix(packet, IP_HEADER_LENGTH(last));
    550         if (!middle)
    551                 return NULL;
    552         memcpy(middle, last, IP_HEADER_LENGTH(last));
    553         middle->flags |= IPFLAG_MORE_FRAGMENTS;
    554         return middle;
     590        // start with the last netif - the newest one
     591        index = ip_netifs_count(&ip_globals.netifs) - 1;
     592        while (index >= 0) {
     593                netif = ip_netifs_get_index(&ip_globals.netifs, index);
     594                if (netif && (netif->state == NETIF_ACTIVE)) {
     595                        route = ip_netif_find_route(netif, destination);
     596                        if (route)
     597                                return route;
     598                }
     599                index--;
     600        }
     601
     602        return &ip_globals.gateway;
     603}
     604
     605/** Returns the network interface's IP address.
     606 *
     607 * @param[in] netif     The network interface.
     608 * @return              The IP address.
     609 * @return              NULL if no IP address was found.
     610 */
     611static in_addr_t *ip_netif_address(ip_netif_t *netif)
     612{
     613        ip_route_t *route;
     614
     615        route = ip_routes_get_index(&netif->routes, 0);
     616        return route ? &route->address : NULL;
    555617}
    556618
     
    621683 *                      function.
    622684 */
    623 static int
    624 ip_prepare_packet(in_addr_t *source, in_addr_t dest, packet_t *packet,
    625     measured_string_t *destination)
     685static int ip_prepare_packet(in_addr_t *source, in_addr_t dest,
     686    packet_t *packet, measured_string_t *destination)
    626687{
    627688        size_t length;
     
    639700        if (destination) {
    640701                rc = packet_set_addr(packet, NULL, (uint8_t *) destination->value,
    641                     CONVERT_SIZE(char, uint8_t, destination->length));
     702                    destination->length);
    642703        } else {
    643704                rc = packet_set_addr(packet, NULL, NULL, 0);
     
    687748                                rc = packet_set_addr(next, NULL,
    688749                                    (uint8_t *) destination->value,
    689                                     CONVERT_SIZE(char, uint8_t,
    690                                     destination->length));
     750                                    destination->length);
    691751                                if (rc != EOK) {
    692752                                        free(last_header);
     
    718778                        rc = packet_set_addr(next, NULL,
    719779                            (uint8_t *) destination->value,
    720                             CONVERT_SIZE(char, uint8_t, destination->length));
     780                            destination->length);
    721781                        if (rc != EOK) {
    722782                                free(last_header);
     
    753813 *                      function.
    754814 */
    755 static int
    756 ip_fragment_packet_data(packet_t *packet, packet_t *new_packet,
     815static int ip_fragment_packet_data(packet_t *packet, packet_t *new_packet,
    757816    ip_header_t *header, ip_header_t *new_header, size_t length,
    758817    const struct sockaddr *src, const struct sockaddr *dest, socklen_t addrlen)
     
    788847
    789848        return pq_insert_after(packet, new_packet);
     849}
     850
     851/** Prefixes a middle fragment header based on the last fragment header to the
     852 * packet.
     853 *
     854 * @param[in] packet    The packet to be prefixed.
     855 * @param[in] last      The last header to be copied.
     856 * @return              The prefixed middle header.
     857 * @return              NULL on error.
     858 */
     859static ip_header_t *ip_create_middle_header(packet_t *packet,
     860    ip_header_t *last)
     861{
     862        ip_header_t *middle;
     863
     864        middle = (ip_header_t *) packet_suffix(packet, IP_HEADER_LENGTH(last));
     865        if (!middle)
     866                return NULL;
     867        memcpy(middle, last, IP_HEADER_LENGTH(last));
     868        middle->flags |= IPFLAG_MORE_FRAGMENTS;
     869        return middle;
    790870}
    791871
     
    9921072 *                      function.
    9931073 */
    994 static int
    995 ip_send_route(packet_t *packet, ip_netif_t *netif, ip_route_t *route,
    996     in_addr_t *src, in_addr_t dest, services_t error)
     1074static int ip_send_route(packet_t *packet, ip_netif_t *netif,
     1075    ip_route_t *route, in_addr_t *src, in_addr_t dest, services_t error)
    9971076{
    9981077        measured_string_t destination;
    9991078        measured_string_t *translation;
    1000         char *data;
     1079        uint8_t *data;
    10011080        int phone;
    10021081        int rc;
     
    10051084        if (netif->arp && (route->address.s_addr != dest.s_addr)) {
    10061085                destination.value = route->gateway.s_addr ?
    1007                     (char *) &route->gateway.s_addr : (char *) &dest.s_addr;
    1008                 destination.length = CONVERT_SIZE(dest.s_addr, char, 1);
     1086                    (uint8_t *) &route->gateway.s_addr : (uint8_t *) &dest.s_addr;
     1087                destination.length = sizeof(dest.s_addr);
    10091088
    10101089                rc = arp_translate_req(netif->arp->phone, netif->device_id,
     
    10571136}
    10581137
    1059 /** Searches the network interfaces if there is a suitable route.
    1060  *
    1061  * @param[in] netif     The network interface to be searched for routes. May be
    1062  *                      NULL.
    1063  * @param[in] destination The destination address.
    1064  * @return              The found route.
    1065  * @return              NULL if no route was found.
    1066  */
    1067 static ip_route_t *
    1068 ip_netif_find_route(ip_netif_t *netif, in_addr_t destination)
    1069 {
    1070         int index;
    1071         ip_route_t *route;
    1072 
    1073         if (!netif)
    1074                 return NULL;
    1075 
    1076         // start with the first one - the direct route
    1077         for (index = 0; index < ip_routes_count(&netif->routes); index++) {
    1078                 route = ip_routes_get_index(&netif->routes, index);
    1079                 if (route &&
    1080                     ((route->address.s_addr & route->netmask.s_addr) ==
    1081                     (destination.s_addr & route->netmask.s_addr))) {
    1082                         return route;
    1083                 }
    1084         }
    1085 
    1086         return NULL;
    1087 }
    1088 
    1089 /** Searches all network interfaces if there is a suitable route.
    1090  *
    1091  * @param[in] destination The destination address.
    1092  * @return              The found route.
    1093  * @return              NULL if no route was found.
    1094  */
    1095 static ip_route_t *ip_find_route(in_addr_t destination) {
    1096         int index;
    1097         ip_route_t *route;
    1098         ip_netif_t *netif;
    1099 
    1100         // start with the last netif - the newest one
    1101         index = ip_netifs_count(&ip_globals.netifs) - 1;
    1102         while (index >= 0) {
    1103                 netif = ip_netifs_get_index(&ip_globals.netifs, index);
    1104                 if (netif && (netif->state == NETIF_ACTIVE)) {
    1105                         route = ip_netif_find_route(netif, destination);
    1106                         if (route)
    1107                                 return route;
    1108                 }
    1109                 index--;
    1110         }
    1111 
    1112         return &ip_globals.gateway;
    1113 }
    1114 
    1115 /** Returns the network interface's IP address.
    1116  *
    1117  * @param[in] netif     The network interface.
    1118  * @return              The IP address.
    1119  * @return              NULL if no IP address was found.
    1120  */
    1121 static in_addr_t *ip_netif_address(ip_netif_t *netif)
    1122 {
    1123         ip_route_t *route;
    1124 
    1125         route = ip_routes_get_index(&netif->routes, 0);
    1126         return route ? &route->address : NULL;
    1127 }
    1128 
    1129 /** Registers the transport layer protocol.
    1130  *
    1131  * The traffic of this protocol will be supplied using either the receive
    1132  * function or IPC message.
    1133  *
    1134  * @param[in] protocol  The transport layer module protocol.
    1135  * @param[in] service   The transport layer module service.
    1136  * @param[in] phone     The transport layer module phone.
    1137  * @param[in] received_msg The receiving function.
    1138  * @return              EOK on success.
    1139  * @return              EINVAL if the protocol parameter and/or the service
    1140  *                      parameter is zero.
    1141  * @return              EINVAL if the phone parameter is not a positive number
    1142  *                      and the tl_receive_msg is NULL.
    1143  * @return              ENOMEM if there is not enough memory left.
    1144  */
    1145 static int
    1146 ip_register(int protocol, services_t service, int phone,
    1147     tl_received_msg_t received_msg)
    1148 {
    1149         ip_proto_t *proto;
    1150         int index;
    1151 
    1152         if (!protocol || !service || ((phone < 0) && !received_msg))
    1153                 return EINVAL;
    1154 
    1155         proto = (ip_proto_t *) malloc(sizeof(ip_protos_t));
    1156         if (!proto)
    1157                 return ENOMEM;
    1158 
    1159         proto->protocol = protocol;
    1160         proto->service = service;
    1161         proto->phone = phone;
    1162         proto->received_msg = received_msg;
    1163 
    1164         fibril_rwlock_write_lock(&ip_globals.protos_lock);
    1165         index = ip_protos_add(&ip_globals.protos, proto->protocol, proto);
    1166         if (index < 0) {
    1167                 fibril_rwlock_write_unlock(&ip_globals.protos_lock);
    1168                 free(proto);
    1169                 return index;
    1170         }
    1171         fibril_rwlock_write_unlock(&ip_globals.protos_lock);
    1172 
    1173         printf("%s: Protocol registered (protocol: %d, phone: %d)\n",
    1174             NAME, proto->protocol, proto->phone);
    1175 
    1176         return EOK;
    1177 }
    1178 
    1179 static int
    1180 ip_device_req_local(int il_phone, device_id_t device_id, services_t netif)
    1181 {
    1182         ip_netif_t *ip_netif;
    1183         ip_route_t *route;
    1184         int index;
    1185         int rc;
    1186 
    1187         ip_netif = (ip_netif_t *) malloc(sizeof(ip_netif_t));
    1188         if (!ip_netif)
    1189                 return ENOMEM;
    1190 
    1191         rc = ip_routes_initialize(&ip_netif->routes);
    1192         if (rc != EOK) {
    1193                 free(ip_netif);
    1194                 return rc;
    1195         }
    1196 
    1197         ip_netif->device_id = device_id;
    1198         ip_netif->service = netif;
    1199         ip_netif->state = NETIF_STOPPED;
    1200 
    1201         fibril_rwlock_write_lock(&ip_globals.netifs_lock);
    1202 
    1203         rc = ip_netif_initialize(ip_netif);
    1204         if (rc != EOK) {
    1205                 fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
    1206                 ip_routes_destroy(&ip_netif->routes);
    1207                 free(ip_netif);
    1208                 return rc;
    1209         }
    1210         if (ip_netif->arp)
    1211                 ip_netif->arp->usage++;
    1212 
    1213         // print the settings
    1214         printf("%s: Device registered (id: %d, phone: %d, ipv: %d, conf: %s)\n",
    1215             NAME, ip_netif->device_id, ip_netif->phone, ip_netif->ipv,
    1216             ip_netif->dhcp ? "dhcp" : "static");
    1217        
    1218         // TODO ipv6 addresses
    1219        
    1220         char address[INET_ADDRSTRLEN];
    1221         char netmask[INET_ADDRSTRLEN];
    1222         char gateway[INET_ADDRSTRLEN];
    1223        
    1224         for (index = 0; index < ip_routes_count(&ip_netif->routes); index++) {
    1225                 route = ip_routes_get_index(&ip_netif->routes, index);
    1226                 if (route) {
    1227                         inet_ntop(AF_INET, (uint8_t *) &route->address.s_addr,
    1228                             address, INET_ADDRSTRLEN);
    1229                         inet_ntop(AF_INET, (uint8_t *) &route->netmask.s_addr,
    1230                             netmask, INET_ADDRSTRLEN);
    1231                         inet_ntop(AF_INET, (uint8_t *) &route->gateway.s_addr,
    1232                             gateway, INET_ADDRSTRLEN);
    1233                         printf("%s: Route %d (address: %s, netmask: %s, "
    1234                             "gateway: %s)\n", NAME, index, address, netmask,
    1235                             gateway);
    1236                 }
    1237         }
    1238        
    1239         inet_ntop(AF_INET, (uint8_t *) &ip_netif->broadcast.s_addr, address,
    1240             INET_ADDRSTRLEN);
    1241         fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
    1242 
    1243         printf("%s: Broadcast (%s)\n", NAME, address);
    1244 
    1245         return EOK;
    1246 }
    1247 
    1248 static int
    1249 ip_send_msg_local(int il_phone, device_id_t device_id, packet_t *packet,
    1250     services_t sender, services_t error)
     1138static int ip_send_msg_local(int il_phone, device_id_t device_id,
     1139    packet_t *packet, services_t sender, services_t error)
    12511140{
    12521141        int addrlen;
     
    12891178        if (device_id > 0) {
    12901179                netif = ip_netifs_find(&ip_globals.netifs, device_id);
    1291                 route = ip_netif_find_route(netif, * dest);
     1180                route = ip_netif_find_route(netif, *dest);
    12921181                if (netif && !route && (ip_globals.gateway.netif == netif))
    12931182                        route = &ip_globals.gateway;
     
    13191208                }
    13201209        }
    1321 
     1210       
    13221211        // if the local host is the destination
    13231212        if ((route->address.s_addr == dest->s_addr) &&
     
    13521241}
    13531242
     1243/** Updates the device state.
     1244 *
     1245 * @param[in] device_id The device identifier.
     1246 * @param[in] state     The new state value.
     1247 * @return              EOK on success.
     1248 * @return              ENOENT if device is not found.
     1249 */
     1250static int ip_device_state_message(device_id_t device_id, device_state_t state)
     1251{
     1252        ip_netif_t *netif;
     1253
     1254        fibril_rwlock_write_lock(&ip_globals.netifs_lock);
     1255        // find the device
     1256        netif = ip_netifs_find(&ip_globals.netifs, device_id);
     1257        if (!netif) {
     1258                fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
     1259                return ENOENT;
     1260        }
     1261        netif->state = state;
     1262        fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
     1263
     1264        printf("%s: Device %d changed state to %d\n", NAME, device_id, state);
     1265
     1266        return EOK;
     1267}
     1268
     1269/** Returns the packet destination address from the IP header.
     1270 *
     1271 * @param[in] header    The packet IP header to be read.
     1272 * @return              The packet destination address.
     1273 */
     1274static in_addr_t ip_get_destination(ip_header_t *header)
     1275{
     1276        in_addr_t destination;
     1277
     1278        // TODO search set ipopt route?
     1279        destination.s_addr = header->destination_address;
     1280        return destination;
     1281}
     1282
     1283/** Delivers the packet to the local host.
     1284 *
     1285 * The packet is either passed to another module or released on error.
     1286 * The ICMP_PROT_UNREACH error notification may be sent if the protocol is not
     1287 * found.
     1288 *
     1289 * @param[in] device_id The source device identifier.
     1290 * @param[in] packet    The packet to be delivered.
     1291 * @param[in] header    The first packet IP header. May be NULL.
     1292 * @param[in] error     The packet error service.
     1293 * @return              EOK on success.
     1294 * @return              ENOTSUP if the packet is a fragment.
     1295 * @return              EAFNOSUPPORT if the address family is not supported.
     1296 * @return              ENOENT if the target protocol is not found.
     1297 * @return              Other error codes as defined for the packet_set_addr()
     1298 *                      function.
     1299 * @return              Other error codes as defined for the packet_trim()
     1300 *                      function.
     1301 * @return              Other error codes as defined for the protocol specific
     1302 *                      tl_received_msg() function.
     1303 */
     1304static int ip_deliver_local(device_id_t device_id, packet_t *packet,
     1305    ip_header_t *header, services_t error)
     1306{
     1307        ip_proto_t *proto;
     1308        int phone;
     1309        services_t service;
     1310        tl_received_msg_t received_msg;
     1311        struct sockaddr *src;
     1312        struct sockaddr *dest;
     1313        struct sockaddr_in src_in;
     1314        struct sockaddr_in dest_in;
     1315        socklen_t addrlen;
     1316        int rc;
     1317
     1318        if ((header->flags & IPFLAG_MORE_FRAGMENTS) ||
     1319            IP_FRAGMENT_OFFSET(header)) {
     1320                // TODO fragmented
     1321                return ENOTSUP;
     1322        }
     1323       
     1324        switch (header->version) {
     1325        case IPVERSION:
     1326                addrlen = sizeof(src_in);
     1327                bzero(&src_in, addrlen);
     1328                src_in.sin_family = AF_INET;
     1329                memcpy(&dest_in, &src_in, addrlen);
     1330                memcpy(&src_in.sin_addr.s_addr, &header->source_address,
     1331                    sizeof(header->source_address));
     1332                memcpy(&dest_in.sin_addr.s_addr, &header->destination_address,
     1333                    sizeof(header->destination_address));
     1334                src = (struct sockaddr *) &src_in;
     1335                dest = (struct sockaddr *) &dest_in;
     1336                break;
     1337
     1338        default:
     1339                return ip_release_and_return(packet, EAFNOSUPPORT);
     1340        }
     1341
     1342        rc = packet_set_addr(packet, (uint8_t *) src, (uint8_t *) dest,
     1343            addrlen);
     1344        if (rc != EOK)
     1345                return ip_release_and_return(packet, rc);
     1346
     1347        // trim padding if present
     1348        if (!error &&
     1349            (IP_TOTAL_LENGTH(header) < packet_get_data_length(packet))) {
     1350                rc = packet_trim(packet, 0,
     1351                    packet_get_data_length(packet) - IP_TOTAL_LENGTH(header));
     1352                if (rc != EOK)
     1353                        return ip_release_and_return(packet, rc);
     1354        }
     1355
     1356        fibril_rwlock_read_lock(&ip_globals.protos_lock);
     1357
     1358        proto = ip_protos_find(&ip_globals.protos, header->protocol);
     1359        if (!proto) {
     1360                fibril_rwlock_read_unlock(&ip_globals.protos_lock);
     1361                phone = ip_prepare_icmp_and_get_phone(error, packet, header);
     1362                if (phone >= 0) {
     1363                        // unreachable ICMP
     1364                        icmp_destination_unreachable_msg(phone,
     1365                            ICMP_PROT_UNREACH, 0, packet);
     1366                }
     1367                return ENOENT;
     1368        }
     1369
     1370        if (proto->received_msg) {
     1371                service = proto->service;
     1372                received_msg = proto->received_msg;
     1373                fibril_rwlock_read_unlock(&ip_globals.protos_lock);
     1374                rc = received_msg(device_id, packet, service, error);
     1375        } else {
     1376                rc = tl_received_msg(proto->phone, device_id, packet,
     1377                    proto->service, error);
     1378                fibril_rwlock_read_unlock(&ip_globals.protos_lock);
     1379        }
     1380
     1381        return rc;
     1382}
     1383
     1384/** Processes the received packet.
     1385 *
     1386 * The packet is either passed to another module or released on error.
     1387 *
     1388 * The ICMP_PARAM_POINTER error notification may be sent if the checksum is
     1389 * invalid.
     1390 * The ICMP_EXC_TTL error notification may be sent if the TTL is less than two.
     1391 * The ICMP_HOST_UNREACH error notification may be sent if no route was found.
     1392 * The ICMP_HOST_UNREACH error notification may be sent if the packet is for
     1393 * another host and the routing is disabled.
     1394 *
     1395 * @param[in] device_id The source device identifier.
     1396 * @param[in] packet    The received packet to be processed.
     1397 * @return              EOK on success.
     1398 * @return              EINVAL if the TTL is less than two.
     1399 * @return              EINVAL if the checksum is invalid.
     1400 * @return              EAFNOSUPPORT if the address family is not supported.
     1401 * @return              ENOENT if no route was found.
     1402 * @return              ENOENT if the packet is for another host and the routing
     1403 *                      is disabled.
     1404 */
     1405static int ip_process_packet(device_id_t device_id, packet_t *packet)
     1406{
     1407        ip_header_t *header;
     1408        in_addr_t dest;
     1409        ip_route_t *route;
     1410        int phone;
     1411        struct sockaddr *addr;
     1412        struct sockaddr_in addr_in;
     1413        socklen_t addrlen;
     1414        int rc;
     1415       
     1416        header = (ip_header_t *) packet_get_data(packet);
     1417        if (!header)
     1418                return ip_release_and_return(packet, ENOMEM);
     1419
     1420        // checksum
     1421        if ((header->header_checksum) &&
     1422            (IP_HEADER_CHECKSUM(header) != IP_CHECKSUM_ZERO)) {
     1423                phone = ip_prepare_icmp_and_get_phone(0, packet, header);
     1424                if (phone >= 0) {
     1425                        // checksum error ICMP
     1426                        icmp_parameter_problem_msg(phone, ICMP_PARAM_POINTER,
     1427                            ((size_t) ((void *) &header->header_checksum)) -
     1428                            ((size_t) ((void *) header)), packet);
     1429                }
     1430                return EINVAL;
     1431        }
     1432
     1433        if (header->ttl <= 1) {
     1434                phone = ip_prepare_icmp_and_get_phone(0, packet, header);
     1435                if (phone >= 0) {
     1436                        // ttl exceeded ICMP
     1437                        icmp_time_exceeded_msg(phone, ICMP_EXC_TTL, packet);
     1438                }
     1439                return EINVAL;
     1440        }
     1441       
     1442        // process ipopt and get destination
     1443        dest = ip_get_destination(header);
     1444
     1445        // set the addrination address
     1446        switch (header->version) {
     1447        case IPVERSION:
     1448                addrlen = sizeof(addr_in);
     1449                bzero(&addr_in, addrlen);
     1450                addr_in.sin_family = AF_INET;
     1451                memcpy(&addr_in.sin_addr.s_addr, &dest, sizeof(dest));
     1452                addr = (struct sockaddr *) &addr_in;
     1453                break;
     1454
     1455        default:
     1456                return ip_release_and_return(packet, EAFNOSUPPORT);
     1457        }
     1458
     1459        rc = packet_set_addr(packet, NULL, (uint8_t *) &addr, addrlen);
     1460        if (rc != EOK)
     1461                return rc;
     1462       
     1463        route = ip_find_route(dest);
     1464        if (!route) {
     1465                phone = ip_prepare_icmp_and_get_phone(0, packet, header);
     1466                if (phone >= 0) {
     1467                        // unreachable ICMP
     1468                        icmp_destination_unreachable_msg(phone,
     1469                            ICMP_HOST_UNREACH, 0, packet);
     1470                }
     1471                return ENOENT;
     1472        }
     1473
     1474        if (route->address.s_addr == dest.s_addr) {
     1475                // local delivery
     1476                return ip_deliver_local(device_id, packet, header, 0);
     1477        }
     1478
     1479        if (route->netif->routing) {
     1480                header->ttl--;
     1481                return ip_send_route(packet, route->netif, route, NULL, dest,
     1482                    0);
     1483        }
     1484
     1485        phone = ip_prepare_icmp_and_get_phone(0, packet, header);
     1486        if (phone >= 0) {
     1487                // unreachable ICMP if no routing
     1488                icmp_destination_unreachable_msg(phone, ICMP_HOST_UNREACH, 0,
     1489                    packet);
     1490        }
     1491       
     1492        return ENOENT;
     1493}
     1494
    13541495/** Returns the device packet dimensions for sending.
    13551496 *
     
    13631504 * @return              EOK on success.
    13641505 */
    1365 static int
    1366 ip_packet_size_message(device_id_t device_id, size_t *addr_len, size_t *prefix,
    1367     size_t *content, size_t *suffix)
     1506static int ip_packet_size_message(device_id_t device_id, size_t *addr_len,
     1507    size_t *prefix, size_t *content, size_t *suffix)
    13681508{
    13691509        ip_netif_t *netif;
     
    14151555}
    14161556
    1417 /** Returns the packet destination address from the IP header.
    1418  *
    1419  * @param[in] header    The packet IP header to be read.
    1420  * @return              The packet destination address.
    1421  */
    1422 static in_addr_t ip_get_destination(ip_header_t *header)
    1423 {
    1424         in_addr_t destination;
    1425 
    1426         // TODO search set ipopt route?
    1427         destination.s_addr = header->destination_address;
    1428         return destination;
    1429 }
    1430 
    1431 /** Delivers the packet to the local host.
    1432  *
    1433  * The packet is either passed to another module or released on error.
    1434  * The ICMP_PROT_UNREACH error notification may be sent if the protocol is not
    1435  * found.
    1436  *
    1437  * @param[in] device_id The source device identifier.
    1438  * @param[in] packet    The packet to be delivered.
    1439  * @param[in] header    The first packet IP header. May be NULL.
    1440  * @param[in] error     The packet error service.
     1557/** Updates the device content length according to the new MTU value.
     1558 *
     1559 * @param[in] device_id The device identifier.
     1560 * @param[in] mtu       The new mtu value.
    14411561 * @return              EOK on success.
    1442  * @return              ENOTSUP if the packet is a fragment.
    1443  * @return              EAFNOSUPPORT if the address family is not supported.
    1444  * @return              ENOENT if the target protocol is not found.
    1445  * @return              Other error codes as defined for the packet_set_addr()
    1446  *                      function.
    1447  * @return              Other error codes as defined for the packet_trim()
    1448  *                      function.
    1449  * @return              Other error codes as defined for the protocol specific
    1450  *                      tl_received_msg() function.
     1562 * @return              ENOENT if device is not found.
     1563 */
     1564static int ip_mtu_changed_message(device_id_t device_id, size_t mtu)
     1565{
     1566        ip_netif_t *netif;
     1567
     1568        fibril_rwlock_write_lock(&ip_globals.netifs_lock);
     1569        netif = ip_netifs_find(&ip_globals.netifs, device_id);
     1570        if (!netif) {
     1571                fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
     1572                return ENOENT;
     1573        }
     1574        netif->packet_dimension.content = mtu;
     1575        fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
     1576
     1577        printf("%s: Device %d changed MTU to %zu\n", NAME, device_id, mtu);
     1578
     1579        return EOK;
     1580}
     1581
     1582/** Process IPC messages from the registered device driver modules
     1583 *
     1584 * @param[in]     iid   Message identifier.
     1585 * @param[in,out] icall Message parameters.
     1586 *
     1587 */
     1588static void ip_receiver(ipc_callid_t iid, ipc_call_t *icall)
     1589{
     1590        packet_t *packet;
     1591        int rc;
     1592       
     1593        while (true) {
     1594                switch (IPC_GET_IMETHOD(*icall)) {
     1595                case NET_IL_DEVICE_STATE:
     1596                        rc = ip_device_state_message(IPC_GET_DEVICE(*icall),
     1597                            IPC_GET_STATE(*icall));
     1598                        ipc_answer_0(iid, (sysarg_t) rc);
     1599                        break;
     1600               
     1601                case NET_IL_RECEIVED:
     1602                        rc = packet_translate_remote(ip_globals.net_phone, &packet,
     1603                            IPC_GET_PACKET(*icall));
     1604                        if (rc == EOK) {
     1605                                do {
     1606                                        packet_t *next = pq_detach(packet);
     1607                                        ip_process_packet(IPC_GET_DEVICE(*icall), packet);
     1608                                        packet = next;
     1609                                } while (packet);
     1610                        }
     1611                       
     1612                        ipc_answer_0(iid, (sysarg_t) rc);
     1613                        break;
     1614               
     1615                case NET_IL_MTU_CHANGED:
     1616                        rc = ip_mtu_changed_message(IPC_GET_DEVICE(*icall),
     1617                            IPC_GET_MTU(*icall));
     1618                        ipc_answer_0(iid, (sysarg_t) rc);
     1619                        break;
     1620               
     1621                default:
     1622                        ipc_answer_0(iid, (sysarg_t) ENOTSUP);
     1623                }
     1624               
     1625                iid = async_get_call(icall);
     1626        }
     1627}
     1628
     1629/** Registers the transport layer protocol.
     1630 *
     1631 * The traffic of this protocol will be supplied using either the receive
     1632 * function or IPC message.
     1633 *
     1634 * @param[in] protocol  The transport layer module protocol.
     1635 * @param[in] service   The transport layer module service.
     1636 * @param[in] phone     The transport layer module phone.
     1637 * @param[in] received_msg The receiving function.
     1638 * @return              EOK on success.
     1639 * @return              EINVAL if the protocol parameter and/or the service
     1640 *                      parameter is zero.
     1641 * @return              EINVAL if the phone parameter is not a positive number
     1642 *                      and the tl_receive_msg is NULL.
     1643 * @return              ENOMEM if there is not enough memory left.
    14511644 */
    14521645static int
    1453 ip_deliver_local(device_id_t device_id, packet_t *packet, ip_header_t *header,
    1454     services_t error)
     1646ip_register(int protocol, services_t service, int phone,
     1647    tl_received_msg_t received_msg)
    14551648{
    14561649        ip_proto_t *proto;
    1457         int phone;
    1458         services_t service;
    1459         tl_received_msg_t received_msg;
    1460         struct sockaddr *src;
    1461         struct sockaddr *dest;
    1462         struct sockaddr_in src_in;
    1463         struct sockaddr_in dest_in;
    1464         socklen_t addrlen;
    1465         int rc;
    1466 
    1467         if ((header->flags & IPFLAG_MORE_FRAGMENTS) ||
    1468             IP_FRAGMENT_OFFSET(header)) {
    1469                 // TODO fragmented
    1470                 return ENOTSUP;
    1471         }
    1472        
    1473         switch (header->version) {
    1474         case IPVERSION:
    1475                 addrlen = sizeof(src_in);
    1476                 bzero(&src_in, addrlen);
    1477                 src_in.sin_family = AF_INET;
    1478                 memcpy(&dest_in, &src_in, addrlen);
    1479                 memcpy(&src_in.sin_addr.s_addr, &header->source_address,
    1480                     sizeof(header->source_address));
    1481                 memcpy(&dest_in.sin_addr.s_addr, &header->destination_address,
    1482                     sizeof(header->destination_address));
    1483                 src = (struct sockaddr *) &src_in;
    1484                 dest = (struct sockaddr *) &dest_in;
    1485                 break;
    1486 
    1487         default:
    1488                 return ip_release_and_return(packet, EAFNOSUPPORT);
    1489         }
    1490 
    1491         rc = packet_set_addr(packet, (uint8_t *) src, (uint8_t *) dest,
    1492             addrlen);
    1493         if (rc != EOK)
    1494                 return ip_release_and_return(packet, rc);
    1495 
    1496         // trim padding if present
    1497         if (!error &&
    1498             (IP_TOTAL_LENGTH(header) < packet_get_data_length(packet))) {
    1499                 rc = packet_trim(packet, 0,
    1500                     packet_get_data_length(packet) - IP_TOTAL_LENGTH(header));
    1501                 if (rc != EOK)
    1502                         return ip_release_and_return(packet, rc);
    1503         }
    1504 
    1505         fibril_rwlock_read_lock(&ip_globals.protos_lock);
    1506 
    1507         proto = ip_protos_find(&ip_globals.protos, header->protocol);
    1508         if (!proto) {
    1509                 fibril_rwlock_read_unlock(&ip_globals.protos_lock);
    1510                 phone = ip_prepare_icmp_and_get_phone(error, packet, header);
    1511                 if (phone >= 0) {
    1512                         // unreachable ICMP
    1513                         icmp_destination_unreachable_msg(phone,
    1514                             ICMP_PROT_UNREACH, 0, packet);
    1515                 }
    1516                 return ENOENT;
    1517         }
    1518 
    1519         if (proto->received_msg) {
    1520                 service = proto->service;
    1521                 received_msg = proto->received_msg;
    1522                 fibril_rwlock_read_unlock(&ip_globals.protos_lock);
    1523                 rc = received_msg(device_id, packet, service, error);
    1524         } else {
    1525                 rc = tl_received_msg(proto->phone, device_id, packet,
    1526                     proto->service, error);
    1527                 fibril_rwlock_read_unlock(&ip_globals.protos_lock);
    1528         }
    1529 
    1530         return rc;
    1531 }
    1532 
    1533 /** Processes the received packet.
    1534  *
    1535  * The packet is either passed to another module or released on error.
    1536  *
    1537  * The ICMP_PARAM_POINTER error notification may be sent if the checksum is
    1538  * invalid.
    1539  * The ICMP_EXC_TTL error notification may be sent if the TTL is less than two.
    1540  * The ICMP_HOST_UNREACH error notification may be sent if no route was found.
    1541  * The ICMP_HOST_UNREACH error notification may be sent if the packet is for
    1542  * another host and the routing is disabled.
    1543  *
    1544  * @param[in] device_id The source device identifier.
    1545  * @param[in] packet    The received packet to be processed.
    1546  * @return              EOK on success.
    1547  * @return              EINVAL if the TTL is less than two.
    1548  * @return              EINVAL if the checksum is invalid.
    1549  * @return              EAFNOSUPPORT if the address family is not supported.
    1550  * @return              ENOENT if no route was found.
    1551  * @return              ENOENT if the packet is for another host and the routing
    1552  *                      is disabled.
    1553  */
    1554 static int
    1555 ip_process_packet(device_id_t device_id, packet_t *packet)
    1556 {
    1557         ip_header_t *header;
    1558         in_addr_t dest;
    1559         ip_route_t *route;
    1560         int phone;
    1561         struct sockaddr *addr;
    1562         struct sockaddr_in addr_in;
    1563         socklen_t addrlen;
    1564         int rc;
    1565 
    1566         header = (ip_header_t *) packet_get_data(packet);
    1567         if (!header)
    1568                 return ip_release_and_return(packet, ENOMEM);
    1569 
    1570         // checksum
    1571         if ((header->header_checksum) &&
    1572             (IP_HEADER_CHECKSUM(header) != IP_CHECKSUM_ZERO)) {
    1573                 phone = ip_prepare_icmp_and_get_phone(0, packet, header);
    1574                 if (phone >= 0) {
    1575                         // checksum error ICMP
    1576                         icmp_parameter_problem_msg(phone, ICMP_PARAM_POINTER,
    1577                             ((size_t) ((void *) &header->header_checksum)) -
    1578                             ((size_t) ((void *) header)), packet);
    1579                 }
     1650        int index;
     1651
     1652        if (!protocol || !service || ((phone < 0) && !received_msg))
    15801653                return EINVAL;
    1581         }
    1582 
    1583         if (header->ttl <= 1) {
    1584                 phone = ip_prepare_icmp_and_get_phone(0, packet, header);
    1585                 if (phone >= 0) {
    1586                         // ttl exceeded ICMP
    1587                         icmp_time_exceeded_msg(phone, ICMP_EXC_TTL, packet);
    1588                 }
    1589                 return EINVAL;
    1590         }
    1591 
    1592         // process ipopt and get destination
    1593         dest = ip_get_destination(header);
    1594 
    1595         // set the addrination address
    1596         switch (header->version) {
    1597         case IPVERSION:
    1598                 addrlen = sizeof(addr_in);
    1599                 bzero(&addr_in, addrlen);
    1600                 addr_in.sin_family = AF_INET;
    1601                 memcpy(&addr_in.sin_addr.s_addr, &dest, sizeof(dest));
    1602                 addr = (struct sockaddr *) &addr_in;
    1603                 break;
    1604 
    1605         default:
    1606                 return ip_release_and_return(packet, EAFNOSUPPORT);
    1607         }
    1608 
    1609         rc = packet_set_addr(packet, NULL, (uint8_t *) &addr, addrlen);
    1610         if (rc != EOK)
    1611                 return rc;
    1612 
    1613         route = ip_find_route(dest);
    1614         if (!route) {
    1615                 phone = ip_prepare_icmp_and_get_phone(0, packet, header);
    1616                 if (phone >= 0) {
    1617                         // unreachable ICMP
    1618                         icmp_destination_unreachable_msg(phone,
    1619                             ICMP_HOST_UNREACH, 0, packet);
    1620                 }
    1621                 return ENOENT;
    1622         }
    1623 
    1624         if (route->address.s_addr == dest.s_addr) {
    1625                 // local delivery
    1626                 return ip_deliver_local(device_id, packet, header, 0);
    1627         }
    1628 
    1629         if (route->netif->routing) {
    1630                 header->ttl--;
    1631                 return ip_send_route(packet, route->netif, route, NULL, dest,
    1632                     0);
    1633         }
    1634 
    1635         phone = ip_prepare_icmp_and_get_phone(0, packet, header);
    1636         if (phone >= 0) {
    1637                 // unreachable ICMP if no routing
    1638                 icmp_destination_unreachable_msg(phone, ICMP_HOST_UNREACH, 0,
    1639                     packet);
    1640         }
    1641        
    1642         return ENOENT;
    1643 }
     1654
     1655        proto = (ip_proto_t *) malloc(sizeof(ip_protos_t));
     1656        if (!proto)
     1657                return ENOMEM;
     1658
     1659        proto->protocol = protocol;
     1660        proto->service = service;
     1661        proto->phone = phone;
     1662        proto->received_msg = received_msg;
     1663
     1664        fibril_rwlock_write_lock(&ip_globals.protos_lock);
     1665        index = ip_protos_add(&ip_globals.protos, proto->protocol, proto);
     1666        if (index < 0) {
     1667                fibril_rwlock_write_unlock(&ip_globals.protos_lock);
     1668                free(proto);
     1669                return index;
     1670        }
     1671        fibril_rwlock_write_unlock(&ip_globals.protos_lock);
     1672
     1673        printf("%s: Protocol registered (protocol: %d, phone: %d)\n",
     1674            NAME, proto->protocol, proto->phone);
     1675
     1676        return EOK;
     1677}
     1678
    16441679
    16451680static int
     
    17571792                    (header->destination_address & route->netmask.s_addr))) {
    17581793                        // clear the ARP mapping if any
    1759                         address.value = (char *) &header->destination_address;
    1760                         address.length = CONVERT_SIZE(uint8_t, char,
    1761                             sizeof(header->destination_address));
     1794                        address.value = (uint8_t *) &header->destination_address;
     1795                        address.length = sizeof(header->destination_address);
    17621796                        arp_clear_address_req(netif->arp->phone,
    17631797                            netif->device_id, SERVICE_IP, &address);
     
    18431877}
    18441878
    1845 /** Processes the received IP packet or the packet queue one by one.
    1846  *
    1847  * The packet is either passed to another module or released on error.
    1848  *
    1849  * @param[in] device_id The source device identifier.
    1850  * @param[in,out] packet The received packet.
    1851  * @return              EOK on success and the packet is no longer needed.
    1852  * @return              EINVAL if the packet is too small to carry the IP
    1853  *                      packet.
    1854  * @return              EINVAL if the received address lengths differs from the
    1855  *                      registered values.
    1856  * @return              ENOENT if the device is not found in the cache.
    1857  * @return              ENOENT if the protocol for the device is not found in
    1858  *                      the cache.
    1859  * @return              ENOMEM if there is not enough memory left.
    1860  */
    1861 static int ip_receive_message(device_id_t device_id, packet_t *packet)
    1862 {
    1863         packet_t *next;
    1864 
    1865         do {
    1866                 next = pq_detach(packet);
    1867                 ip_process_packet(device_id, packet);
    1868                 packet = next;
    1869         } while (packet);
    1870 
    1871         return EOK;
    1872 }
    1873 
    18741879/** Processes the IP message.
    18751880 *
     
    18831888 *
    18841889 * @see ip_interface.h
    1885  * @see il_interface.h
     1890 * @see il_remote.h
    18861891 * @see IS_NET_IP_MESSAGE()
    18871892 */
    1888 int
    1889 ip_message_standalone(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer,
    1890     int *answer_count)
     1893int il_module_message(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer,
     1894    size_t *answer_count)
    18911895{
    18921896        packet_t *packet;
    18931897        struct sockaddr *addr;
     1898        void *header;
     1899        size_t headerlen;
    18941900        size_t addrlen;
    18951901        size_t prefix;
    18961902        size_t suffix;
    18971903        size_t content;
    1898         void *header;
    1899         size_t headerlen;
    19001904        device_id_t device_id;
    19011905        int rc;
    19021906       
    19031907        *answer_count = 0;
    1904         switch (IPC_GET_METHOD(*call)) {
     1908        switch (IPC_GET_IMETHOD(*call)) {
    19051909        case IPC_M_PHONE_HUNGUP:
    19061910                return EOK;
    19071911       
    19081912        case IPC_M_CONNECT_TO_ME:
    1909                 return ip_register(IL_GET_PROTO(call), IL_GET_SERVICE(call),
    1910                     IPC_GET_PHONE(call), NULL);
    1911        
    1912         case NET_IL_DEVICE:
    1913                 return ip_device_req_local(0, IPC_GET_DEVICE(call),
    1914                     IPC_GET_SERVICE(call));
    1915        
    1916         case NET_IL_SEND:
     1913                return ip_register(IL_GET_PROTO(*call), IL_GET_SERVICE(*call),
     1914                    IPC_GET_PHONE(*call), NULL);
     1915       
     1916        case NET_IP_DEVICE:
     1917                return ip_device_req_local(0, IPC_GET_DEVICE(*call),
     1918                    IPC_GET_SERVICE(*call));
     1919       
     1920        case NET_IP_RECEIVED_ERROR:
    19171921                rc = packet_translate_remote(ip_globals.net_phone, &packet,
    1918                     IPC_GET_PACKET(call));
     1922                    IPC_GET_PACKET(*call));
    19191923                if (rc != EOK)
    19201924                        return rc;
    1921                 return ip_send_msg_local(0, IPC_GET_DEVICE(call), packet, 0,
    1922                     IPC_GET_ERROR(call));
    1923        
    1924         case NET_IL_DEVICE_STATE:
    1925                 return ip_device_state_message(IPC_GET_DEVICE(call),
    1926                     IPC_GET_STATE(call));
    1927        
    1928         case NET_IL_RECEIVED:
    1929                 rc = packet_translate_remote(ip_globals.net_phone, &packet,
    1930                     IPC_GET_PACKET(call));
    1931                 if (rc != EOK)
    1932                         return rc;
    1933                 return ip_receive_message(IPC_GET_DEVICE(call), packet);
    1934        
    1935         case NET_IP_RECEIVED_ERROR:
    1936                 rc = packet_translate_remote(ip_globals.net_phone, &packet,
    1937                     IPC_GET_PACKET(call));
    1938                 if (rc != EOK)
    1939                         return rc;
    1940                 return ip_received_error_msg_local(0, IPC_GET_DEVICE(call),
    1941                     packet, IPC_GET_TARGET(call), IPC_GET_ERROR(call));
     1925                return ip_received_error_msg_local(0, IPC_GET_DEVICE(*call),
     1926                    packet, IPC_GET_TARGET(*call), IPC_GET_ERROR(*call));
    19421927       
    19431928        case NET_IP_ADD_ROUTE:
    1944                 return ip_add_route_req_local(0, IPC_GET_DEVICE(call),
    1945                     IP_GET_ADDRESS(call), IP_GET_NETMASK(call),
    1946                     IP_GET_GATEWAY(call));
     1929                return ip_add_route_req_local(0, IPC_GET_DEVICE(*call),
     1930                    IP_GET_ADDRESS(*call), IP_GET_NETMASK(*call),
     1931                    IP_GET_GATEWAY(*call));
    19471932
    19481933        case NET_IP_SET_GATEWAY:
    1949                 return ip_set_gateway_req_local(0, IPC_GET_DEVICE(call),
    1950                     IP_GET_GATEWAY(call));
     1934                return ip_set_gateway_req_local(0, IPC_GET_DEVICE(*call),
     1935                    IP_GET_GATEWAY(*call));
    19511936
    19521937        case NET_IP_GET_ROUTE:
    1953                 rc = data_receive((void **) &addr, &addrlen);
     1938                rc = async_data_write_accept((void **) &addr, false, 0, 0, 0,
     1939                    &addrlen);
    19541940                if (rc != EOK)
    19551941                        return rc;
    19561942               
    1957                 rc = ip_get_route_req_local(0, IP_GET_PROTOCOL(call), addr,
     1943                rc = ip_get_route_req_local(0, IP_GET_PROTOCOL(*call), addr,
    19581944                    (socklen_t) addrlen, &device_id, &header, &headerlen);
    19591945                if (rc != EOK)
    19601946                        return rc;
    19611947               
    1962                 IPC_SET_DEVICE(answer, device_id);
    1963                 IP_SET_HEADERLEN(answer, headerlen);
     1948                IPC_SET_DEVICE(*answer, device_id);
     1949                IP_SET_HEADERLEN(*answer, headerlen);
    19641950               
    19651951                *answer_count = 2;
     
    19721958                return rc;
    19731959       
    1974         case NET_IL_PACKET_SPACE:
    1975                 rc = ip_packet_size_message(IPC_GET_DEVICE(call), &addrlen,
     1960        case NET_IP_PACKET_SPACE:
     1961                rc = ip_packet_size_message(IPC_GET_DEVICE(*call), &addrlen,
    19761962                    &prefix, &content, &suffix);
    19771963                if (rc != EOK)
    19781964                        return rc;
    19791965               
    1980                 IPC_SET_ADDR(answer, addrlen);
    1981                 IPC_SET_PREFIX(answer, prefix);
    1982                 IPC_SET_CONTENT(answer, content);
    1983                 IPC_SET_SUFFIX(answer, suffix);
     1966                IPC_SET_ADDR(*answer, addrlen);
     1967                IPC_SET_PREFIX(*answer, prefix);
     1968                IPC_SET_CONTENT(*answer, content);
     1969                IPC_SET_SUFFIX(*answer, suffix);
    19841970                *answer_count = 4;
    19851971                return EOK;
    19861972       
    1987         case NET_IL_MTU_CHANGED:
    1988                 return ip_mtu_changed_message(IPC_GET_DEVICE(call),
    1989                     IPC_GET_MTU(call));
     1973        case NET_IP_SEND:
     1974                rc = packet_translate_remote(ip_globals.net_phone, &packet,
     1975                    IPC_GET_PACKET(*call));
     1976                if (rc != EOK)
     1977                        return rc;
     1978               
     1979                return ip_send_msg_local(0, IPC_GET_DEVICE(*call), packet, 0,
     1980                    IPC_GET_ERROR(*call));
    19901981        }
    19911982       
     
    19931984}
    19941985
    1995 /** Default thread for new connections.
    1996  *
    1997  * @param[in] iid       The initial message identifier.
    1998  * @param[in] icall     The initial message call structure.
    1999  */
    2000 static void il_client_connection(ipc_callid_t iid, ipc_call_t *icall)
    2001 {
    2002         /*
    2003          * Accept the connection
    2004          *  - Answer the first IPC_M_CONNECT_ME_TO call.
    2005          */
    2006         ipc_answer_0(iid, EOK);
    2007        
    2008         while (true) {
    2009                 ipc_call_t answer;
    2010                 int answer_count;
    2011                
    2012                 /* Clear the answer structure */
    2013                 refresh_answer(&answer, &answer_count);
    2014                
    2015                 /* Fetch the next message */
    2016                 ipc_call_t call;
    2017                 ipc_callid_t callid = async_get_call(&call);
    2018                
    2019                 /* Process the message */
    2020                 int res = il_module_message_standalone(callid, &call, &answer,
    2021                     &answer_count);
    2022                
    2023                 /*
    2024                  * End if told to either by the message or the processing
    2025                  * result.
    2026                  */
    2027                 if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) ||
    2028                     (res == EHANGUP)) {
    2029                         return;
    2030                 }
    2031                
    2032                 /* Answer the message */
    2033                 answer_call(callid, res, &answer, answer_count);
    2034         }
    2035 }
    2036 
    2037 /** Starts the module.
    2038  *
    2039  * @return EOK on success.
    2040  * @return Other error codes as defined for each specific module start function.
    2041  */
    20421986int main(int argc, char *argv[])
    20431987{
    2044         int rc;
    2045        
    20461988        /* Start the module */
    2047         rc = il_module_start_standalone(il_client_connection);
    2048         return rc;
     1989        return il_module_start(SERVICE_IP);
    20491990}
    20501991
  • uspace/srv/net/il/ip/ip.h

    rcead2aa r357b5f5  
    138138/** IP global data. */
    139139struct ip_globals {
    140         /** Default client connection function for support modules. */
    141         async_client_conn_t client_connection;
    142140        /** Default gateway. */
    143141        ip_route_t gateway;
  • uspace/srv/net/net/net.c

    rcead2aa r357b5f5  
    4545#include <stdio.h>
    4646#include <str.h>
     47#include <str_error.h>
    4748
    4849#include <ipc/ipc.h>
     
    5152#include <ipc/net_net.h>
    5253#include <ipc/il.h>
     54#include <ipc/nil.h>
    5355
    5456#include <net/modules.h>
     
    6264
    6365#include <netif_remote.h>
    64 #include <nil_interface.h>
     66#include <nil_remote.h>
    6567#include <net_interface.h>
    6668#include <ip_interface.h>
     
    9092 *
    9193 */
    92 int add_configuration(measured_strings_t *configuration, const char *name,
    93     const char *value)
     94int add_configuration(measured_strings_t *configuration, const uint8_t *name,
     95    const uint8_t *value)
    9496{
    9597        int rc;
     
    119121}
    120122
    121 static int parse_line(measured_strings_t *configuration, char *line)
     123static int parse_line(measured_strings_t *configuration, uint8_t *line)
    122124{
    123125        int rc;
    124126       
    125127        /* From the beginning */
    126         char *name = line;
     128        uint8_t *name = line;
    127129       
    128130        /* Skip comments and blank lines */
     
    135137       
    136138        /* Remember the name start */
    137         char *value = name;
     139        uint8_t *value = name;
    138140       
    139141        /* Skip the name */
     
    186188       
    187189        /* Construct the full filename */
    188         char line[BUFFER_SIZE];
    189         if (snprintf(line, BUFFER_SIZE, "%s/%s", directory, filename) > BUFFER_SIZE)
     190        char fname[BUFFER_SIZE];
     191        if (snprintf(fname, BUFFER_SIZE, "%s/%s", directory, filename) > BUFFER_SIZE)
    190192                return EOVERFLOW;
    191193       
    192194        /* Open the file */
    193         FILE *cfg = fopen(line, "r");
     195        FILE *cfg = fopen(fname, "r");
    194196        if (!cfg)
    195197                return ENOENT;
     
    201203        unsigned int line_number = 0;
    202204        size_t index = 0;
     205        uint8_t line[BUFFER_SIZE];
     206       
    203207        while (!ferror(cfg) && !feof(cfg)) {
    204208                int read = fgetc(cfg);
     
    207211                                line[BUFFER_SIZE - 1] = '\0';
    208212                                fprintf(stderr, "%s: Configuration line %u too "
    209                                     "long: %s\n", NAME, line_number, line);
     213                                    "long: %s\n", NAME, line_number, (char *) line);
    210214                               
    211215                                /* No space left in the line buffer */
     
    213217                        }
    214218                        /* Append the character */
    215                         line[index] = (char) read;
     219                        line[index] = (uint8_t) read;
    216220                        index++;
    217221                } else {
     
    221225                        if (parse_line(configuration, line) != EOK) {
    222226                                fprintf(stderr, "%s: Configuration error on "
    223                                     "line %u: %s\n", NAME, line_number, line);
     227                                    "line %u: %s\n", NAME, line_number, (char *) line);
    224228                        }
    225229                       
     
    282286                return rc;
    283287       
    284         rc = add_module(NULL, &net_globals.modules, LO_NAME, LO_FILENAME,
    285             SERVICE_LO, 0, connect_to_service);
    286         if (rc != EOK)
    287                 return rc;
    288         rc = add_module(NULL, &net_globals.modules, DP8390_NAME,
    289             DP8390_FILENAME, SERVICE_DP8390, 0, connect_to_service);
    290         if (rc != EOK)
    291                 return rc;
    292         rc = add_module(NULL, &net_globals.modules, ETHERNET_NAME,
    293             ETHERNET_FILENAME, SERVICE_ETHERNET, 0, connect_to_service);
    294         if (rc != EOK)
    295                 return rc;
    296         rc = add_module(NULL, &net_globals.modules, NILDUMMY_NAME,
    297             NILDUMMY_FILENAME, SERVICE_NILDUMMY, 0, connect_to_service);
     288        rc = add_module(NULL, &net_globals.modules, (uint8_t *) LO_NAME,
     289            (uint8_t *) LO_FILENAME, SERVICE_LO, 0, connect_to_service);
     290        if (rc != EOK)
     291                return rc;
     292        rc = add_module(NULL, &net_globals.modules, (uint8_t *) NE2000_NAME,
     293            (uint8_t *) NE2000_FILENAME, SERVICE_NE2000, 0, connect_to_service);
     294        if (rc != EOK)
     295                return rc;
     296        rc = add_module(NULL, &net_globals.modules, (uint8_t *) ETHERNET_NAME,
     297            (uint8_t *) ETHERNET_FILENAME, SERVICE_ETHERNET, 0, connect_to_service);
     298        if (rc != EOK)
     299                return rc;
     300        rc = add_module(NULL, &net_globals.modules, (uint8_t *) NILDUMMY_NAME,
     301            (uint8_t *) NILDUMMY_FILENAME, SERVICE_NILDUMMY, 0, connect_to_service);
    298302        if (rc != EOK)
    299303                return rc;
     
    322326static int net_module_start(async_client_conn_t client_connection)
    323327{
    324         ipcarg_t phonehash;
     328        sysarg_t phonehash;
    325329        int rc;
    326330       
     
    330334                return rc;
    331335       
    332        
    333336        rc = net_initialize(client_connection);
    334337        if (rc != EOK)
    335338                goto out;
    336339       
    337         rc = REGISTER_ME(SERVICE_NETWORKING, &phonehash);
     340        rc = ipc_connect_to_me(PHONE_NS, SERVICE_NETWORKING, 0, 0, &phonehash);
    338341        if (rc != EOK)
    339342                goto out;
     
    364367 */
    365368static int net_get_conf(measured_strings_t *netif_conf,
    366     measured_string_t *configuration, size_t count, char **data)
     369    measured_string_t *configuration, size_t count, uint8_t **data)
    367370{
    368371        if (data)
     
    390393
    391394int net_get_conf_req(int net_phone, measured_string_t **configuration,
    392     size_t count, char **data)
     395    size_t count, uint8_t **data)
    393396{
    394397        if (!configuration || (count <= 0))
     
    399402
    400403int net_get_device_conf_req(int net_phone, device_id_t device_id,
    401     measured_string_t **configuration, size_t count, char **data)
     404    measured_string_t **configuration, size_t count, uint8_t **data)
    402405{
    403406        if ((!configuration) || (count == 0))
     
    411414}
    412415
    413 void net_free_settings(measured_string_t *settings, char *data)
     416void net_free_settings(measured_string_t *settings, uint8_t *data)
    414417{
    415418}
     
    437440        /* Mandatory netif */
    438441        measured_string_t *setting =
    439             measured_strings_find(&netif->configuration, CONF_NETIF, 0);
     442            measured_strings_find(&netif->configuration, (uint8_t *) CONF_NETIF, 0);
    440443       
    441444        netif->driver = get_running_module(&net_globals.modules, setting->value);
     
    447450       
    448451        /* Optional network interface layer */
    449         setting = measured_strings_find(&netif->configuration, CONF_NIL, 0);
     452        setting = measured_strings_find(&netif->configuration, (uint8_t *) CONF_NIL, 0);
    450453        if (setting) {
    451454                netif->nil = get_running_module(&net_globals.modules, setting->value);
     
    459462       
    460463        /* Mandatory internet layer */
    461         setting = measured_strings_find(&netif->configuration, CONF_IL, 0);
     464        setting = measured_strings_find(&netif->configuration, (uint8_t *) CONF_IL, 0);
    462465        netif->il = get_running_module(&net_globals.modules, setting->value);
    463466        if (!netif->il) {
     
    468471       
    469472        /* Hardware configuration */
    470         setting = measured_strings_find(&netif->configuration, CONF_IRQ, 0);
    471         int irq = setting ? strtol(setting->value, NULL, 10) : 0;
    472        
    473         setting = measured_strings_find(&netif->configuration, CONF_IO, 0);
    474         int io = setting ? strtol(setting->value, NULL, 16) : 0;
    475        
    476         rc = netif_probe_req_remote(netif->driver->phone, netif->id, irq, io);
     473        setting = measured_strings_find(&netif->configuration, (uint8_t *) CONF_IRQ, 0);
     474        int irq = setting ? strtol((char *) setting->value, NULL, 10) : 0;
     475       
     476        setting = measured_strings_find(&netif->configuration, (uint8_t *) CONF_IO, 0);
     477        uintptr_t io = setting ? strtol((char *) setting->value, NULL, 16) : 0;
     478       
     479        rc = netif_probe_req(netif->driver->phone, netif->id, irq, (void *) io);
    477480        if (rc != EOK)
    478481                return rc;
     
    481484        services_t internet_service;
    482485        if (netif->nil) {
    483                 setting = measured_strings_find(&netif->configuration, CONF_MTU, 0);
     486                setting = measured_strings_find(&netif->configuration, (uint8_t *) CONF_MTU, 0);
    484487                if (!setting)
    485488                        setting = measured_strings_find(&net_globals.configuration,
    486                             CONF_MTU, 0);
    487                
    488                 int mtu = setting ? strtol(setting->value, NULL, 10) : 0;
     489                            (uint8_t *) CONF_MTU, 0);
     490               
     491                int mtu = setting ? strtol((char *) setting->value, NULL, 10) : 0;
    489492               
    490493                rc = nil_device_req(netif->nil->phone, netif->id, mtu,
     
    509512        }
    510513       
    511         return netif_start_req_remote(netif->driver->phone, netif->id);
     514        return netif_start_req(netif->driver->phone, netif->id);
    512515}
    513516
     
    558561                /* Mandatory name */
    559562                measured_string_t *setting =
    560                     measured_strings_find(&netif->configuration, CONF_NAME, 0);
     563                    measured_strings_find(&netif->configuration, (uint8_t *) CONF_NAME, 0);
    561564                if (!setting) {
    562565                        fprintf(stderr, "%s: Network interface name is missing\n", NAME);
     
    589592                rc = start_device(netif);
    590593                if (rc != EOK) {
     594                        printf("%s: Error starting interface %s (%s)\n", NAME,
     595                            netif->name, str_error(rc));
    591596                        measured_strings_destroy(&netif->configuration);
    592597                        netifs_exclude_index(&net_globals.netifs, index);
     598                       
    593599                        return rc;
    594600                }
     
    602608                printf("%s: Network interface started (name: %s, id: %d, driver: %s, "
    603609                    "nil: %s, il: %s)\n", NAME, netif->name, netif->id,
    604                     netif->driver->name,  netif->nil ? netif->nil->name : "[none]",
     610                    netif->driver->name, netif->nil ? (char *) netif->nil->name : "[none]",
    605611                    netif->il->name);
    606612        }
     
    611617/** Process the networking message.
    612618 *
    613  * @param[in] callid        The message identifier.
    614  * @param[in] call          The message parameters.
     619 * @param[in]  callid       The message identifier.
     620 * @param[in]  call         The message parameters.
    615621 * @param[out] answer       The message answer parameters.
    616622 * @param[out] answer_count The last parameter for the actual answer
     
    625631 */
    626632int net_message(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer,
    627     int *answer_count)
     633    size_t *answer_count)
    628634{
    629635        measured_string_t *strings;
    630         char *data;
     636        uint8_t *data;
    631637        int rc;
    632638       
    633639        *answer_count = 0;
    634         switch (IPC_GET_METHOD(*call)) {
     640        switch (IPC_GET_IMETHOD(*call)) {
    635641        case IPC_M_PHONE_HUNGUP:
    636642                return EOK;
    637643        case NET_NET_GET_DEVICE_CONF:
    638644                rc = measured_strings_receive(&strings, &data,
    639                     IPC_GET_COUNT(call));
     645                    IPC_GET_COUNT(*call));
    640646                if (rc != EOK)
    641647                        return rc;
    642                 net_get_device_conf_req(0, IPC_GET_DEVICE(call), &strings,
    643                     IPC_GET_COUNT(call), NULL);
     648                net_get_device_conf_req(0, IPC_GET_DEVICE(*call), &strings,
     649                    IPC_GET_COUNT(*call), NULL);
    644650               
    645651                /* Strings should not contain received data anymore */
    646652                free(data);
    647653               
    648                 rc = measured_strings_reply(strings, IPC_GET_COUNT(call));
     654                rc = measured_strings_reply(strings, IPC_GET_COUNT(*call));
    649655                free(strings);
    650656                return rc;
    651657        case NET_NET_GET_CONF:
    652658                rc = measured_strings_receive(&strings, &data,
    653                     IPC_GET_COUNT(call));
     659                    IPC_GET_COUNT(*call));
    654660                if (rc != EOK)
    655661                        return rc;
    656                 net_get_conf_req(0, &strings, IPC_GET_COUNT(call), NULL);
     662                net_get_conf_req(0, &strings, IPC_GET_COUNT(*call), NULL);
    657663               
    658664                /* Strings should not contain received data anymore */
    659665                free(data);
    660666               
    661                 rc = measured_strings_reply(strings, IPC_GET_COUNT(call));
     667                rc = measured_strings_reply(strings, IPC_GET_COUNT(*call));
    662668                free(strings);
    663669                return rc;
     
    686692                /* Clear the answer structure */
    687693                ipc_call_t answer;
    688                 int answer_count;
     694                size_t answer_count;
    689695                refresh_answer(&answer, &answer_count);
    690696               
     
    697703               
    698704                /* End if told to either by the message or the processing result */
    699                 if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) || (res == EHANGUP))
     705                if ((IPC_GET_IMETHOD(call) == IPC_M_PHONE_HUNGUP) || (res == EHANGUP))
    700706                        return;
    701707               
     
    707713int main(int argc, char *argv[])
    708714{
    709         int rc;
    710        
    711         rc = net_module_start(net_client_connection);
    712         if (rc != EOK) {
    713                 fprintf(stderr, "%s: net_module_start error %i\n", NAME, rc);
    714                 return rc;
    715         }
    716        
    717         return EOK;
     715        return net_module_start(net_client_connection);
    718716}
    719717
  • uspace/srv/net/net/net.h

    rcead2aa r357b5f5  
    5252 */
    5353
    54 #define DP8390_FILENAME  "/srv/dp8390"
    55 #define DP8390_NAME      "dp8390"
     54#define NE2000_FILENAME  "/srv/ne2000"
     55#define NE2000_NAME      "ne2000"
    5656
    5757#define ETHERNET_FILENAME  "/srv/eth"
     
    105105        module_t *driver;
    106106       
    107         device_id_t id; /**< System-unique network interface identifier. */
    108         module_t *il;   /**< Serving internet layer module index. */
    109         char *name;     /**< System-unique network interface name. */
    110         module_t *nil;  /**< Serving link layer module index. */
     107        device_id_t id;  /**< System-unique network interface identifier. */
     108        module_t *il;    /**< Serving internet layer module index. */
     109        uint8_t *name;   /**< System-unique network interface name. */
     110        module_t *nil;   /**< Serving link layer module index. */
    111111} netif_t;
    112112
     
    133133} net_globals_t;
    134134
    135 extern int add_configuration(measured_strings_t *, const char *, const char *);
    136 extern int net_module_message(ipc_callid_t, ipc_call_t *, ipc_call_t *, int *);
     135extern int add_configuration(measured_strings_t *, const uint8_t *,
     136    const uint8_t *);
     137extern int net_module_message(ipc_callid_t, ipc_call_t *, ipc_call_t *, size_t *);
    137138extern int net_initialize_build(async_client_conn_t);
    138 extern int net_message(ipc_callid_t, ipc_call_t *, ipc_call_t *, int *);
     139extern int net_message(ipc_callid_t, ipc_call_t *, ipc_call_t *, size_t *);
    139140
    140141#endif
  • uspace/srv/net/net/net_standalone.c

    rcead2aa r357b5f5  
    6363        int rc;
    6464       
    65         task_id_t task_id = spawn("/srv/ip");
     65        task_id_t task_id = net_spawn((uint8_t *) "/srv/ip");
    6666        if (!task_id)
    6767                return EINVAL;
    6868       
    69         rc = add_module(NULL, &net_globals.modules, IP_NAME,
    70             IP_FILENAME, SERVICE_IP, task_id, ip_connect_module);
     69        rc = add_module(NULL, &net_globals.modules, (uint8_t *) IP_NAME,
     70            (uint8_t *) IP_FILENAME, SERVICE_IP, task_id, ip_connect_module);
    7171        if (rc != EOK)
    7272                return rc;
    7373       
    74         if (!spawn("/srv/icmp"))
     74        if (!net_spawn((uint8_t *) "/srv/icmp"))
    7575                return EINVAL;
    7676       
    77         if (!spawn("/srv/udp"))
     77        if (!net_spawn((uint8_t *) "/srv/udp"))
    7878                return EINVAL;
    7979       
    80         if (!spawn("/srv/tcp"))
     80        if (!net_spawn((uint8_t *) "/srv/tcp"))
    8181                return EINVAL;
    8282       
     
    100100 */
    101101int net_module_message(ipc_callid_t callid, ipc_call_t *call,
    102     ipc_call_t *answer, int *answer_count)
     102    ipc_call_t *answer, size_t *count)
    103103{
    104         if (IS_NET_PACKET_MESSAGE(call))
    105                 return packet_server_message(callid, call, answer, answer_count);
     104        if (IS_NET_PACKET_MESSAGE(*call))
     105                return packet_server_message(callid, call, answer, count);
    106106       
    107         return net_message(callid, call, answer, answer_count);
     107        return net_message(callid, call, answer, count);
    108108}
    109109
  • uspace/srv/net/netif/lo/Makefile

    rcead2aa r357b5f5  
    3939-include $(CONFIG_MAKEFILE)
    4040
    41 ifeq ($(CONFIG_NETIF_NIL_BUNDLE),y)
    42         LIBS += $(USPACE_PREFIX)/srv/net/nil/nildummy/libnildummy.a
    43 endif
    44 
    4541BINARY = lo
    4642
  • uspace/srv/net/netif/lo/lo.c

    rcead2aa r357b5f5  
    4848#include <packet_client.h>
    4949#include <net/device.h>
    50 #include <nil_interface.h>
    51 #include <netif_interface.h>
    52 #include <netif_local.h>
    53 
    54 /** Default hardware address. */
    55 #define DEFAULT_ADDR            "\0\0\0\0\0\0"
     50#include <netif_skel.h>
     51#include <nil_remote.h>
    5652
    5753/** Default address length. */
    58 #define DEFAULT_ADDR_LEN        (sizeof(DEFAULT_ADDR) / sizeof(char))
     54#define DEFAULT_ADDR_LEN  6
    5955
    6056/** Loopback module name. */
    6157#define NAME  "lo"
    6258
    63 /** Network interface global data. */
    64 netif_globals_t netif_globals;
     59static uint8_t default_addr[DEFAULT_ADDR_LEN] =
     60    {0, 0, 0, 0, 0, 0};
    6561
    6662int netif_specific_message(ipc_callid_t callid, ipc_call_t *call,
    67     ipc_call_t *answer, int *answer_count)
     63    ipc_call_t *answer, size_t *count)
    6864{
    6965        return ENOTSUP;
     
    7470        if (!address)
    7571                return EBADMEM;
    76 
    77         address->value = str_dup(DEFAULT_ADDR);
     72       
     73        address->value = default_addr;
    7874        address->length = DEFAULT_ADDR_LEN;
    79 
     75       
    8076        return EOK;
    8177}
     
    8379int netif_get_device_stats(device_id_t device_id, device_stats_t *stats)
    8480{
    85         netif_device_t *device;
    86         int rc;
    87 
    8881        if (!stats)
    8982                return EBADMEM;
    90 
    91         rc = find_device(device_id, &device);
     83       
     84        netif_device_t *device;
     85        int rc = find_device(device_id, &device);
    9286        if (rc != EOK)
    9387                return rc;
    94 
     88       
    9589        memcpy(stats, (device_stats_t *) device->specific,
    9690            sizeof(device_stats_t));
    97 
    98         return EOK;
    99 }
    100 
    101 /** Changes the loopback state.
    102  *
    103  * @param[in] device    The device structure.
    104  * @param[in] state     The new device state.
    105  * @return              The new state if changed.
    106  * @return              EOK otherwise.
    107  */
    108 static int change_state_message(netif_device_t *device, device_state_t state)
     91       
     92        return EOK;
     93}
     94
     95/** Change the loopback state.
     96 *
     97 * @param[in] device The device structure.
     98 * @param[in] state  The new device state.
     99 *
     100 * @return New state if changed.
     101 * @return EOK otherwise.
     102 *
     103 */
     104static void change_state_message(netif_device_t *device, device_state_t state)
    109105{
    110106        if (device->state != state) {
    111107                device->state = state;
    112108               
    113                 printf("%s: State changed to %s\n", NAME,
    114                     (state == NETIF_ACTIVE) ? "active" : "stopped");
     109                const char *desc;
     110                switch (state) {
     111                case NETIF_ACTIVE:
     112                        desc = "active";
     113                        break;
     114                case NETIF_STOPPED:
     115                        desc = "stopped";
     116                        break;
     117                default:
     118                        desc = "unknown";
     119                }
    115120               
    116                 return state;
    117         }
    118        
    119         return EOK;
    120 }
    121 
    122 /** Creates and returns the loopback network interface structure.
    123  *
    124  * @param[in] device_id The new devce identifier.
    125  * @param[out] device   The device structure.
    126  * @return              EOK on success.
    127  * @return              EXDEV if one loopback network interface already exists.
    128  * @return              ENOMEM if there is not enough memory left.
    129  */
    130 static int create(device_id_t device_id, netif_device_t **device)
    131 {
    132         int index;
    133 
     121                printf("%s: State changed to %s\n", NAME, desc);
     122        }
     123}
     124
     125/** Create and return the loopback network interface structure.
     126 *
     127 * @param[in]  device_id New devce identifier.
     128 * @param[out] device    Device structure.
     129 *
     130 * @return EOK on success.
     131 * @return EXDEV if one loopback network interface already exists.
     132 * @return ENOMEM if there is not enough memory left.
     133 *
     134 */
     135static int lo_create(device_id_t device_id, netif_device_t **device)
     136{
    134137        if (netif_device_map_count(&netif_globals.device_map) > 0)
    135138                return EXDEV;
    136 
     139       
    137140        *device = (netif_device_t *) malloc(sizeof(netif_device_t));
    138141        if (!*device)
    139142                return ENOMEM;
    140 
     143       
    141144        (*device)->specific = (device_stats_t *) malloc(sizeof(device_stats_t));
    142145        if (!(*device)->specific) {
     
    144147                return ENOMEM;
    145148        }
    146 
     149       
    147150        null_device_stats((device_stats_t *) (*device)->specific);
    148151        (*device)->device_id = device_id;
    149152        (*device)->nil_phone = -1;
    150153        (*device)->state = NETIF_STOPPED;
    151         index = netif_device_map_add(&netif_globals.device_map,
     154        int index = netif_device_map_add(&netif_globals.device_map,
    152155            (*device)->device_id, *device);
    153 
     156       
    154157        if (index < 0) {
    155158                free(*device);
     
    164167int netif_initialize(void)
    165168{
    166         ipcarg_t phonehash;
    167 
    168         return REGISTER_ME(SERVICE_LO, &phonehash);
    169 }
    170 
    171 int netif_probe_message(device_id_t device_id, int irq, uintptr_t io)
    172 {
     169        sysarg_t phonehash;
     170        return ipc_connect_to_me(PHONE_NS, SERVICE_LO, 0, 0, &phonehash);
     171}
     172
     173int netif_probe_message(device_id_t device_id, int irq, void *io)
     174{
     175        /* Create a new device */
    173176        netif_device_t *device;
    174         int rc;
    175 
    176         /* Create a new device */
    177         rc = create(device_id, &device);
     177        int rc = lo_create(device_id, &device);
    178178        if (rc != EOK)
    179179                return rc;
    180 
    181         /* Print the settings */
     180       
    182181        printf("%s: Device created (id: %d)\n", NAME, device->device_id);
    183 
    184182        return EOK;
    185183}
     
    188186{
    189187        netif_device_t *device;
    190         size_t length;
    191         packet_t *next;
    192         int phone;
    193         int rc;
    194 
    195         rc = find_device(device_id, &device);
     188        int rc = find_device(device_id, &device);
    196189        if (rc != EOK)
    197190                return EOK;
    198 
     191       
    199192        if (device->state != NETIF_ACTIVE) {
    200193                netif_pq_release(packet_get_id(packet));
    201194                return EFORWARD;
    202195        }
    203 
    204         next = packet;
     196       
     197        packet_t *next = packet;
    205198        do {
    206199                ((device_stats_t *) device->specific)->send_packets++;
    207200                ((device_stats_t *) device->specific)->receive_packets++;
    208                 length = packet_get_data_length(next);
     201                size_t length = packet_get_data_length(next);
    209202                ((device_stats_t *) device->specific)->send_bytes += length;
    210203                ((device_stats_t *) device->specific)->receive_bytes += length;
    211204                next = pq_next(next);
    212         } while(next);
    213 
    214         phone = device->nil_phone;
     205        } while (next);
     206       
     207        int phone = device->nil_phone;
    215208        fibril_rwlock_write_unlock(&netif_globals.lock);
     209       
    216210        nil_received_msg(phone, device_id, packet, sender);
     211       
    217212        fibril_rwlock_write_lock(&netif_globals.lock);
    218        
    219213        return EOK;
    220214}
     
    222216int netif_start_message(netif_device_t *device)
    223217{
    224         return change_state_message(device, NETIF_ACTIVE);
     218        change_state_message(device, NETIF_ACTIVE);
     219        return device->state;
    225220}
    226221
    227222int netif_stop_message(netif_device_t *device)
    228223{
    229         return change_state_message(device, NETIF_STOPPED);
    230 }
    231 
    232 /** Default thread for new connections.
    233  *
    234  * @param[in] iid       The initial message identifier.
    235  * @param[in] icall     The initial message call structure.
    236  */
    237 static void netif_client_connection(ipc_callid_t iid, ipc_call_t *icall)
    238 {
    239         /*
    240          * Accept the connection
    241          *  - Answer the first IPC_M_CONNECT_ME_TO call.
    242          */
    243         ipc_answer_0(iid, EOK);
    244        
    245         while (true) {
    246                 ipc_call_t answer;
    247                 int answer_count;
    248                
    249                 /* Clear the answer structure */
    250                 refresh_answer(&answer, &answer_count);
    251                
    252                 /* Fetch the next message */
    253                 ipc_call_t call;
    254                 ipc_callid_t callid = async_get_call(&call);
    255                
    256                 /* Process the message */
    257                 int res = netif_module_message(NAME, callid, &call, &answer,
    258                     &answer_count);
    259                
    260                 /*
    261                  * End if told to either by the message or the processing
    262                  * result.
    263                  */
    264                 if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) ||
    265                     (res == EHANGUP))
    266                         return;
    267                
    268                 /* Answer the message */
    269                 answer_call(callid, res, &answer, answer_count);
    270         }
     224        change_state_message(device, NETIF_STOPPED);
     225        return device->state;
    271226}
    272227
    273228int main(int argc, char *argv[])
    274229{
    275         int rc;
    276        
    277230        /* Start the module */
    278         rc = netif_module_start(netif_client_connection);
    279         return rc;
     231        return netif_module_start();
    280232}
    281233
  • uspace/srv/net/nil/eth/Makefile

    rcead2aa r357b5f5  
    3939-include $(CONFIG_MAKEFILE)
    4040
    41 ifeq ($(CONFIG_NETIF_NIL_BUNDLE),y)
    42         LIBRARY = libeth
    43 else
    44         BINARY = eth
    45 endif
     41BINARY = eth
    4642
    4743SOURCES = \
    48         eth.c \
    49         eth_module.c
     44        eth.c
    5045
    5146include $(USPACE_PREFIX)/Makefile.common
  • uspace/srv/net/nil/eth/eth.c

    rcead2aa r357b5f5  
    4545
    4646#include <ipc/ipc.h>
     47#include <ipc/nil.h>
    4748#include <ipc/net.h>
    4849#include <ipc/services.h>
     
    5455#include <protocol_map.h>
    5556#include <net/device.h>
    56 #include <netif_interface.h>
     57#include <netif_remote.h>
    5758#include <net_interface.h>
    58 #include <nil_interface.h>
    59 #include <il_interface.h>
     59#include <il_remote.h>
    6060#include <adt/measured_strings.h>
    6161#include <packet_client.h>
    6262#include <packet_remote.h>
    63 #include <nil_local.h>
     63#include <nil_skel.h>
    6464
    6565#include "eth.h"
    66 #include "eth_header.h"
    6766
    6867/** The module name. */
     
    7271#define ETH_PREFIX \
    7372        (sizeof(eth_header_t) + sizeof(eth_header_lsap_t) + \
    74         sizeof(eth_header_snap_t))
     73            sizeof(eth_header_snap_t))
    7574
    7675/** Reserved packet suffix length. */
    77 #define ETH_SUFFIX \
    78         sizeof(eth_fcs_t)
     76#define ETH_SUFFIX  (sizeof(eth_fcs_t))
    7977
    8078/** Maximum packet content length. */
    81 #define ETH_MAX_CONTENT 1500u
     79#define ETH_MAX_CONTENT  1500u
    8280
    8381/** Minimum packet content length. */
    84 #define ETH_MIN_CONTENT 46u
     82#define ETH_MIN_CONTENT  46u
    8583
    8684/** Maximum tagged packet content length. */
    8785#define ETH_MAX_TAGGED_CONTENT(flags) \
    8886        (ETH_MAX_CONTENT - \
    89         ((IS_8023_2_LSAP(flags) || IS_8023_2_SNAP(flags)) ? \
    90         sizeof(eth_header_lsap_t) : 0) - \
    91         (IS_8023_2_SNAP(flags) ? sizeof(eth_header_snap_t) : 0))
     87            ((IS_8023_2_LSAP(flags) || IS_8023_2_SNAP(flags)) ? \
     88            sizeof(eth_header_lsap_t) : 0) - \
     89            (IS_8023_2_SNAP(flags) ? sizeof(eth_header_snap_t) : 0))
    9290
    9391/** Minimum tagged packet content length. */
    9492#define ETH_MIN_TAGGED_CONTENT(flags) \
    9593        (ETH_MIN_CONTENT - \
    96         ((IS_8023_2_LSAP(flags) || IS_8023_2_SNAP(flags)) ? \
    97         sizeof(eth_header_lsap_t) : 0) - \
    98         (IS_8023_2_SNAP(flags) ? sizeof(eth_header_snap_t) : 0))
     94            ((IS_8023_2_LSAP(flags) || IS_8023_2_SNAP(flags)) ? \
     95            sizeof(eth_header_lsap_t) : 0) - \
     96            (IS_8023_2_SNAP(flags) ? sizeof(eth_header_snap_t) : 0))
    9997
    10098/** Dummy flag shift value. */
    101 #define ETH_DUMMY_SHIFT 0
     99#define ETH_DUMMY_SHIFT  0
    102100
    103101/** Mode flag shift value. */
    104 #define ETH_MODE_SHIFT  1
     102#define ETH_MODE_SHIFT  1
    105103
    106104/** Dummy device flag.
    107105 * Preamble and FCS are mandatory part of the packets.
    108106 */
    109 #define ETH_DUMMY               (1 << ETH_DUMMY_SHIFT)
     107#define ETH_DUMMY  (1 << ETH_DUMMY_SHIFT)
    110108
    111109/** Returns the dummy flag.
    112110 * @see ETH_DUMMY
    113111 */
    114 #define IS_DUMMY(flags)         ((flags) & ETH_DUMMY)
     112#define IS_DUMMY(flags)  ((flags) & ETH_DUMMY)
    115113
    116114/** Device mode flags.
     
    119117 * @see ETH_8023_2_SNAP
    120118 */
    121 #define ETH_MODE_MASK           (3 << ETH_MODE_SHIFT)
     119#define ETH_MODE_MASK  (3 << ETH_MODE_SHIFT)
    122120
    123121/** DIX Ethernet mode flag. */
    124 #define ETH_DIX                 (1 << ETH_MODE_SHIFT)
    125 
    126 /** Returns whether the DIX Ethernet mode flag is set.
    127  *
    128  * @param[in] flags     The ethernet flags.
     122#define ETH_DIX  (1 << ETH_MODE_SHIFT)
     123
     124/** Return whether the DIX Ethernet mode flag is set.
     125 *
     126 * @param[in] flags Ethernet flags.
    129127 * @see ETH_DIX
    130  */
    131 #define IS_DIX(flags)           (((flags) & ETH_MODE_MASK) == ETH_DIX)
     128 *
     129 */
     130#define IS_DIX(flags)  (((flags) & ETH_MODE_MASK) == ETH_DIX)
    132131
    133132/** 802.3 + 802.2 + LSAP mode flag. */
    134 #define ETH_8023_2_LSAP         (2 << ETH_MODE_SHIFT)
    135 
    136 /** Returns whether the 802.3 + 802.2 + LSAP mode flag is set.
    137  *
    138  * @param[in] flags     The ethernet flags.
     133#define ETH_8023_2_LSAP  (2 << ETH_MODE_SHIFT)
     134
     135/** Return whether the 802.3 + 802.2 + LSAP mode flag is set.
     136 *
     137 * @param[in] flags Ethernet flags.
    139138 * @see ETH_8023_2_LSAP
    140  */
    141 #define IS_8023_2_LSAP(flags)   (((flags) & ETH_MODE_MASK) == ETH_8023_2_LSAP)
     139 *
     140 */
     141#define IS_8023_2_LSAP(flags)  (((flags) & ETH_MODE_MASK) == ETH_8023_2_LSAP)
    142142
    143143/** 802.3 + 802.2 + LSAP + SNAP mode flag. */
    144 #define ETH_8023_2_SNAP         (3 << ETH_MODE_SHIFT)
    145 
    146 /** Returns whether the 802.3 + 802.2 + LSAP + SNAP mode flag is set.
    147  *
    148  * @param[in] flags     The ethernet flags.
     144#define ETH_8023_2_SNAP  (3 << ETH_MODE_SHIFT)
     145
     146/** Return whether the 802.3 + 802.2 + LSAP + SNAP mode flag is set.
     147 *
     148 * @param[in] flags Ethernet flags.
    149149 * @see ETH_8023_2_SNAP
    150  */
    151 #define IS_8023_2_SNAP(flags)   (((flags) & ETH_MODE_MASK) == ETH_8023_2_SNAP)
     150 *
     151 */
     152#define IS_8023_2_SNAP(flags)  (((flags) & ETH_MODE_MASK) == ETH_8023_2_SNAP)
    152153
    153154/** Type definition of the ethernet address type.
     
    201202
    202203        eth_globals.broadcast_addr =
    203             measured_string_create_bulk("\xFF\xFF\xFF\xFF\xFF\xFF",
    204             CONVERT_SIZE(uint8_t, char, ETH_ADDR));
     204            measured_string_create_bulk((uint8_t *) "\xFF\xFF\xFF\xFF\xFF\xFF", ETH_ADDR);
    205205        if (!eth_globals.broadcast_addr) {
    206206                rc = ENOMEM;
     
    238238
    239239        while (true) {
    240                 switch (IPC_GET_METHOD(*icall)) {
     240                switch (IPC_GET_IMETHOD(*icall)) {
    241241                case NET_NIL_DEVICE_STATE:
    242                         nil_device_state_msg_local(0, IPC_GET_DEVICE(icall),
    243                             IPC_GET_STATE(icall));
     242                        nil_device_state_msg_local(0, IPC_GET_DEVICE(*icall),
     243                            IPC_GET_STATE(*icall));
    244244                        ipc_answer_0(iid, EOK);
    245245                        break;
    246246                case NET_NIL_RECEIVED:
    247247                        rc = packet_translate_remote(eth_globals.net_phone,
    248                             &packet, IPC_GET_PACKET(icall));
    249                         if (rc == EOK) {
     248                            &packet, IPC_GET_PACKET(*icall));
     249                        if (rc == EOK)
    250250                                rc = nil_received_msg_local(0,
    251                                     IPC_GET_DEVICE(icall), packet, 0);
    252                         }
    253                         ipc_answer_0(iid, (ipcarg_t) rc);
     251                                    IPC_GET_DEVICE(*icall), packet, 0);
     252                       
     253                        ipc_answer_0(iid, (sysarg_t) rc);
    254254                        break;
    255255                default:
    256                         ipc_answer_0(iid, (ipcarg_t) ENOTSUP);
     256                        ipc_answer_0(iid, (sysarg_t) ENOTSUP);
    257257                }
    258258               
     
    285285        measured_string_t names[2] = {
    286286                {
    287                         (char *) "ETH_MODE",
     287                        (uint8_t *) "ETH_MODE",
    288288                        8
    289289                },
    290290                {
    291                         (char *) "ETH_DUMMY",
     291                        (uint8_t *) "ETH_DUMMY",
    292292                        9
    293293                }
     
    295295        measured_string_t *configuration;
    296296        size_t count = sizeof(names) / sizeof(measured_string_t);
    297         char *data;
     297        uint8_t *data;
    298298        eth_proto_t *proto;
    299299        int rc;
     
    359359
    360360        if (configuration) {
    361                 if (!str_lcmp(configuration[0].value, "DIX",
     361                if (!str_lcmp((char *) configuration[0].value, "DIX",
    362362                    configuration[0].length)) {
    363363                        device->flags |= ETH_DIX;
    364                 } else if(!str_lcmp(configuration[0].value, "8023_2_LSAP",
     364                } else if(!str_lcmp((char *) configuration[0].value, "8023_2_LSAP",
    365365                    configuration[0].length)) {
    366366                        device->flags |= ETH_8023_2_LSAP;
     
    408408       
    409409        printf("%s: Device registered (id: %d, service: %d: mtu: %zu, "
    410             "mac: %x:%x:%x:%x:%x:%x, flags: 0x%x)\n",
     410            "mac: %02x:%02x:%02x:%02x:%02x:%02x, flags: 0x%x)\n",
    411411            NAME, device->device_id, device->service, device->mtu,
    412412            device->addr_data[0], device->addr_data[1],
     
    837837}
    838838
    839 int nil_message_standalone(const char *name, ipc_callid_t callid,
    840     ipc_call_t *call, ipc_call_t *answer, int *answer_count)
     839int nil_module_message(ipc_callid_t callid, ipc_call_t *call,
     840    ipc_call_t *answer, size_t *answer_count)
    841841{
    842842        measured_string_t *address;
     
    849849       
    850850        *answer_count = 0;
    851         switch (IPC_GET_METHOD(*call)) {
     851        switch (IPC_GET_IMETHOD(*call)) {
    852852        case IPC_M_PHONE_HUNGUP:
    853853                return EOK;
    854854       
    855855        case NET_NIL_DEVICE:
    856                 return eth_device_message(IPC_GET_DEVICE(call),
    857                     IPC_GET_SERVICE(call), IPC_GET_MTU(call));
     856                return eth_device_message(IPC_GET_DEVICE(*call),
     857                    IPC_GET_SERVICE(*call), IPC_GET_MTU(*call));
    858858        case NET_NIL_SEND:
    859859                rc = packet_translate_remote(eth_globals.net_phone, &packet,
    860                     IPC_GET_PACKET(call));
     860                    IPC_GET_PACKET(*call));
    861861                if (rc != EOK)
    862862                        return rc;
    863                 return eth_send_message(IPC_GET_DEVICE(call), packet,
    864                     IPC_GET_SERVICE(call));
     863                return eth_send_message(IPC_GET_DEVICE(*call), packet,
     864                    IPC_GET_SERVICE(*call));
    865865        case NET_NIL_PACKET_SPACE:
    866                 rc = eth_packet_space_message(IPC_GET_DEVICE(call), &addrlen,
     866                rc = eth_packet_space_message(IPC_GET_DEVICE(*call), &addrlen,
    867867                    &prefix, &content, &suffix);
    868868                if (rc != EOK)
    869869                        return rc;
    870                 IPC_SET_ADDR(answer, addrlen);
    871                 IPC_SET_PREFIX(answer, prefix);
    872                 IPC_SET_CONTENT(answer, content);
    873                 IPC_SET_SUFFIX(answer, suffix);
     870                IPC_SET_ADDR(*answer, addrlen);
     871                IPC_SET_PREFIX(*answer, prefix);
     872                IPC_SET_CONTENT(*answer, content);
     873                IPC_SET_SUFFIX(*answer, suffix);
    874874                *answer_count = 4;
    875875                return EOK;
    876876        case NET_NIL_ADDR:
    877                 rc = eth_addr_message(IPC_GET_DEVICE(call), ETH_LOCAL_ADDR,
     877                rc = eth_addr_message(IPC_GET_DEVICE(*call), ETH_LOCAL_ADDR,
    878878                    &address);
    879879                if (rc != EOK)
     
    881881                return measured_strings_reply(address, 1);
    882882        case NET_NIL_BROADCAST_ADDR:
    883                 rc = eth_addr_message(IPC_GET_DEVICE(call), ETH_BROADCAST_ADDR,
     883                rc = eth_addr_message(IPC_GET_DEVICE(*call), ETH_BROADCAST_ADDR,
    884884                    &address);
    885885                if (rc != EOK)
     
    887887                return measured_strings_reply(address, 1);
    888888        case IPC_M_CONNECT_TO_ME:
    889                 return eth_register_message(NIL_GET_PROTO(call),
    890                     IPC_GET_PHONE(call));
     889                return eth_register_message(NIL_GET_PROTO(*call),
     890                    IPC_GET_PHONE(*call));
    891891        }
    892892       
     
    894894}
    895895
    896 /** Default thread for new connections.
    897  *
    898  * @param[in] iid       The initial message identifier.
    899  * @param[in] icall     The initial message call structure.
    900  */
    901 static void nil_client_connection(ipc_callid_t iid, ipc_call_t *icall)
    902 {
    903         /*
    904          * Accept the connection
    905          *  - Answer the first IPC_M_CONNECT_ME_TO call.
    906          */
    907         ipc_answer_0(iid, EOK);
    908        
    909         while (true) {
    910                 ipc_call_t answer;
    911                 int answer_count;
    912                
    913                 /* Clear the answer structure */
    914                 refresh_answer(&answer, &answer_count);
    915                
    916                 /* Fetch the next message */
    917                 ipc_call_t call;
    918                 ipc_callid_t callid = async_get_call(&call);
    919                
    920                 /* Process the message */
    921                 int res = nil_module_message_standalone(NAME, callid, &call,
    922                     &answer, &answer_count);
    923                
    924                 /*
    925                  * End if told to either by the message or the processing
    926                  * result.
    927                  */
    928                 if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) ||
    929                     (res == EHANGUP))
    930                         return;
    931                
    932                 /* Answer the message */
    933                 answer_call(callid, res, &answer, answer_count);
    934         }
    935 }
    936 
    937896int main(int argc, char *argv[])
    938897{
    939         int rc;
    940        
    941898        /* Start the module */
    942         rc = nil_module_start_standalone(nil_client_connection);
    943         return rc;
     899        return nil_module_start(SERVICE_ETHERNET);
    944900}
    945901
  • uspace/srv/net/nil/eth/eth.h

    rcead2aa r357b5f5  
    4444#include <adt/measured_strings.h>
    4545
     46/** Ethernet address length. */
     47#define ETH_ADDR  6
     48
     49/** Ethernet header preamble value. */
     50#define ETH_PREAMBLE  0x55
     51
     52/** Ethernet header start of frame value. */
     53#define ETH_SFD  0xD5
     54
     55/** IEEE 802.2 unordered information control field. */
     56#define IEEE_8023_2_UI  0x03
     57
     58/** Type definition of the Ethernet header IEEE 802.3 + 802.2 + SNAP extensions.
     59 * @see eth_header_snap
     60 */
     61typedef struct eth_header_snap eth_header_snap_t;
     62
     63/** Type definition of the Ethernet header IEEE 802.3 + 802.2 + SNAP extensions.
     64 * @see eth_header_lsap
     65 */
     66typedef struct eth_header_lsap eth_header_lsap_t;
     67
     68/** Type definition of the Ethernet header LSAP extension.
     69 * @see eth_ieee_lsap
     70 */
     71typedef struct eth_ieee_lsap eth_ieee_lsap_t;
     72
     73/** Type definition of the Ethernet header SNAP extension.
     74 * @see eth_snap
     75 */
     76typedef struct eth_snap eth_snap_t;
     77
     78/** Type definition of the Ethernet header preamble.
     79 * @see preamble
     80 */
     81typedef struct eth_preamble eth_preamble_t;
     82
     83/** Type definition of the Ethernet header.
     84 * @see eth_header
     85 */
     86typedef struct eth_header eth_header_t;
     87
     88/** Ethernet header Link Service Access Point extension. */
     89struct eth_ieee_lsap {
     90        /**
     91         * Destination Service Access Point identifier.
     92         * The possible values are assigned by an IEEE committee.
     93         */
     94        uint8_t dsap;
     95       
     96        /**
     97         * Source Service Access Point identifier.
     98         * The possible values are assigned by an IEEE committee.
     99         */
     100        uint8_t ssap;
     101       
     102        /**
     103         * Control parameter.
     104         * The possible values are assigned by an IEEE committee.
     105         */
     106        uint8_t ctrl;
     107} __attribute__ ((packed));
     108
     109/** Ethernet header SNAP extension. */
     110struct eth_snap {
     111        /** Protocol identifier or organization code. */
     112        uint8_t protocol[3];
     113       
     114        /**
     115         * Ethernet protocol identifier in the network byte order (big endian).
     116         * @see ethernet_protocols.h
     117         */
     118        uint16_t ethertype;
     119} __attribute__ ((packed));
     120
     121/** Ethernet header preamble.
     122 *
     123 * Used for dummy devices.
     124 */
     125struct eth_preamble {
     126        /**
     127         * Controlling preamble used for the frame transmission synchronization.
     128         * All should be set to ETH_PREAMBLE.
     129         */
     130        uint8_t preamble[7];
     131       
     132        /**
     133         * Start of Frame Delimiter used for the frame transmission
     134         * synchronization.
     135         * Should be set to ETH_SFD.
     136         */
     137        uint8_t sfd;
     138} __attribute__ ((packed));
     139
     140/** Ethernet header. */
     141struct eth_header {
     142        /** Destination host Ethernet address (MAC address). */
     143        uint8_t destination_address[ETH_ADDR];
     144        /** Source host Ethernet address (MAC address). */
     145        uint8_t source_address[ETH_ADDR];
     146       
     147        /**
     148         * Ethernet protocol identifier in the network byte order (big endian).
     149         * @see ethernet_protocols.h
     150         */
     151        uint16_t ethertype;
     152} __attribute__ ((packed));
     153
     154/** Ethernet header IEEE 802.3 + 802.2 extension. */
     155struct eth_header_lsap {
     156        /** Ethernet header. */
     157        eth_header_t header;
     158       
     159        /**
     160         * LSAP extension.
     161         * If DSAP and SSAP are set to ETH_LSAP_SNAP the SNAP extension is being
     162         * used.
     163         * If DSAP and SSAP fields are equal to ETH_RAW the raw Ethernet packet
     164         * without any extensions is being used and the frame content starts
     165         * rigth after the two fields.
     166         */
     167        eth_ieee_lsap_t lsap;
     168} __attribute__ ((packed));
     169
     170/** Ethernet header IEEE 802.3 + 802.2 + SNAP extensions. */
     171struct eth_header_snap {
     172        /** Ethernet header. */
     173        eth_header_t header;
     174       
     175        /**
     176         * LSAP extension.
     177         * If DSAP and SSAP are set to ETH_LSAP_SNAP the SNAP extension is being
     178         * used.
     179         * If DSAP and SSAP fields are equal to ETH_RAW the raw Ethernet packet
     180         * without any extensions is being used and the frame content starts
     181         * rigth after the two fields.
     182         */
     183        eth_ieee_lsap_t lsap;
     184       
     185        /** SNAP extension. */
     186        eth_snap_t snap;
     187} __attribute__ ((packed));
     188
     189/** Ethernet Frame Check Sequence. */
     190typedef uint32_t eth_fcs_t;
     191
    46192/** Type definition of the Ethernet global data.
    47193 * @see eth_globals
     
    91237        /** Actual device hardware address. */
    92238        measured_string_t *addr;
     239       
    93240        /** Actual device hardware address data. */
    94         char *addr_data;
     241        uint8_t *addr_data;
    95242};
    96243
  • uspace/srv/net/nil/nildummy/Makefile

    rcead2aa r357b5f5  
    3939-include $(CONFIG_MAKEFILE)
    4040
    41 ifeq ($(CONFIG_NETIF_NIL_BUNDLE),y)
    42         LIBRARY = libnildummy
    43 else
    44         BINARY = nildummy
    45 endif
     41BINARY = nildummy
    4642
    4743SOURCES = \
    48         nildummy.c \
    49         nildummy_module.c
     44        nildummy.c
    5045
    5146include $(USPACE_PREFIX)/Makefile.common
  • uspace/srv/net/nil/nildummy/nildummy.c

    rcead2aa r357b5f5  
    4242#include <str.h>
    4343#include <ipc/ipc.h>
     44#include <ipc/nil.h>
    4445#include <ipc/net.h>
    4546#include <ipc/services.h>
     
    4748#include <net/modules.h>
    4849#include <net/device.h>
    49 #include <netif_interface.h>
    50 #include <nil_interface.h>
    51 #include <il_interface.h>
     50#include <il_remote.h>
    5251#include <adt/measured_strings.h>
    5352#include <net/packet.h>
    5453#include <packet_remote.h>
    55 #include <nil_local.h>
     54#include <netif_remote.h>
     55#include <nil_skel.h>
    5656
    5757#include "nildummy.h"
     
    8181int nil_initialize(int net_phone)
    8282{
    83         int rc;
    84        
    8583        fibril_rwlock_initialize(&nildummy_globals.devices_lock);
    8684        fibril_rwlock_initialize(&nildummy_globals.protos_lock);
     
    9088        nildummy_globals.net_phone = net_phone;
    9189        nildummy_globals.proto.phone = 0;
    92         rc = nildummy_devices_initialize(&nildummy_globals.devices);
     90        int rc = nildummy_devices_initialize(&nildummy_globals.devices);
    9391       
    9492        fibril_rwlock_write_unlock(&nildummy_globals.protos_lock);
     
    9896}
    9997
    100 /** Process IPC messages from the registered device driver modules in an
    101  * infinite loop.
    102  *
    103  * @param[in] iid       The message identifier.
    104  * @param[in,out]       icall The message parameters.
     98/** Process IPC messages from the registered device driver modules
     99 *
     100 * @param[in]     iid   Message identifier.
     101 * @param[in,out] icall Message parameters.
     102 *
    105103 */
    106104static void nildummy_receiver(ipc_callid_t iid, ipc_call_t *icall)
     
    108106        packet_t *packet;
    109107        int rc;
    110 
     108       
    111109        while (true) {
    112                 switch (IPC_GET_METHOD(*icall)) {
     110                switch (IPC_GET_IMETHOD(*icall)) {
    113111                case NET_NIL_DEVICE_STATE:
    114112                        rc = nil_device_state_msg_local(0,
    115                             IPC_GET_DEVICE(icall), IPC_GET_STATE(icall));
    116                         ipc_answer_0(iid, (ipcarg_t) rc);
     113                            IPC_GET_DEVICE(*icall), IPC_GET_STATE(*icall));
     114                        ipc_answer_0(iid, (sysarg_t) rc);
    117115                        break;
    118116               
    119117                case NET_NIL_RECEIVED:
    120118                        rc = packet_translate_remote(nildummy_globals.net_phone,
    121                             &packet, IPC_GET_PACKET(icall));
    122                         if (rc == EOK) {
     119                            &packet, IPC_GET_PACKET(*icall));
     120                        if (rc == EOK)
    123121                                rc = nil_received_msg_local(0,
    124                                     IPC_GET_DEVICE(icall), packet, 0);
    125                         }
    126                         ipc_answer_0(iid, (ipcarg_t) rc);
     122                                    IPC_GET_DEVICE(*icall), packet, 0);
     123                       
     124                        ipc_answer_0(iid, (sysarg_t) rc);
    127125                        break;
    128126               
    129127                default:
    130                         ipc_answer_0(iid, (ipcarg_t) ENOTSUP);
     128                        ipc_answer_0(iid, (sysarg_t) ENOTSUP);
    131129                }
    132130               
     
    139137 * Determine the device local hardware address.
    140138 *
    141  * @param[in] device_id The new device identifier.
    142  * @param[in] service   The device driver service.
    143  * @param[in] mtu       The device maximum transmission unit.
    144  * @return              EOK on success.
    145  * @return              EEXIST if the device with the different service exists.
    146  * @return              ENOMEM if there is not enough memory left.
    147  * @return              Other error codes as defined for the
    148  *                      netif_bind_service() function.
    149  * @return              Other error codes as defined for the
    150  *                      netif_get_addr_req() function.
     139 * @param[in] device_id New device identifier.
     140 * @param[in] service   Device driver service.
     141 * @param[in] mtu       Device maximum transmission unit.
     142 *
     143 * @return EOK on success.
     144 * @return EEXIST if the device with the different service exists.
     145 * @return ENOMEM if there is not enough memory left.
     146 * @return Other error codes as defined for the
     147 *         netif_bind_service() function.
     148 * @return Other error codes as defined for the
     149 *         netif_get_addr_req() function.
     150 *
    151151 */
    152152static int nildummy_device_message(device_id_t device_id, services_t service,
    153153    size_t mtu)
    154154{
    155         nildummy_device_t *device;
    156         int index;
    157         int rc;
    158 
    159155        fibril_rwlock_write_lock(&nildummy_globals.devices_lock);
    160 
     156       
    161157        /* An existing device? */
    162         device = nildummy_devices_find(&nildummy_globals.devices, device_id);
     158        nildummy_device_t *device =
     159            nildummy_devices_find(&nildummy_globals.devices, device_id);
    163160        if (device) {
    164161                if (device->service != service) {
     
    213210       
    214211        /* Get hardware address */
    215         rc = netif_get_addr_req(device->phone, device->device_id, &device->addr,
    216             &device->addr_data);
     212        int rc = netif_get_addr_req(device->phone, device->device_id,
     213            &device->addr, &device->addr_data);
    217214        if (rc != EOK) {
    218215                fibril_rwlock_write_unlock(&nildummy_globals.devices_lock);
     
    222219       
    223220        /* Add to the cache */
    224         index = nildummy_devices_add(&nildummy_globals.devices,
     221        int index = nildummy_devices_add(&nildummy_globals.devices,
    225222            device->device_id, device);
    226223        if (index < 0) {
     
    240237/** Return the device hardware address.
    241238 *
    242  * @param[in] device_id The device identifier.
    243  * @param[out] address  The device hardware address.
    244  * @return               EOK on success.
    245  * @return              EBADMEM if the address parameter is NULL.
    246  * @return              ENOENT if there no such device.
     239 * @param[in]  device_id Device identifier.
     240 * @param[out] address   Device hardware address.
     241 *
     242 * @return EOK on success.
     243 * @return EBADMEM if the address parameter is NULL.
     244 * @return ENOENT if there no such device.
    247245 *
    248246 */
     
    250248    measured_string_t **address)
    251249{
    252         nildummy_device_t *device;
    253 
    254250        if (!address)
    255251                return EBADMEM;
    256252       
    257253        fibril_rwlock_read_lock(&nildummy_globals.devices_lock);
    258         device = nildummy_devices_find(&nildummy_globals.devices, device_id);
     254       
     255        nildummy_device_t *device =
     256            nildummy_devices_find(&nildummy_globals.devices, device_id);
    259257        if (!device) {
    260258                fibril_rwlock_read_unlock(&nildummy_globals.devices_lock);
    261259                return ENOENT;
    262260        }
     261       
    263262        *address = device->addr;
     263       
    264264        fibril_rwlock_read_unlock(&nildummy_globals.devices_lock);
    265265       
     
    269269/** Return the device packet dimensions for sending.
    270270 *
    271  * @param[in] device_id The device identifier.
    272  * @param[out] addr_len The minimum reserved address length.
    273  * @param[out] prefix   The minimum reserved prefix size.
    274  * @param[out] content  The maximum content size.
    275  * @param[out] suffix   The minimum reserved suffix size.
    276  * @return              EOK on success.
    277  * @return              EBADMEM if either one of the parameters is NULL.
    278  * @return              ENOENT if there is no such device.
     271 * @param[in]  device_id Device identifier.
     272 * @param[out] addr_len  Minimum reserved address length.
     273 * @param[out] prefix    Minimum reserved prefix size.
     274 * @param[out] content   Maximum content size.
     275 * @param[out] suffix    Minimum reserved suffix size.
     276 *
     277 * @return EOK on success.
     278 * @return EBADMEM if either one of the parameters is NULL.
     279 * @return ENOENT if there is no such device.
    279280 *
    280281 */
     
    282283    size_t *prefix, size_t *content, size_t *suffix)
    283284{
    284         nildummy_device_t *device;
    285 
    286         if (!addr_len || !prefix || !content || !suffix)
     285        if ((!addr_len) || (!prefix) || (!content) || (!suffix))
    287286                return EBADMEM;
    288287       
    289288        fibril_rwlock_read_lock(&nildummy_globals.devices_lock);
    290         device = nildummy_devices_find(&nildummy_globals.devices, device_id);
     289       
     290        nildummy_device_t *device =
     291            nildummy_devices_find(&nildummy_globals.devices, device_id);
    291292        if (!device) {
    292293                fibril_rwlock_read_unlock(&nildummy_globals.devices_lock);
    293294                return ENOENT;
    294295        }
    295 
     296       
    296297        *content = device->mtu;
     298       
    297299        fibril_rwlock_read_unlock(&nildummy_globals.devices_lock);
    298300       
     
    306308    packet_t *packet, services_t target)
    307309{
    308         packet_t *next;
    309 
    310310        fibril_rwlock_read_lock(&nildummy_globals.protos_lock);
     311       
    311312        if (nildummy_globals.proto.phone) {
    312313                do {
    313                         next = pq_detach(packet);
     314                        packet_t *next = pq_detach(packet);
    314315                        il_received_msg(nildummy_globals.proto.phone, device_id,
    315316                            packet, nildummy_globals.proto.service);
    316317                        packet = next;
    317                 } while(packet);
    318         }
     318                } while (packet);
     319        }
     320       
    319321        fibril_rwlock_read_unlock(&nildummy_globals.protos_lock);
    320322       
     
    326328 * Pass received packets for this service.
    327329 *
    328  * @param[in] service   The module service.
    329  * @param[in] phone     The service phone.
    330  * @return              EOK on success.
    331  * @return              ENOENT if the service is not known.
    332  * @return              ENOMEM if there is not enough memory left.
     330 * @param[in] service Module service.
     331 * @param[in] phone   Service phone.
     332 *
     333 * @return EOK on success.
     334 * @return ENOENT if the service is not known.
     335 * @return ENOMEM if there is not enough memory left.
     336 *
    333337 */
    334338static int nildummy_register_message(services_t service, int phone)
     
    347351/** Send the packet queue.
    348352 *
    349  * @param[in] device_id The device identifier.
    350  * @param[in] packet    The packet queue.
    351  * @param[in] sender    The sending module service.
    352  * @return              EOK on success.
    353  * @return              ENOENT if there no such device.
    354  * @return              EINVAL if the service parameter is not known.
     353 * @param[in] device_id Device identifier.
     354 * @param[in] packet    Packet queue.
     355 * @param[in] sender    Sending module service.
     356 *
     357 * @return EOK on success.
     358 * @return ENOENT if there no such device.
     359 * @return EINVAL if the service parameter is not known.
     360 *
    355361 */
    356362static int nildummy_send_message(device_id_t device_id, packet_t *packet,
    357363    services_t sender)
    358364{
    359         nildummy_device_t *device;
    360 
    361365        fibril_rwlock_read_lock(&nildummy_globals.devices_lock);
    362         device = nildummy_devices_find(&nildummy_globals.devices, device_id);
     366       
     367        nildummy_device_t *device =
     368            nildummy_devices_find(&nildummy_globals.devices, device_id);
    363369        if (!device) {
    364370                fibril_rwlock_read_unlock(&nildummy_globals.devices_lock);
    365371                return ENOENT;
    366372        }
    367 
     373       
    368374        /* Send packet queue */
    369375        if (packet)
    370376                netif_send_msg(device->phone, device_id, packet,
    371377                    SERVICE_NILDUMMY);
     378       
    372379        fibril_rwlock_read_unlock(&nildummy_globals.devices_lock);
    373         return EOK;
    374 }
    375 
    376 int nil_message_standalone(const char *name, ipc_callid_t callid,
    377     ipc_call_t *call, ipc_call_t *answer, int *answer_count)
     380       
     381        return EOK;
     382}
     383
     384int nil_module_message(ipc_callid_t callid, ipc_call_t *call,
     385    ipc_call_t *answer, size_t *answer_count)
    378386{
    379387        measured_string_t *address;
     
    386394       
    387395        *answer_count = 0;
    388         switch (IPC_GET_METHOD(*call)) {
     396        switch (IPC_GET_IMETHOD(*call)) {
    389397        case IPC_M_PHONE_HUNGUP:
    390398                return EOK;
    391399       
    392400        case NET_NIL_DEVICE:
    393                 return nildummy_device_message(IPC_GET_DEVICE(call),
    394                     IPC_GET_SERVICE(call), IPC_GET_MTU(call));
     401                return nildummy_device_message(IPC_GET_DEVICE(*call),
     402                    IPC_GET_SERVICE(*call), IPC_GET_MTU(*call));
    395403       
    396404        case NET_NIL_SEND:
    397405                rc = packet_translate_remote(nildummy_globals.net_phone,
    398                     &packet, IPC_GET_PACKET(call));
     406                    &packet, IPC_GET_PACKET(*call));
    399407                if (rc != EOK)
    400408                        return rc;
    401                 return nildummy_send_message(IPC_GET_DEVICE(call), packet,
    402                     IPC_GET_SERVICE(call));
     409                return nildummy_send_message(IPC_GET_DEVICE(*call), packet,
     410                    IPC_GET_SERVICE(*call));
    403411       
    404412        case NET_NIL_PACKET_SPACE:
    405                 rc = nildummy_packet_space_message(IPC_GET_DEVICE(call),
     413                rc = nildummy_packet_space_message(IPC_GET_DEVICE(*call),
    406414                    &addrlen, &prefix, &content, &suffix);
    407415                if (rc != EOK)
    408416                        return rc;
    409                 IPC_SET_ADDR(answer, addrlen);
    410                 IPC_SET_PREFIX(answer, prefix);
    411                 IPC_SET_CONTENT(answer, content);
    412                 IPC_SET_SUFFIX(answer, suffix);
     417                IPC_SET_ADDR(*answer, addrlen);
     418                IPC_SET_PREFIX(*answer, prefix);
     419                IPC_SET_CONTENT(*answer, content);
     420                IPC_SET_SUFFIX(*answer, suffix);
    413421                *answer_count = 4;
    414422                return EOK;
    415423       
    416424        case NET_NIL_ADDR:
    417                 rc = nildummy_addr_message(IPC_GET_DEVICE(call), &address);
     425                rc = nildummy_addr_message(IPC_GET_DEVICE(*call), &address);
    418426                if (rc != EOK)
    419427                        return rc;
     
    421429       
    422430        case NET_NIL_BROADCAST_ADDR:
    423                 rc = nildummy_addr_message(IPC_GET_DEVICE(call), &address);
     431                rc = nildummy_addr_message(IPC_GET_DEVICE(*call), &address);
    424432                if (rc != EOK)
    425433                        return rc;
     
    427435       
    428436        case IPC_M_CONNECT_TO_ME:
    429                 return nildummy_register_message(NIL_GET_PROTO(call),
    430                     IPC_GET_PHONE(call));
     437                return nildummy_register_message(NIL_GET_PROTO(*call),
     438                    IPC_GET_PHONE(*call));
    431439        }
    432440       
     
    434442}
    435443
    436 /** Default thread for new connections.
    437  *
    438  * @param[in] iid       The initial message identifier.
    439  * @param[in] icall     The initial message call structure.
    440  */
    441 static void nil_client_connection(ipc_callid_t iid, ipc_call_t *icall)
    442 {
    443         /*
    444          * Accept the connection
    445          *  - Answer the first IPC_M_CONNECT_ME_TO call.
    446          */
    447         ipc_answer_0(iid, EOK);
    448        
    449         while (true) {
    450                 ipc_call_t answer;
    451                 int answer_count;
    452                
    453                 /* Clear the answer structure */
    454                 refresh_answer(&answer, &answer_count);
    455                
    456                 /* Fetch the next message */
    457                 ipc_call_t call;
    458                 ipc_callid_t callid = async_get_call(&call);
    459                
    460                 /* Process the message */
    461                 int res = nil_module_message_standalone(NAME, callid, &call,
    462                     &answer, &answer_count);
    463                
    464                 /*
    465                  * End if told to either by the message or the processing
    466                  * result.
    467                  */
    468                 if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) ||
    469                     (res == EHANGUP))
    470                         return;
    471                
    472                 /* Answer the message */
    473                 answer_call(callid, res, &answer, answer_count);
    474         }
    475 }
    476 
    477444int main(int argc, char *argv[])
    478445{
    479         int rc;
    480        
    481446        /* Start the module */
    482         rc = nil_module_start_standalone(nil_client_connection);
    483         return rc;
     447        return nil_module_start(SERVICE_NILDUMMY);
    484448}
    485449
  • uspace/srv/net/nil/nildummy/nildummy.h

    rcead2aa r357b5f5  
    4545
    4646/** Type definition of the dummy nil global data.
     47 *
    4748 * @see nildummy_globals
     49 *
    4850 */
    4951typedef struct nildummy_globals nildummy_globals_t;
    5052
    5153/** Type definition of the dummy nil device specific data.
     54 *
    5255 * @see nildummy_device
     56 *
    5357 */
    5458typedef struct nildummy_device nildummy_device_t;
    5559
    5660/** Type definition of the dummy nil protocol specific data.
     61 *
    5762 * @see nildummy_proto
     63 *
    5864 */
    5965typedef struct nildummy_proto nildummy_proto_t;
    6066
    6167/** Dummy nil device map.
    62  * Maps devices to the dummy nil device specific data.
     68 *
     69 * Map devices to the dummy nil device specific data.
    6370 * @see device.h
     71 *
    6472 */
    6573DEVICE_MAP_DECLARE(nildummy_devices, nildummy_device_t);
     
    6977        /** Device identifier. */
    7078        device_id_t device_id;
     79       
    7180        /** Device driver service. */
    7281        services_t service;
     82       
    7383        /** Driver phone. */
    7484        int phone;
     85       
    7586        /** Maximal transmission unit. */
    7687        size_t mtu;
     88       
    7789        /** Actual device hardware address. */
    7890        measured_string_t *addr;
     91       
    7992        /** Actual device hardware address data. */
    80         char *addr_data;
     93        uint8_t *addr_data;
    8194};
    8295
     
    8598        /** Protocol service. */
    8699        services_t service;
     100       
    87101        /** Protocol module phone. */
    88102        int phone;
     
    93107        /** Networking module phone. */
    94108        int net_phone;
    95         /** Safety lock for devices. */
     109       
     110        /** Lock for devices. */
    96111        fibril_rwlock_t devices_lock;
     112       
    97113        /** All known Ethernet devices. */
    98114        nildummy_devices_t devices;
     115       
    99116        /** Safety lock for protocols. */
    100117        fibril_rwlock_t protos_lock;
     118       
    101119        /** Default protocol. */
    102120        nildummy_proto_t proto;
  • uspace/srv/net/tl/icmp/Makefile

    rcead2aa r357b5f5  
    3434
    3535SOURCES = \
    36         icmp.c \
    37         icmp_module.c
     36        icmp.c
    3837
    3938include $(USPACE_PREFIX)/Makefile.common
  • uspace/srv/net/tl/icmp/icmp.c

    rcead2aa r357b5f5  
    3333/** @file
    3434 * ICMP module implementation.
    35  * @see icmp.h
    36  */
    37 
    38 #include "icmp.h"
    39 #include "icmp_module.h"
     35 */
    4036
    4137#include <async.h>
     
    5450#include <byteorder.h>
    5551#include <errno.h>
     52#include <adt/hash_table.h>
    5653
    5754#include <net/socket_codes.h>
     
    6764#include <net_checksum.h>
    6865#include <icmp_client.h>
    69 #include <icmp_interface.h>
    70 #include <il_interface.h>
     66#include <icmp_remote.h>
     67#include <il_remote.h>
    7168#include <ip_client.h>
    7269#include <ip_interface.h>
    7370#include <net_interface.h>
    74 #include <tl_interface.h>
    75 #include <tl_local.h>
     71#include <tl_remote.h>
     72#include <tl_skel.h>
    7673#include <icmp_header.h>
    7774
    78 /** ICMP module name. */
    79 #define NAME    "ICMP protocol"
    80 
    81 /** Default ICMP error reporting. */
    82 #define NET_DEFAULT_ICMP_ERROR_REPORTING        true
    83 
    84 /** Default ICMP echo replying. */
    85 #define NET_DEFAULT_ICMP_ECHO_REPLYING          true
    86 
    87 /** Original datagram length in bytes transfered to the error notification
    88  * message.
    89  */
    90 #define ICMP_KEEP_LENGTH        8
    91 
    92 /** Free identifier numbers pool start. */
    93 #define ICMP_FREE_IDS_START     1
    94 
    95 /** Free identifier numbers pool end. */
    96 #define ICMP_FREE_IDS_END       UINT16_MAX
    97 
    98 /** Computes the ICMP datagram checksum.
    99  *
    100  * @param[in,out] header The ICMP datagram header.
    101  * @param[in] length    The total datagram length.
    102  * @return              The computed checksum.
     75/** ICMP module name */
     76#define NAME  "icmp"
     77
     78/** Number of replies hash table keys */
     79#define REPLY_KEYS  2
     80
     81/** Number of replies hash table buckets */
     82#define REPLY_BUCKETS  1024
     83
     84/**
     85 * Original datagram length in bytes transfered to the error
     86 * notification message.
     87 */
     88#define ICMP_KEEP_LENGTH  8
     89
     90/** Compute the ICMP datagram checksum.
     91 *
     92 * @param[in,out] header ICMP datagram header.
     93 * @param[in]     length Total datagram length.
     94 *
     95 * @return Computed checksum.
     96 *
    10397 */
    10498#define ICMP_CHECKSUM(header, length) \
     
    106100
    107101/** An echo request datagrams pattern. */
    108 #define ICMP_ECHO_TEXT          "Hello from HelenOS."
    109 
    110 /** Computes an ICMP reply data key.
    111  *
    112  * @param[in] id        The message identifier.
    113  * @param[in] sequence  The message sequence number.
    114  * @return              The computed ICMP reply data key.
    115  */
    116 #define ICMP_GET_REPLY_KEY(id, sequence) \
    117         (((id) << 16) | (sequence & 0xFFFF))
    118 
    119 
    120 /** ICMP global data. */
    121 icmp_globals_t  icmp_globals;
    122 
    123 INT_MAP_IMPLEMENT(icmp_replies, icmp_reply_t);
    124 INT_MAP_IMPLEMENT(icmp_echo_data, icmp_echo_t);
    125 
    126 /** Releases the packet and returns the result.
    127  *
    128  * @param[in] packet    The packet queue to be released.
    129  * @param[in] result    The result to be returned.
    130  * @return              The result parameter.
    131  */
    132 static int icmp_release_and_return(packet_t *packet, int result)
    133 {
    134         pq_release_remote(icmp_globals.net_phone, packet_get_id(packet));
    135         return result;
    136 }
    137 
    138 /** Sends the ICMP message.
    139  *
    140  * Sets the message type and code and computes the checksum.
     102#define ICMP_ECHO_TEXT  "ICMP hello from HelenOS."
     103
     104/** ICMP reply data. */
     105typedef struct {
     106        /** Hash table link */
     107        link_t link;
     108       
     109        /** Reply identification and sequence */
     110        icmp_param_t id;
     111        icmp_param_t sequence;
     112       
     113        /** Reply signaling */
     114        fibril_condvar_t condvar;
     115       
     116        /** Reply result */
     117        int result;
     118} icmp_reply_t;
     119
     120/** Global data */
     121static int phone_net = -1;
     122static int phone_ip = -1;
     123static bool error_reporting = true;
     124static bool echo_replying = true;
     125static packet_dimension_t icmp_dimension;
     126
     127/** ICMP client identification counter */
     128static atomic_t icmp_client;
     129
     130/** ICMP identifier and sequence number (client-specific) */
     131static fibril_local icmp_param_t icmp_id;
     132static fibril_local icmp_param_t icmp_seq;
     133
     134/** Reply hash table */
     135static fibril_mutex_t reply_lock;
     136static hash_table_t replies;
     137
     138static hash_index_t replies_hash(unsigned long key[])
     139{
     140        /*
     141         * ICMP identifier and sequence numbers
     142         * are 16-bit values.
     143         */
     144        hash_index_t index = ((key[0] & 0xffff) << 16) | (key[1] & 0xffff);
     145        return (index % REPLY_BUCKETS);
     146}
     147
     148static int replies_compare(unsigned long key[], hash_count_t keys, link_t *item)
     149{
     150        icmp_reply_t *reply =
     151            hash_table_get_instance(item, icmp_reply_t, link);
     152       
     153        if (keys == 1)
     154                return (reply->id == key[0]);
     155        else
     156                return ((reply->id == key[0]) && (reply->sequence == key[1]));
     157}
     158
     159static void replies_remove_callback(link_t *item)
     160{
     161}
     162
     163static hash_table_operations_t reply_ops = {
     164        .hash = replies_hash,
     165        .compare = replies_compare,
     166        .remove_callback = replies_remove_callback
     167};
     168
     169/** Release the packet and return the result.
     170 *
     171 * @param[in] packet Packet queue to be released.
     172 *
     173 */
     174static void icmp_release(packet_t *packet)
     175{
     176        pq_release_remote(phone_net, packet_get_id(packet));
     177}
     178
     179/** Send the ICMP message.
     180 *
     181 * Set the message type and code and compute the checksum.
    141182 * Error messages are sent only if allowed in the configuration.
    142  * Releases the packet on errors.
    143  *
    144  * @param[in] type      The message type.
    145  * @param[in] code      The message code.
    146  * @param[in] packet    The message packet to be sent.
    147  * @param[in] header    The ICMP header.
    148  * @param[in] error     The error service to be announced. Should be
    149  *                      SERVICE_ICMP or zero.
    150  * @param[in] ttl       The time to live.
    151  * @param[in] tos       The type of service.
    152  * @param[in] dont_fragment The value indicating whether the datagram must not
    153  *                      be fragmented. Is used as a MTU discovery.
    154  * @return              EOK on success.
    155  * @return              EPERM if the error message is not allowed.
    156  */
    157 static int icmp_send_packet(icmp_type_t type, icmp_code_t code, packet_t *packet,
    158     icmp_header_t *header, services_t error, ip_ttl_t ttl, ip_tos_t tos,
    159     int dont_fragment)
    160 {
    161         int rc;
    162 
     183 * Release the packet on errors.
     184 *
     185 * @param[in] type          Message type.
     186 * @param[in] code          Message code.
     187 * @param[in] packet        Message packet to be sent.
     188 * @param[in] header        ICMP header.
     189 * @param[in] error         Error service to be announced. Should be
     190 *                          SERVICE_ICMP or zero.
     191 * @param[in] ttl           Time to live.
     192 * @param[in] tos           Type of service.
     193 * @param[in] dont_fragment Disable fragmentation.
     194 *
     195 * @return EOK on success.
     196 * @return EPERM if the error message is not allowed.
     197 *
     198 */
     199static int icmp_send_packet(icmp_type_t type, icmp_code_t code,
     200    packet_t *packet, icmp_header_t *header, services_t error, ip_ttl_t ttl,
     201    ip_tos_t tos, bool dont_fragment)
     202{
    163203        /* Do not send an error if disabled */
    164         if (error && !icmp_globals.error_reporting)
    165                 return icmp_release_and_return(packet, EPERM);
    166 
     204        if ((error) && (!error_reporting)) {
     205                icmp_release(packet);
     206                return EPERM;
     207        }
     208       
    167209        header->type = type;
    168210        header->code = code;
     211       
     212        /*
     213         * The checksum needs to be calculated
     214         * with a virtual checksum field set to
     215         * zero.
     216         */
    169217        header->checksum = 0;
    170218        header->checksum = ICMP_CHECKSUM(header,
    171219            packet_get_data_length(packet));
    172220       
    173         rc = ip_client_prepare_packet(packet, IPPROTO_ICMP, ttl, tos,
     221        int rc = ip_client_prepare_packet(packet, IPPROTO_ICMP, ttl, tos,
    174222            dont_fragment, 0);
    175         if (rc != EOK)
    176                 return icmp_release_and_return(packet, rc);
    177 
    178         return ip_send_msg(icmp_globals.ip_phone, -1, packet, SERVICE_ICMP,
    179             error);
    180 }
    181 
    182 /** Prepares the ICMP error packet.
    183  *
    184  * Truncates the original packet if longer than ICMP_KEEP_LENGTH bytes.
    185  * Prefixes and returns the ICMP header.
    186  *
    187  * @param[in,out] packet The original packet.
     223        if (rc != EOK) {
     224                icmp_release(packet);
     225                return rc;
     226        }
     227       
     228        return ip_send_msg(phone_ip, -1, packet, SERVICE_ICMP, error);
     229}
     230
     231/** Prepare the ICMP error packet.
     232 *
     233 * Truncate the original packet if longer than ICMP_KEEP_LENGTH bytes.
     234 * Prefix and return the ICMP header.
     235 *
     236 * @param[in,out] packet Original packet.
     237 *
    188238 * @return The prefixed ICMP header.
    189239 * @return NULL on errors.
     240 *
    190241 */
    191242static icmp_header_t *icmp_prepare_packet(packet_t *packet)
    192243{
    193         icmp_header_t *header;
    194         size_t header_length;
    195         size_t total_length;
    196 
    197         total_length = packet_get_data_length(packet);
     244        size_t total_length = packet_get_data_length(packet);
    198245        if (total_length <= 0)
    199246                return NULL;
    200 
    201         header_length = ip_client_header_length(packet);
     247       
     248        size_t header_length = ip_client_header_length(packet);
    202249        if (header_length <= 0)
    203250                return NULL;
    204 
     251       
    205252        /* Truncate if longer than 64 bits (without the IP header) */
    206253        if ((total_length > header_length + ICMP_KEEP_LENGTH) &&
    207254            (packet_trim(packet, 0,
    208             total_length - header_length - ICMP_KEEP_LENGTH) != EOK)) {
     255            total_length - header_length - ICMP_KEEP_LENGTH) != EOK))
    209256                return NULL;
    210         }
    211 
    212         header = PACKET_PREFIX(packet, icmp_header_t);
     257       
     258        icmp_header_t *header = PACKET_PREFIX(packet, icmp_header_t);
    213259        if (!header)
    214260                return NULL;
    215 
     261       
    216262        bzero(header, sizeof(*header));
    217263        return header;
    218264}
    219265
    220 /** Requests an echo message.
    221  *
    222  * Sends a packet with specified parameters to the target host and waits for
    223  * the reply upto the given timeout.
    224  * Blocks the caller until the reply or the timeout occurs.
    225  *
    226  * @param[in] id        The message identifier.
    227  * @param[in] sequence  The message sequence parameter.
    228  * @param[in] size      The message data length in bytes.
    229  * @param[in] timeout   The timeout in miliseconds.
    230  * @param[in] ttl       The time to live.
    231  * @param[in] tos       The type of service.
    232  * @param[in] dont_fragment The value indicating whether the datagram must not
    233  *                      be fragmented. Is used as a MTU discovery.
    234  * @param[in] addr      The target host address.
    235  * @param[in] addrlen   The torget host address length.
    236  * @return              ICMP_ECHO on success.
    237  * @return              ETIMEOUT if the reply has not arrived before the
    238  *                      timeout.
    239  * @return              ICMP type of the received error notification.
    240  * @return              EINVAL if the addrlen parameter is less or equal to
    241  *                      zero.
    242  * @return              ENOMEM if there is not enough memory left.
    243  * @return              EPARTY if there was an internal error.
     266/** Request an echo message.
     267 *
     268 * Send a packet with specified parameters to the target host
     269 * and wait for the reply upto the given timeout.
     270 * Block the caller until the reply or the timeout occurs.
     271 *
     272 * @param[in] id            Message identifier.
     273 * @param[in] sequence      Message sequence parameter.
     274 * @param[in] size          Message data length in bytes.
     275 * @param[in] timeout       Timeout in miliseconds.
     276 * @param[in] ttl           Time to live.
     277 * @param[in] tos           Type of service.
     278 * @param[in] dont_fragment Disable fragmentation.
     279 * @param[in] addr          Target host address.
     280 * @param[in] addrlen       Torget host address length.
     281 *
     282 * @return ICMP_ECHO on success.
     283 * @return ETIMEOUT if the reply has not arrived before the
     284 *         timeout.
     285 * @return ICMP type of the received error notification.
     286 * @return EINVAL if the addrlen parameter is less or equal to
     287 *         zero.
     288 * @return ENOMEM if there is not enough memory left.
     289 *
    244290 */
    245291static int icmp_echo(icmp_param_t id, icmp_param_t sequence, size_t size,
    246     mseconds_t timeout, ip_ttl_t ttl, ip_tos_t tos, int dont_fragment,
    247     const struct sockaddr * addr, socklen_t addrlen)
    248 {
    249         icmp_header_t *header;
    250         packet_t *packet;
    251         size_t length;
    252         uint8_t *data;
    253         icmp_reply_t *reply;
    254         int reply_key;
    255         int index;
    256         int rc;
    257 
     292    mseconds_t timeout, ip_ttl_t ttl, ip_tos_t tos, bool dont_fragment,
     293    const struct sockaddr *addr, socklen_t addrlen)
     294{
    258295        if (addrlen <= 0)
    259296                return EINVAL;
    260 
    261         length = (size_t) addrlen;
    262         /* TODO do not ask all the time */
    263         rc = ip_packet_size_req(icmp_globals.ip_phone, -1,
    264             &icmp_globals.packet_dimension);
    265         if (rc != EOK)
    266                 return rc;
    267 
    268         packet = packet_get_4_remote(icmp_globals.net_phone, size,
    269             icmp_globals.packet_dimension.addr_len,
    270             ICMP_HEADER_SIZE + icmp_globals.packet_dimension.prefix,
    271             icmp_globals.packet_dimension.suffix);
     297       
     298        size_t length = (size_t) addrlen;
     299       
     300        packet_t *packet = packet_get_4_remote(phone_net, size,
     301            icmp_dimension.addr_len, ICMP_HEADER_SIZE + icmp_dimension.prefix,
     302            icmp_dimension.suffix);
    272303        if (!packet)
    273304                return ENOMEM;
    274 
     305       
    275306        /* Prepare the requesting packet, set the destination address. */
    276         rc = packet_set_addr(packet, NULL, (const uint8_t *) addr, length);
    277         if (rc != EOK)
    278                 return icmp_release_and_return(packet, rc);
    279 
     307        int rc = packet_set_addr(packet, NULL, (const uint8_t *) addr, length);
     308        if (rc != EOK) {
     309                icmp_release(packet);
     310                return rc;
     311        }
     312       
    280313        /* Allocate space in the packet */
    281         data = (uint8_t *) packet_suffix(packet, size);
    282         if (!data)
    283                 return icmp_release_and_return(packet, ENOMEM);
    284 
     314        uint8_t *data = (uint8_t *) packet_suffix(packet, size);
     315        if (!data) {
     316                icmp_release(packet);
     317                return ENOMEM;
     318        }
     319       
    285320        /* Fill the data */
    286321        length = 0;
     
    290325        }
    291326        memcpy(data + length, ICMP_ECHO_TEXT, size - length);
    292 
     327       
    293328        /* Prefix the header */
    294         header = PACKET_PREFIX(packet, icmp_header_t);
    295         if (!header)
    296                 return icmp_release_and_return(packet, ENOMEM);
    297 
    298         bzero(header, sizeof(*header));
     329        icmp_header_t *header = PACKET_PREFIX(packet, icmp_header_t);
     330        if (!header) {
     331                icmp_release(packet);
     332                return ENOMEM;
     333        }
     334       
     335        bzero(header, sizeof(icmp_header_t));
    299336        header->un.echo.identifier = id;
    300337        header->un.echo.sequence_number = sequence;
    301 
     338       
    302339        /* Prepare the reply structure */
    303         reply = malloc(sizeof(*reply));
    304         if (!reply)
    305                 return icmp_release_and_return(packet, ENOMEM);
    306 
    307         fibril_mutex_initialize(&reply->mutex);
    308         fibril_mutex_lock(&reply->mutex);
     340        icmp_reply_t *reply = malloc(sizeof(icmp_reply_t));
     341        if (!reply) {
     342                icmp_release(packet);
     343                return ENOMEM;
     344        }
     345       
     346        reply->id = id;
     347        reply->sequence = sequence;
    309348        fibril_condvar_initialize(&reply->condvar);
    310         reply_key = ICMP_GET_REPLY_KEY(header->un.echo.identifier,
    311             header->un.echo.sequence_number);
    312         index = icmp_replies_add(&icmp_globals.replies, reply_key, reply);
    313         if (index < 0) {
    314                 free(reply);
    315                 return icmp_release_and_return(packet, index);
    316         }
    317 
    318         /* Unlock the globals so that we can wait for the reply */
    319         fibril_rwlock_write_unlock(&icmp_globals.lock);
    320 
     349       
     350        /* Add the reply to the replies hash table */
     351        fibril_mutex_lock(&reply_lock);
     352       
     353        unsigned long key[REPLY_KEYS] = {id, sequence};
     354        hash_table_insert(&replies, key, &reply->link);
     355       
    321356        /* Send the request */
    322357        icmp_send_packet(ICMP_ECHO, 0, packet, header, 0, ttl, tos,
    323358            dont_fragment);
    324 
     359       
    325360        /* Wait for the reply. Timeout in microseconds. */
    326         rc = fibril_condvar_wait_timeout(&reply->condvar, &reply->mutex,
     361        rc = fibril_condvar_wait_timeout(&reply->condvar, &reply_lock,
    327362            timeout * 1000);
    328363        if (rc == EOK)
    329364                rc = reply->result;
    330 
    331         /* Drop the reply mutex before locking the globals again */
    332         fibril_mutex_unlock(&reply->mutex);
    333         fibril_rwlock_write_lock(&icmp_globals.lock);
    334 
    335         /* Destroy the reply structure */
    336         icmp_replies_exclude_index(&icmp_globals.replies, index);
    337 
     365       
     366        /* Remove the reply from the replies hash table */
     367        hash_table_remove(&replies, key, REPLY_KEYS);
     368       
     369        fibril_mutex_unlock(&reply_lock);
     370       
     371        free(reply);
     372       
    338373        return rc;
    339374}
    340375
    341 static int icmp_destination_unreachable_msg_local(int icmp_phone,
    342     icmp_code_t code, icmp_param_t mtu, packet_t *packet)
    343 {
    344         icmp_header_t *header;
    345 
    346         header = icmp_prepare_packet(packet);
    347         if (!header)
    348                 return icmp_release_and_return(packet, ENOMEM);
    349 
     376static int icmp_destination_unreachable(icmp_code_t code, icmp_param_t mtu,
     377    packet_t *packet)
     378{
     379        icmp_header_t *header = icmp_prepare_packet(packet);
     380        if (!header) {
     381                icmp_release(packet);
     382                return ENOMEM;
     383        }
     384       
    350385        if (mtu)
    351386                header->un.frag.mtu = mtu;
    352 
     387       
    353388        return icmp_send_packet(ICMP_DEST_UNREACH, code, packet, header,
    354             SERVICE_ICMP, 0, 0, 0);
    355 }
    356 
    357 static int icmp_source_quench_msg_local(int icmp_phone, packet_t *packet)
    358 {
    359         icmp_header_t *header;
    360 
    361         header = icmp_prepare_packet(packet);
    362         if (!header)
    363                 return icmp_release_and_return(packet, ENOMEM);
    364 
     389            SERVICE_ICMP, 0, 0, false);
     390}
     391
     392static int icmp_source_quench(packet_t *packet)
     393{
     394        icmp_header_t *header = icmp_prepare_packet(packet);
     395        if (!header) {
     396                icmp_release(packet);
     397                return ENOMEM;
     398        }
     399       
    365400        return icmp_send_packet(ICMP_SOURCE_QUENCH, 0, packet, header,
    366             SERVICE_ICMP, 0, 0, 0);
    367 }
    368 
    369 static int icmp_time_exceeded_msg_local(int icmp_phone, icmp_code_t code,
     401            SERVICE_ICMP, 0, 0, false);
     402}
     403
     404static int icmp_time_exceeded(icmp_code_t code, packet_t *packet)
     405{
     406        icmp_header_t *header = icmp_prepare_packet(packet);
     407        if (!header) {
     408                icmp_release(packet);
     409                return ENOMEM;
     410        }
     411       
     412        return icmp_send_packet(ICMP_TIME_EXCEEDED, code, packet, header,
     413            SERVICE_ICMP, 0, 0, false);
     414}
     415
     416static int icmp_parameter_problem(icmp_code_t code, icmp_param_t pointer,
    370417    packet_t *packet)
    371418{
    372         icmp_header_t *header;
    373 
    374         header = icmp_prepare_packet(packet);
    375         if (!header)
    376                 return icmp_release_and_return(packet, ENOMEM);
    377 
    378         return icmp_send_packet(ICMP_TIME_EXCEEDED, code, packet, header,
    379             SERVICE_ICMP, 0, 0, 0);
    380 }
    381 
    382 static int icmp_parameter_problem_msg_local(int icmp_phone, icmp_code_t code,
    383     icmp_param_t pointer, packet_t *packet)
    384 {
    385         icmp_header_t *header;
    386 
    387         header = icmp_prepare_packet(packet);
    388         if (!header)
    389                 return icmp_release_and_return(packet, ENOMEM);
    390 
     419        icmp_header_t *header = icmp_prepare_packet(packet);
     420        if (!header) {
     421                icmp_release(packet);
     422                return ENOMEM;
     423        }
     424       
    391425        header->un.param.pointer = pointer;
    392426        return icmp_send_packet(ICMP_PARAMETERPROB, code, packet, header,
    393             SERVICE_ICMP, 0, 0, 0);
    394 }
    395 
    396 /** Initializes the ICMP module.
    397  *
    398  * @param[in] client_connection The client connection processing function. The
    399  *                      module skeleton propagates its own one.
    400  * @return              EOK on success.
    401  * @return              ENOMEM if there is not enough memory left.
    402  */
    403 int icmp_initialize(async_client_conn_t client_connection)
    404 {
    405         measured_string_t names[] = {
    406                 {
    407                         (char *) "ICMP_ERROR_REPORTING",
    408                         20
    409                 },
    410                 {
    411                         (char *) "ICMP_ECHO_REPLYING",
    412                         18
    413                 }
    414         };
    415         measured_string_t *configuration;
    416         size_t count = sizeof(names) / sizeof(measured_string_t);
    417         char *data;
    418         int rc;
    419 
    420         fibril_rwlock_initialize(&icmp_globals.lock);
    421         fibril_rwlock_write_lock(&icmp_globals.lock);
    422         icmp_replies_initialize(&icmp_globals.replies);
    423         icmp_echo_data_initialize(&icmp_globals.echo_data);
    424        
    425         icmp_globals.ip_phone = ip_bind_service(SERVICE_IP, IPPROTO_ICMP,
    426             SERVICE_ICMP, client_connection);
    427         if (icmp_globals.ip_phone < 0) {
    428                 fibril_rwlock_write_unlock(&icmp_globals.lock);
    429                 return icmp_globals.ip_phone;
    430         }
    431        
    432         rc = ip_packet_size_req(icmp_globals.ip_phone, -1,
    433             &icmp_globals.packet_dimension);
    434         if (rc != EOK) {
    435                 fibril_rwlock_write_unlock(&icmp_globals.lock);
    436                 return rc;
    437         }
    438 
    439         icmp_globals.packet_dimension.prefix += ICMP_HEADER_SIZE;
    440         icmp_globals.packet_dimension.content -= ICMP_HEADER_SIZE;
    441 
    442         icmp_globals.error_reporting = NET_DEFAULT_ICMP_ERROR_REPORTING;
    443         icmp_globals.echo_replying = NET_DEFAULT_ICMP_ECHO_REPLYING;
    444 
    445         /* Get configuration */
    446         configuration = &names[0];
    447         rc = net_get_conf_req(icmp_globals.net_phone, &configuration, count,
    448             &data);
    449         if (rc != EOK) {
    450                 fibril_rwlock_write_unlock(&icmp_globals.lock);
    451                 return rc;
    452         }
    453        
    454         if (configuration) {
    455                 if (configuration[0].value) {
    456                         icmp_globals.error_reporting =
    457                             (configuration[0].value[0] == 'y');
    458                 }
    459                 if (configuration[1].value) {
    460                         icmp_globals.echo_replying =
    461                             (configuration[1].value[0] == 'y');
    462                 }
    463                 net_free_settings(configuration, data);
    464         }
    465 
    466         fibril_rwlock_write_unlock(&icmp_globals.lock);
    467         return EOK;
    468 }
    469 
    470 /** Tries to set the pending reply result as the received message type.
     427            SERVICE_ICMP, 0, 0, false);
     428}
     429
     430/** Try to set the pending reply result as the received message type.
    471431 *
    472432 * If the reply data is not present, the reply timed out and the other fibril
    473  * is already awake.
    474  * Releases the packet.
    475  *
    476  * @param[in] packet    The received reply message.
    477  * @param[in] header    The ICMP message header.
    478  * @param[in] type      The received reply message type.
    479  * @param[in] code      The received reply message code.
    480  */
    481 static void  icmp_process_echo_reply(packet_t *packet, icmp_header_t *header,
     433 * is already awake. The packet is released.
     434 *
     435 * @param[in] packet The received reply message.
     436 * @param[in] header The ICMP message header.
     437 * @param[in] type   The received reply message type.
     438 * @param[in] code   The received reply message code.
     439 *
     440 */
     441static void icmp_process_echo_reply(packet_t *packet, icmp_header_t *header,
    482442    icmp_type_t type, icmp_code_t code)
    483443{
    484         int reply_key;
    485         icmp_reply_t *reply;
    486 
    487         /* Compute the reply key */
    488         reply_key = ICMP_GET_REPLY_KEY(header->un.echo.identifier,
    489             header->un.echo.sequence_number);
    490         pq_release_remote(icmp_globals.net_phone, packet_get_id(packet));
    491 
     444        unsigned long key[REPLY_KEYS] =
     445            {header->un.echo.identifier, header->un.echo.sequence_number};
     446       
     447        /* The packet is no longer needed */
     448        icmp_release(packet);
     449       
    492450        /* Find the pending reply */
    493         fibril_rwlock_write_lock(&icmp_globals.lock);
    494         reply = icmp_replies_find(&icmp_globals.replies, reply_key);
    495         if (reply) {
     451        fibril_mutex_lock(&reply_lock);
     452       
     453        link_t *link = hash_table_find(&replies, key);
     454        if (link != NULL) {
     455                icmp_reply_t *reply =
     456                   hash_table_get_instance(link, icmp_reply_t, link);
     457               
    496458                reply->result = type;
    497459                fibril_condvar_signal(&reply->condvar);
    498460        }
    499         fibril_rwlock_write_unlock(&icmp_globals.lock);
    500 }
    501 
    502 /** Processes the received ICMP packet.
    503  *
    504  * Notifies the destination socket application.
    505  *
    506  * @param[in,out] packet The received packet.
    507  * @param[in] error     The packet error reporting service. Prefixes the
    508  *                      received packet.
    509  * @return              EOK on success.
    510  * @return              EINVAL if the packet is not valid.
    511  * @return              EINVAL if the stored packet address is not the an_addr_t.
    512  * @return              EINVAL if the packet does not contain any data.
    513  * @return              NO_DATA if the packet content is shorter than the user
    514  *                      datagram header.
    515  * @return              ENOMEM if there is not enough memory left.
    516  * @return              EADDRNOTAVAIL if the destination socket does not exist.
    517  * @return              Other error codes as defined for the
    518  *                      ip_client_process_packet() function.
     461       
     462        fibril_mutex_unlock(&reply_lock);
     463}
     464
     465/** Process the received ICMP packet.
     466 *
     467 * Notify the destination socket application.
     468 *
     469 * @param[in,out] packet Received packet.
     470 * @param[in]     error  Packet error reporting service to prefix
     471 *                       the received packet.
     472 *
     473 * @return EOK on success.
     474 * @return EINVAL if the packet is not valid.
     475 * @return EINVAL if the stored packet address is not the an_addr_t.
     476 * @return EINVAL if the packet does not contain any data.
     477 * @return NO_DATA if the packet content is shorter than the user
     478 *         datagram header.
     479 * @return ENOMEM if there is not enough memory left.
     480 * @return EADDRNOTAVAIL if the destination socket does not exist.
     481 * @return Other error codes as defined for the
     482 *         ip_client_process_packet() function.
     483 *
    519484 */
    520485static int icmp_process_packet(packet_t *packet, services_t error)
    521486{
    522         size_t length;
    523         uint8_t *src;
    524         int addrlen;
    525         int result;
    526         void *data;
    527         icmp_header_t *header;
    528487        icmp_type_t type;
    529488        icmp_code_t code;
    530489        int rc;
    531 
     490       
    532491        switch (error) {
    533492        case SERVICE_NONE:
     
    535494        case SERVICE_ICMP:
    536495                /* Process error */
    537                 result = icmp_client_process_packet(packet, &type, &code, NULL,
    538                     NULL);
    539                 if (result < 0)
    540                         return result;
    541                 length = (size_t) result;
     496                rc = icmp_client_process_packet(packet, &type, &code, NULL, NULL);
     497                if (rc < 0)
     498                        return rc;
     499               
    542500                /* Remove the error header */
    543                 rc = packet_trim(packet, length, 0);
     501                rc = packet_trim(packet, (size_t) rc, 0);
    544502                if (rc != EOK)
    545503                        return rc;
     504               
    546505                break;
    547506        default:
    548507                return ENOTSUP;
    549508        }
    550 
     509       
    551510        /* Get rid of the IP header */
    552         length = ip_client_header_length(packet);
     511        size_t length = ip_client_header_length(packet);
    553512        rc = packet_trim(packet, length, 0);
    554513        if (rc != EOK)
    555514                return rc;
    556 
     515       
    557516        length = packet_get_data_length(packet);
    558517        if (length <= 0)
    559518                return EINVAL;
    560 
     519       
    561520        if (length < ICMP_HEADER_SIZE)
    562521                return EINVAL;
    563 
    564         data = packet_get_data(packet);
     522       
     523        void *data = packet_get_data(packet);
    565524        if (!data)
    566525                return EINVAL;
    567 
     526       
    568527        /* Get ICMP header */
    569         header = (icmp_header_t *) data;
    570 
     528        icmp_header_t *header = (icmp_header_t *) data;
     529       
    571530        if (header->checksum) {
    572531                while (ICMP_CHECKSUM(header, length) != IP_CHECKSUM_ZERO) {
     
    582541                                }
    583542                        }
     543                       
    584544                        return EINVAL;
    585545                }
    586546        }
    587 
     547       
    588548        switch (header->type) {
    589549        case ICMP_ECHOREPLY:
     
    592552                else
    593553                        icmp_process_echo_reply(packet, header, ICMP_ECHO, 0);
    594 
     554               
    595555                return EOK;
    596 
     556       
    597557        case ICMP_ECHO:
    598558                if (error) {
     
    602562               
    603563                /* Do not send a reply if disabled */
    604                 if (icmp_globals.echo_replying) {
    605                         addrlen = packet_get_addr(packet, &src, NULL);
    606 
     564                if (echo_replying) {
     565                        uint8_t *src;
     566                        int addrlen = packet_get_addr(packet, &src, NULL);
     567                       
    607568                        /*
    608                          * Set both addresses to the source one (avoids the
     569                         * Set both addresses to the source one (avoid the
    609570                         * source address deletion before setting the
    610571                         * destination one).
     
    617578                                return EOK;
    618579                        }
    619 
     580                       
    620581                        return EINVAL;
    621582                }
    622 
     583               
    623584                return EPERM;
    624 
     585       
    625586        case ICMP_DEST_UNREACH:
    626587        case ICMP_SOURCE_QUENCH:
     
    635596        case ICMP_SKIP:
    636597        case ICMP_PHOTURIS:
    637                 ip_received_error_msg(icmp_globals.ip_phone, -1, packet,
     598                ip_received_error_msg(phone_ip, -1, packet,
    638599                    SERVICE_IP, SERVICE_ICMP);
    639600                return EOK;
    640 
     601       
    641602        default:
    642603                return ENOTSUP;
     
    644605}
    645606
    646 /** Processes the received ICMP packet.
    647  *
    648  * Is used as an entry point from the underlying IP module.
    649  * Releases the packet on error.
    650  *
    651  * @param device_id     The device identifier. Ignored parameter.
    652  * @param[in,out] packet The received packet.
    653  * @param receiver      The target service. Ignored parameter.
    654  * @param[in] error     The packet error reporting service. Prefixes the
    655  *                      received packet.
    656  * @return              EOK on success.
    657  * @return              Other error codes as defined for the
    658  *                      icmp_process_packet() function.
    659  */
    660 static int icmp_received_msg_local(device_id_t device_id, packet_t *packet,
    661     services_t receiver, services_t error)
    662 {
    663         int rc;
    664 
    665         rc = icmp_process_packet(packet, error);
    666         if (rc != EOK)
    667                 return icmp_release_and_return(packet, rc);
    668 
    669         return EOK;
    670 }
    671 
    672 /** Processes the generic client messages.
    673  *
    674  * @param[in] call      The message parameters.
    675  * @return              EOK on success.
    676  * @return              ENOTSUP if the message is not known.
    677  * @return              Other error codes as defined for the packet_translate()
    678  *                      function.
    679  * @return              Other error codes as defined for the
    680  *                      icmp_destination_unreachable_msg_local() function.
    681  * @return              Other error codes as defined for the
    682  *                      icmp_source_quench_msg_local() function.
    683  * @return              Other error codes as defined for the
    684  *                      icmp_time_exceeded_msg_local() function.
    685  * @return              Other error codes as defined for the
    686  *                      icmp_parameter_problem_msg_local() function.
    687  *
    688  * @see icmp_interface.h
    689  */
    690 static int icmp_process_message(ipc_call_t *call)
    691 {
     607/** Process IPC messages from the IP module
     608 *
     609 * @param[in]     iid   Message identifier.
     610 * @param[in,out] icall Message parameters.
     611 *
     612 */
     613static void icmp_receiver(ipc_callid_t iid, ipc_call_t *icall)
     614{
     615        bool loop = true;
    692616        packet_t *packet;
    693617        int rc;
    694 
    695         switch (IPC_GET_METHOD(*call)) {
    696         case NET_ICMP_DEST_UNREACH:
    697                 rc = packet_translate_remote(icmp_globals.net_phone, &packet,
    698                     IPC_GET_PACKET(call));
     618       
     619        while (loop) {
     620                switch (IPC_GET_IMETHOD(*icall)) {
     621                case NET_TL_RECEIVED:
     622                        rc = packet_translate_remote(phone_net, &packet,
     623                            IPC_GET_PACKET(*icall));
     624                        if (rc == EOK) {
     625                                rc = icmp_process_packet(packet, IPC_GET_ERROR(*icall));
     626                                if (rc != EOK)
     627                                        icmp_release(packet);
     628                        }
     629                       
     630                        ipc_answer_0(iid, (sysarg_t) rc);
     631                        break;
     632                case IPC_M_PHONE_HUNGUP:
     633                        loop = false;
     634                        continue;
     635                default:
     636                        ipc_answer_0(iid, (sysarg_t) ENOTSUP);
     637                }
     638               
     639                iid = async_get_call(icall);
     640        }
     641}
     642
     643/** Initialize the ICMP module.
     644 *
     645 * @param[in] net_phone Network module phone.
     646 *
     647 * @return EOK on success.
     648 * @return ENOMEM if there is not enough memory left.
     649 *
     650 */
     651int tl_initialize(int net_phone)
     652{
     653        measured_string_t names[] = {
     654                {
     655                        (uint8_t *) "ICMP_ERROR_REPORTING",
     656                        20
     657                },
     658                {
     659                        (uint8_t *) "ICMP_ECHO_REPLYING",
     660                        18
     661                }
     662        };
     663        measured_string_t *configuration;
     664        size_t count = sizeof(names) / sizeof(measured_string_t);
     665        uint8_t *data;
     666       
     667        if (!hash_table_create(&replies, REPLY_BUCKETS, REPLY_KEYS, &reply_ops))
     668                return ENOMEM;
     669       
     670        fibril_mutex_initialize(&reply_lock);
     671        atomic_set(&icmp_client, 0);
     672       
     673        phone_net = net_phone;
     674        phone_ip = ip_bind_service(SERVICE_IP, IPPROTO_ICMP, SERVICE_ICMP,
     675            icmp_receiver);
     676        if (phone_ip < 0)
     677                return phone_ip;
     678       
     679        int rc = ip_packet_size_req(phone_ip, -1, &icmp_dimension);
     680        if (rc != EOK)
     681                return rc;
     682       
     683        icmp_dimension.prefix += ICMP_HEADER_SIZE;
     684        icmp_dimension.content -= ICMP_HEADER_SIZE;
     685       
     686        /* Get configuration */
     687        configuration = &names[0];
     688        rc = net_get_conf_req(phone_net, &configuration, count, &data);
     689        if (rc != EOK)
     690                return rc;
     691       
     692        if (configuration) {
     693                if (configuration[0].value)
     694                        error_reporting = (configuration[0].value[0] == 'y');
     695               
     696                if (configuration[1].value)
     697                        echo_replying = (configuration[1].value[0] == 'y');
     698               
     699                net_free_settings(configuration, data);
     700        }
     701       
     702        return EOK;
     703}
     704
     705/** Per-connection initialization
     706 *
     707 * Initialize client-specific global variables.
     708 *
     709 */
     710void tl_connection(void)
     711{
     712        icmp_id = (icmp_param_t) atomic_postinc(&icmp_client);
     713        icmp_seq = 1;
     714}
     715
     716/** Process the ICMP message.
     717 *
     718 * @param[in]  callid Message identifier.
     719 * @param[in]  call   Message parameters.
     720 * @param[out] answer Answer.
     721 * @param[out] count  Number of arguments of the answer.
     722 *
     723 * @return EOK on success.
     724 * @return ENOTSUP if the message is not known.
     725 * @return Other error codes as defined for the packet_translate()
     726 *         function.
     727 * @return Other error codes as defined for the
     728 *         icmp_destination_unreachable() function.
     729 * @return Other error codes as defined for the
     730 *         icmp_source_quench() function.
     731 * @return Other error codes as defined for the
     732 *         icmp_time_exceeded() function.
     733 * @return Other error codes as defined for the
     734 *         icmp_parameter_problem() function.
     735 *
     736 * @see icmp_remote.h
     737 * @see IS_NET_ICMP_MESSAGE()
     738 *
     739 */
     740int tl_message(ipc_callid_t callid, ipc_call_t *call,
     741    ipc_call_t *answer, size_t *count)
     742{
     743        struct sockaddr *addr;
     744        size_t size;
     745        packet_t *packet;
     746        int rc;
     747       
     748        *count = 0;
     749       
     750        switch (IPC_GET_IMETHOD(*call)) {
     751        case NET_ICMP_ECHO:
     752                rc = async_data_write_accept((void **) &addr, false, 0, 0, 0, &size);
    699753                if (rc != EOK)
    700754                        return rc;
    701                 return icmp_destination_unreachable_msg_local(0,
    702                     ICMP_GET_CODE(call), ICMP_GET_MTU(call), packet);
    703         case NET_ICMP_SOURCE_QUENCH:
    704                 rc = packet_translate_remote(icmp_globals.net_phone, &packet,
    705                     IPC_GET_PACKET(call));
     755               
     756                rc = icmp_echo(icmp_id, icmp_seq, ICMP_GET_SIZE(*call),
     757                    ICMP_GET_TIMEOUT(*call), ICMP_GET_TTL(*call),
     758                    ICMP_GET_TOS(*call), ICMP_GET_DONT_FRAGMENT(*call),
     759                    addr, (socklen_t) size);
     760               
     761                free(addr);
     762                icmp_seq++;
     763                return rc;
     764       
     765        case NET_ICMP_DEST_UNREACH:
     766                rc = packet_translate_remote(phone_net, &packet,
     767                    IPC_GET_PACKET(*call));
    706768                if (rc != EOK)
    707769                        return rc;
    708                 return icmp_source_quench_msg_local(0, packet);
    709         case NET_ICMP_TIME_EXCEEDED:
    710                 rc = packet_translate_remote(icmp_globals.net_phone, &packet,
    711                     IPC_GET_PACKET(call));
     770               
     771                return icmp_destination_unreachable(ICMP_GET_CODE(*call),
     772                    ICMP_GET_MTU(*call), packet);
     773       
     774        case NET_ICMP_SOURCE_QUENCH:
     775                rc = packet_translate_remote(phone_net, &packet,
     776                    IPC_GET_PACKET(*call));
    712777                if (rc != EOK)
    713778                        return rc;
    714                 return icmp_time_exceeded_msg_local(0, ICMP_GET_CODE(call),
    715                     packet);
    716         case NET_ICMP_PARAMETERPROB:
    717                 rc = packet_translate_remote(icmp_globals.net_phone, &packet,
    718                     IPC_GET_PACKET(call));
     779               
     780                return icmp_source_quench(packet);
     781       
     782        case NET_ICMP_TIME_EXCEEDED:
     783                rc = packet_translate_remote(phone_net, &packet,
     784                    IPC_GET_PACKET(*call));
    719785                if (rc != EOK)
    720786                        return rc;
    721                 return icmp_parameter_problem_msg_local(0, ICMP_GET_CODE(call),
    722                     ICMP_GET_POINTER(call), packet);
    723         default:
    724                 return ENOTSUP;
    725         }
    726 }
    727 
    728 /** Assigns a new identifier for the connection.
    729  *
    730  * Fills the echo data parameter with the assigned values.
    731  *
    732  * @param[in,out] echo_data The echo data to be bound.
    733  * @return              Index of the inserted echo data.
    734  * @return              EBADMEM if the echo_data parameter is NULL.
    735  * @return              ENOTCONN if no free identifier have been found.
    736  */
    737 static int icmp_bind_free_id(icmp_echo_t *echo_data)
    738 {
    739         icmp_param_t index;
    740 
    741         if (!echo_data)
    742                 return EBADMEM;
    743 
    744         /* From the last used one */
    745         index = icmp_globals.last_used_id;
    746         do {
    747                 index++;
    748                 /* til the range end */
    749                 if (index >= ICMP_FREE_IDS_END) {
    750                         /* start from the range beginning */
    751                         index = ICMP_FREE_IDS_START - 1;
    752                         do {
    753                                 index++;
    754                                 /* til the last used one */
    755                                 if (index >= icmp_globals.last_used_id) {
    756                                         /* none found */
    757                                         return ENOTCONN;
    758                                 }
    759                         } while(icmp_echo_data_find(&icmp_globals.echo_data,
    760                             index) != NULL);
    761 
    762                         /* Found, break immediately */
    763                         break;
    764                 }
    765         } while (icmp_echo_data_find(&icmp_globals.echo_data, index) != NULL);
    766 
    767         echo_data->identifier = index;
    768         echo_data->sequence_number = 0;
    769 
    770         return icmp_echo_data_add(&icmp_globals.echo_data, index, echo_data);
    771 }
    772 
    773 /** Processes the client messages.
    774  *
    775  * Remembers the assigned identifier and sequence numbers.
    776  * Runs until the client module disconnects.
    777  *
    778  * @param[in] callid    The message identifier.
    779  * @param[in] call      The message parameters.
    780  * @return EOK.
    781  *
    782  * @see icmp_interface.h
    783  * @see icmp_api.h
    784  */
    785 static int icmp_process_client_messages(ipc_callid_t callid, ipc_call_t call)
    786 {
    787         bool keep_on_going = true;
    788         ipc_call_t answer;
    789         int answer_count;
    790         size_t length;
    791         struct sockaddr *addr;
    792         ipc_callid_t data_callid;
    793         icmp_echo_t *echo_data;
    794         int rc = EOK;
    795 
    796         /*
    797          * Accept the connection
    798          *  - Answer the first NET_ICMP_INIT call.
    799          */
    800         answer_count = 0;
    801 
    802         echo_data = (icmp_echo_t *) malloc(sizeof(*echo_data));
    803         if (!echo_data)
    804                 return ENOMEM;
    805 
    806         /* Assign a new identifier */
    807         fibril_rwlock_write_lock(&icmp_globals.lock);
    808         rc = icmp_bind_free_id(echo_data);
    809         fibril_rwlock_write_unlock(&icmp_globals.lock);
    810         if (rc < 0) {
    811                 free(echo_data);
    812                 return rc;
    813         }
    814 
    815         while (keep_on_going) {
    816                 /* Answer the call */
    817                 answer_call(callid, rc, &answer, answer_count);
    818 
    819                 /* Refresh data */
    820                 refresh_answer(&answer, &answer_count);
    821 
    822                 /* Get the next call */
    823                 callid = async_get_call(&call);
    824 
    825                 /* Process the call */
    826                 switch (IPC_GET_METHOD(call)) {
    827                 case IPC_M_PHONE_HUNGUP:
    828                         keep_on_going = false;
    829                         rc = EHANGUP;
    830                         break;
    831                
    832                 case NET_ICMP_ECHO:
    833                         if (!async_data_write_receive(&data_callid, &length)) {
    834                                 rc = EINVAL;
    835                                 break;
    836                         }
    837                        
    838                         addr = malloc(length);
    839                         if (!addr) {
    840                                 rc = ENOMEM;
    841                                 break;
    842                         }
    843                        
    844                         rc = async_data_write_finalize(data_callid, addr,
    845                             length);
    846                         if (rc != EOK) {
    847                                 free(addr);
    848                                 break;
    849                         }
    850 
    851                         fibril_rwlock_write_lock(&icmp_globals.lock);
    852                         rc = icmp_echo(echo_data->identifier,
    853                             echo_data->sequence_number, ICMP_GET_SIZE(call),
    854                             ICMP_GET_TIMEOUT(call), ICMP_GET_TTL(call),
    855                             ICMP_GET_TOS(call), ICMP_GET_DONT_FRAGMENT(call),
    856                             addr, (socklen_t) length);
    857                         fibril_rwlock_write_unlock(&icmp_globals.lock);
    858 
    859                         free(addr);
    860 
    861                         if (echo_data->sequence_number < UINT16_MAX)
    862                                 echo_data->sequence_number++;
    863                         else
    864                                 echo_data->sequence_number = 0;
    865 
    866                         break;
    867 
    868                 default:
    869                         rc = icmp_process_message(&call);
    870                 }
    871 
    872         }
    873 
    874         /* Release the identifier */
    875         fibril_rwlock_write_lock(&icmp_globals.lock);
    876         icmp_echo_data_exclude(&icmp_globals.echo_data, echo_data->identifier);
    877         fibril_rwlock_write_unlock(&icmp_globals.lock);
    878 
    879         return rc;
    880 }
    881 
    882 /** Processes the ICMP message.
    883  *
    884  * @param[in] callid    The message identifier.
    885  * @param[in] call      The message parameters.
    886  * @param[out] answer   The message answer parameters.
    887  * @param[out] answer_count The last parameter for the actual answer in the
    888  *                      answer parameter.
    889  * @return              EOK on success.
    890  * @return              ENOTSUP if the message is not known.
    891  *
    892  * @see icmp_interface.h
    893  * @see IS_NET_ICMP_MESSAGE()
    894  */
    895 int icmp_message_standalone(ipc_callid_t callid, ipc_call_t *call,
    896     ipc_call_t *answer, int *answer_count)
    897 {
    898         packet_t *packet;
    899         int rc;
    900 
    901         *answer_count = 0;
    902         switch (IPC_GET_METHOD(*call)) {
    903         case NET_TL_RECEIVED:
    904                 rc = packet_translate_remote(icmp_globals.net_phone, &packet,
    905                     IPC_GET_PACKET(call));
     787               
     788                return icmp_time_exceeded(ICMP_GET_CODE(*call), packet);
     789       
     790        case NET_ICMP_PARAMETERPROB:
     791                rc = packet_translate_remote(phone_net, &packet,
     792                    IPC_GET_PACKET(*call));
    906793                if (rc != EOK)
    907794                        return rc;
    908                 return icmp_received_msg_local(IPC_GET_DEVICE(call), packet,
    909                     SERVICE_ICMP, IPC_GET_ERROR(call));
    910        
    911         case NET_ICMP_INIT:
    912                 return icmp_process_client_messages(callid, * call);
    913        
    914         default:
    915                 return icmp_process_message(call);
    916         }
    917 
     795               
     796                return icmp_parameter_problem(ICMP_GET_CODE(*call),
     797                    ICMP_GET_POINTER(*call), packet);
     798        }
     799       
    918800        return ENOTSUP;
    919801}
    920802
    921 
    922 /** Default thread for new connections.
    923  *
    924  * @param[in] iid The initial message identifier.
    925  * @param[in] icall The initial message call structure.
    926  *
    927  */
    928 static void tl_client_connection(ipc_callid_t iid, ipc_call_t *icall)
    929 {
    930         /*
    931          * Accept the connection
    932          *  - Answer the first IPC_M_CONNECT_ME_TO call.
    933          */
    934         ipc_answer_0(iid, EOK);
    935        
    936         while (true) {
    937                 ipc_call_t answer;
    938                 int answer_count;
    939                
    940                 /* Clear the answer structure */
    941                 refresh_answer(&answer, &answer_count);
    942                
    943                 /* Fetch the next message */
    944                 ipc_call_t call;
    945                 ipc_callid_t callid = async_get_call(&call);
    946                
    947                 /* Process the message */
    948                 int res = tl_module_message_standalone(callid, &call, &answer,
    949                     &answer_count);
    950                
    951                 /*
    952                  * End if told to either by the message or the processing
    953                  * result.
    954                  */
    955                 if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) ||
    956                     (res == EHANGUP))
    957                         return;
    958                
    959                 /* Answer the message */
    960                 answer_call(callid, res, &answer, answer_count);
    961         }
    962 }
    963 
    964 /** Starts the module.
    965  *
    966  * @return              EOK on success.
    967  * @return              Other error codes as defined for each specific module
    968  *                      start function.
    969  */
    970803int main(int argc, char *argv[])
    971804{
    972         int rc;
    973        
    974805        /* Start the module */
    975         rc = tl_module_start_standalone(tl_client_connection);
    976         return rc;
     806        return tl_module_start(SERVICE_ICMP);
    977807}
    978808
    979809/** @}
    980810 */
    981 
  • uspace/srv/net/tl/tcp/Makefile

    rcead2aa r357b5f5  
    3434
    3535SOURCES = \
    36         tcp.c \
    37         tcp_module.c
     36        tcp.c
    3837
    3938include $(USPACE_PREFIX)/Makefile.common
  • uspace/srv/net/tl/tcp/tcp.c

    rcead2aa r357b5f5  
    3636 */
    3737
    38 #include "tcp.h"
    39 #include "tcp_header.h"
    40 #include "tcp_module.h"
    41 
    4238#include <assert.h>
    4339#include <async.h>
     
    6864#include <ip_interface.h>
    6965#include <icmp_client.h>
    70 #include <icmp_interface.h>
     66#include <icmp_remote.h>
    7167#include <net_interface.h>
    7268#include <socket_core.h>
    7369#include <tl_common.h>
    74 #include <tl_local.h>
    75 #include <tl_interface.h>
     70#include <tl_remote.h>
     71#include <tl_skel.h>
     72
     73#include "tcp.h"
     74#include "tcp_header.h"
    7675
    7776/** TCP module name. */
    78 #define NAME    "TCP protocol"
     77#define NAME  "tcp"
    7978
    8079/** The TCP window default value. */
     
    154153
    155154        /** Port map key. */
    156         char *key;
     155        uint8_t *key;
    157156
    158157        /** Port map key length. */
     
    205204static int tcp_queue_received_packet(socket_core_t *, tcp_socket_data_t *,
    206205    packet_t *, int, size_t);
     206static void tcp_queue_received_end_of_data(socket_core_t *socket);
    207207
    208208static int tcp_received_msg(device_id_t, packet_t *, services_t, services_t);
     
    219219/** TCP global data. */
    220220tcp_globals_t tcp_globals;
    221 
    222 /** Initializes the TCP module.
    223  *
    224  * @param[in] client_connection The client connection processing function. The
    225  *                      module skeleton propagates its own one.
    226  * @return              EOK on success.
    227  * @return              ENOMEM if there is not enough memory left.
    228  */
    229 int tcp_initialize(async_client_conn_t client_connection)
    230 {
    231         int rc;
    232 
    233         assert(client_connection);
    234 
    235         fibril_rwlock_initialize(&tcp_globals.lock);
    236         fibril_rwlock_write_lock(&tcp_globals.lock);
    237 
    238         tcp_globals.icmp_phone = icmp_connect_module(SERVICE_ICMP,
    239             ICMP_CONNECT_TIMEOUT);
    240         tcp_globals.ip_phone = ip_bind_service(SERVICE_IP, IPPROTO_TCP,
    241             SERVICE_TCP, client_connection);
    242         if (tcp_globals.ip_phone < 0) {
    243                 fibril_rwlock_write_unlock(&tcp_globals.lock);
    244                 return tcp_globals.ip_phone;
    245         }
    246        
    247         rc = socket_ports_initialize(&tcp_globals.sockets);
    248         if (rc != EOK)
    249                 goto out;
    250 
    251         rc = packet_dimensions_initialize(&tcp_globals.dimensions);
    252         if (rc != EOK) {
    253                 socket_ports_destroy(&tcp_globals.sockets);
    254                 goto out;
    255         }
    256 
    257         tcp_globals.last_used_port = TCP_FREE_PORTS_START - 1;
    258 
    259 out:
    260         fibril_rwlock_write_unlock(&tcp_globals.lock);
    261         return rc;
    262 }
    263221
    264222int tcp_received_msg(device_id_t device_id, packet_t *packet,
     
    357315        /* Find the destination socket */
    358316        socket = socket_port_find(&tcp_globals.sockets,
    359             ntohs(header->destination_port), (const char *) src, addrlen);
     317            ntohs(header->destination_port), (uint8_t *) src, addrlen);
    360318        if (!socket) {
    361319                /* Find the listening destination socket */
    362320                socket = socket_port_find(&tcp_globals.sockets,
    363                     ntohs(header->destination_port), SOCKET_MAP_KEY_LISTENING,
    364                     0);
     321                    ntohs(header->destination_port),
     322                    (uint8_t *) SOCKET_MAP_KEY_LISTENING, 0);
    365323        }
    366324
     
    453411
    454412has_error_service:
    455         fibril_rwlock_read_unlock(&tcp_globals.lock);
     413        fibril_rwlock_write_unlock(&tcp_globals.lock);
    456414
    457415        /* TODO error reporting/handling */
     
    504462        size_t offset;
    505463        uint32_t new_sequence_number;
     464        bool forced_ack;
    506465        int rc;
    507466
     
    512471        assert(packet);
    513472
     473        forced_ack = false;
     474
    514475        new_sequence_number = ntohl(header->sequence_number);
    515476        old_incoming = socket_data->next_incoming;
    516477
    517         if (header->finalize)
    518                 socket_data->fin_incoming = new_sequence_number;
     478        if (header->finalize) {
     479                socket_data->fin_incoming = new_sequence_number +
     480                    total_length - TCP_HEADER_LENGTH(header);
     481        }
    519482
    520483        /* Trim begining if containing expected data */
     
    760723                /* Release duplicite or restricted */
    761724                pq_release_remote(tcp_globals.net_phone, packet_get_id(packet));
    762         }
    763 
    764         /* Change state according to the acknowledging incoming fin */
    765         if (IS_IN_INTERVAL_OVERFLOW(old_incoming, socket_data->fin_incoming,
    766             socket_data->next_incoming)) {
     725                forced_ack = true;
     726        }
     727
     728        /* If next in sequence is an incoming FIN */
     729        if (socket_data->next_incoming == socket_data->fin_incoming) {
     730                /* Advance sequence number */
     731                socket_data->next_incoming += 1;
     732
     733                /* Handle FIN */
    767734                switch (socket_data->state) {
    768735                case TCP_SOCKET_FIN_WAIT_1:
     
    771738                        socket_data->state = TCP_SOCKET_CLOSING;
    772739                        break;
    773                 /*case TCP_ESTABLISHED:*/
     740                case TCP_SOCKET_ESTABLISHED:
     741                        /* Queue end-of-data marker on the socket. */
     742                        tcp_queue_received_end_of_data(socket);
     743                        socket_data->state = TCP_SOCKET_CLOSE_WAIT;
     744                        break;
    774745                default:
    775746                        socket_data->state = TCP_SOCKET_CLOSE_WAIT;
     
    779750
    780751        packet = tcp_get_packets_to_send(socket, socket_data);
    781         if (!packet) {
     752        if (!packet && (socket_data->next_incoming != old_incoming || forced_ack)) {
    782753                /* Create the notification packet */
    783754                rc = tcp_create_notification_packet(&packet, socket,
     
    829800        /* Notify the destination socket */
    830801        async_msg_5(socket->phone, NET_SOCKET_RECEIVED,
    831             (ipcarg_t) socket->socket_id,
     802            (sysarg_t) socket->socket_id,
    832803            ((packet_dimension->content < socket_data->data_fragment_size) ?
    833804            packet_dimension->content : socket_data->data_fragment_size), 0, 0,
    834             (ipcarg_t) fragments);
     805            (sysarg_t) fragments);
    835806
    836807        return EOK;
     808}
     809
     810/** Queue end-of-data marker on the socket.
     811 *
     812 * Next element in the sequence space is FIN. Queue end-of-data marker
     813 * on the socket.
     814 *
     815 * @param socket        Socket
     816 */
     817static void tcp_queue_received_end_of_data(socket_core_t *socket)
     818{
     819        assert(socket != NULL);
     820
     821        /* Notify the destination socket */
     822        async_msg_5(socket->phone, NET_SOCKET_RECEIVED,
     823            (sysarg_t) socket->socket_id,
     824            0, 0, 0,
     825            (sysarg_t) 0 /* 0 fragments == no more data */);
    837826}
    838827
     
    966955        /* Find the destination socket */
    967956        listening_socket = socket_port_find(&tcp_globals.sockets,
    968             listening_port, SOCKET_MAP_KEY_LISTENING, 0);
     957            listening_port, (uint8_t *) SOCKET_MAP_KEY_LISTENING, 0);
    969958        if (!listening_socket ||
    970959            (listening_socket->socket_id != listening_socket_id)) {
     
    990979
    991980        rc = socket_port_add(&tcp_globals.sockets, listening_port, socket,
    992             (const char *) socket_data->addr, socket_data->addrlen);
     981            (uint8_t *) socket_data->addr, socket_data->addrlen);
    993982        assert(socket == socket_port_find(&tcp_globals.sockets, listening_port,
    994             (const char *) socket_data->addr, socket_data->addrlen));
     983            (uint8_t *) socket_data->addr, socket_data->addrlen));
    995984
    996985//      rc = socket_bind_free_port(&tcp_globals.sockets, socket,
     
    10901079                        /* Notify the destination socket */
    10911080                        async_msg_5(socket->phone, NET_SOCKET_ACCEPTED,
    1092                             (ipcarg_t) listening_socket->socket_id,
     1081                            (sysarg_t) listening_socket->socket_id,
    10931082                            socket_data->data_fragment_size, TCP_HEADER_SIZE,
    1094                             0, (ipcarg_t) socket->socket_id);
     1083                            0, (sysarg_t) socket->socket_id);
    10951084
    10961085                        fibril_rwlock_write_unlock(socket_data->local_lock);
     
    12151204}
    12161205
     1206/** Per-connection initialization
     1207 *
     1208 */
     1209void tl_connection(void)
     1210{
     1211}
     1212
    12171213/** Processes the TCP message.
    12181214 *
     
    12281224 * @see IS_NET_TCP_MESSAGE()
    12291225 */
    1230 int
    1231 tcp_message_standalone(ipc_callid_t callid, ipc_call_t *call,
    1232     ipc_call_t *answer, int *answer_count)
    1233 {
    1234         packet_t *packet;
    1235         int rc;
    1236 
     1226int tl_message(ipc_callid_t callid, ipc_call_t *call,
     1227    ipc_call_t *answer, size_t *answer_count)
     1228{
    12371229        assert(call);
    12381230        assert(answer);
     
    12401232
    12411233        *answer_count = 0;
    1242         switch (IPC_GET_METHOD(*call)) {
    1243         case NET_TL_RECEIVED:
    1244 //              fibril_rwlock_read_lock(&tcp_globals.lock);
    1245                 rc = packet_translate_remote(tcp_globals.net_phone, &packet,
    1246                     IPC_GET_PACKET(call));
    1247                 if (rc != EOK) {
    1248 //                      fibril_rwlock_read_unlock(&tcp_globals.lock);
    1249                         return rc;
    1250                 }
    1251                 rc = tcp_received_msg(IPC_GET_DEVICE(call), packet, SERVICE_TCP,
    1252                     IPC_GET_ERROR(call));
    1253 //              fibril_rwlock_read_unlock(&tcp_globals.lock);
    1254                 return rc;
     1234        switch (IPC_GET_IMETHOD(*call)) {
    12551235        case IPC_M_CONNECT_TO_ME:
    12561236                return tcp_process_client_messages(callid, *call);
     
    12911271        bool keep_on_going = true;
    12921272        socket_cores_t local_sockets;
    1293         int app_phone = IPC_GET_PHONE(&call);
     1273        int app_phone = IPC_GET_PHONE(call);
    12941274        struct sockaddr *addr;
    12951275        int socket_id;
     
    12981278        fibril_rwlock_t lock;
    12991279        ipc_call_t answer;
    1300         int answer_count;
     1280        size_t answer_count;
    13011281        tcp_socket_data_t *socket_data;
    13021282        socket_core_t *socket;
     
    13231303
    13241304                /* Process the call */
    1325                 switch (IPC_GET_METHOD(call)) {
     1305                switch (IPC_GET_IMETHOD(call)) {
    13261306                case IPC_M_PHONE_HUNGUP:
    13271307                        keep_on_going = false;
     
    13651345
    13661346                case NET_SOCKET_BIND:
    1367                         res = data_receive((void **) &addr, &addrlen);
     1347                        res = async_data_write_accept((void **) &addr, false,
     1348                            0, 0, 0, &addrlen);
    13681349                        if (res != EOK)
    13691350                                break;
     
    14021383
    14031384                case NET_SOCKET_CONNECT:
    1404                         res = data_receive((void **) &addr, &addrlen);
     1385                        res = async_data_write_accept((void **) &addr, false,
     1386                            0, 0, 0, &addrlen);
    14051387                        if (res != EOK)
    14061388                                break;
     
    14531435
    14541436                case NET_SOCKET_SENDTO:
    1455                         res = data_receive((void **) &addr, &addrlen);
     1437                        res = async_data_write_accept((void **) &addr, false,
     1438                            0, 0, 0, &addrlen);
    14561439                        if (res != EOK)
    14571440                                break;
     
    18001783                        fibril_rwlock_write_unlock(socket_data->local_lock);
    18011784
     1785                        socket_data->state = TCP_SOCKET_SYN_SENT;
     1786
    18021787                        /* Send the packet */
    18031788                        printf("connecting %d\n", packet_get_id(packet));
     
    20722057
    20732058        /* Copy the key */
    2074         operation_timeout->key = ((char *) operation_timeout) +
     2059        operation_timeout->key = ((uint8_t *) operation_timeout) +
    20752060            sizeof(*operation_timeout);
    20762061        operation_timeout->key_length = socket->key_length;
     
    20822067        if (!fibril) {
    20832068                free(operation_timeout);
    2084                 return EPARTY;  /* FIXME: use another EC */
    2085         }
     2069                return ENOMEM;
     2070        }
     2071
    20862072//      fibril_mutex_lock(&socket_data->operation.mutex);
    20872073        /* Start the timeout fibril */
     
    22062192
    22072193                tcp_prepare_operation_header(socket, socket_data, header, 0, 0);
    2208                 rc = tcp_queue_packet(socket, socket_data, packet, 0);
     2194                rc = tcp_queue_packet(socket, socket_data, packet, total_length);
    22092195                if (rc != EOK)
    22102196                        return rc;
     
    24482434}
    24492435
    2450 /** Default thread for new connections.
     2436/** Process IPC messages from the IP module
    24512437 *
    2452  * @param[in] iid       The initial message identifier.
    2453  * @param[in] icall     The initial message call structure.
     2438 * @param[in]     iid   Message identifier.
     2439 * @param[in,out] icall Message parameters.
    24542440 *
    24552441 */
    2456 static void tl_client_connection(ipc_callid_t iid, ipc_call_t * icall)
    2457 {
    2458         /*
    2459          * Accept the connection
    2460          *  - Answer the first IPC_M_CONNECT_ME_TO call.
    2461          */
    2462         ipc_answer_0(iid, EOK);
    2463 
     2442static void tcp_receiver(ipc_callid_t iid, ipc_call_t *icall)
     2443{
     2444        packet_t *packet;
     2445        int rc;
     2446       
    24642447        while (true) {
    2465                 ipc_call_t answer;
    2466                 int answer_count;
    2467 
    2468                 /* Clear the answer structure */
    2469                 refresh_answer(&answer, &answer_count);
    2470 
    2471                 /* Fetch the next message */
    2472                 ipc_call_t call;
    2473                 ipc_callid_t callid = async_get_call(&call);
    2474 
    2475                 /* Process the message */
    2476                 int res = tl_module_message_standalone(callid, &call, &answer,
    2477                     &answer_count);
    2478 
    2479                 /*
    2480                  * End if told to either by the message or the processing
    2481                  * result.
    2482                  */
    2483                 if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) ||
    2484                     (res == EHANGUP))
    2485                         return;
    2486 
    2487                 /*
    2488                  * Answer the message
    2489                  */
    2490                 answer_call(callid, res, &answer, answer_count);
    2491         }
    2492 }
    2493 
    2494 /** Starts the module.
     2448                switch (IPC_GET_IMETHOD(*icall)) {
     2449                case NET_TL_RECEIVED:
     2450                        rc = packet_translate_remote(tcp_globals.net_phone, &packet,
     2451                            IPC_GET_PACKET(*icall));
     2452                        if (rc == EOK)
     2453                                rc = tcp_received_msg(IPC_GET_DEVICE(*icall), packet,
     2454                                    SERVICE_TCP, IPC_GET_ERROR(*icall));
     2455                       
     2456                        ipc_answer_0(iid, (sysarg_t) rc);
     2457                        break;
     2458                default:
     2459                        ipc_answer_0(iid, (sysarg_t) ENOTSUP);
     2460                }
     2461               
     2462                iid = async_get_call(icall);
     2463        }
     2464}
     2465
     2466/** Initialize the TCP module.
    24952467 *
    2496  * @return              EOK on success.
    2497  * @return              Other error codes as defined for each specific module
    2498  *                      start function.
     2468 * @param[in] net_phone Network module phone.
     2469 *
     2470 * @return EOK on success.
     2471 * @return ENOMEM if there is not enough memory left.
     2472 *
    24992473 */
    2500 int
    2501 main(int argc, char *argv[])
    2502 {
    2503         int rc;
    2504 
    2505         rc = tl_module_start_standalone(tl_client_connection);
     2474int tl_initialize(int net_phone)
     2475{
     2476        fibril_rwlock_initialize(&tcp_globals.lock);
     2477        fibril_rwlock_write_lock(&tcp_globals.lock);
     2478       
     2479        tcp_globals.net_phone = net_phone;
     2480       
     2481        tcp_globals.icmp_phone = icmp_connect_module(ICMP_CONNECT_TIMEOUT);
     2482        tcp_globals.ip_phone = ip_bind_service(SERVICE_IP, IPPROTO_TCP,
     2483            SERVICE_TCP, tcp_receiver);
     2484        if (tcp_globals.ip_phone < 0) {
     2485                fibril_rwlock_write_unlock(&tcp_globals.lock);
     2486                return tcp_globals.ip_phone;
     2487        }
     2488       
     2489        int rc = socket_ports_initialize(&tcp_globals.sockets);
     2490        if (rc != EOK)
     2491                goto out;
     2492
     2493        rc = packet_dimensions_initialize(&tcp_globals.dimensions);
     2494        if (rc != EOK) {
     2495                socket_ports_destroy(&tcp_globals.sockets);
     2496                goto out;
     2497        }
     2498
     2499        tcp_globals.last_used_port = TCP_FREE_PORTS_START - 1;
     2500
     2501out:
     2502        fibril_rwlock_write_unlock(&tcp_globals.lock);
    25062503        return rc;
     2504}
     2505
     2506int main(int argc, char *argv[])
     2507{
     2508        return tl_module_start(SERVICE_TCP);
    25072509}
    25082510
  • uspace/srv/net/tl/udp/Makefile

    rcead2aa r357b5f5  
    3434
    3535SOURCES = \
    36         udp.c \
    37         udp_module.c
     36        udp.c
    3837
    3938include $(USPACE_PREFIX)/Makefile.common
  • uspace/srv/net/tl/udp/udp.c

    rcead2aa r357b5f5  
    3535 * @see udp.h
    3636 */
    37 
    38 #include "udp.h"
    39 #include "udp_header.h"
    40 #include "udp_module.h"
    4137
    4238#include <async.h>
     
    6561#include <ip_interface.h>
    6662#include <icmp_client.h>
    67 #include <icmp_interface.h>
     63#include <icmp_remote.h>
    6864#include <net_interface.h>
    6965#include <socket_core.h>
    7066#include <tl_common.h>
    71 #include <tl_local.h>
    72 #include <tl_interface.h>
     67#include <tl_remote.h>
     68#include <tl_skel.h>
     69
     70#include "udp.h"
     71#include "udp_header.h"
    7372
    7473/** UDP module name. */
    75 #define NAME    "UDP protocol"
     74#define NAME  "udp"
    7675
    7776/** Default UDP checksum computing. */
     
    9291/** UDP global data.  */
    9392udp_globals_t udp_globals;
    94 
    95 /** Initializes the UDP module.
    96  *
    97  * @param[in] client_connection The client connection processing function. The
    98  *                      module skeleton propagates its own one.
    99  * @return              EOK on success.
    100  * @return              ENOMEM if there is not enough memory left.
    101  */
    102 int udp_initialize(async_client_conn_t client_connection)
    103 {
    104         measured_string_t names[] = {
    105                 {
    106                         (char *) "UDP_CHECKSUM_COMPUTING",
    107                         22
    108                 },
    109                 {
    110                         (char *) "UDP_AUTOBINDING",
    111                         15
    112                 }
    113         };
    114         measured_string_t *configuration;
    115         size_t count = sizeof(names) / sizeof(measured_string_t);
    116         char *data;
    117         int rc;
    118 
    119         fibril_rwlock_initialize(&udp_globals.lock);
    120         fibril_rwlock_write_lock(&udp_globals.lock);
    121 
    122         udp_globals.icmp_phone = icmp_connect_module(SERVICE_ICMP,
    123             ICMP_CONNECT_TIMEOUT);
    124        
    125         udp_globals.ip_phone = ip_bind_service(SERVICE_IP, IPPROTO_UDP,
    126             SERVICE_UDP, client_connection);
    127         if (udp_globals.ip_phone < 0) {
    128                 fibril_rwlock_write_unlock(&udp_globals.lock);
    129                 return udp_globals.ip_phone;
    130         }
    131 
    132         /* Read default packet dimensions */
    133         rc = ip_packet_size_req(udp_globals.ip_phone, -1,
    134             &udp_globals.packet_dimension);
    135         if (rc != EOK) {
    136                 fibril_rwlock_write_unlock(&udp_globals.lock);
    137                 return rc;
    138         }
    139        
    140         rc = socket_ports_initialize(&udp_globals.sockets);
    141         if (rc != EOK) {
    142                 fibril_rwlock_write_unlock(&udp_globals.lock);
    143                 return rc;
    144         }
    145        
    146         rc = packet_dimensions_initialize(&udp_globals.dimensions);
    147         if (rc != EOK) {
    148                 socket_ports_destroy(&udp_globals.sockets);
    149                 fibril_rwlock_write_unlock(&udp_globals.lock);
    150                 return rc;
    151         }
    152        
    153         udp_globals.packet_dimension.prefix += sizeof(udp_header_t);
    154         udp_globals.packet_dimension.content -= sizeof(udp_header_t);
    155         udp_globals.last_used_port = UDP_FREE_PORTS_START - 1;
    156 
    157         udp_globals.checksum_computing = NET_DEFAULT_UDP_CHECKSUM_COMPUTING;
    158         udp_globals.autobinding = NET_DEFAULT_UDP_AUTOBINDING;
    159 
    160         /* Get configuration */
    161         configuration = &names[0];
    162         rc = net_get_conf_req(udp_globals.net_phone, &configuration, count,
    163             &data);
    164         if (rc != EOK) {
    165                 socket_ports_destroy(&udp_globals.sockets);
    166                 fibril_rwlock_write_unlock(&udp_globals.lock);
    167                 return rc;
    168         }
    169        
    170         if (configuration) {
    171                 if (configuration[0].value)
    172                         udp_globals.checksum_computing =
    173                             (configuration[0].value[0] == 'y');
    174                
    175                 if (configuration[1].value)
    176                         udp_globals.autobinding =
    177                             (configuration[1].value[0] == 'y');
    178 
    179                 net_free_settings(configuration, data);
    180         }
    181 
    182         fibril_rwlock_write_unlock(&udp_globals.lock);
    183         return EOK;
    184 }
    18593
    18694/** Releases the packet and returns the result.
     
    283191        /* Find the destination socket */
    284192        socket = socket_port_find(&udp_globals.sockets,
    285         ntohs(header->destination_port), SOCKET_MAP_KEY_LISTENING, 0);
     193            ntohs(header->destination_port), (uint8_t *) SOCKET_MAP_KEY_LISTENING, 0);
    286194        if (!socket) {
    287195                if (tl_prepare_icmp_packet(udp_globals.net_phone,
     
    393301        fibril_rwlock_write_unlock(&udp_globals.lock);
    394302        async_msg_5(socket->phone, NET_SOCKET_RECEIVED,
    395             (ipcarg_t) socket->socket_id, packet_dimension->content, 0, 0,
    396             (ipcarg_t) fragments);
     303            (sysarg_t) socket->socket_id, packet_dimension->content, 0, 0,
     304            (sysarg_t) fragments);
    397305
    398306        return EOK;
     
    424332
    425333        return result;
     334}
     335
     336/** Process IPC messages from the IP module
     337 *
     338 * @param[in]     iid   Message identifier.
     339 * @param[in,out] icall Message parameters.
     340 *
     341 */
     342static void udp_receiver(ipc_callid_t iid, ipc_call_t *icall)
     343{
     344        packet_t *packet;
     345        int rc;
     346       
     347        while (true) {
     348                switch (IPC_GET_IMETHOD(*icall)) {
     349                case NET_TL_RECEIVED:
     350                        rc = packet_translate_remote(udp_globals.net_phone, &packet,
     351                            IPC_GET_PACKET(*icall));
     352                        if (rc == EOK)
     353                                rc = udp_received_msg(IPC_GET_DEVICE(*icall), packet,
     354                                    SERVICE_UDP, IPC_GET_ERROR(*icall));
     355                       
     356                        ipc_answer_0(iid, (sysarg_t) rc);
     357                        break;
     358                default:
     359                        ipc_answer_0(iid, (sysarg_t) ENOTSUP);
     360                }
     361               
     362                iid = async_get_call(icall);
     363        }
     364}
     365
     366/** Initialize the UDP module.
     367 *
     368 * @param[in] net_phone Network module phone.
     369 *
     370 * @return EOK on success.
     371 * @return ENOMEM if there is not enough memory left.
     372 *
     373 */
     374int tl_initialize(int net_phone)
     375{
     376        measured_string_t names[] = {
     377                {
     378                        (uint8_t *) "UDP_CHECKSUM_COMPUTING",
     379                        22
     380                },
     381                {
     382                        (uint8_t *) "UDP_AUTOBINDING",
     383                        15
     384                }
     385        };
     386        measured_string_t *configuration;
     387        size_t count = sizeof(names) / sizeof(measured_string_t);
     388        uint8_t *data;
     389       
     390        fibril_rwlock_initialize(&udp_globals.lock);
     391        fibril_rwlock_write_lock(&udp_globals.lock);
     392       
     393        udp_globals.net_phone = net_phone;
     394       
     395        udp_globals.icmp_phone = icmp_connect_module(ICMP_CONNECT_TIMEOUT);
     396       
     397        udp_globals.ip_phone = ip_bind_service(SERVICE_IP, IPPROTO_UDP,
     398            SERVICE_UDP, udp_receiver);
     399        if (udp_globals.ip_phone < 0) {
     400                fibril_rwlock_write_unlock(&udp_globals.lock);
     401                return udp_globals.ip_phone;
     402        }
     403       
     404        /* Read default packet dimensions */
     405        int rc = ip_packet_size_req(udp_globals.ip_phone, -1,
     406            &udp_globals.packet_dimension);
     407        if (rc != EOK) {
     408                fibril_rwlock_write_unlock(&udp_globals.lock);
     409                return rc;
     410        }
     411       
     412        rc = socket_ports_initialize(&udp_globals.sockets);
     413        if (rc != EOK) {
     414                fibril_rwlock_write_unlock(&udp_globals.lock);
     415                return rc;
     416        }
     417       
     418        rc = packet_dimensions_initialize(&udp_globals.dimensions);
     419        if (rc != EOK) {
     420                socket_ports_destroy(&udp_globals.sockets);
     421                fibril_rwlock_write_unlock(&udp_globals.lock);
     422                return rc;
     423        }
     424       
     425        udp_globals.packet_dimension.prefix += sizeof(udp_header_t);
     426        udp_globals.packet_dimension.content -= sizeof(udp_header_t);
     427        udp_globals.last_used_port = UDP_FREE_PORTS_START - 1;
     428
     429        udp_globals.checksum_computing = NET_DEFAULT_UDP_CHECKSUM_COMPUTING;
     430        udp_globals.autobinding = NET_DEFAULT_UDP_AUTOBINDING;
     431
     432        /* Get configuration */
     433        configuration = &names[0];
     434        rc = net_get_conf_req(udp_globals.net_phone, &configuration, count,
     435            &data);
     436        if (rc != EOK) {
     437                socket_ports_destroy(&udp_globals.sockets);
     438                fibril_rwlock_write_unlock(&udp_globals.lock);
     439                return rc;
     440        }
     441       
     442        if (configuration) {
     443                if (configuration[0].value)
     444                        udp_globals.checksum_computing =
     445                            (configuration[0].value[0] == 'y');
     446               
     447                if (configuration[1].value)
     448                        udp_globals.autobinding =
     449                            (configuration[1].value[0] == 'y');
     450
     451                net_free_settings(configuration, data);
     452        }
     453
     454        fibril_rwlock_write_unlock(&udp_globals.lock);
     455        return EOK;
    426456}
    427457
     
    707737        bool keep_on_going = true;
    708738        socket_cores_t local_sockets;
    709         int app_phone = IPC_GET_PHONE(&call);
     739        int app_phone = IPC_GET_PHONE(call);
    710740        struct sockaddr *addr;
    711741        int socket_id;
     
    713743        size_t size;
    714744        ipc_call_t answer;
    715         int answer_count;
     745        size_t answer_count;
    716746        packet_dimension_t *packet_dimension;
    717747
     
    742772
    743773                /* Process the call */
    744                 switch (IPC_GET_METHOD(call)) {
     774                switch (IPC_GET_IMETHOD(call)) {
    745775                case IPC_M_PHONE_HUNGUP:
    746776                        keep_on_going = false;
     
    771801
    772802                case NET_SOCKET_BIND:
    773                         res = data_receive((void **) &addr, &addrlen);
     803                        res = async_data_write_accept((void **) &addr, false,
     804                            0, 0, 0, &addrlen);
    774805                        if (res != EOK)
    775806                                break;
     
    784815
    785816                case NET_SOCKET_SENDTO:
    786                         res = data_receive((void **) &addr, &addrlen);
     817                        res = async_data_write_accept((void **) &addr, false,
     818                            0, 0, 0, &addrlen);
    787819                        if (res != EOK)
    788820                                break;
     
    845877}
    846878
     879/** Per-connection initialization
     880 *
     881 */
     882void tl_connection(void)
     883{
     884}
     885
    847886/** Processes the UDP message.
    848887 *
     
    858897 * @see IS_NET_UDP_MESSAGE()
    859898 */
    860 int udp_message_standalone(ipc_callid_t callid, ipc_call_t *call,
    861     ipc_call_t *answer, int *answer_count)
    862 {
    863         packet_t *packet;
    864         int rc;
    865 
     899int tl_message(ipc_callid_t callid, ipc_call_t *call,
     900    ipc_call_t *answer, size_t *answer_count)
     901{
    866902        *answer_count = 0;
    867903
    868         switch (IPC_GET_METHOD(*call)) {
    869         case NET_TL_RECEIVED:
    870                 rc = packet_translate_remote(udp_globals.net_phone, &packet,
    871                     IPC_GET_PACKET(call));
    872                 if (rc != EOK)
    873                         return rc;
    874                 return udp_received_msg(IPC_GET_DEVICE(call), packet,
    875                     SERVICE_UDP, IPC_GET_ERROR(call));
     904        switch (IPC_GET_IMETHOD(*call)) {
    876905        case IPC_M_CONNECT_TO_ME:
    877                 return udp_process_client_messages(callid, * call);
     906                return udp_process_client_messages(callid, *call);
    878907        }
    879908
     
    881910}
    882911
    883 /** Default thread for new connections.
    884  *
    885  * @param[in] iid       The initial message identifier.
    886  * @param[in] icall     The initial message call structure.
    887  */
    888 static void tl_client_connection(ipc_callid_t iid, ipc_call_t * icall)
    889 {
    890         /*
    891          * Accept the connection
    892          *  - Answer the first IPC_M_CONNECT_ME_TO call.
    893          */
    894         ipc_answer_0(iid, EOK);
    895        
    896         while (true) {
    897                 ipc_call_t answer;
    898                 int answer_count;
    899                
    900                 /* Clear the answer structure */
    901                 refresh_answer(&answer, &answer_count);
    902                
    903                 /* Fetch the next message */
    904                 ipc_call_t call;
    905                 ipc_callid_t callid = async_get_call(&call);
    906                
    907                 /* Process the message */
    908                 int res = tl_module_message_standalone(callid, &call, &answer,
    909                     &answer_count);
    910                
    911                 /*
    912                  * End if told to either by the message or the processing
    913                  * result.
    914                  */
    915                 if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) ||
    916                     (res == EHANGUP))
    917                         return;
    918                
    919                 /* Answer the message */
    920                 answer_call(callid, res, &answer, answer_count);
    921         }
    922 }
    923 
    924 /** Starts the module.
    925  *
    926  * @return              EOK on success.
    927  * @return              Other error codes as defined for each specific module
    928  *                      start function.
    929  */
    930912int main(int argc, char *argv[])
    931913{
    932         int rc;
    933        
    934914        /* Start the module */
    935         rc = tl_module_start_standalone(tl_client_connection);
    936         return rc;
     915        return tl_module_start(SERVICE_UDP);
    937916}
    938917
Note: See TracChangeset for help on using the changeset viewer.