Changeset 80cd7cd in mainline for uspace/srv/net/il


Ignore:
Timestamp:
2011-01-13T20:58:24Z (15 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
87e373b
Parents:
eaef141 (diff), a613fea1 (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/il
Files:
5 deleted
6 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/net/il/arp/Makefile

    reaef141 r80cd7cd  
    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

    reaef141 r80cd7cd  
    3535 * @see arp.h
    3636 */
    37 
    38 #include "arp.h"
    39 #include "arp_header.h"
    40 #include "arp_oc.h"
    41 #include "arp_module.h"
    4237
    4338#include <async.h>
     
    5449#include <ipc/arp.h>
    5550#include <ipc/il.h>
     51#include <ipc/nil.h>
    5652#include <byteorder.h>
    5753#include <errno.h>
    58 
    5954#include <net/modules.h>
    6055#include <net/device.h>
    6156#include <net/packet.h>
    62 
    63 #include <nil_interface.h>
     57#include <nil_remote.h>
    6458#include <protocol_map.h>
    6559#include <packet_client.h>
    6660#include <packet_remote.h>
    67 #include <il_interface.h>
    68 #include <il_local.h>
    69 
     61#include <il_remote.h>
     62#include <il_skel.h>
     63#include "arp.h"
    7064
    7165/** ARP module name. */
     
    7367
    7468/** Number of microseconds to wait for an ARP reply. */
    75 #define ARP_TRANS_WAIT  1000000
     69#define ARP_TRANS_WAIT  1000000
     70
     71/** @name ARP operation codes definitions */
     72/*@{*/
     73
     74/** REQUEST operation code. */
     75#define ARPOP_REQUEST  1
     76
     77/** REPLY operation code. */
     78#define ARPOP_REPLY  2
     79
     80/*@}*/
     81
     82/** Type definition of an ARP protocol header.
     83 * @see arp_header
     84 */
     85typedef struct arp_header arp_header_t;
     86
     87/** ARP protocol header. */
     88struct arp_header {
     89        /**
     90         * Hardware type identifier.
     91         * @see hardware.h
     92         */
     93        uint16_t hardware;
     94       
     95        /** Protocol identifier. */
     96        uint16_t protocol;
     97        /** Hardware address length in bytes. */
     98        uint8_t hardware_length;
     99        /** Protocol address length in bytes. */
     100        uint8_t protocol_length;
     101       
     102        /**
     103         * ARP packet type.
     104         * @see arp_oc.h
     105         */
     106        uint16_t operation;
     107} __attribute__ ((packed));
    76108
    77109/** ARP global data. */
     
    88120                trans->hw_addr = NULL;
    89121        }
     122       
    90123        fibril_condvar_broadcast(&trans->cv);
    91124}
     
    94127{
    95128        int count;
    96         arp_trans_t *trans;
    97 
     129       
    98130        for (count = arp_addr_count(addresses) - 1; count >= 0; count--) {
    99                 trans = arp_addr_items_get_index(&addresses->values, count);
     131                arp_trans_t *trans = arp_addr_items_get_index(&addresses->values,
     132                    count);
    100133                if (trans)
    101134                        arp_clear_trans(trans);
     
    103136}
    104137
    105 
    106 /** Clears the device specific data.
    107  *
    108  * @param[in] device    The device specific data.
     138/** Clear the device specific data.
     139 *
     140 * @param[in] device Device specific data.
    109141 */
    110142static void arp_clear_device(arp_device_t *device)
    111143{
    112144        int count;
    113         arp_proto_t *proto;
    114 
     145       
    115146        for (count = arp_protos_count(&device->protos) - 1; count >= 0;
    116147            count--) {
    117                 proto = arp_protos_get_index(&device->protos, count);
     148                arp_proto_t *proto = arp_protos_get_index(&device->protos,
     149                    count);
     150               
    118151                if (proto) {
    119152                        if (proto->addr)
    120153                                free(proto->addr);
     154                       
    121155                        if (proto->addr_data)
    122156                                free(proto->addr_data);
     157                       
    123158                        arp_clear_addr(&proto->addresses);
    124159                        arp_addr_destroy(&proto->addresses);
    125160                }
    126161        }
     162       
    127163        arp_protos_clear(&device->protos);
    128164}
     
    131167{
    132168        int count;
    133         arp_device_t *device;
    134 
     169       
    135170        fibril_mutex_lock(&arp_globals.lock);
    136171        for (count = arp_cache_count(&arp_globals.cache) - 1; count >= 0;
    137172            count--) {
    138                 device = arp_cache_get_index(&arp_globals.cache, count);
     173                arp_device_t *device = arp_cache_get_index(&arp_globals.cache,
     174                    count);
     175               
    139176                if (device) {
    140177                        arp_clear_device(device);
    141178                        if (device->addr_data)
    142179                                free(device->addr_data);
     180                       
    143181                        if (device->broadcast_data)
    144182                                free(device->broadcast_data);
    145183                }
    146184        }
     185       
    147186        arp_cache_clear(&arp_globals.cache);
    148187        fibril_mutex_unlock(&arp_globals.lock);
    149         printf("Cache cleaned\n");
     188       
    150189        return EOK;
    151190}
     
    154193    services_t protocol, measured_string_t *address)
    155194{
    156         arp_device_t *device;
    157         arp_proto_t *proto;
    158         arp_trans_t *trans;
    159 
    160195        fibril_mutex_lock(&arp_globals.lock);
    161         device = arp_cache_find(&arp_globals.cache, device_id);
     196       
     197        arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
    162198        if (!device) {
    163199                fibril_mutex_unlock(&arp_globals.lock);
    164200                return ENOENT;
    165201        }
    166         proto = arp_protos_find(&device->protos, protocol);
     202       
     203        arp_proto_t *proto = arp_protos_find(&device->protos, protocol);
    167204        if (!proto) {
    168205                fibril_mutex_unlock(&arp_globals.lock);
    169206                return ENOENT;
    170207        }
    171         trans = arp_addr_find(&proto->addresses, address->value, address->length);
     208       
     209        arp_trans_t *trans = arp_addr_find(&proto->addresses, address->value,
     210            address->length);
    172211        if (trans)
    173212                arp_clear_trans(trans);
     213       
    174214        arp_addr_exclude(&proto->addresses, address->value, address->length);
     215       
    175216        fibril_mutex_unlock(&arp_globals.lock);
    176217        return EOK;
    177218}
    178219
    179 
    180220static int arp_clear_device_req(int arp_phone, device_id_t device_id)
    181221{
    182         arp_device_t *device;
    183 
    184222        fibril_mutex_lock(&arp_globals.lock);
    185         device = arp_cache_find(&arp_globals.cache, device_id);
     223       
     224        arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
    186225        if (!device) {
    187226                fibril_mutex_unlock(&arp_globals.lock);
    188227                return ENOENT;
    189228        }
     229       
    190230        arp_clear_device(device);
    191         printf("Device %d cleared\n", device_id);
     231       
    192232        fibril_mutex_unlock(&arp_globals.lock);
    193233        return EOK;
    194234}
    195235
    196 /** Creates new protocol specific data.
    197  *
    198  * Allocates and returns the needed memory block as the proto parameter.
    199  *
    200  * @param[out] proto    The allocated protocol specific data.
    201  * @param[in] service   The protocol module service.
    202  * @param[in] address   The actual protocol device address.
    203  * @return              EOK on success.
    204  * @return              ENOMEM if there is not enough memory left.
     236/** Create new protocol specific data.
     237 *
     238 * Allocate and return the needed memory block as the proto parameter.
     239 *
     240 * @param[out] proto   Allocated protocol specific data.
     241 * @param[in]  service Protocol module service.
     242 * @param[in]  address Actual protocol device address.
     243 *
     244 * @return EOK on success.
     245 * @return ENOMEM if there is not enough memory left.
     246 *
    205247 */
    206248static int arp_proto_create(arp_proto_t **proto, services_t service,
    207249    measured_string_t *address)
    208250{
    209         int rc;
    210 
    211251        *proto = (arp_proto_t *) malloc(sizeof(arp_proto_t));
    212252        if (!*proto)
     
    217257        (*proto)->addr_data = address->value;
    218258       
    219         rc = arp_addr_initialize(&(*proto)->addresses);
     259        int rc = arp_addr_initialize(&(*proto)->addresses);
    220260        if (rc != EOK) {
    221261                free(*proto);
     
    226266}
    227267
    228 /** Registers the device.
    229  *
    230  * Creates new device entry in the cache or updates the protocol address if the
    231  * device with the device identifier and the driver service exists.
    232  *
    233  * @param[in] device_id The device identifier.
    234  * @param[in] service   The device driver service.
    235  * @param[in] protocol  The protocol service.
    236  * @param[in] address   The actual device protocol address.
    237  * @return              EOK on success.
    238  * @return              EEXIST if another device with the same device identifier
    239  *                      and different driver service exists.
    240  * @return              ENOMEM if there is not enough memory left.
    241  * @return              Other error codes as defined for the
    242  *                      measured_strings_return() function.
    243  */
    244 static int arp_device_message(device_id_t device_id, services_t service,
    245     services_t protocol, measured_string_t *address)
    246 {
    247         arp_device_t *device;
    248         arp_proto_t *proto;
    249         hw_type_t hardware;
    250         int index;
     268/** Process the received ARP packet.
     269 *
     270 * Update the source hardware address if the source entry exists or the packet
     271 * is targeted to my protocol address.
     272 *
     273 * Respond to the ARP request if the packet is the ARP request and is
     274 * targeted to my address.
     275 *
     276 * @param[in]     device_id Source device identifier.
     277 * @param[in,out] packet    Received packet.
     278 *
     279 * @return EOK on success and the packet is no longer needed.
     280 * @return One on success and the packet has been reused.
     281 * @return EINVAL if the packet is too small to carry an ARP
     282 *         packet.
     283 * @return EINVAL if the received address lengths differs from
     284 *         the registered values.
     285 * @return ENOENT if the device is not found in the cache.
     286 * @return ENOENT if the protocol for the device is not found in
     287 *         the cache.
     288 * @return ENOMEM if there is not enough memory left.
     289 *
     290 */
     291static int arp_receive_message(device_id_t device_id, packet_t *packet)
     292{
    251293        int rc;
    252 
    253         fibril_mutex_lock(&arp_globals.lock);
    254 
    255         /* An existing device? */
    256         device = arp_cache_find(&arp_globals.cache, device_id);
    257 
    258         if (device) {
    259                 if (device->service != service) {
    260                         printf("Device %d already exists\n", device->device_id);
    261                         fibril_mutex_unlock(&arp_globals.lock);
    262                         return EEXIST;
    263                 }
    264                 proto = arp_protos_find(&device->protos, protocol);
    265                 if (proto) {
    266                         free(proto->addr);
    267                         free(proto->addr_data);
    268                         proto->addr = address;
    269                         proto->addr_data = address->value;
    270                 } else {
    271                         rc = arp_proto_create(&proto, protocol, address);
    272                         if (rc != EOK) {
    273                                 fibril_mutex_unlock(&arp_globals.lock);
    274                                 return rc;
    275                         }
    276                         index = arp_protos_add(&device->protos, proto->service,
    277                             proto);
    278                         if (index < 0) {
    279                                 fibril_mutex_unlock(&arp_globals.lock);
    280                                 free(proto);
    281                                 return index;
    282                         }
    283                         printf("New protocol added:\n\tdevice id\t= "
    284                             "%d\n\tproto\t= %d", device_id, protocol);
    285                 }
    286         } else {
    287                 hardware = hardware_map(service);
    288                 if (!hardware)
    289                         return ENOENT;
    290                
    291                 /* Create a new device */
    292                 device = (arp_device_t *) malloc(sizeof(arp_device_t));
    293                 if (!device) {
    294                         fibril_mutex_unlock(&arp_globals.lock);
    295                         return ENOMEM;
    296                 }
    297                 device->hardware = hardware;
    298                 device->device_id = device_id;
    299                 rc = arp_protos_initialize(&device->protos);
    300                 if (rc != EOK) {
    301                         fibril_mutex_unlock(&arp_globals.lock);
    302                         free(device);
    303                         return rc;
    304                 }
    305                 rc = arp_proto_create(&proto, protocol, address);
    306                 if (rc != EOK) {
    307                         fibril_mutex_unlock(&arp_globals.lock);
    308                         free(device);
    309                         return rc;
    310                 }
    311                 index = arp_protos_add(&device->protos, proto->service, proto);
    312                 if (index < 0) {
    313                         fibril_mutex_unlock(&arp_globals.lock);
    314                         arp_protos_destroy(&device->protos);
    315                         free(device);
    316                         return index;
    317                 }
    318                 device->service = service;
    319                
    320                 /* Bind the new one */
    321                 device->phone = nil_bind_service(device->service,
    322                     (sysarg_t) device->device_id, SERVICE_ARP,
    323                     arp_globals.client_connection);
    324                 if (device->phone < 0) {
    325                         fibril_mutex_unlock(&arp_globals.lock);
    326                         arp_protos_destroy(&device->protos);
    327                         free(device);
    328                         return EREFUSED;
    329                 }
    330                
    331                 /* Get packet dimensions */
    332                 rc = nil_packet_size_req(device->phone, device_id,
    333                     &device->packet_dimension);
    334                 if (rc != EOK) {
    335                         fibril_mutex_unlock(&arp_globals.lock);
    336                         arp_protos_destroy(&device->protos);
    337                         free(device);
    338                         return rc;
    339                 }
    340                
    341                 /* Get hardware address */
    342                 rc = nil_get_addr_req(device->phone, device_id, &device->addr,
    343                     &device->addr_data);
    344                 if (rc != EOK) {
    345                         fibril_mutex_unlock(&arp_globals.lock);
    346                         arp_protos_destroy(&device->protos);
    347                         free(device);
    348                         return rc;
    349                 }
    350                
    351                 /* Get broadcast address */
    352                 rc = nil_get_broadcast_addr_req(device->phone, device_id,
    353                     &device->broadcast_addr, &device->broadcast_data);
    354                 if (rc != EOK) {
    355                         fibril_mutex_unlock(&arp_globals.lock);
    356                         free(device->addr);
    357                         free(device->addr_data);
    358                         arp_protos_destroy(&device->protos);
    359                         free(device);
    360                         return rc;
    361                 }
    362                
    363                 rc = arp_cache_add(&arp_globals.cache, device->device_id,
    364                     device);
    365                 if (rc != EOK) {
    366                         fibril_mutex_unlock(&arp_globals.lock);
    367                         free(device->addr);
    368                         free(device->addr_data);
    369                         free(device->broadcast_addr);
    370                         free(device->broadcast_data);
    371                         arp_protos_destroy(&device->protos);
    372                         free(device);
    373                         return rc;
    374                 }
    375                 printf("%s: Device registered (id: %d, type: 0x%x, service: %d,"
    376                     " proto: %d)\n", NAME, device->device_id, device->hardware,
    377                     device->service, protocol);
    378         }
    379         fibril_mutex_unlock(&arp_globals.lock);
    380        
    381         return EOK;
    382 }
    383 
    384 /** Initializes the ARP module.
    385  *
    386  *  @param[in] client_connection The client connection processing function.
    387  *                      The module skeleton propagates its own one.
    388  *  @return             EOK on success.
    389  *  @return             ENOMEM if there is not enough memory left.
    390  */
    391 int arp_initialize(async_client_conn_t client_connection)
    392 {
    393         int rc;
    394 
    395         fibril_mutex_initialize(&arp_globals.lock);
    396         fibril_mutex_lock(&arp_globals.lock);
    397         arp_globals.client_connection = client_connection;
    398         rc = arp_cache_initialize(&arp_globals.cache);
    399         fibril_mutex_unlock(&arp_globals.lock);
    400        
    401         return rc;
    402 }
    403 
    404 /** Updates the device content length according to the new MTU value.
    405  *
    406  * @param[in] device_id The device identifier.
    407  * @param[in] mtu       The new mtu value.
    408  * @return              ENOENT if device is not found.
    409  * @return              EOK on success.
    410  */
    411 static int arp_mtu_changed_message(device_id_t device_id, size_t mtu)
    412 {
    413         arp_device_t *device;
    414 
    415         fibril_mutex_lock(&arp_globals.lock);
    416         device = arp_cache_find(&arp_globals.cache, device_id);
    417         if (!device) {
    418                 fibril_mutex_unlock(&arp_globals.lock);
    419                 return ENOENT;
    420         }
    421         device->packet_dimension.content = mtu;
    422         fibril_mutex_unlock(&arp_globals.lock);
    423         printf("arp - device %d changed mtu to %zu\n\n", device_id, mtu);
    424         return EOK;
    425 }
    426 
    427 /** Processes the received ARP packet.
    428  *
    429  * Updates the source hardware address if the source entry exists or the packet
    430  * is targeted to my protocol address.
    431  * Responses to the ARP request if the packet is the ARP request and is
    432  * targeted to my address.
    433  *
    434  * @param[in] device_id The source device identifier.
    435  * @param[in,out] packet The received packet.
    436  * @return              EOK on success and the packet is no longer needed.
    437  * @return              One on success and the packet has been reused.
    438  * @return              EINVAL if the packet is too small to carry an ARP
    439  *                      packet.
    440  * @return              EINVAL if the received address lengths differs from
    441  *                      the registered values.
    442  * @return              ENOENT if the device is not found in the cache.
    443  * @return              ENOENT if the protocol for the device is not found in
    444  *                      the cache.
    445  * @return              ENOMEM if there is not enough memory left.
    446  */
    447 static int arp_receive_message(device_id_t device_id, packet_t *packet)
    448 {
    449         size_t length;
    450         arp_header_t *header;
    451         arp_device_t *device;
    452         arp_proto_t *proto;
    453         arp_trans_t *trans;
    454         uint8_t *src_hw;
    455         uint8_t *src_proto;
    456         uint8_t *des_hw;
    457         uint8_t *des_proto;
    458         int rc;
    459 
    460         length = packet_get_data_length(packet);
     294       
     295        size_t length = packet_get_data_length(packet);
    461296        if (length <= sizeof(arp_header_t))
    462297                return EINVAL;
    463 
    464         device = arp_cache_find(&arp_globals.cache, device_id);
     298       
     299        arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
    465300        if (!device)
    466301                return ENOENT;
    467 
    468         header = (arp_header_t *) packet_get_data(packet);
     302       
     303        arp_header_t *header = (arp_header_t *) packet_get_data(packet);
    469304        if ((ntohs(header->hardware) != device->hardware) ||
    470305            (length < sizeof(arp_header_t) + header->hardware_length * 2U +
     
    472307                return EINVAL;
    473308        }
    474 
    475         proto = arp_protos_find(&device->protos,
     309       
     310        arp_proto_t *proto = arp_protos_find(&device->protos,
    476311            protocol_unmap(device->service, ntohs(header->protocol)));
    477312        if (!proto)
    478313                return ENOENT;
    479 
    480         src_hw = ((uint8_t *) header) + sizeof(arp_header_t);
    481         src_proto = src_hw + header->hardware_length;
    482         des_hw = src_proto + header->protocol_length;
    483         des_proto = des_hw + header->hardware_length;
    484         trans = arp_addr_find(&proto->addresses, (char *) src_proto,
     314       
     315        uint8_t *src_hw = ((uint8_t *) header) + sizeof(arp_header_t);
     316        uint8_t *src_proto = src_hw + header->hardware_length;
     317        uint8_t *des_hw = src_proto + header->protocol_length;
     318        uint8_t *des_proto = des_hw + header->hardware_length;
     319       
     320        arp_trans_t *trans = arp_addr_find(&proto->addresses, src_proto,
    485321            header->protocol_length);
    486         /* Exists? */
    487         if (trans && trans->hw_addr) {
     322       
     323        if ((trans) && (trans->hw_addr)) {
     324                /* Translation exists */
    488325                if (trans->hw_addr->length != header->hardware_length)
    489326                        return EINVAL;
     327               
    490328                memcpy(trans->hw_addr->value, src_hw, trans->hw_addr->length);
    491329        }
     330       
    492331        /* Is my protocol address? */
    493332        if (proto->addr->length != header->protocol_length)
    494333                return EINVAL;
    495         if (!str_lcmp(proto->addr->value, (char *) des_proto,
    496             proto->addr->length)) {
    497                 /* Not already updated? */
     334       
     335        if (!bcmp(proto->addr->value, des_proto, proto->addr->length)) {
    498336                if (!trans) {
     337                        /* Update the translation */
    499338                        trans = (arp_trans_t *) malloc(sizeof(arp_trans_t));
    500339                        if (!trans)
    501340                                return ENOMEM;
     341                       
    502342                        trans->hw_addr = NULL;
    503343                        fibril_condvar_initialize(&trans->cv);
    504                         rc = arp_addr_add(&proto->addresses, (char *) src_proto,
     344                        rc = arp_addr_add(&proto->addresses, src_proto,
    505345                            header->protocol_length, trans);
    506346                        if (rc != EOK) {
     
    509349                        }
    510350                }
     351               
    511352                if (!trans->hw_addr) {
    512                         trans->hw_addr = measured_string_create_bulk(
    513                             (char *) src_hw, header->hardware_length);
     353                        trans->hw_addr = measured_string_create_bulk(src_hw,
     354                            header->hardware_length);
    514355                        if (!trans->hw_addr)
    515356                                return ENOMEM;
    516 
     357                       
    517358                        /* Notify the fibrils that wait for the translation. */
    518359                        fibril_condvar_broadcast(&trans->cv);
    519360                }
     361               
    520362                if (ntohs(header->operation) == ARPOP_REQUEST) {
    521363                        header->operation = htons(ARPOP_REPLY);
     
    538380                }
    539381        }
    540 
     382       
    541383        return EOK;
    542384}
    543385
    544 
    545 /** Returns the hardware address for the given protocol address.
    546  *
    547  * Sends the ARP request packet if the hardware address is not found in the
    548  * cache.
    549  *
    550  * @param[in] device_id The device identifier.
    551  * @param[in] protocol  The protocol service.
    552  * @param[in] target    The target protocol address.
    553  * @param[out] translation Where the hardware address of the target is stored.
    554  * @return              EOK on success.
    555  * @return              EAGAIN if the caller should try again.
    556  * @return              Other error codes in case of error.
    557  */
    558 static int
    559 arp_translate_message(device_id_t device_id, services_t protocol,
    560     measured_string_t *target, measured_string_t **translation)
    561 {
    562         arp_device_t *device;
    563         arp_proto_t *proto;
    564         arp_trans_t *trans;
    565         size_t length;
     386/** Update the device content length according to the new MTU value.
     387 *
     388 * @param[in] device_id Device identifier.
     389 * @param[in] mtu       New MTU value.
     390 *
     391 * @return ENOENT if device is not found.
     392 * @return EOK on success.
     393 *
     394 */
     395static int arp_mtu_changed_message(device_id_t device_id, size_t mtu)
     396{
     397        fibril_mutex_lock(&arp_globals.lock);
     398       
     399        arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
     400        if (!device) {
     401                fibril_mutex_unlock(&arp_globals.lock);
     402                return ENOENT;
     403        }
     404       
     405        device->packet_dimension.content = mtu;
     406       
     407        fibril_mutex_unlock(&arp_globals.lock);
     408       
     409        printf("%s: Device %d changed MTU to %zu\n", NAME, device_id, mtu);
     410       
     411        return EOK;
     412}
     413
     414/** Process IPC messages from the registered device driver modules
     415 *
     416 * @param[in]     iid   Message identifier.
     417 * @param[in,out] icall Message parameters.
     418 *
     419 */
     420static void arp_receiver(ipc_callid_t iid, ipc_call_t *icall)
     421{
    566422        packet_t *packet;
    567         arp_header_t *header;
    568         bool retry = false;
    569423        int rc;
    570 
    571 restart:
    572         if (!target || !translation)
    573                 return EBADMEM;
    574 
    575         device = arp_cache_find(&arp_globals.cache, device_id);
    576         if (!device)
    577                 return ENOENT;
    578 
    579         proto = arp_protos_find(&device->protos, protocol);
    580         if (!proto || (proto->addr->length != target->length))
    581                 return ENOENT;
    582 
    583         trans = arp_addr_find(&proto->addresses, target->value, target->length);
    584         if (trans) {
    585                 if (trans->hw_addr) {
    586                         *translation = trans->hw_addr;
    587                         return EOK;
    588                 }
    589                 if (retry)
    590                         return EAGAIN;
    591                 rc = fibril_condvar_wait_timeout(&trans->cv, &arp_globals.lock,
    592                     ARP_TRANS_WAIT);
    593                 if (rc == ETIMEOUT)
     424       
     425        while (true) {
     426                switch (IPC_GET_IMETHOD(*icall)) {
     427                case NET_IL_DEVICE_STATE:
     428                        /* Do nothing - keep the cache */
     429                        ipc_answer_0(iid, (sysarg_t) EOK);
     430                        break;
     431               
     432                case NET_IL_RECEIVED:
     433                        rc = packet_translate_remote(arp_globals.net_phone, &packet,
     434                            IPC_GET_PACKET(*icall));
     435                        if (rc == EOK) {
     436                                fibril_mutex_lock(&arp_globals.lock);
     437                                do {
     438                                        packet_t *next = pq_detach(packet);
     439                                        rc = arp_receive_message(IPC_GET_DEVICE(*icall), packet);
     440                                        if (rc != 1) {
     441                                                pq_release_remote(arp_globals.net_phone,
     442                                                    packet_get_id(packet));
     443                                        }
     444                                       
     445                                        packet = next;
     446                                } while (packet);
     447                                fibril_mutex_unlock(&arp_globals.lock);
     448                        }
     449                        ipc_answer_0(iid, (sysarg_t) rc);
     450                        break;
     451               
     452                case NET_IL_MTU_CHANGED:
     453                        rc = arp_mtu_changed_message(IPC_GET_DEVICE(*icall),
     454                            IPC_GET_MTU(*icall));
     455                        ipc_answer_0(iid, (sysarg_t) rc);
     456                        break;
     457               
     458                default:
     459                        ipc_answer_0(iid, (sysarg_t) ENOTSUP);
     460                }
     461               
     462                iid = async_get_call(icall);
     463        }
     464}
     465
     466/** Register the device.
     467 *
     468 * Create new device entry in the cache or update the protocol address if the
     469 * device with the device identifier and the driver service exists.
     470 *
     471 * @param[in] device_id Device identifier.
     472 * @param[in] service   Device driver service.
     473 * @param[in] protocol  Protocol service.
     474 * @param[in] address   Actual device protocol address.
     475 *
     476 * @return EOK on success.
     477 * @return EEXIST if another device with the same device identifier
     478 *         and different driver service exists.
     479 * @return ENOMEM if there is not enough memory left.
     480 * @return Other error codes as defined for the
     481 *         measured_strings_return() function.
     482 *
     483 */
     484static int arp_device_message(device_id_t device_id, services_t service,
     485    services_t protocol, measured_string_t *address)
     486{
     487        int index;
     488        int rc;
     489       
     490        fibril_mutex_lock(&arp_globals.lock);
     491       
     492        /* An existing device? */
     493        arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
     494        if (device) {
     495                if (device->service != service) {
     496                        printf("%s: Device %d already exists\n", NAME,
     497                            device->device_id);
     498                        fibril_mutex_unlock(&arp_globals.lock);
     499                        return EEXIST;
     500                }
     501               
     502                arp_proto_t *proto = arp_protos_find(&device->protos, protocol);
     503                if (proto) {
     504                        free(proto->addr);
     505                        free(proto->addr_data);
     506                        proto->addr = address;
     507                        proto->addr_data = address->value;
     508                } else {
     509                        rc = arp_proto_create(&proto, protocol, address);
     510                        if (rc != EOK) {
     511                                fibril_mutex_unlock(&arp_globals.lock);
     512                                return rc;
     513                        }
     514                       
     515                        index = arp_protos_add(&device->protos, proto->service,
     516                            proto);
     517                        if (index < 0) {
     518                                fibril_mutex_unlock(&arp_globals.lock);
     519                                free(proto);
     520                                return index;
     521                        }
     522                       
     523                        printf("%s: New protocol added (id: %d, proto: %d)\n", NAME,
     524                            device_id, protocol);
     525                }
     526        } else {
     527                hw_type_t hardware = hardware_map(service);
     528                if (!hardware)
    594529                        return ENOENT;
    595                 retry = true;
    596                 goto restart;
    597         }
    598         if (retry)
    599                 return EAGAIN;
    600 
     530               
     531                /* Create new device */
     532                device = (arp_device_t *) malloc(sizeof(arp_device_t));
     533                if (!device) {
     534                        fibril_mutex_unlock(&arp_globals.lock);
     535                        return ENOMEM;
     536                }
     537               
     538                device->hardware = hardware;
     539                device->device_id = device_id;
     540                rc = arp_protos_initialize(&device->protos);
     541                if (rc != EOK) {
     542                        fibril_mutex_unlock(&arp_globals.lock);
     543                        free(device);
     544                        return rc;
     545                }
     546               
     547                arp_proto_t *proto;
     548                rc = arp_proto_create(&proto, protocol, address);
     549                if (rc != EOK) {
     550                        fibril_mutex_unlock(&arp_globals.lock);
     551                        free(device);
     552                        return rc;
     553                }
     554               
     555                index = arp_protos_add(&device->protos, proto->service, proto);
     556                if (index < 0) {
     557                        fibril_mutex_unlock(&arp_globals.lock);
     558                        arp_protos_destroy(&device->protos);
     559                        free(device);
     560                        return index;
     561                }
     562               
     563                device->service = service;
     564               
     565                /* Bind */
     566                device->phone = nil_bind_service(device->service,
     567                    (sysarg_t) device->device_id, SERVICE_ARP,
     568                    arp_receiver);
     569                if (device->phone < 0) {
     570                        fibril_mutex_unlock(&arp_globals.lock);
     571                        arp_protos_destroy(&device->protos);
     572                        free(device);
     573                        return EREFUSED;
     574                }
     575               
     576                /* Get packet dimensions */
     577                rc = nil_packet_size_req(device->phone, device_id,
     578                    &device->packet_dimension);
     579                if (rc != EOK) {
     580                        fibril_mutex_unlock(&arp_globals.lock);
     581                        arp_protos_destroy(&device->protos);
     582                        free(device);
     583                        return rc;
     584                }
     585               
     586                /* Get hardware address */
     587                rc = nil_get_addr_req(device->phone, device_id, &device->addr,
     588                    &device->addr_data);
     589                if (rc != EOK) {
     590                        fibril_mutex_unlock(&arp_globals.lock);
     591                        arp_protos_destroy(&device->protos);
     592                        free(device);
     593                        return rc;
     594                }
     595               
     596                /* Get broadcast address */
     597                rc = nil_get_broadcast_addr_req(device->phone, device_id,
     598                    &device->broadcast_addr, &device->broadcast_data);
     599                if (rc != EOK) {
     600                        fibril_mutex_unlock(&arp_globals.lock);
     601                        free(device->addr);
     602                        free(device->addr_data);
     603                        arp_protos_destroy(&device->protos);
     604                        free(device);
     605                        return rc;
     606                }
     607               
     608                rc = arp_cache_add(&arp_globals.cache, device->device_id,
     609                    device);
     610                if (rc != EOK) {
     611                        fibril_mutex_unlock(&arp_globals.lock);
     612                        free(device->addr);
     613                        free(device->addr_data);
     614                        free(device->broadcast_addr);
     615                        free(device->broadcast_data);
     616                        arp_protos_destroy(&device->protos);
     617                        free(device);
     618                        return rc;
     619                }
     620                printf("%s: Device registered (id: %d, type: 0x%x, service: %d,"
     621                    " proto: %d)\n", NAME, device->device_id, device->hardware,
     622                    device->service, protocol);
     623        }
     624       
     625        fibril_mutex_unlock(&arp_globals.lock);
     626        return EOK;
     627}
     628
     629int il_initialize(int net_phone)
     630{
     631        fibril_mutex_initialize(&arp_globals.lock);
     632       
     633        fibril_mutex_lock(&arp_globals.lock);
     634        arp_globals.net_phone = net_phone;
     635        int rc = arp_cache_initialize(&arp_globals.cache);
     636        fibril_mutex_unlock(&arp_globals.lock);
     637       
     638        return rc;
     639}
     640
     641static int arp_send_request(device_id_t device_id, services_t protocol,
     642    measured_string_t *target, arp_device_t *device, arp_proto_t *proto)
     643{
    601644        /* ARP packet content size = header + (address + translation) * 2 */
    602         length = 8 + 2 * (proto->addr->length + device->addr->length);
     645        size_t length = 8 + 2 * (proto->addr->length + device->addr->length);
    603646        if (length > device->packet_dimension.content)
    604647                return ELIMIT;
    605 
    606         packet = packet_get_4_remote(arp_globals.net_phone,
     648       
     649        packet_t *packet = packet_get_4_remote(arp_globals.net_phone,
    607650            device->packet_dimension.addr_len, device->packet_dimension.prefix,
    608651            length, device->packet_dimension.suffix);
    609652        if (!packet)
    610653                return ENOMEM;
    611 
    612         header = (arp_header_t *) packet_suffix(packet, length);
     654       
     655        arp_header_t *header = (arp_header_t *) packet_suffix(packet, length);
    613656        if (!header) {
    614657                pq_release_remote(arp_globals.net_phone, packet_get_id(packet));
    615658                return ENOMEM;
    616659        }
    617 
     660       
    618661        header->hardware = htons(device->hardware);
    619662        header->hardware_length = (uint8_t) device->addr->length;
     
    621664        header->protocol_length = (uint8_t) proto->addr->length;
    622665        header->operation = htons(ARPOP_REQUEST);
     666       
    623667        length = sizeof(arp_header_t);
     668       
    624669        memcpy(((uint8_t *) header) + length, device->addr->value,
    625670            device->addr->length);
     
    631676        length += device->addr->length;
    632677        memcpy(((uint8_t *) header) + length, target->value, target->length);
    633 
    634         rc = packet_set_addr(packet, (uint8_t *) device->addr->value,
     678       
     679        int rc = packet_set_addr(packet, (uint8_t *) device->addr->value,
    635680            (uint8_t *) device->broadcast_addr->value, device->addr->length);
    636681        if (rc != EOK) {
     
    638683                return rc;
    639684        }
    640 
     685       
    641686        nil_send_msg(device->phone, device_id, packet, SERVICE_ARP);
    642 
     687        return EOK;
     688}
     689
     690/** Return the hardware address for the given protocol address.
     691 *
     692 * Send the ARP request packet if the hardware address is not found in the
     693 * cache.
     694 *
     695 * @param[in]  device_id   Device identifier.
     696 * @param[in]  protocol    Protocol service.
     697 * @param[in]  target      Target protocol address.
     698 * @param[out] translation Where the hardware address of the target is stored.
     699 *
     700 * @return EOK on success.
     701 * @return EAGAIN if the caller should try again.
     702 * @return Other error codes in case of error.
     703 *
     704 */
     705static int arp_translate_message(device_id_t device_id, services_t protocol,
     706    measured_string_t *target, measured_string_t **translation)
     707{
     708        bool retry = false;
     709        int rc;
     710       
     711restart:
     712        if ((!target) || (!translation))
     713                return EBADMEM;
     714       
     715        arp_device_t *device = arp_cache_find(&arp_globals.cache, device_id);
     716        if (!device)
     717                return ENOENT;
     718       
     719        arp_proto_t *proto = arp_protos_find(&device->protos, protocol);
     720        if ((!proto) || (proto->addr->length != target->length))
     721                return ENOENT;
     722       
     723        arp_trans_t *trans = arp_addr_find(&proto->addresses, target->value,
     724            target->length);
     725        if (trans) {
     726                if (trans->hw_addr) {
     727                        *translation = trans->hw_addr;
     728                        return EOK;
     729                }
     730               
     731                if (retry) {
     732                        /* Remove the translation from the map */
     733                        arp_clear_trans(trans);
     734                        arp_addr_exclude(&proto->addresses, target->value,
     735                            target->length);
     736                        return EAGAIN;
     737                }
     738               
     739                rc = fibril_condvar_wait_timeout(&trans->cv, &arp_globals.lock,
     740                    ARP_TRANS_WAIT);
     741                if (rc == ETIMEOUT)
     742                        return ENOENT;
     743               
     744                retry = true;
     745                goto restart;
     746        }
     747       
     748        if (retry)
     749                return EAGAIN;
     750       
    643751        trans = (arp_trans_t *) malloc(sizeof(arp_trans_t));
    644752        if (!trans)
    645753                return ENOMEM;
     754       
    646755        trans->hw_addr = NULL;
    647756        fibril_condvar_initialize(&trans->cv);
     757       
    648758        rc = arp_addr_add(&proto->addresses, target->value, target->length,
    649759            trans);
     
    653763        }
    654764       
     765        rc = arp_send_request(device_id, protocol, target, device, proto);
     766        if (rc != EOK)
     767                return rc;
     768       
    655769        rc = fibril_condvar_wait_timeout(&trans->cv, &arp_globals.lock,
    656770            ARP_TRANS_WAIT);
    657771        if (rc == ETIMEOUT)
    658772                return ENOENT;
     773       
    659774        retry = true;
    660775        goto restart;
    661776}
    662777
    663 
    664 /** Processes the ARP message.
    665  *
    666  * @param[in] callid    The message identifier.
    667  * @param[in] call      The message parameters.
    668  * @param[out] answer   The message answer parameters.
    669  * @param[out] answer_count The last parameter for the actual answer in the
    670  *                      answer parameter.
    671  * @return              EOK on success.
    672  * @return              ENOTSUP if the message is not known.
     778/** Process the ARP message.
     779 *
     780 * @param[in]  callid Message identifier.
     781 * @param[in]  call   Message parameters.
     782 * @param[out] answer Answer.
     783 * @param[out] count  Number of arguments of the answer.
     784 *
     785 * @return EOK on success.
     786 * @return ENOTSUP if the message is not known.
    673787 *
    674788 * @see arp_interface.h
    675789 * @see IS_NET_ARP_MESSAGE()
    676  */
    677 int
    678 arp_message_standalone(ipc_callid_t callid, ipc_call_t *call,
    679     ipc_call_t *answer, int *answer_count)
     790 *
     791 */
     792int il_module_message(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer,
     793    size_t *count)
    680794{
    681795        measured_string_t *address;
    682796        measured_string_t *translation;
    683         char *data;
    684         packet_t *packet;
    685         packet_t *next;
     797        uint8_t *data;
    686798        int rc;
    687799       
    688         *answer_count = 0;
     800        *count = 0;
    689801        switch (IPC_GET_IMETHOD(*call)) {
    690802        case IPC_M_PHONE_HUNGUP:
     
    696808                        return rc;
    697809               
    698                 rc = arp_device_message(IPC_GET_DEVICE(call),
    699                     IPC_GET_SERVICE(call), ARP_GET_NETIF(call), address);
     810                rc = arp_device_message(IPC_GET_DEVICE(*call),
     811                    IPC_GET_SERVICE(*call), ARP_GET_NETIF(*call), address);
    700812                if (rc != EOK) {
    701813                        free(address);
    702814                        free(data);
    703815                }
     816               
    704817                return rc;
    705818       
     
    710823               
    711824                fibril_mutex_lock(&arp_globals.lock);
    712                 rc = arp_translate_message(IPC_GET_DEVICE(call),
    713                     IPC_GET_SERVICE(call), address, &translation);
     825                rc = arp_translate_message(IPC_GET_DEVICE(*call),
     826                    IPC_GET_SERVICE(*call), address, &translation);
    714827                free(address);
    715828                free(data);
     829               
    716830                if (rc != EOK) {
    717831                        fibril_mutex_unlock(&arp_globals.lock);
    718832                        return rc;
    719833                }
     834               
    720835                if (!translation) {
    721836                        fibril_mutex_unlock(&arp_globals.lock);
    722837                        return ENOENT;
    723838                }
     839               
    724840                rc = measured_strings_reply(translation, 1);
    725841                fibril_mutex_unlock(&arp_globals.lock);
    726842                return rc;
    727 
     843       
    728844        case NET_ARP_CLEAR_DEVICE:
    729                 return arp_clear_device_req(0, IPC_GET_DEVICE(call));
    730 
     845                return arp_clear_device_req(0, IPC_GET_DEVICE(*call));
     846       
    731847        case NET_ARP_CLEAR_ADDRESS:
    732848                rc = measured_strings_receive(&address, &data, 1);
     
    734850                        return rc;
    735851               
    736                 arp_clear_address_req(0, IPC_GET_DEVICE(call),
    737                     IPC_GET_SERVICE(call), address);
     852                arp_clear_address_req(0, IPC_GET_DEVICE(*call),
     853                    IPC_GET_SERVICE(*call), address);
    738854                free(address);
    739855                free(data);
     
    742858        case NET_ARP_CLEAN_CACHE:
    743859                return arp_clean_cache_req(0);
    744        
    745         case NET_IL_DEVICE_STATE:
    746                 /* Do nothing - keep the cache */
    747                 return EOK;
    748        
    749         case NET_IL_RECEIVED:
    750                 rc = packet_translate_remote(arp_globals.net_phone, &packet,
    751                     IPC_GET_PACKET(call));
    752                 if (rc != EOK)
    753                         return rc;
    754                
    755                 fibril_mutex_lock(&arp_globals.lock);
    756                 do {
    757                         next = pq_detach(packet);
    758                         rc = arp_receive_message(IPC_GET_DEVICE(call), packet);
    759                         if (rc != 1) {
    760                                 pq_release_remote(arp_globals.net_phone,
    761                                     packet_get_id(packet));
    762                         }
    763                         packet = next;
    764                 } while (packet);
    765                 fibril_mutex_unlock(&arp_globals.lock);
    766                
    767                 return EOK;
    768        
    769         case NET_IL_MTU_CHANGED:
    770                 return arp_mtu_changed_message(IPC_GET_DEVICE(call),
    771                     IPC_GET_MTU(call));
    772860        }
    773861       
     
    775863}
    776864
    777 /** Default thread for new connections.
    778  *
    779  * @param[in] iid       The initial message identifier.
    780  * @param[in] icall     The initial message call structure.
    781  */
    782 static void il_client_connection(ipc_callid_t iid, ipc_call_t *icall)
    783 {
    784         /*
    785          * Accept the connection
    786          *  - Answer the first IPC_M_CONNECT_ME_TO call.
    787          */
    788         ipc_answer_0(iid, EOK);
    789        
    790         while (true) {
    791                 ipc_call_t answer;
    792                 int answer_count;
    793                
    794                 /* Clear the answer structure */
    795                 refresh_answer(&answer, &answer_count);
    796                
    797                 /* Fetch the next message */
    798                 ipc_call_t call;
    799                 ipc_callid_t callid = async_get_call(&call);
    800                
    801                 /* Process the message */
    802                 int res = il_module_message_standalone(callid, &call, &answer,
    803                     &answer_count);
    804                
    805                 /*
    806                  * End if told to either by the message or the processing
    807                  * result.
    808                  */
    809                 if ((IPC_GET_IMETHOD(call) == IPC_M_PHONE_HUNGUP) ||
    810                     (res == EHANGUP))
    811                         return;
    812                
    813                 /* Answer the message */
    814                 answer_call(callid, res, &answer, answer_count);
    815         }
    816 }
    817 
    818 /** Starts the module.
    819  *
    820  * @return              EOK on success.
    821  * @return              Other error codes as defined for each specific module
    822  *                      start function.
    823  */
    824865int main(int argc, char *argv[])
    825866{
    826         int rc;
    827        
    828867        /* Start the module */
    829         rc = il_module_start_standalone(il_client_connection);
    830         return rc;
     868        return il_module_start(SERVICE_ARP);
    831869}
    832870
    833871/** @}
    834872 */
    835 
  • uspace/srv/net/il/arp/arp.h

    reaef141 r80cd7cd  
    9696        measured_string_t *addr;
    9797        /** Actual device hardware address data. */
    98         char *addr_data;
     98        uint8_t *addr_data;
    9999        /** Broadcast device hardware address. */
    100100        measured_string_t *broadcast_addr;
    101101        /** Broadcast device hardware address data. */
    102         char *broadcast_data;
     102        uint8_t *broadcast_data;
    103103        /** Device identifier. */
    104104        device_id_t device_id;
     
    125125        arp_cache_t cache;
    126126       
    127         /**
    128          * The client connection processing function.
    129          * The module skeleton propagates its own one.
    130          */
    131         async_client_conn_t client_connection;
    132        
    133127        /** Networking module phone. */
    134128        int net_phone;
     
    142136        measured_string_t *addr;
    143137        /** Actual device protocol address data. */
    144         char *addr_data;
     138        uint8_t *addr_data;
    145139        /** Address map. */
    146140        arp_addr_t addresses;
     
    154148         * Hardware address for the translation. NULL denotes an incomplete
    155149         * record with possible waiters.
    156          */ 
     150         */
    157151        measured_string_t *hw_addr;
    158152        /** Condition variable used for waiting for completion of the record. */
  • uspace/srv/net/il/ip/Makefile

    reaef141 r80cd7cd  
    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

    reaef141 r80cd7cd  
    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>
     
    7068#include <icmp_client.h>
    7169#include <icmp_interface.h>
    72 #include <il_interface.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                            {
     
    431423        ip_netif->phone = nil_bind_service(ip_netif->service,
    432424            (sysarg_t) ip_netif->device_id, SERVICE_IP,
    433             ip_globals.client_connection);
     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;
     435                        address.value = (uint8_t *) &route->address.s_addr;
    444436                        address.length = sizeof(in_addr_t);
    445437                       
     
    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;
     
    752813 *                      function.
    753814 */
    754 static int
    755 ip_fragment_packet_data(packet_t *packet, packet_t *new_packet,
     815static int ip_fragment_packet_data(packet_t *packet, packet_t *new_packet,
    756816    ip_header_t *header, ip_header_t *new_header, size_t length,
    757817    const struct sockaddr *src, const struct sockaddr *dest, socklen_t addrlen)
     
    787847
    788848        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;
    789870}
    790871
     
    9911072 *                      function.
    9921073 */
    993 static int
    994 ip_send_route(packet_t *packet, ip_netif_t *netif, ip_route_t *route,
    995     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)
    9961076{
    9971077        measured_string_t destination;
    9981078        measured_string_t *translation;
    999         char *data;
     1079        uint8_t *data;
    10001080        int phone;
    10011081        int rc;
     
    10041084        if (netif->arp && (route->address.s_addr != dest.s_addr)) {
    10051085                destination.value = route->gateway.s_addr ?
    1006                     (char *) &route->gateway.s_addr : (char *) &dest.s_addr;
     1086                    (uint8_t *) &route->gateway.s_addr : (uint8_t *) &dest.s_addr;
    10071087                destination.length = sizeof(dest.s_addr);
    10081088
     
    10561136}
    10571137
    1058 /** Searches the network interfaces if there is a suitable route.
    1059  *
    1060  * @param[in] netif     The network interface to be searched for routes. May be
    1061  *                      NULL.
    1062  * @param[in] destination The destination address.
    1063  * @return              The found route.
    1064  * @return              NULL if no route was found.
    1065  */
    1066 static ip_route_t *
    1067 ip_netif_find_route(ip_netif_t *netif, in_addr_t destination)
    1068 {
    1069         int index;
    1070         ip_route_t *route;
    1071 
    1072         if (!netif)
    1073                 return NULL;
    1074 
    1075         // start with the first one - the direct route
    1076         for (index = 0; index < ip_routes_count(&netif->routes); index++) {
    1077                 route = ip_routes_get_index(&netif->routes, index);
    1078                 if (route &&
    1079                     ((route->address.s_addr & route->netmask.s_addr) ==
    1080                     (destination.s_addr & route->netmask.s_addr))) {
    1081                         return route;
    1082                 }
    1083         }
    1084 
    1085         return NULL;
    1086 }
    1087 
    1088 /** Searches all network interfaces if there is a suitable route.
    1089  *
    1090  * @param[in] destination The destination address.
    1091  * @return              The found route.
    1092  * @return              NULL if no route was found.
    1093  */
    1094 static ip_route_t *ip_find_route(in_addr_t destination) {
    1095         int index;
    1096         ip_route_t *route;
    1097         ip_netif_t *netif;
    1098 
    1099         // start with the last netif - the newest one
    1100         index = ip_netifs_count(&ip_globals.netifs) - 1;
    1101         while (index >= 0) {
    1102                 netif = ip_netifs_get_index(&ip_globals.netifs, index);
    1103                 if (netif && (netif->state == NETIF_ACTIVE)) {
    1104                         route = ip_netif_find_route(netif, destination);
    1105                         if (route)
    1106                                 return route;
    1107                 }
    1108                 index--;
    1109         }
    1110 
    1111         return &ip_globals.gateway;
    1112 }
    1113 
    1114 /** Returns the network interface's IP address.
    1115  *
    1116  * @param[in] netif     The network interface.
    1117  * @return              The IP address.
    1118  * @return              NULL if no IP address was found.
    1119  */
    1120 static in_addr_t *ip_netif_address(ip_netif_t *netif)
    1121 {
    1122         ip_route_t *route;
    1123 
    1124         route = ip_routes_get_index(&netif->routes, 0);
    1125         return route ? &route->address : NULL;
    1126 }
    1127 
    1128 /** Registers the transport layer protocol.
    1129  *
    1130  * The traffic of this protocol will be supplied using either the receive
    1131  * function or IPC message.
    1132  *
    1133  * @param[in] protocol  The transport layer module protocol.
    1134  * @param[in] service   The transport layer module service.
    1135  * @param[in] phone     The transport layer module phone.
    1136  * @param[in] received_msg The receiving function.
    1137  * @return              EOK on success.
    1138  * @return              EINVAL if the protocol parameter and/or the service
    1139  *                      parameter is zero.
    1140  * @return              EINVAL if the phone parameter is not a positive number
    1141  *                      and the tl_receive_msg is NULL.
    1142  * @return              ENOMEM if there is not enough memory left.
    1143  */
    1144 static int
    1145 ip_register(int protocol, services_t service, int phone,
    1146     tl_received_msg_t received_msg)
    1147 {
    1148         ip_proto_t *proto;
    1149         int index;
    1150 
    1151         if (!protocol || !service || ((phone < 0) && !received_msg))
    1152                 return EINVAL;
    1153 
    1154         proto = (ip_proto_t *) malloc(sizeof(ip_protos_t));
    1155         if (!proto)
    1156                 return ENOMEM;
    1157 
    1158         proto->protocol = protocol;
    1159         proto->service = service;
    1160         proto->phone = phone;
    1161         proto->received_msg = received_msg;
    1162 
    1163         fibril_rwlock_write_lock(&ip_globals.protos_lock);
    1164         index = ip_protos_add(&ip_globals.protos, proto->protocol, proto);
    1165         if (index < 0) {
    1166                 fibril_rwlock_write_unlock(&ip_globals.protos_lock);
    1167                 free(proto);
    1168                 return index;
    1169         }
    1170         fibril_rwlock_write_unlock(&ip_globals.protos_lock);
    1171 
    1172         printf("%s: Protocol registered (protocol: %d, phone: %d)\n",
    1173             NAME, proto->protocol, proto->phone);
    1174 
    1175         return EOK;
    1176 }
    1177 
    1178 static int
    1179 ip_device_req_local(int il_phone, device_id_t device_id, services_t netif)
    1180 {
    1181         ip_netif_t *ip_netif;
    1182         ip_route_t *route;
    1183         int index;
    1184         int rc;
    1185 
    1186         ip_netif = (ip_netif_t *) malloc(sizeof(ip_netif_t));
    1187         if (!ip_netif)
    1188                 return ENOMEM;
    1189 
    1190         rc = ip_routes_initialize(&ip_netif->routes);
    1191         if (rc != EOK) {
    1192                 free(ip_netif);
    1193                 return rc;
    1194         }
    1195 
    1196         ip_netif->device_id = device_id;
    1197         ip_netif->service = netif;
    1198         ip_netif->state = NETIF_STOPPED;
    1199 
    1200         fibril_rwlock_write_lock(&ip_globals.netifs_lock);
    1201 
    1202         rc = ip_netif_initialize(ip_netif);
    1203         if (rc != EOK) {
    1204                 fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
    1205                 ip_routes_destroy(&ip_netif->routes);
    1206                 free(ip_netif);
    1207                 return rc;
    1208         }
    1209         if (ip_netif->arp)
    1210                 ip_netif->arp->usage++;
    1211 
    1212         // print the settings
    1213         printf("%s: Device registered (id: %d, phone: %d, ipv: %d, conf: %s)\n",
    1214             NAME, ip_netif->device_id, ip_netif->phone, ip_netif->ipv,
    1215             ip_netif->dhcp ? "dhcp" : "static");
    1216        
    1217         // TODO ipv6 addresses
    1218        
    1219         char address[INET_ADDRSTRLEN];
    1220         char netmask[INET_ADDRSTRLEN];
    1221         char gateway[INET_ADDRSTRLEN];
    1222        
    1223         for (index = 0; index < ip_routes_count(&ip_netif->routes); index++) {
    1224                 route = ip_routes_get_index(&ip_netif->routes, index);
    1225                 if (route) {
    1226                         inet_ntop(AF_INET, (uint8_t *) &route->address.s_addr,
    1227                             address, INET_ADDRSTRLEN);
    1228                         inet_ntop(AF_INET, (uint8_t *) &route->netmask.s_addr,
    1229                             netmask, INET_ADDRSTRLEN);
    1230                         inet_ntop(AF_INET, (uint8_t *) &route->gateway.s_addr,
    1231                             gateway, INET_ADDRSTRLEN);
    1232                         printf("%s: Route %d (address: %s, netmask: %s, "
    1233                             "gateway: %s)\n", NAME, index, address, netmask,
    1234                             gateway);
    1235                 }
    1236         }
    1237        
    1238         inet_ntop(AF_INET, (uint8_t *) &ip_netif->broadcast.s_addr, address,
    1239             INET_ADDRSTRLEN);
    1240         fibril_rwlock_write_unlock(&ip_globals.netifs_lock);
    1241 
    1242         printf("%s: Broadcast (%s)\n", NAME, address);
    1243 
    1244         return EOK;
    1245 }
    1246 
    1247 static int
    1248 ip_send_msg_local(int il_phone, device_id_t device_id, packet_t *packet,
    1249     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)
    12501140{
    12511141        int addrlen;
     
    12881178        if (device_id > 0) {
    12891179                netif = ip_netifs_find(&ip_globals.netifs, device_id);
    1290                 route = ip_netif_find_route(netif, * dest);
     1180                route = ip_netif_find_route(netif, *dest);
    12911181                if (netif && !route && (ip_globals.gateway.netif == netif))
    12921182                        route = &ip_globals.gateway;
     
    13181208                }
    13191209        }
    1320 
     1210       
    13211211        // if the local host is the destination
    13221212        if ((route->address.s_addr == dest->s_addr) &&
     
    13511241}
    13521242
     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
    13531495/** Returns the device packet dimensions for sending.
    13541496 *
     
    13621504 * @return              EOK on success.
    13631505 */
    1364 static int
    1365 ip_packet_size_message(device_id_t device_id, size_t *addr_len, size_t *prefix,
    1366     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)
    13671508{
    13681509        ip_netif_t *netif;
     
    14141555}
    14151556
    1416 /** Returns the packet destination address from the IP header.
    1417  *
    1418  * @param[in] header    The packet IP header to be read.
    1419  * @return              The packet destination address.
    1420  */
    1421 static in_addr_t ip_get_destination(ip_header_t *header)
    1422 {
    1423         in_addr_t destination;
    1424 
    1425         // TODO search set ipopt route?
    1426         destination.s_addr = header->destination_address;
    1427         return destination;
    1428 }
    1429 
    1430 /** Delivers the packet to the local host.
    1431  *
    1432  * The packet is either passed to another module or released on error.
    1433  * The ICMP_PROT_UNREACH error notification may be sent if the protocol is not
    1434  * found.
    1435  *
    1436  * @param[in] device_id The source device identifier.
    1437  * @param[in] packet    The packet to be delivered.
    1438  * @param[in] header    The first packet IP header. May be NULL.
    1439  * @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.
    14401561 * @return              EOK on success.
    1441  * @return              ENOTSUP if the packet is a fragment.
    1442  * @return              EAFNOSUPPORT if the address family is not supported.
    1443  * @return              ENOENT if the target protocol is not found.
    1444  * @return              Other error codes as defined for the packet_set_addr()
    1445  *                      function.
    1446  * @return              Other error codes as defined for the packet_trim()
    1447  *                      function.
    1448  * @return              Other error codes as defined for the protocol specific
    1449  *                      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.
    14501644 */
    14511645static int
    1452 ip_deliver_local(device_id_t device_id, packet_t *packet, ip_header_t *header,
    1453     services_t error)
     1646ip_register(int protocol, services_t service, int phone,
     1647    tl_received_msg_t received_msg)
    14541648{
    14551649        ip_proto_t *proto;
    1456         int phone;
    1457         services_t service;
    1458         tl_received_msg_t received_msg;
    1459         struct sockaddr *src;
    1460         struct sockaddr *dest;
    1461         struct sockaddr_in src_in;
    1462         struct sockaddr_in dest_in;
    1463         socklen_t addrlen;
    1464         int rc;
    1465 
    1466         if ((header->flags & IPFLAG_MORE_FRAGMENTS) ||
    1467             IP_FRAGMENT_OFFSET(header)) {
    1468                 // TODO fragmented
    1469                 return ENOTSUP;
    1470         }
    1471        
    1472         switch (header->version) {
    1473         case IPVERSION:
    1474                 addrlen = sizeof(src_in);
    1475                 bzero(&src_in, addrlen);
    1476                 src_in.sin_family = AF_INET;
    1477                 memcpy(&dest_in, &src_in, addrlen);
    1478                 memcpy(&src_in.sin_addr.s_addr, &header->source_address,
    1479                     sizeof(header->source_address));
    1480                 memcpy(&dest_in.sin_addr.s_addr, &header->destination_address,
    1481                     sizeof(header->destination_address));
    1482                 src = (struct sockaddr *) &src_in;
    1483                 dest = (struct sockaddr *) &dest_in;
    1484                 break;
    1485 
    1486         default:
    1487                 return ip_release_and_return(packet, EAFNOSUPPORT);
    1488         }
    1489 
    1490         rc = packet_set_addr(packet, (uint8_t *) src, (uint8_t *) dest,
    1491             addrlen);
    1492         if (rc != EOK)
    1493                 return ip_release_and_return(packet, rc);
    1494 
    1495         // trim padding if present
    1496         if (!error &&
    1497             (IP_TOTAL_LENGTH(header) < packet_get_data_length(packet))) {
    1498                 rc = packet_trim(packet, 0,
    1499                     packet_get_data_length(packet) - IP_TOTAL_LENGTH(header));
    1500                 if (rc != EOK)
    1501                         return ip_release_and_return(packet, rc);
    1502         }
    1503 
    1504         fibril_rwlock_read_lock(&ip_globals.protos_lock);
    1505 
    1506         proto = ip_protos_find(&ip_globals.protos, header->protocol);
    1507         if (!proto) {
    1508                 fibril_rwlock_read_unlock(&ip_globals.protos_lock);
    1509                 phone = ip_prepare_icmp_and_get_phone(error, packet, header);
    1510                 if (phone >= 0) {
    1511                         // unreachable ICMP
    1512                         icmp_destination_unreachable_msg(phone,
    1513                             ICMP_PROT_UNREACH, 0, packet);
    1514                 }
    1515                 return ENOENT;
    1516         }
    1517 
    1518         if (proto->received_msg) {
    1519                 service = proto->service;
    1520                 received_msg = proto->received_msg;
    1521                 fibril_rwlock_read_unlock(&ip_globals.protos_lock);
    1522                 rc = received_msg(device_id, packet, service, error);
    1523         } else {
    1524                 rc = tl_received_msg(proto->phone, device_id, packet,
    1525                     proto->service, error);
    1526                 fibril_rwlock_read_unlock(&ip_globals.protos_lock);
    1527         }
    1528 
    1529         return rc;
    1530 }
    1531 
    1532 /** Processes the received packet.
    1533  *
    1534  * The packet is either passed to another module or released on error.
    1535  *
    1536  * The ICMP_PARAM_POINTER error notification may be sent if the checksum is
    1537  * invalid.
    1538  * The ICMP_EXC_TTL error notification may be sent if the TTL is less than two.
    1539  * The ICMP_HOST_UNREACH error notification may be sent if no route was found.
    1540  * The ICMP_HOST_UNREACH error notification may be sent if the packet is for
    1541  * another host and the routing is disabled.
    1542  *
    1543  * @param[in] device_id The source device identifier.
    1544  * @param[in] packet    The received packet to be processed.
    1545  * @return              EOK on success.
    1546  * @return              EINVAL if the TTL is less than two.
    1547  * @return              EINVAL if the checksum is invalid.
    1548  * @return              EAFNOSUPPORT if the address family is not supported.
    1549  * @return              ENOENT if no route was found.
    1550  * @return              ENOENT if the packet is for another host and the routing
    1551  *                      is disabled.
    1552  */
    1553 static int
    1554 ip_process_packet(device_id_t device_id, packet_t *packet)
    1555 {
    1556         ip_header_t *header;
    1557         in_addr_t dest;
    1558         ip_route_t *route;
    1559         int phone;
    1560         struct sockaddr *addr;
    1561         struct sockaddr_in addr_in;
    1562         socklen_t addrlen;
    1563         int rc;
    1564 
    1565         header = (ip_header_t *) packet_get_data(packet);
    1566         if (!header)
    1567                 return ip_release_and_return(packet, ENOMEM);
    1568 
    1569         // checksum
    1570         if ((header->header_checksum) &&
    1571             (IP_HEADER_CHECKSUM(header) != IP_CHECKSUM_ZERO)) {
    1572                 phone = ip_prepare_icmp_and_get_phone(0, packet, header);
    1573                 if (phone >= 0) {
    1574                         // checksum error ICMP
    1575                         icmp_parameter_problem_msg(phone, ICMP_PARAM_POINTER,
    1576                             ((size_t) ((void *) &header->header_checksum)) -
    1577                             ((size_t) ((void *) header)), packet);
    1578                 }
     1650        int index;
     1651
     1652        if (!protocol || !service || ((phone < 0) && !received_msg))
    15791653                return EINVAL;
    1580         }
    1581 
    1582         if (header->ttl <= 1) {
    1583                 phone = ip_prepare_icmp_and_get_phone(0, packet, header);
    1584                 if (phone >= 0) {
    1585                         // ttl exceeded ICMP
    1586                         icmp_time_exceeded_msg(phone, ICMP_EXC_TTL, packet);
    1587                 }
    1588                 return EINVAL;
    1589         }
    1590 
    1591         // process ipopt and get destination
    1592         dest = ip_get_destination(header);
    1593 
    1594         // set the addrination address
    1595         switch (header->version) {
    1596         case IPVERSION:
    1597                 addrlen = sizeof(addr_in);
    1598                 bzero(&addr_in, addrlen);
    1599                 addr_in.sin_family = AF_INET;
    1600                 memcpy(&addr_in.sin_addr.s_addr, &dest, sizeof(dest));
    1601                 addr = (struct sockaddr *) &addr_in;
    1602                 break;
    1603 
    1604         default:
    1605                 return ip_release_and_return(packet, EAFNOSUPPORT);
    1606         }
    1607 
    1608         rc = packet_set_addr(packet, NULL, (uint8_t *) &addr, addrlen);
    1609         if (rc != EOK)
    1610                 return rc;
    1611 
    1612         route = ip_find_route(dest);
    1613         if (!route) {
    1614                 phone = ip_prepare_icmp_and_get_phone(0, packet, header);
    1615                 if (phone >= 0) {
    1616                         // unreachable ICMP
    1617                         icmp_destination_unreachable_msg(phone,
    1618                             ICMP_HOST_UNREACH, 0, packet);
    1619                 }
    1620                 return ENOENT;
    1621         }
    1622 
    1623         if (route->address.s_addr == dest.s_addr) {
    1624                 // local delivery
    1625                 return ip_deliver_local(device_id, packet, header, 0);
    1626         }
    1627 
    1628         if (route->netif->routing) {
    1629                 header->ttl--;
    1630                 return ip_send_route(packet, route->netif, route, NULL, dest,
    1631                     0);
    1632         }
    1633 
    1634         phone = ip_prepare_icmp_and_get_phone(0, packet, header);
    1635         if (phone >= 0) {
    1636                 // unreachable ICMP if no routing
    1637                 icmp_destination_unreachable_msg(phone, ICMP_HOST_UNREACH, 0,
    1638                     packet);
    1639         }
    1640        
    1641         return ENOENT;
    1642 }
     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
    16431679
    16441680static int
     
    17561792                    (header->destination_address & route->netmask.s_addr))) {
    17571793                        // clear the ARP mapping if any
    1758                         address.value = (char *) &header->destination_address;
     1794                        address.value = (uint8_t *) &header->destination_address;
    17591795                        address.length = sizeof(header->destination_address);
    17601796                        arp_clear_address_req(netif->arp->phone,
     
    18411877}
    18421878
    1843 /** Processes the received IP packet or the packet queue one by one.
    1844  *
    1845  * The packet is either passed to another module or released on error.
    1846  *
    1847  * @param[in] device_id The source device identifier.
    1848  * @param[in,out] packet The received packet.
    1849  * @return              EOK on success and the packet is no longer needed.
    1850  * @return              EINVAL if the packet is too small to carry the IP
    1851  *                      packet.
    1852  * @return              EINVAL if the received address lengths differs from the
    1853  *                      registered values.
    1854  * @return              ENOENT if the device is not found in the cache.
    1855  * @return              ENOENT if the protocol for the device is not found in
    1856  *                      the cache.
    1857  * @return              ENOMEM if there is not enough memory left.
    1858  */
    1859 static int ip_receive_message(device_id_t device_id, packet_t *packet)
    1860 {
    1861         packet_t *next;
    1862 
    1863         do {
    1864                 next = pq_detach(packet);
    1865                 ip_process_packet(device_id, packet);
    1866                 packet = next;
    1867         } while (packet);
    1868 
    1869         return EOK;
    1870 }
    1871 
    18721879/** Processes the IP message.
    18731880 *
     
    18811888 *
    18821889 * @see ip_interface.h
    1883  * @see il_interface.h
     1890 * @see il_remote.h
    18841891 * @see IS_NET_IP_MESSAGE()
    18851892 */
    1886 int
    1887 ip_message_standalone(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer,
    1888     int *answer_count)
     1893int il_module_message(ipc_callid_t callid, ipc_call_t *call, ipc_call_t *answer,
     1894    size_t *answer_count)
    18891895{
    18901896        packet_t *packet;
    18911897        struct sockaddr *addr;
     1898        void *header;
     1899        size_t headerlen;
    18921900        size_t addrlen;
    18931901        size_t prefix;
    18941902        size_t suffix;
    18951903        size_t content;
    1896         void *header;
    1897         size_t headerlen;
    18981904        device_id_t device_id;
    18991905        int rc;
     
    19051911       
    19061912        case IPC_M_CONNECT_TO_ME:
    1907                 return ip_register(IL_GET_PROTO(call), IL_GET_SERVICE(call),
    1908                     IPC_GET_PHONE(call), NULL);
    1909        
    1910         case NET_IL_DEVICE:
    1911                 return ip_device_req_local(0, IPC_GET_DEVICE(call),
    1912                     IPC_GET_SERVICE(call));
    1913        
    1914         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:
    19151921                rc = packet_translate_remote(ip_globals.net_phone, &packet,
    1916                     IPC_GET_PACKET(call));
     1922                    IPC_GET_PACKET(*call));
    19171923                if (rc != EOK)
    19181924                        return rc;
    1919                 return ip_send_msg_local(0, IPC_GET_DEVICE(call), packet, 0,
    1920                     IPC_GET_ERROR(call));
    1921        
    1922         case NET_IL_DEVICE_STATE:
    1923                 return ip_device_state_message(IPC_GET_DEVICE(call),
    1924                     IPC_GET_STATE(call));
    1925        
    1926         case NET_IL_RECEIVED:
    1927                 rc = packet_translate_remote(ip_globals.net_phone, &packet,
    1928                     IPC_GET_PACKET(call));
    1929                 if (rc != EOK)
    1930                         return rc;
    1931                 return ip_receive_message(IPC_GET_DEVICE(call), packet);
    1932        
    1933         case NET_IP_RECEIVED_ERROR:
    1934                 rc = packet_translate_remote(ip_globals.net_phone, &packet,
    1935                     IPC_GET_PACKET(call));
    1936                 if (rc != EOK)
    1937                         return rc;
    1938                 return ip_received_error_msg_local(0, IPC_GET_DEVICE(call),
    1939                     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));
    19401927       
    19411928        case NET_IP_ADD_ROUTE:
    1942                 return ip_add_route_req_local(0, IPC_GET_DEVICE(call),
    1943                     IP_GET_ADDRESS(call), IP_GET_NETMASK(call),
    1944                     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));
    19451932
    19461933        case NET_IP_SET_GATEWAY:
    1947                 return ip_set_gateway_req_local(0, IPC_GET_DEVICE(call),
    1948                     IP_GET_GATEWAY(call));
     1934                return ip_set_gateway_req_local(0, IPC_GET_DEVICE(*call),
     1935                    IP_GET_GATEWAY(*call));
    19491936
    19501937        case NET_IP_GET_ROUTE:
     
    19541941                        return rc;
    19551942               
    1956                 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,
    19571944                    (socklen_t) addrlen, &device_id, &header, &headerlen);
    19581945                if (rc != EOK)
    19591946                        return rc;
    19601947               
    1961                 IPC_SET_DEVICE(answer, device_id);
    1962                 IP_SET_HEADERLEN(answer, headerlen);
     1948                IPC_SET_DEVICE(*answer, device_id);
     1949                IP_SET_HEADERLEN(*answer, headerlen);
    19631950               
    19641951                *answer_count = 2;
     
    19711958                return rc;
    19721959       
    1973         case NET_IL_PACKET_SPACE:
    1974                 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,
    19751962                    &prefix, &content, &suffix);
    19761963                if (rc != EOK)
    19771964                        return rc;
    19781965               
    1979                 IPC_SET_ADDR(answer, addrlen);
    1980                 IPC_SET_PREFIX(answer, prefix);
    1981                 IPC_SET_CONTENT(answer, content);
    1982                 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);
    19831970                *answer_count = 4;
    19841971                return EOK;
    19851972       
    1986         case NET_IL_MTU_CHANGED:
    1987                 return ip_mtu_changed_message(IPC_GET_DEVICE(call),
    1988                     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));
    19891981        }
    19901982       
     
    19921984}
    19931985
    1994 /** Default thread for new connections.
    1995  *
    1996  * @param[in] iid       The initial message identifier.
    1997  * @param[in] icall     The initial message call structure.
    1998  */
    1999 static void il_client_connection(ipc_callid_t iid, ipc_call_t *icall)
    2000 {
    2001         /*
    2002          * Accept the connection
    2003          *  - Answer the first IPC_M_CONNECT_ME_TO call.
    2004          */
    2005         ipc_answer_0(iid, EOK);
    2006        
    2007         while (true) {
    2008                 ipc_call_t answer;
    2009                 int answer_count;
    2010                
    2011                 /* Clear the answer structure */
    2012                 refresh_answer(&answer, &answer_count);
    2013                
    2014                 /* Fetch the next message */
    2015                 ipc_call_t call;
    2016                 ipc_callid_t callid = async_get_call(&call);
    2017                
    2018                 /* Process the message */
    2019                 int res = il_module_message_standalone(callid, &call, &answer,
    2020                     &answer_count);
    2021                
    2022                 /*
    2023                  * End if told to either by the message or the processing
    2024                  * result.
    2025                  */
    2026                 if ((IPC_GET_IMETHOD(call) == IPC_M_PHONE_HUNGUP) ||
    2027                     (res == EHANGUP)) {
    2028                         return;
    2029                 }
    2030                
    2031                 /* Answer the message */
    2032                 answer_call(callid, res, &answer, answer_count);
    2033         }
    2034 }
    2035 
    2036 /** Starts the module.
    2037  *
    2038  * @return EOK on success.
    2039  * @return Other error codes as defined for each specific module start function.
    2040  */
    20411986int main(int argc, char *argv[])
    20421987{
    2043         int rc;
    2044        
    20451988        /* Start the module */
    2046         rc = il_module_start_standalone(il_client_connection);
    2047         return rc;
     1989        return il_module_start(SERVICE_IP);
    20481990}
    20491991
  • uspace/srv/net/il/ip/ip.h

    reaef141 r80cd7cd  
    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;
Note: See TracChangeset for help on using the changeset viewer.