Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/net/tl/icmp/icmp.c

    rffa2c8ef r61bfc370  
    3333/** @file
    3434 * ICMP module implementation.
    35  */
     35 * @see icmp.h
     36 */
     37
     38#include "icmp.h"
     39#include "icmp_module.h"
    3640
    3741#include <async.h>
     
    4145#include <stdint.h>
    4246#include <str.h>
     47#include <ipc/ipc.h>
    4348#include <ipc/services.h>
    4449#include <ipc/net.h>
     
    4954#include <byteorder.h>
    5055#include <errno.h>
    51 #include <adt/hash_table.h>
    5256
    5357#include <net/socket_codes.h>
     
    6367#include <net_checksum.h>
    6468#include <icmp_client.h>
    65 #include <icmp_remote.h>
    66 #include <il_remote.h>
     69#include <icmp_interface.h>
     70#include <il_interface.h>
    6771#include <ip_client.h>
    6872#include <ip_interface.h>
    6973#include <net_interface.h>
    70 #include <tl_remote.h>
    71 #include <tl_skel.h>
     74#include <tl_interface.h>
     75#include <tl_local.h>
    7276#include <icmp_header.h>
    7377
    74 /** ICMP module name */
    75 #define NAME  "icmp"
    76 
    77 /** Number of replies hash table keys */
    78 #define REPLY_KEYS  2
    79 
    80 /** Number of replies hash table buckets */
    81 #define REPLY_BUCKETS  1024
    82 
    83 /**
    84  * Original datagram length in bytes transfered to the error
    85  * notification message.
    86  */
    87 #define ICMP_KEEP_LENGTH  8
    88 
    89 /** Compute the ICMP datagram checksum.
    90  *
    91  * @param[in,out] header ICMP datagram header.
    92  * @param[in]     length Total datagram length.
    93  *
    94  * @return Computed checksum.
    95  *
     78/** ICMP module name. */
     79#define NAME    "ICMP protocol"
     80
     81/** Default ICMP error reporting. */
     82#define NET_DEFAULT_ICMP_ERROR_REPORTING        true
     83
     84/** Default ICMP echo replying. */
     85#define NET_DEFAULT_ICMP_ECHO_REPLYING          true
     86
     87/** Original datagram length in bytes transfered to the error notification
     88 * message.
     89 */
     90#define ICMP_KEEP_LENGTH        8
     91
     92/** Free identifier numbers pool start. */
     93#define ICMP_FREE_IDS_START     1
     94
     95/** Free identifier numbers pool end. */
     96#define ICMP_FREE_IDS_END       UINT16_MAX
     97
     98/** Computes the ICMP datagram checksum.
     99 *
     100 * @param[in,out] header The ICMP datagram header.
     101 * @param[in] length    The total datagram length.
     102 * @return              The computed checksum.
    96103 */
    97104#define ICMP_CHECKSUM(header, length) \
     
    99106
    100107/** An echo request datagrams pattern. */
    101 #define ICMP_ECHO_TEXT  "ICMP hello from HelenOS."
    102 
    103 /** ICMP reply data. */
    104 typedef struct {
    105         /** Hash table link */
    106         link_t link;
    107        
    108         /** Reply identification and sequence */
    109         icmp_param_t id;
    110         icmp_param_t sequence;
    111        
    112         /** Reply signaling */
    113         fibril_condvar_t condvar;
    114        
    115         /** Reply result */
    116         int result;
    117 } icmp_reply_t;
    118 
    119 /** Global data */
    120 static int phone_net = -1;
    121 static int phone_ip = -1;
    122 static bool error_reporting = true;
    123 static bool echo_replying = true;
    124 static packet_dimension_t icmp_dimension;
    125 
    126 /** ICMP client identification counter */
    127 static atomic_t icmp_client;
    128 
    129 /** ICMP identifier and sequence number (client-specific) */
    130 static fibril_local icmp_param_t icmp_id;
    131 static fibril_local icmp_param_t icmp_seq;
    132 
    133 /** Reply hash table */
    134 static fibril_mutex_t reply_lock;
    135 static hash_table_t replies;
    136 
    137 static hash_index_t replies_hash(unsigned long key[])
    138 {
    139         /*
    140          * ICMP identifier and sequence numbers
    141          * are 16-bit values.
    142          */
    143         hash_index_t index = ((key[0] & 0xffff) << 16) | (key[1] & 0xffff);
    144         return (index % REPLY_BUCKETS);
    145 }
    146 
    147 static int replies_compare(unsigned long key[], hash_count_t keys, link_t *item)
    148 {
    149         icmp_reply_t *reply =
    150             hash_table_get_instance(item, icmp_reply_t, link);
    151        
    152         if (keys == 1)
    153                 return (reply->id == key[0]);
    154         else
    155                 return ((reply->id == key[0]) && (reply->sequence == key[1]));
    156 }
    157 
    158 static void replies_remove_callback(link_t *item)
    159 {
    160 }
    161 
    162 static hash_table_operations_t reply_ops = {
    163         .hash = replies_hash,
    164         .compare = replies_compare,
    165         .remove_callback = replies_remove_callback
    166 };
    167 
    168 /** Release the packet and return the result.
    169  *
    170  * @param[in] packet Packet queue to be released.
    171  *
    172  */
    173 static void icmp_release(packet_t *packet)
    174 {
    175         pq_release_remote(phone_net, packet_get_id(packet));
    176 }
    177 
    178 /** Send the ICMP message.
    179  *
    180  * Set the message type and code and compute the checksum.
     108#define ICMP_ECHO_TEXT          "Hello from HelenOS."
     109
     110/** Computes an ICMP reply data key.
     111 *
     112 * @param[in] id        The message identifier.
     113 * @param[in] sequence  The message sequence number.
     114 * @return              The computed ICMP reply data key.
     115 */
     116#define ICMP_GET_REPLY_KEY(id, sequence) \
     117        (((id) << 16) | (sequence & 0xFFFF))
     118
     119
     120/** ICMP global data. */
     121icmp_globals_t  icmp_globals;
     122
     123INT_MAP_IMPLEMENT(icmp_replies, icmp_reply_t);
     124INT_MAP_IMPLEMENT(icmp_echo_data, icmp_echo_t);
     125
     126/** Releases the packet and returns the result.
     127 *
     128 * @param[in] packet    The packet queue to be released.
     129 * @param[in] result    The result to be returned.
     130 * @return              The result parameter.
     131 */
     132static int icmp_release_and_return(packet_t *packet, int result)
     133{
     134        pq_release_remote(icmp_globals.net_phone, packet_get_id(packet));
     135        return result;
     136}
     137
     138/** Sends the ICMP message.
     139 *
     140 * Sets the message type and code and computes the checksum.
    181141 * Error messages are sent only if allowed in the configuration.
    182  * Release the packet on errors.
    183  *
    184  * @param[in] type          Message type.
    185  * @param[in] code          Message code.
    186  * @param[in] packet        Message packet to be sent.
    187  * @param[in] header        ICMP header.
    188  * @param[in] error         Error service to be announced. Should be
    189  *                          SERVICE_ICMP or zero.
    190  * @param[in] ttl           Time to live.
    191  * @param[in] tos           Type of service.
    192  * @param[in] dont_fragment Disable fragmentation.
    193  *
    194  * @return EOK on success.
    195  * @return EPERM if the error message is not allowed.
    196  *
    197  */
    198 static int icmp_send_packet(icmp_type_t type, icmp_code_t code,
    199     packet_t *packet, icmp_header_t *header, services_t error, ip_ttl_t ttl,
    200     ip_tos_t tos, bool dont_fragment)
    201 {
     142 * Releases the packet on errors.
     143 *
     144 * @param[in] type      The message type.
     145 * @param[in] code      The message code.
     146 * @param[in] packet    The message packet to be sent.
     147 * @param[in] header    The ICMP header.
     148 * @param[in] error     The error service to be announced. Should be
     149 *                      SERVICE_ICMP or zero.
     150 * @param[in] ttl       The time to live.
     151 * @param[in] tos       The type of service.
     152 * @param[in] dont_fragment The value indicating whether the datagram must not
     153 *                      be fragmented. Is used as a MTU discovery.
     154 * @return              EOK on success.
     155 * @return              EPERM if the error message is not allowed.
     156 */
     157static int icmp_send_packet(icmp_type_t type, icmp_code_t code, packet_t *packet,
     158    icmp_header_t *header, services_t error, ip_ttl_t ttl, ip_tos_t tos,
     159    int dont_fragment)
     160{
     161        int rc;
     162
    202163        /* Do not send an error if disabled */
    203         if ((error) && (!error_reporting)) {
    204                 icmp_release(packet);
    205                 return EPERM;
    206         }
    207        
     164        if (error && !icmp_globals.error_reporting)
     165                return icmp_release_and_return(packet, EPERM);
     166
    208167        header->type = type;
    209168        header->code = code;
    210        
    211         /*
    212          * The checksum needs to be calculated
    213          * with a virtual checksum field set to
    214          * zero.
    215          */
    216169        header->checksum = 0;
    217170        header->checksum = ICMP_CHECKSUM(header,
    218171            packet_get_data_length(packet));
    219172       
    220         int rc = ip_client_prepare_packet(packet, IPPROTO_ICMP, ttl, tos,
     173        rc = ip_client_prepare_packet(packet, IPPROTO_ICMP, ttl, tos,
    221174            dont_fragment, 0);
    222         if (rc != EOK) {
    223                 icmp_release(packet);
    224                 return rc;
    225         }
    226        
    227         return ip_send_msg(phone_ip, -1, packet, SERVICE_ICMP, error);
    228 }
    229 
    230 /** Prepare the ICMP error packet.
    231  *
    232  * Truncate the original packet if longer than ICMP_KEEP_LENGTH bytes.
    233  * Prefix and return the ICMP header.
    234  *
    235  * @param[in,out] packet Original packet.
    236  *
     175        if (rc != EOK)
     176                return icmp_release_and_return(packet, rc);
     177
     178        return ip_send_msg(icmp_globals.ip_phone, -1, packet, SERVICE_ICMP,
     179            error);
     180}
     181
     182/** Prepares the ICMP error packet.
     183 *
     184 * Truncates the original packet if longer than ICMP_KEEP_LENGTH bytes.
     185 * Prefixes and returns the ICMP header.
     186 *
     187 * @param[in,out] packet The original packet.
    237188 * @return The prefixed ICMP header.
    238189 * @return NULL on errors.
    239  *
    240190 */
    241191static icmp_header_t *icmp_prepare_packet(packet_t *packet)
    242192{
    243         size_t total_length = packet_get_data_length(packet);
     193        icmp_header_t *header;
     194        size_t header_length;
     195        size_t total_length;
     196
     197        total_length = packet_get_data_length(packet);
    244198        if (total_length <= 0)
    245199                return NULL;
    246        
    247         size_t header_length = ip_client_header_length(packet);
     200
     201        header_length = ip_client_header_length(packet);
    248202        if (header_length <= 0)
    249203                return NULL;
    250        
     204
    251205        /* Truncate if longer than 64 bits (without the IP header) */
    252206        if ((total_length > header_length + ICMP_KEEP_LENGTH) &&
    253207            (packet_trim(packet, 0,
    254             total_length - header_length - ICMP_KEEP_LENGTH) != EOK))
     208            total_length - header_length - ICMP_KEEP_LENGTH) != EOK)) {
    255209                return NULL;
    256        
    257         icmp_header_t *header = PACKET_PREFIX(packet, icmp_header_t);
     210        }
     211
     212        header = PACKET_PREFIX(packet, icmp_header_t);
    258213        if (!header)
    259214                return NULL;
    260        
     215
    261216        bzero(header, sizeof(*header));
    262217        return header;
    263218}
    264219
    265 /** Request an echo message.
    266  *
    267  * Send a packet with specified parameters to the target host
    268  * and wait for the reply upto the given timeout.
    269  * Block the caller until the reply or the timeout occurs.
    270  *
    271  * @param[in] id            Message identifier.
    272  * @param[in] sequence      Message sequence parameter.
    273  * @param[in] size          Message data length in bytes.
    274  * @param[in] timeout       Timeout in miliseconds.
    275  * @param[in] ttl           Time to live.
    276  * @param[in] tos           Type of service.
    277  * @param[in] dont_fragment Disable fragmentation.
    278  * @param[in] addr          Target host address.
    279  * @param[in] addrlen       Torget host address length.
    280  *
    281  * @return ICMP_ECHO on success.
    282  * @return ETIMEOUT if the reply has not arrived before the
    283  *         timeout.
    284  * @return ICMP type of the received error notification.
    285  * @return EINVAL if the addrlen parameter is less or equal to
    286  *         zero.
    287  * @return ENOMEM if there is not enough memory left.
    288  *
     220/** Requests an echo message.
     221 *
     222 * Sends a packet with specified parameters to the target host and waits for
     223 * the reply upto the given timeout.
     224 * Blocks the caller until the reply or the timeout occurs.
     225 *
     226 * @param[in] id        The message identifier.
     227 * @param[in] sequence  The message sequence parameter.
     228 * @param[in] size      The message data length in bytes.
     229 * @param[in] timeout   The timeout in miliseconds.
     230 * @param[in] ttl       The time to live.
     231 * @param[in] tos       The type of service.
     232 * @param[in] dont_fragment The value indicating whether the datagram must not
     233 *                      be fragmented. Is used as a MTU discovery.
     234 * @param[in] addr      The target host address.
     235 * @param[in] addrlen   The torget host address length.
     236 * @return              ICMP_ECHO on success.
     237 * @return              ETIMEOUT if the reply has not arrived before the
     238 *                      timeout.
     239 * @return              ICMP type of the received error notification.
     240 * @return              EINVAL if the addrlen parameter is less or equal to
     241 *                      zero.
     242 * @return              ENOMEM if there is not enough memory left.
     243 * @return              EPARTY if there was an internal error.
    289244 */
    290245static int icmp_echo(icmp_param_t id, icmp_param_t sequence, size_t size,
    291     mseconds_t timeout, ip_ttl_t ttl, ip_tos_t tos, bool dont_fragment,
    292     const struct sockaddr *addr, socklen_t addrlen)
    293 {
     246    mseconds_t timeout, ip_ttl_t ttl, ip_tos_t tos, int dont_fragment,
     247    const struct sockaddr * addr, socklen_t addrlen)
     248{
     249        icmp_header_t *header;
     250        packet_t *packet;
     251        size_t length;
     252        uint8_t *data;
     253        icmp_reply_t *reply;
     254        int reply_key;
     255        int index;
     256        int rc;
     257
    294258        if (addrlen <= 0)
    295259                return EINVAL;
    296        
    297         size_t length = (size_t) addrlen;
    298        
    299         packet_t *packet = packet_get_4_remote(phone_net, size,
    300             icmp_dimension.addr_len, ICMP_HEADER_SIZE + icmp_dimension.prefix,
    301             icmp_dimension.suffix);
     260
     261        length = (size_t) addrlen;
     262        /* TODO do not ask all the time */
     263        rc = ip_packet_size_req(icmp_globals.ip_phone, -1,
     264            &icmp_globals.packet_dimension);
     265        if (rc != EOK)
     266                return rc;
     267
     268        packet = packet_get_4_remote(icmp_globals.net_phone, size,
     269            icmp_globals.packet_dimension.addr_len,
     270            ICMP_HEADER_SIZE + icmp_globals.packet_dimension.prefix,
     271            icmp_globals.packet_dimension.suffix);
    302272        if (!packet)
    303273                return ENOMEM;
    304        
     274
    305275        /* Prepare the requesting packet, set the destination address. */
    306         int rc = packet_set_addr(packet, NULL, (const uint8_t *) addr, length);
    307         if (rc != EOK) {
    308                 icmp_release(packet);
    309                 return rc;
    310         }
    311        
     276        rc = packet_set_addr(packet, NULL, (const uint8_t *) addr, length);
     277        if (rc != EOK)
     278                return icmp_release_and_return(packet, rc);
     279
    312280        /* Allocate space in the packet */
    313         uint8_t *data = (uint8_t *) packet_suffix(packet, size);
    314         if (!data) {
    315                 icmp_release(packet);
    316                 return ENOMEM;
    317         }
    318        
     281        data = (uint8_t *) packet_suffix(packet, size);
     282        if (!data)
     283                return icmp_release_and_return(packet, ENOMEM);
     284
    319285        /* Fill the data */
    320286        length = 0;
     
    324290        }
    325291        memcpy(data + length, ICMP_ECHO_TEXT, size - length);
    326        
     292
    327293        /* Prefix the header */
    328         icmp_header_t *header = PACKET_PREFIX(packet, icmp_header_t);
    329         if (!header) {
    330                 icmp_release(packet);
    331                 return ENOMEM;
    332         }
    333        
    334         bzero(header, sizeof(icmp_header_t));
     294        header = PACKET_PREFIX(packet, icmp_header_t);
     295        if (!header)
     296                return icmp_release_and_return(packet, ENOMEM);
     297
     298        bzero(header, sizeof(*header));
    335299        header->un.echo.identifier = id;
    336300        header->un.echo.sequence_number = sequence;
    337        
     301
    338302        /* Prepare the reply structure */
    339         icmp_reply_t *reply = malloc(sizeof(icmp_reply_t));
    340         if (!reply) {
    341                 icmp_release(packet);
    342                 return ENOMEM;
    343         }
    344        
    345         reply->id = id;
    346         reply->sequence = sequence;
     303        reply = malloc(sizeof(*reply));
     304        if (!reply)
     305                return icmp_release_and_return(packet, ENOMEM);
     306
     307        fibril_mutex_initialize(&reply->mutex);
     308        fibril_mutex_lock(&reply->mutex);
    347309        fibril_condvar_initialize(&reply->condvar);
    348        
    349         /* Add the reply to the replies hash table */
    350         fibril_mutex_lock(&reply_lock);
    351        
    352         unsigned long key[REPLY_KEYS] = {id, sequence};
    353         hash_table_insert(&replies, key, &reply->link);
    354        
     310        reply_key = ICMP_GET_REPLY_KEY(header->un.echo.identifier,
     311            header->un.echo.sequence_number);
     312        index = icmp_replies_add(&icmp_globals.replies, reply_key, reply);
     313        if (index < 0) {
     314                free(reply);
     315                return icmp_release_and_return(packet, index);
     316        }
     317
     318        /* Unlock the globals so that we can wait for the reply */
     319        fibril_rwlock_write_unlock(&icmp_globals.lock);
     320
    355321        /* Send the request */
    356322        icmp_send_packet(ICMP_ECHO, 0, packet, header, 0, ttl, tos,
    357323            dont_fragment);
    358        
     324
    359325        /* Wait for the reply. Timeout in microseconds. */
    360         rc = fibril_condvar_wait_timeout(&reply->condvar, &reply_lock,
     326        rc = fibril_condvar_wait_timeout(&reply->condvar, &reply->mutex,
    361327            timeout * 1000);
    362328        if (rc == EOK)
    363329                rc = reply->result;
    364        
    365         /* Remove the reply from the replies hash table */
    366         hash_table_remove(&replies, key, REPLY_KEYS);
    367        
    368         fibril_mutex_unlock(&reply_lock);
    369        
    370         free(reply);
    371        
     330
     331        /* Drop the reply mutex before locking the globals again */
     332        fibril_mutex_unlock(&reply->mutex);
     333        fibril_rwlock_write_lock(&icmp_globals.lock);
     334
     335        /* Destroy the reply structure */
     336        icmp_replies_exclude_index(&icmp_globals.replies, index);
     337
    372338        return rc;
    373339}
    374340
    375 static int icmp_destination_unreachable(icmp_code_t code, icmp_param_t mtu,
    376     packet_t *packet)
    377 {
    378         icmp_header_t *header = icmp_prepare_packet(packet);
    379         if (!header) {
    380                 icmp_release(packet);
    381                 return ENOMEM;
    382         }
    383        
     341static int icmp_destination_unreachable_msg_local(int icmp_phone,
     342    icmp_code_t code, icmp_param_t mtu, packet_t *packet)
     343{
     344        icmp_header_t *header;
     345
     346        header = icmp_prepare_packet(packet);
     347        if (!header)
     348                return icmp_release_and_return(packet, ENOMEM);
     349
    384350        if (mtu)
    385351                header->un.frag.mtu = mtu;
    386        
     352
    387353        return icmp_send_packet(ICMP_DEST_UNREACH, code, packet, header,
    388             SERVICE_ICMP, 0, 0, false);
    389 }
    390 
    391 static int icmp_source_quench(packet_t *packet)
    392 {
    393         icmp_header_t *header = icmp_prepare_packet(packet);
    394         if (!header) {
    395                 icmp_release(packet);
    396                 return ENOMEM;
    397         }
    398        
     354            SERVICE_ICMP, 0, 0, 0);
     355}
     356
     357static int icmp_source_quench_msg_local(int icmp_phone, packet_t *packet)
     358{
     359        icmp_header_t *header;
     360
     361        header = icmp_prepare_packet(packet);
     362        if (!header)
     363                return icmp_release_and_return(packet, ENOMEM);
     364
    399365        return icmp_send_packet(ICMP_SOURCE_QUENCH, 0, packet, header,
    400             SERVICE_ICMP, 0, 0, false);
    401 }
    402 
    403 static int icmp_time_exceeded(icmp_code_t code, packet_t *packet)
    404 {
    405         icmp_header_t *header = icmp_prepare_packet(packet);
    406         if (!header) {
    407                 icmp_release(packet);
    408                 return ENOMEM;
    409         }
    410        
     366            SERVICE_ICMP, 0, 0, 0);
     367}
     368
     369static int icmp_time_exceeded_msg_local(int icmp_phone, icmp_code_t code,
     370    packet_t *packet)
     371{
     372        icmp_header_t *header;
     373
     374        header = icmp_prepare_packet(packet);
     375        if (!header)
     376                return icmp_release_and_return(packet, ENOMEM);
     377
    411378        return icmp_send_packet(ICMP_TIME_EXCEEDED, code, packet, header,
    412             SERVICE_ICMP, 0, 0, false);
    413 }
    414 
    415 static int icmp_parameter_problem(icmp_code_t code, icmp_param_t pointer,
    416     packet_t *packet)
    417 {
    418         icmp_header_t *header = icmp_prepare_packet(packet);
    419         if (!header) {
    420                 icmp_release(packet);
    421                 return ENOMEM;
    422         }
    423        
     379            SERVICE_ICMP, 0, 0, 0);
     380}
     381
     382static int icmp_parameter_problem_msg_local(int icmp_phone, icmp_code_t code,
     383    icmp_param_t pointer, packet_t *packet)
     384{
     385        icmp_header_t *header;
     386
     387        header = icmp_prepare_packet(packet);
     388        if (!header)
     389                return icmp_release_and_return(packet, ENOMEM);
     390
    424391        header->un.param.pointer = pointer;
    425392        return icmp_send_packet(ICMP_PARAMETERPROB, code, packet, header,
    426             SERVICE_ICMP, 0, 0, false);
    427 }
    428 
    429 /** Try to set the pending reply result as the received message type.
     393            SERVICE_ICMP, 0, 0, 0);
     394}
     395
     396/** Initializes the ICMP module.
     397 *
     398 * @param[in] client_connection The client connection processing function. The
     399 *                      module skeleton propagates its own one.
     400 * @return              EOK on success.
     401 * @return              ENOMEM if there is not enough memory left.
     402 */
     403int icmp_initialize(async_client_conn_t client_connection)
     404{
     405        measured_string_t names[] = {
     406                {
     407                        (uint8_t *) "ICMP_ERROR_REPORTING",
     408                        20
     409                },
     410                {
     411                        (uint8_t *) "ICMP_ECHO_REPLYING",
     412                        18
     413                }
     414        };
     415        measured_string_t *configuration;
     416        size_t count = sizeof(names) / sizeof(measured_string_t);
     417        uint8_t *data;
     418        int rc;
     419
     420        fibril_rwlock_initialize(&icmp_globals.lock);
     421        fibril_rwlock_write_lock(&icmp_globals.lock);
     422        icmp_replies_initialize(&icmp_globals.replies);
     423        icmp_echo_data_initialize(&icmp_globals.echo_data);
     424       
     425        icmp_globals.ip_phone = ip_bind_service(SERVICE_IP, IPPROTO_ICMP,
     426            SERVICE_ICMP, client_connection);
     427        if (icmp_globals.ip_phone < 0) {
     428                fibril_rwlock_write_unlock(&icmp_globals.lock);
     429                return icmp_globals.ip_phone;
     430        }
     431       
     432        rc = ip_packet_size_req(icmp_globals.ip_phone, -1,
     433            &icmp_globals.packet_dimension);
     434        if (rc != EOK) {
     435                fibril_rwlock_write_unlock(&icmp_globals.lock);
     436                return rc;
     437        }
     438
     439        icmp_globals.packet_dimension.prefix += ICMP_HEADER_SIZE;
     440        icmp_globals.packet_dimension.content -= ICMP_HEADER_SIZE;
     441
     442        icmp_globals.error_reporting = NET_DEFAULT_ICMP_ERROR_REPORTING;
     443        icmp_globals.echo_replying = NET_DEFAULT_ICMP_ECHO_REPLYING;
     444
     445        /* Get configuration */
     446        configuration = &names[0];
     447        rc = net_get_conf_req(icmp_globals.net_phone, &configuration, count,
     448            &data);
     449        if (rc != EOK) {
     450                fibril_rwlock_write_unlock(&icmp_globals.lock);
     451                return rc;
     452        }
     453       
     454        if (configuration) {
     455                if (configuration[0].value) {
     456                        icmp_globals.error_reporting =
     457                            (configuration[0].value[0] == 'y');
     458                }
     459                if (configuration[1].value) {
     460                        icmp_globals.echo_replying =
     461                            (configuration[1].value[0] == 'y');
     462                }
     463                net_free_settings(configuration, data);
     464        }
     465
     466        fibril_rwlock_write_unlock(&icmp_globals.lock);
     467        return EOK;
     468}
     469
     470/** Tries to set the pending reply result as the received message type.
    430471 *
    431472 * If the reply data is not present, the reply timed out and the other fibril
    432  * is already awake. The packet is released.
    433  *
    434  * @param[in] packet The received reply message.
    435  * @param[in] header The ICMP message header.
    436  * @param[in] type   The received reply message type.
    437  * @param[in] code   The received reply message code.
    438  *
    439  */
    440 static void icmp_process_echo_reply(packet_t *packet, icmp_header_t *header,
     473 * is already awake.
     474 * Releases the packet.
     475 *
     476 * @param[in] packet    The received reply message.
     477 * @param[in] header    The ICMP message header.
     478 * @param[in] type      The received reply message type.
     479 * @param[in] code      The received reply message code.
     480 */
     481static void  icmp_process_echo_reply(packet_t *packet, icmp_header_t *header,
    441482    icmp_type_t type, icmp_code_t code)
    442483{
    443         unsigned long key[REPLY_KEYS] =
    444             {header->un.echo.identifier, header->un.echo.sequence_number};
    445        
    446         /* The packet is no longer needed */
    447         icmp_release(packet);
    448        
     484        int reply_key;
     485        icmp_reply_t *reply;
     486
     487        /* Compute the reply key */
     488        reply_key = ICMP_GET_REPLY_KEY(header->un.echo.identifier,
     489            header->un.echo.sequence_number);
     490        pq_release_remote(icmp_globals.net_phone, packet_get_id(packet));
     491
    449492        /* Find the pending reply */
    450         fibril_mutex_lock(&reply_lock);
    451        
    452         link_t *link = hash_table_find(&replies, key);
    453         if (link != NULL) {
    454                 icmp_reply_t *reply =
    455                    hash_table_get_instance(link, icmp_reply_t, link);
    456                
     493        fibril_rwlock_write_lock(&icmp_globals.lock);
     494        reply = icmp_replies_find(&icmp_globals.replies, reply_key);
     495        if (reply) {
    457496                reply->result = type;
    458497                fibril_condvar_signal(&reply->condvar);
    459498        }
    460        
    461         fibril_mutex_unlock(&reply_lock);
    462 }
    463 
    464 /** Process the received ICMP packet.
    465  *
    466  * Notify the destination socket application.
    467  *
    468  * @param[in,out] packet Received packet.
    469  * @param[in]     error  Packet error reporting service to prefix
    470  *                       the received packet.
    471  *
    472  * @return EOK on success.
    473  * @return EINVAL if the packet is not valid.
    474  * @return EINVAL if the stored packet address is not the an_addr_t.
    475  * @return EINVAL if the packet does not contain any data.
    476  * @return NO_DATA if the packet content is shorter than the user
    477  *         datagram header.
    478  * @return ENOMEM if there is not enough memory left.
    479  * @return EADDRNOTAVAIL if the destination socket does not exist.
    480  * @return Other error codes as defined for the
    481  *         ip_client_process_packet() function.
    482  *
     499        fibril_rwlock_write_unlock(&icmp_globals.lock);
     500}
     501
     502/** Processes the received ICMP packet.
     503 *
     504 * Notifies the destination socket application.
     505 *
     506 * @param[in,out] packet The received packet.
     507 * @param[in] error     The packet error reporting service. Prefixes the
     508 *                      received packet.
     509 * @return              EOK on success.
     510 * @return              EINVAL if the packet is not valid.
     511 * @return              EINVAL if the stored packet address is not the an_addr_t.
     512 * @return              EINVAL if the packet does not contain any data.
     513 * @return              NO_DATA if the packet content is shorter than the user
     514 *                      datagram header.
     515 * @return              ENOMEM if there is not enough memory left.
     516 * @return              EADDRNOTAVAIL if the destination socket does not exist.
     517 * @return              Other error codes as defined for the
     518 *                      ip_client_process_packet() function.
    483519 */
    484520static int icmp_process_packet(packet_t *packet, services_t error)
    485521{
     522        size_t length;
     523        uint8_t *src;
     524        int addrlen;
     525        int result;
     526        void *data;
     527        icmp_header_t *header;
    486528        icmp_type_t type;
    487529        icmp_code_t code;
     
    493535        case SERVICE_ICMP:
    494536                /* Process error */
    495                 rc = icmp_client_process_packet(packet, &type, &code, NULL, NULL);
    496                 if (rc < 0)
    497                         return rc;
    498                
     537                result = icmp_client_process_packet(packet, &type, &code, NULL,
     538                    NULL);
     539                if (result < 0)
     540                        return result;
     541                length = (size_t) result;
    499542                /* Remove the error header */
    500                 rc = packet_trim(packet, (size_t) rc, 0);
     543                rc = packet_trim(packet, length, 0);
    501544                if (rc != EOK)
    502545                        return rc;
    503                
    504546                break;
    505547        default:
    506548                return ENOTSUP;
    507549        }
    508        
     550
    509551        /* Get rid of the IP header */
    510         size_t length = ip_client_header_length(packet);
     552        length = ip_client_header_length(packet);
    511553        rc = packet_trim(packet, length, 0);
    512554        if (rc != EOK)
    513555                return rc;
    514        
     556
    515557        length = packet_get_data_length(packet);
    516558        if (length <= 0)
    517559                return EINVAL;
    518        
     560
    519561        if (length < ICMP_HEADER_SIZE)
    520562                return EINVAL;
    521        
    522         void *data = packet_get_data(packet);
     563
     564        data = packet_get_data(packet);
    523565        if (!data)
    524566                return EINVAL;
    525        
     567
    526568        /* Get ICMP header */
    527         icmp_header_t *header = (icmp_header_t *) data;
    528        
     569        header = (icmp_header_t *) data;
     570
    529571        if (header->checksum) {
    530572                while (ICMP_CHECKSUM(header, length) != IP_CHECKSUM_ZERO) {
     
    540582                                }
    541583                        }
    542                        
    543584                        return EINVAL;
    544585                }
    545586        }
    546        
     587
    547588        switch (header->type) {
    548589        case ICMP_ECHOREPLY:
     
    551592                else
    552593                        icmp_process_echo_reply(packet, header, ICMP_ECHO, 0);
    553                
     594
    554595                return EOK;
    555        
     596
    556597        case ICMP_ECHO:
    557598                if (error) {
     
    561602               
    562603                /* Do not send a reply if disabled */
    563                 if (echo_replying) {
    564                         uint8_t *src;
    565                         int addrlen = packet_get_addr(packet, &src, NULL);
    566                        
     604                if (icmp_globals.echo_replying) {
     605                        addrlen = packet_get_addr(packet, &src, NULL);
     606
    567607                        /*
    568                          * Set both addresses to the source one (avoid the
     608                         * Set both addresses to the source one (avoids the
    569609                         * source address deletion before setting the
    570610                         * destination one).
     
    577617                                return EOK;
    578618                        }
    579                        
     619
    580620                        return EINVAL;
    581621                }
    582                
     622
    583623                return EPERM;
    584        
     624
    585625        case ICMP_DEST_UNREACH:
    586626        case ICMP_SOURCE_QUENCH:
     
    595635        case ICMP_SKIP:
    596636        case ICMP_PHOTURIS:
    597                 ip_received_error_msg(phone_ip, -1, packet,
     637                ip_received_error_msg(icmp_globals.ip_phone, -1, packet,
    598638                    SERVICE_IP, SERVICE_ICMP);
    599639                return EOK;
     640
     641        default:
     642                return ENOTSUP;
     643        }
     644}
     645
     646/** Processes the received ICMP packet.
     647 *
     648 * Is used as an entry point from the underlying IP module.
     649 * Releases the packet on error.
     650 *
     651 * @param device_id     The device identifier. Ignored parameter.
     652 * @param[in,out] packet The received packet.
     653 * @param receiver      The target service. Ignored parameter.
     654 * @param[in] error     The packet error reporting service. Prefixes the
     655 *                      received packet.
     656 * @return              EOK on success.
     657 * @return              Other error codes as defined for the
     658 *                      icmp_process_packet() function.
     659 */
     660static int icmp_received_msg_local(device_id_t device_id, packet_t *packet,
     661    services_t receiver, services_t error)
     662{
     663        int rc;
     664
     665        rc = icmp_process_packet(packet, error);
     666        if (rc != EOK)
     667                return icmp_release_and_return(packet, rc);
     668
     669        return EOK;
     670}
     671
     672/** Processes the generic client messages.
     673 *
     674 * @param[in] call      The message parameters.
     675 * @return              EOK on success.
     676 * @return              ENOTSUP if the message is not known.
     677 * @return              Other error codes as defined for the packet_translate()
     678 *                      function.
     679 * @return              Other error codes as defined for the
     680 *                      icmp_destination_unreachable_msg_local() function.
     681 * @return              Other error codes as defined for the
     682 *                      icmp_source_quench_msg_local() function.
     683 * @return              Other error codes as defined for the
     684 *                      icmp_time_exceeded_msg_local() function.
     685 * @return              Other error codes as defined for the
     686 *                      icmp_parameter_problem_msg_local() function.
     687 *
     688 * @see icmp_interface.h
     689 */
     690static int icmp_process_message(ipc_call_t *call)
     691{
     692        packet_t *packet;
     693        int rc;
     694
     695        switch (IPC_GET_IMETHOD(*call)) {
     696        case NET_ICMP_DEST_UNREACH:
     697                rc = packet_translate_remote(icmp_globals.net_phone, &packet,
     698                    IPC_GET_PACKET(call));
     699                if (rc != EOK)
     700                        return rc;
     701                return icmp_destination_unreachable_msg_local(0,
     702                    ICMP_GET_CODE(call), ICMP_GET_MTU(call), packet);
     703        case NET_ICMP_SOURCE_QUENCH:
     704                rc = packet_translate_remote(icmp_globals.net_phone, &packet,
     705                    IPC_GET_PACKET(call));
     706                if (rc != EOK)
     707                        return rc;
     708                return icmp_source_quench_msg_local(0, packet);
     709        case NET_ICMP_TIME_EXCEEDED:
     710                rc = packet_translate_remote(icmp_globals.net_phone, &packet,
     711                    IPC_GET_PACKET(call));
     712                if (rc != EOK)
     713                        return rc;
     714                return icmp_time_exceeded_msg_local(0, ICMP_GET_CODE(call),
     715                    packet);
     716        case NET_ICMP_PARAMETERPROB:
     717                rc = packet_translate_remote(icmp_globals.net_phone, &packet,
     718                    IPC_GET_PACKET(call));
     719                if (rc != EOK)
     720                        return rc;
     721                return icmp_parameter_problem_msg_local(0, ICMP_GET_CODE(call),
     722                    ICMP_GET_POINTER(call), packet);
     723        default:
     724                return ENOTSUP;
     725        }
     726}
     727
     728/** Assigns a new identifier for the connection.
     729 *
     730 * Fills the echo data parameter with the assigned values.
     731 *
     732 * @param[in,out] echo_data The echo data to be bound.
     733 * @return              Index of the inserted echo data.
     734 * @return              EBADMEM if the echo_data parameter is NULL.
     735 * @return              ENOTCONN if no free identifier have been found.
     736 */
     737static int icmp_bind_free_id(icmp_echo_t *echo_data)
     738{
     739        icmp_param_t index;
     740
     741        if (!echo_data)
     742                return EBADMEM;
     743
     744        /* From the last used one */
     745        index = icmp_globals.last_used_id;
     746        do {
     747                index++;
     748                /* til the range end */
     749                if (index >= ICMP_FREE_IDS_END) {
     750                        /* start from the range beginning */
     751                        index = ICMP_FREE_IDS_START - 1;
     752                        do {
     753                                index++;
     754                                /* til the last used one */
     755                                if (index >= icmp_globals.last_used_id) {
     756                                        /* none found */
     757                                        return ENOTCONN;
     758                                }
     759                        } while(icmp_echo_data_find(&icmp_globals.echo_data,
     760                            index) != NULL);
     761
     762                        /* Found, break immediately */
     763                        break;
     764                }
     765        } while (icmp_echo_data_find(&icmp_globals.echo_data, index) != NULL);
     766
     767        echo_data->identifier = index;
     768        echo_data->sequence_number = 0;
     769
     770        return icmp_echo_data_add(&icmp_globals.echo_data, index, echo_data);
     771}
     772
     773/** Processes the client messages.
     774 *
     775 * Remembers the assigned identifier and sequence numbers.
     776 * Runs until the client module disconnects.
     777 *
     778 * @param[in] callid    The message identifier.
     779 * @param[in] call      The message parameters.
     780 * @return EOK.
     781 *
     782 * @see icmp_interface.h
     783 * @see icmp_api.h
     784 */
     785static int icmp_process_client_messages(ipc_callid_t callid, ipc_call_t call)
     786{
     787        bool keep_on_going = true;
     788        ipc_call_t answer;
     789        int answer_count;
     790        size_t length;
     791        struct sockaddr *addr;
     792        ipc_callid_t data_callid;
     793        icmp_echo_t *echo_data;
     794        int rc = EOK;
     795
     796        /*
     797         * Accept the connection
     798         *  - Answer the first NET_ICMP_INIT call.
     799         */
     800        answer_count = 0;
     801
     802        echo_data = (icmp_echo_t *) malloc(sizeof(*echo_data));
     803        if (!echo_data)
     804                return ENOMEM;
     805
     806        /* Assign a new identifier */
     807        fibril_rwlock_write_lock(&icmp_globals.lock);
     808        rc = icmp_bind_free_id(echo_data);
     809        fibril_rwlock_write_unlock(&icmp_globals.lock);
     810        if (rc < 0) {
     811                free(echo_data);
     812                return rc;
     813        }
     814
     815        while (keep_on_going) {
     816                /* Answer the call */
     817                answer_call(callid, rc, &answer, answer_count);
     818
     819                /* Refresh data */
     820                refresh_answer(&answer, &answer_count);
     821
     822                /* Get the next call */
     823                callid = async_get_call(&call);
     824
     825                /* Process the call */
     826                switch (IPC_GET_IMETHOD(call)) {
     827                case IPC_M_PHONE_HUNGUP:
     828                        keep_on_going = false;
     829                        rc = EHANGUP;
     830                        break;
     831               
     832                case NET_ICMP_ECHO:
     833                        if (!async_data_write_receive(&data_callid, &length)) {
     834                                rc = EINVAL;
     835                                break;
     836                        }
     837                       
     838                        addr = malloc(length);
     839                        if (!addr) {
     840                                rc = ENOMEM;
     841                                break;
     842                        }
     843                       
     844                        rc = async_data_write_finalize(data_callid, addr,
     845                            length);
     846                        if (rc != EOK) {
     847                                free(addr);
     848                                break;
     849                        }
     850
     851                        fibril_rwlock_write_lock(&icmp_globals.lock);
     852                        rc = icmp_echo(echo_data->identifier,
     853                            echo_data->sequence_number, ICMP_GET_SIZE(call),
     854                            ICMP_GET_TIMEOUT(call), ICMP_GET_TTL(call),
     855                            ICMP_GET_TOS(call), ICMP_GET_DONT_FRAGMENT(call),
     856                            addr, (socklen_t) length);
     857                        fibril_rwlock_write_unlock(&icmp_globals.lock);
     858
     859                        free(addr);
     860
     861                        if (echo_data->sequence_number < UINT16_MAX)
     862                                echo_data->sequence_number++;
     863                        else
     864                                echo_data->sequence_number = 0;
     865
     866                        break;
     867
     868                default:
     869                        rc = icmp_process_message(&call);
     870                }
     871
     872        }
     873
     874        /* Release the identifier */
     875        fibril_rwlock_write_lock(&icmp_globals.lock);
     876        icmp_echo_data_exclude(&icmp_globals.echo_data, echo_data->identifier);
     877        fibril_rwlock_write_unlock(&icmp_globals.lock);
     878
     879        return rc;
     880}
     881
     882/** Processes the ICMP message.
     883 *
     884 * @param[in] callid    The message identifier.
     885 * @param[in] call      The message parameters.
     886 * @param[out] answer   The message answer parameters.
     887 * @param[out] answer_count The last parameter for the actual answer in the
     888 *                      answer parameter.
     889 * @return              EOK on success.
     890 * @return              ENOTSUP if the message is not known.
     891 *
     892 * @see icmp_interface.h
     893 * @see IS_NET_ICMP_MESSAGE()
     894 */
     895int icmp_message_standalone(ipc_callid_t callid, ipc_call_t *call,
     896    ipc_call_t *answer, int *answer_count)
     897{
     898        packet_t *packet;
     899        int rc;
     900
     901        *answer_count = 0;
     902        switch (IPC_GET_IMETHOD(*call)) {
     903        case NET_TL_RECEIVED:
     904                rc = packet_translate_remote(icmp_globals.net_phone, &packet,
     905                    IPC_GET_PACKET(call));
     906                if (rc != EOK)
     907                        return rc;
     908                return icmp_received_msg_local(IPC_GET_DEVICE(call), packet,
     909                    SERVICE_ICMP, IPC_GET_ERROR(call));
     910       
     911        case NET_ICMP_INIT:
     912                return icmp_process_client_messages(callid, * call);
    600913       
    601914        default:
    602                 return ENOTSUP;
    603         }
    604 }
    605 
    606 /** Process IPC messages from the IP module
    607  *
    608  * @param[in]     iid   Message identifier.
    609  * @param[in,out] icall Message parameters.
    610  *
    611  */
    612 static void icmp_receiver(ipc_callid_t iid, ipc_call_t *icall)
    613 {
    614         bool loop = true;
    615         packet_t *packet;
     915                return icmp_process_message(call);
     916        }
     917
     918        return ENOTSUP;
     919}
     920
     921
     922/** Default thread for new connections.
     923 *
     924 * @param[in] iid The initial message identifier.
     925 * @param[in] icall The initial message call structure.
     926 *
     927 */
     928static void tl_client_connection(ipc_callid_t iid, ipc_call_t *icall)
     929{
     930        /*
     931         * Accept the connection
     932         *  - Answer the first IPC_M_CONNECT_ME_TO call.
     933         */
     934        ipc_answer_0(iid, EOK);
     935       
     936        while (true) {
     937                ipc_call_t answer;
     938                int answer_count;
     939               
     940                /* Clear the answer structure */
     941                refresh_answer(&answer, &answer_count);
     942               
     943                /* Fetch the next message */
     944                ipc_call_t call;
     945                ipc_callid_t callid = async_get_call(&call);
     946               
     947                /* Process the message */
     948                int res = tl_module_message_standalone(callid, &call, &answer,
     949                    &answer_count);
     950               
     951                /*
     952                 * End if told to either by the message or the processing
     953                 * result.
     954                 */
     955                if ((IPC_GET_IMETHOD(call) == IPC_M_PHONE_HUNGUP) ||
     956                    (res == EHANGUP))
     957                        return;
     958               
     959                /* Answer the message */
     960                answer_call(callid, res, &answer, answer_count);
     961        }
     962}
     963
     964/** Starts the module.
     965 *
     966 * @return              EOK on success.
     967 * @return              Other error codes as defined for each specific module
     968 *                      start function.
     969 */
     970int main(int argc, char *argv[])
     971{
    616972        int rc;
    617973       
    618         while (loop) {
    619                 switch (IPC_GET_IMETHOD(*icall)) {
    620                 case NET_TL_RECEIVED:
    621                         rc = packet_translate_remote(phone_net, &packet,
    622                             IPC_GET_PACKET(*icall));
    623                         if (rc == EOK) {
    624                                 rc = icmp_process_packet(packet, IPC_GET_ERROR(*icall));
    625                                 if (rc != EOK)
    626                                         icmp_release(packet);
    627                         }
    628                        
    629                         async_answer_0(iid, (sysarg_t) rc);
    630                         break;
    631                 case IPC_M_PHONE_HUNGUP:
    632                         loop = false;
    633                         continue;
    634                 default:
    635                         async_answer_0(iid, (sysarg_t) ENOTSUP);
    636                 }
    637                
    638                 iid = async_get_call(icall);
    639         }
    640 }
    641 
    642 /** Initialize the ICMP module.
    643  *
    644  * @param[in] net_phone Network module phone.
    645  *
    646  * @return EOK on success.
    647  * @return ENOMEM if there is not enough memory left.
    648  *
    649  */
    650 int tl_initialize(int net_phone)
    651 {
    652         measured_string_t names[] = {
    653                 {
    654                         (uint8_t *) "ICMP_ERROR_REPORTING",
    655                         20
    656                 },
    657                 {
    658                         (uint8_t *) "ICMP_ECHO_REPLYING",
    659                         18
    660                 }
    661         };
    662         measured_string_t *configuration;
    663         size_t count = sizeof(names) / sizeof(measured_string_t);
    664         uint8_t *data;
    665        
    666         if (!hash_table_create(&replies, REPLY_BUCKETS, REPLY_KEYS, &reply_ops))
    667                 return ENOMEM;
    668        
    669         fibril_mutex_initialize(&reply_lock);
    670         atomic_set(&icmp_client, 0);
    671        
    672         phone_net = net_phone;
    673         phone_ip = ip_bind_service(SERVICE_IP, IPPROTO_ICMP, SERVICE_ICMP,
    674             icmp_receiver);
    675         if (phone_ip < 0)
    676                 return phone_ip;
    677        
    678         int rc = ip_packet_size_req(phone_ip, -1, &icmp_dimension);
    679         if (rc != EOK)
    680                 return rc;
    681        
    682         icmp_dimension.prefix += ICMP_HEADER_SIZE;
    683         icmp_dimension.content -= ICMP_HEADER_SIZE;
    684        
    685         /* Get configuration */
    686         configuration = &names[0];
    687         rc = net_get_conf_req(phone_net, &configuration, count, &data);
    688         if (rc != EOK)
    689                 return rc;
    690        
    691         if (configuration) {
    692                 if (configuration[0].value)
    693                         error_reporting = (configuration[0].value[0] == 'y');
    694                
    695                 if (configuration[1].value)
    696                         echo_replying = (configuration[1].value[0] == 'y');
    697                
    698                 net_free_settings(configuration, data);
    699         }
    700        
    701         return EOK;
    702 }
    703 
    704 /** Per-connection initialization
    705  *
    706  * Initialize client-specific global variables.
    707  *
    708  */
    709 void tl_connection(void)
    710 {
    711         icmp_id = (icmp_param_t) atomic_postinc(&icmp_client);
    712         icmp_seq = 1;
    713 }
    714 
    715 /** Process the ICMP message.
    716  *
    717  * @param[in]  callid Message identifier.
    718  * @param[in]  call   Message parameters.
    719  * @param[out] answer Answer.
    720  * @param[out] count  Number of arguments of the answer.
    721  *
    722  * @return EOK on success.
    723  * @return ENOTSUP if the message is not known.
    724  * @return Other error codes as defined for the packet_translate()
    725  *         function.
    726  * @return Other error codes as defined for the
    727  *         icmp_destination_unreachable() function.
    728  * @return Other error codes as defined for the
    729  *         icmp_source_quench() function.
    730  * @return Other error codes as defined for the
    731  *         icmp_time_exceeded() function.
    732  * @return Other error codes as defined for the
    733  *         icmp_parameter_problem() function.
    734  *
    735  * @see icmp_remote.h
    736  * @see IS_NET_ICMP_MESSAGE()
    737  *
    738  */
    739 int tl_message(ipc_callid_t callid, ipc_call_t *call,
    740     ipc_call_t *answer, size_t *count)
    741 {
    742         struct sockaddr *addr;
    743         size_t size;
    744         packet_t *packet;
    745         int rc;
    746        
    747         *count = 0;
    748        
    749         switch (IPC_GET_IMETHOD(*call)) {
    750         case NET_ICMP_ECHO:
    751                 rc = async_data_write_accept((void **) &addr, false, 0, 0, 0, &size);
    752                 if (rc != EOK)
    753                         return rc;
    754                
    755                 rc = icmp_echo(icmp_id, icmp_seq, ICMP_GET_SIZE(*call),
    756                     ICMP_GET_TIMEOUT(*call), ICMP_GET_TTL(*call),
    757                     ICMP_GET_TOS(*call), ICMP_GET_DONT_FRAGMENT(*call),
    758                     addr, (socklen_t) size);
    759                
    760                 free(addr);
    761                 icmp_seq++;
    762                 return rc;
    763        
    764         case NET_ICMP_DEST_UNREACH:
    765                 rc = packet_translate_remote(phone_net, &packet,
    766                     IPC_GET_PACKET(*call));
    767                 if (rc != EOK)
    768                         return rc;
    769                
    770                 return icmp_destination_unreachable(ICMP_GET_CODE(*call),
    771                     ICMP_GET_MTU(*call), packet);
    772        
    773         case NET_ICMP_SOURCE_QUENCH:
    774                 rc = packet_translate_remote(phone_net, &packet,
    775                     IPC_GET_PACKET(*call));
    776                 if (rc != EOK)
    777                         return rc;
    778                
    779                 return icmp_source_quench(packet);
    780        
    781         case NET_ICMP_TIME_EXCEEDED:
    782                 rc = packet_translate_remote(phone_net, &packet,
    783                     IPC_GET_PACKET(*call));
    784                 if (rc != EOK)
    785                         return rc;
    786                
    787                 return icmp_time_exceeded(ICMP_GET_CODE(*call), packet);
    788        
    789         case NET_ICMP_PARAMETERPROB:
    790                 rc = packet_translate_remote(phone_net, &packet,
    791                     IPC_GET_PACKET(*call));
    792                 if (rc != EOK)
    793                         return rc;
    794                
    795                 return icmp_parameter_problem(ICMP_GET_CODE(*call),
    796                     ICMP_GET_POINTER(*call), packet);
    797         }
    798        
    799         return ENOTSUP;
    800 }
    801 
    802 int main(int argc, char *argv[])
    803 {
    804974        /* Start the module */
    805         return tl_module_start(SERVICE_ICMP);
     975        rc = tl_module_start_standalone(tl_client_connection);
     976        return rc;
    806977}
    807978
    808979/** @}
    809980 */
     981
Note: See TracChangeset for help on using the changeset viewer.