Changeset f1938c6 in mainline


Ignore:
Timestamp:
2011-01-17T15:41:30Z (14 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
a2d8d59, ffaba00
Parents:
9f3864a
Message:

streamline ICMP implementation

  • generate ICMP identification based on fibril counter
  • use fibril-local ICMP sequence numbers
  • use hash table (instead of char map) for ICMP replies
  • simplify locking
  • simplify ICMP communication
Location:
uspace
Files:
1 deleted
12 edited
1 moved

Legend:

Unmodified
Added
Removed
  • uspace/app/ping/ping.c

    r9f3864a rf1938c6  
    340340            config.dest_str, config.size, config.size);
    341341       
    342         int icmp_phone = icmp_connect_module(SERVICE_ICMP, ICMP_CONNECT_TIMEOUT);
     342        int icmp_phone = icmp_connect_module(ICMP_CONNECT_TIMEOUT);
    343343        if (icmp_phone < 0) {
    344344                fprintf(stderr, "%s: Unable to connect to ICMP service (%s)\n", NAME,
  • uspace/lib/c/generic/net/icmp_common.c

    r9f3864a rf1938c6  
    2727 */
    2828
    29 /** @addtogroup libc 
     29/** @addtogroup libc
    3030 *  @{
    3131 */
     
    3838#include <net/modules.h>
    3939#include <net/icmp_common.h>
    40 
    4140#include <ipc/services.h>
    4241#include <ipc/icmp.h>
    43 
    4442#include <sys/time.h>
    4543#include <async.h>
    4644
    47 /** Connects to the ICMP module.
     45/** Connect to the ICMP module.
    4846 *
    49  * @param service       The ICMP module service. Ignored parameter.
    50  * @param[in] timeout   The connection timeout in microseconds. No timeout if
    51  *                      set to zero.
    52  * @return              The ICMP module phone on success.
    53  * @return              ETIMEOUT if the connection timeouted.
     47 * @param[in] timeout Connection timeout in microseconds, zero
     48 *                    for no timeout.
     49 *
     50 * @return ICMP module phone on success.
     51 * @return ETIMEOUT if the connection timeouted.
     52 *
    5453 */
    55 int icmp_connect_module(services_t service, suseconds_t timeout)
     54int icmp_connect_module(suseconds_t timeout)
    5655{
    57         int phone;
    58 
    59         phone = connect_to_service_timeout(SERVICE_ICMP, timeout);
    60         if (phone >= 0)
    61                 async_req_0_0(phone, NET_ICMP_INIT);
    62 
    63         return phone;
     56        return connect_to_service_timeout(SERVICE_ICMP, timeout);
    6457}
    6558
  • uspace/lib/c/include/ipc/icmp.h

    r9f3864a rf1938c6  
    3333/** @file
    3434 * ICMP module messages.
    35  * @see icmp_interface.h
     35 * @see icmp_remote.h
    3636 */
    3737
     
    4848/** ICMP module messages. */
    4949typedef enum {
    50         /** Sends echo request. @see icmp_echo() */
     50        /** Send echo request. @see icmp_echo() */
    5151        NET_ICMP_ECHO = NET_ICMP_FIRST,
    5252       
    5353        /**
    54          * Sends destination unreachable error message.
     54         * Send destination unreachable error message.
    5555         * @see icmp_destination_unreachable_msg()
    5656         */
     
    5858       
    5959        /**
    60          * Sends source quench error message.
     60         * Send source quench error message.
    6161         * @see icmp_source_quench_msg()
    6262         */
     
    6464       
    6565        /**
    66          * Sends time exceeded error message.
     66         * Send time exceeded error message.
    6767         * @see icmp_time_exceeded_msg()
    6868         */
     
    7070       
    7171        /**
    72          * Sends parameter problem error message.
     72         * Send parameter problem error message.
    7373         * @see icmp_parameter_problem_msg()
    7474         */
    75         NET_ICMP_PARAMETERPROB,
    76        
    77         /** Initializes new connection. */
    78         NET_ICMP_INIT
    79 } icmp_messages;
     75        NET_ICMP_PARAMETERPROB
     76} icmp_messages_t;
    8077
    8178/** @name ICMP specific message parameters definitions */
  • uspace/lib/c/include/net/icmp_common.h

    r9f3864a rf1938c6  
    4141#include <sys/time.h>
    4242
    43 /** Default timeout for incoming connections in microseconds. */
    44 #define ICMP_CONNECT_TIMEOUT    (1 * 1000 * 1000)
     43/** Default timeout for incoming connections in microseconds (1 sec). */
     44#define ICMP_CONNECT_TIMEOUT  1000000
    4545
    46 extern int icmp_connect_module(services_t, suseconds_t);
     46extern int icmp_connect_module(suseconds_t);
    4747
    4848#endif
  • uspace/lib/net/include/icmp_remote.h

    r9f3864a rf1938c6  
    2727 */
    2828
    29 /** @addtogroup libnet 
     29/** @addtogroup libnet
    3030 *  @{
    3131 */
    3232
    33 #ifndef LIBNET_ICMP_INTERFACE_H_
    34 #define LIBNET_ICMP_INTERFACE_H_
     33#ifndef LIBNET_ICMP_REMOTE_H_
     34#define LIBNET_ICMP_REMOTE_H_
    3535
    3636#include <net/socket_codes.h>
     
    5454extern int icmp_source_quench_msg(int, packet_t *);
    5555extern int icmp_time_exceeded_msg(int, icmp_code_t, packet_t *);
    56 extern int icmp_parameter_problem_msg(int, icmp_code_t, icmp_param_t, packet_t *);
     56extern int icmp_parameter_problem_msg(int, icmp_code_t, icmp_param_t,
     57    packet_t *);
    5758
    5859/*@}*/
  • uspace/lib/net/include/tl_skel.h

    r9f3864a rf1938c6  
    6161extern int tl_initialize(int net_phone);
    6262
     63/** Per-connection module initialization.
     64 *
     65 * This has to be implemented in user code.
     66 *
     67 */
     68extern void tl_connection(void);
     69
    6370/** Process the transport layer module message.
    6471 *
     
    7481 *
    7582 */
    76 extern int tl_module_message(ipc_callid_t, ipc_call_t *,
     83extern int tl_message(ipc_callid_t, ipc_call_t *,
    7784    ipc_call_t *, size_t *);
    7885
  • uspace/lib/net/tl/icmp_remote.c

    r9f3864a rf1938c6  
    3333/** @file
    3434 * ICMP interface implementation for remote modules.
    35  * @see icmp_interface.h
     35 * @see icmp_remote.h
    3636 */
    3737
    38 #include <icmp_interface.h>
     38#include <icmp_remote.h>
    3939#include <net/modules.h>
    4040#include <packet_client.h>
  • uspace/lib/net/tl/tl_common.c

    r9f3864a rf1938c6  
    2727 */
    2828
    29 /** @addtogroup libnet 
     29/** @addtogroup libnet
    3030 * @{
    3131 */
     
    3939#include <packet_client.h>
    4040#include <packet_remote.h>
    41 #include <icmp_interface.h>
     41#include <icmp_remote.h>
    4242#include <ip_remote.h>
    4343#include <ip_interface.h>
  • uspace/lib/net/tl/tl_skel.c

    r9f3864a rf1938c6  
    5656        ipc_answer_0(iid, EOK);
    5757       
     58        /* Per-connection initialization */
     59        tl_connection();
     60       
    5861        while (true) {
    5962                ipc_call_t answer;
     
    6871               
    6972                /* Process the message */
    70                 int res = tl_module_message(callid, &call, &answer,
    71                     &count);
     73                int res = tl_message(callid, &call, &answer, &count);
    7274               
    7375                /*
  • uspace/srv/net/il/ip/ip.c

    r9f3864a rf1938c6  
    6767#include <net_checksum.h>
    6868#include <icmp_client.h>
    69 #include <icmp_interface.h>
     69#include <icmp_remote.h>
    7070#include <ip_client.h>
    7171#include <ip_interface.h>
  • uspace/srv/net/tl/icmp/icmp.c

    r9f3864a rf1938c6  
    3333/** @file
    3434 * ICMP module implementation.
    35  * @see icmp.h
    3635 */
    3736
     
    5150#include <byteorder.h>
    5251#include <errno.h>
     52#include <adt/hash_table.h>
    5353
    5454#include <net/socket_codes.h>
     
    6464#include <net_checksum.h>
    6565#include <icmp_client.h>
    66 #include <icmp_interface.h>
     66#include <icmp_remote.h>
    6767#include <il_remote.h>
    6868#include <ip_client.h>
     
    7373#include <icmp_header.h>
    7474
    75 #include "icmp.h"
    76 
    77 /** ICMP module name. */
     75/** ICMP module name */
    7876#define NAME  "icmp"
    7977
    80 /** Default ICMP error reporting. */
    81 #define NET_DEFAULT_ICMP_ERROR_REPORTING        true
    82 
    83 /** Default ICMP echo replying. */
    84 #define NET_DEFAULT_ICMP_ECHO_REPLYING          true
    85 
    86 /** Original datagram length in bytes transfered to the error notification
    87  * message.
    88  */
    89 #define ICMP_KEEP_LENGTH        8
    90 
    91 /** Free identifier numbers pool start. */
    92 #define ICMP_FREE_IDS_START     1
    93 
    94 /** Free identifier numbers pool end. */
    95 #define ICMP_FREE_IDS_END       UINT16_MAX
    96 
    97 /** Computes the ICMP datagram checksum.
    98  *
    99  * @param[in,out] header The ICMP datagram header.
    100  * @param[in] length    The total datagram length.
    101  * @return              The computed checksum.
     78/** Number of replies hash table keys */
     79#define REPLY_KEYS  2
     80
     81/** Number of replies hash table buckets */
     82#define REPLY_BUCKETS  1024
     83
     84/**
     85 * Original datagram length in bytes transfered to the error
     86 * notification message.
     87 */
     88#define ICMP_KEEP_LENGTH  8
     89
     90/** Compute the ICMP datagram checksum.
     91 *
     92 * @param[in,out] header ICMP datagram header.
     93 * @param[in]     length Total datagram length.
     94 *
     95 * @return Computed checksum.
     96 *
    10297 */
    10398#define ICMP_CHECKSUM(header, length) \
     
    105100
    106101/** An echo request datagrams pattern. */
    107 #define ICMP_ECHO_TEXT          "Hello from HelenOS."
    108 
    109 /** Computes an ICMP reply data key.
    110  *
    111  * @param[in] id        The message identifier.
    112  * @param[in] sequence  The message sequence number.
    113  * @return              The computed ICMP reply data key.
    114  */
    115 #define ICMP_GET_REPLY_KEY(id, sequence) \
    116         (((id) << 16) | (sequence & 0xFFFF))
    117 
    118 
    119 /** ICMP global data. */
    120 icmp_globals_t  icmp_globals;
    121 
    122 INT_MAP_IMPLEMENT(icmp_replies, icmp_reply_t);
    123 INT_MAP_IMPLEMENT(icmp_echo_data, icmp_echo_t);
    124 
    125 /** Releases the packet and returns the result.
    126  *
    127  * @param[in] packet    The packet queue to be released.
    128  * @param[in] result    The result to be returned.
    129  * @return              The result parameter.
    130  */
    131 static int icmp_release_and_return(packet_t *packet, int result)
    132 {
    133         pq_release_remote(icmp_globals.net_phone, packet_get_id(packet));
    134         return result;
    135 }
    136 
    137 /** Sends the ICMP message.
    138  *
    139  * Sets the message type and code and computes the checksum.
     102#define ICMP_ECHO_TEXT  "ICMP hello from HelenOS."
     103
     104/** ICMP reply data. */
     105typedef struct {
     106        /** Hash table link */
     107        link_t link;
     108       
     109        /** Reply identification and sequence */
     110        icmp_param_t id;
     111        icmp_param_t sequence;
     112       
     113        /** Reply signaling */
     114        fibril_condvar_t condvar;
     115       
     116        /** Reply result */
     117        int result;
     118} icmp_reply_t;
     119
     120/** Global data */
     121static int phone_net = -1;
     122static int phone_ip = -1;
     123static bool error_reporting = true;
     124static bool echo_replying = true;
     125
     126/** ICMP client identification counter */
     127static atomic_t icmp_client;
     128static packet_dimension_t icmp_dimension;
     129
     130/** ICMP identifier and sequence number */
     131static fibril_local icmp_param_t icmp_id;
     132static fibril_local icmp_param_t icmp_seq;
     133
     134/** Reply hash table */
     135static fibril_mutex_t reply_lock;
     136static hash_table_t replies;
     137
     138static hash_index_t replies_hash(unsigned long key[])
     139{
     140        /*
     141         * ICMP identifier and sequence numbers
     142         * are 16-bit values.
     143         */
     144        hash_index_t index = (key[0] & 0xffff) << 16 | (key[1] & 0xffff);
     145        return index % REPLY_BUCKETS;
     146}
     147
     148static int replies_compare(unsigned long key[], hash_count_t keys, link_t *item)
     149{
     150        icmp_reply_t *reply =
     151            hash_table_get_instance(item, icmp_reply_t, link);
     152       
     153        if (keys == 1)
     154                return (reply->id == key[0]);
     155        else
     156                return ((reply->id == key[0]) && (reply->sequence == key[1]));
     157}
     158
     159static void replies_remove_callback(link_t *item)
     160{
     161}
     162
     163static hash_table_operations_t reply_ops = {
     164        .hash = replies_hash,
     165        .compare = replies_compare,
     166        .remove_callback = replies_remove_callback
     167};
     168
     169/** Release the packet and return the result.
     170 *
     171 * @param[in] packet Packet queue to be released.
     172 *
     173 */
     174static void icmp_release(packet_t *packet)
     175{
     176        pq_release_remote(phone_net, packet_get_id(packet));
     177}
     178
     179/** Send the ICMP message.
     180 *
     181 * Set the message type and code and compute the checksum.
    140182 * Error messages are sent only if allowed in the configuration.
    141  * Releases the packet on errors.
    142  *
    143  * @param[in] type      The message type.
    144  * @param[in] code      The message code.
    145  * @param[in] packet    The message packet to be sent.
    146  * @param[in] header    The ICMP header.
    147  * @param[in] error     The error service to be announced. Should be
    148  *                      SERVICE_ICMP or zero.
    149  * @param[in] ttl       The time to live.
    150  * @param[in] tos       The type of service.
    151  * @param[in] dont_fragment The value indicating whether the datagram must not
    152  *                      be fragmented. Is used as a MTU discovery.
    153  * @return              EOK on success.
    154  * @return              EPERM if the error message is not allowed.
    155  */
    156 static int icmp_send_packet(icmp_type_t type, icmp_code_t code, packet_t *packet,
    157     icmp_header_t *header, services_t error, ip_ttl_t ttl, ip_tos_t tos,
    158     int dont_fragment)
    159 {
    160         int rc;
    161 
     183 * Release the packet on errors.
     184 *
     185 * @param[in] type          Message type.
     186 * @param[in] code          Message code.
     187 * @param[in] packet        Message packet to be sent.
     188 * @param[in] header        ICMP header.
     189 * @param[in] error         Error service to be announced. Should be
     190 *                          SERVICE_ICMP or zero.
     191 * @param[in] ttl           Time to live.
     192 * @param[in] tos           Type of service.
     193 * @param[in] dont_fragment Disable fragmentation.
     194 *
     195 * @return EOK on success.
     196 * @return EPERM if the error message is not allowed.
     197 *
     198 */
     199static int icmp_send_packet(icmp_type_t type, icmp_code_t code,
     200    packet_t *packet, icmp_header_t *header, services_t error, ip_ttl_t ttl,
     201    ip_tos_t tos, bool dont_fragment)
     202{
    162203        /* Do not send an error if disabled */
    163         if (error && !icmp_globals.error_reporting)
    164                 return icmp_release_and_return(packet, EPERM);
    165 
     204        if ((error) && (!error_reporting)) {
     205                icmp_release(packet);
     206                return EPERM;
     207        }
     208       
    166209        header->type = type;
    167210        header->code = code;
     
    170213            packet_get_data_length(packet));
    171214       
    172         rc = ip_client_prepare_packet(packet, IPPROTO_ICMP, ttl, tos,
     215        int rc = ip_client_prepare_packet(packet, IPPROTO_ICMP, ttl, tos,
    173216            dont_fragment, 0);
    174         if (rc != EOK)
    175                 return icmp_release_and_return(packet, rc);
    176 
    177         return ip_send_msg(icmp_globals.ip_phone, -1, packet, SERVICE_ICMP,
    178             error);
    179 }
    180 
    181 /** Prepares the ICMP error packet.
    182  *
    183  * Truncates the original packet if longer than ICMP_KEEP_LENGTH bytes.
    184  * Prefixes and returns the ICMP header.
    185  *
    186  * @param[in,out] packet The original packet.
     217        if (rc != EOK) {
     218                icmp_release(packet);
     219                return rc;
     220        }
     221       
     222        return ip_send_msg(phone_ip, -1, packet, SERVICE_ICMP, error);
     223}
     224
     225/** Prepare the ICMP error packet.
     226 *
     227 * Truncate the original packet if longer than ICMP_KEEP_LENGTH bytes.
     228 * Prefix and return the ICMP header.
     229 *
     230 * @param[in,out] packet Original packet.
     231 *
    187232 * @return The prefixed ICMP header.
    188233 * @return NULL on errors.
     234 *
    189235 */
    190236static icmp_header_t *icmp_prepare_packet(packet_t *packet)
    191237{
    192         icmp_header_t *header;
    193         size_t header_length;
    194         size_t total_length;
    195 
    196         total_length = packet_get_data_length(packet);
     238        size_t total_length = packet_get_data_length(packet);
    197239        if (total_length <= 0)
    198240                return NULL;
    199 
    200         header_length = ip_client_header_length(packet);
     241       
     242        size_t header_length = ip_client_header_length(packet);
    201243        if (header_length <= 0)
    202244                return NULL;
    203 
     245       
    204246        /* Truncate if longer than 64 bits (without the IP header) */
    205247        if ((total_length > header_length + ICMP_KEEP_LENGTH) &&
    206248            (packet_trim(packet, 0,
    207             total_length - header_length - ICMP_KEEP_LENGTH) != EOK)) {
     249            total_length - header_length - ICMP_KEEP_LENGTH) != EOK))
    208250                return NULL;
    209         }
    210 
    211         header = PACKET_PREFIX(packet, icmp_header_t);
     251       
     252        icmp_header_t *header = PACKET_PREFIX(packet, icmp_header_t);
    212253        if (!header)
    213254                return NULL;
    214 
     255       
    215256        bzero(header, sizeof(*header));
    216257        return header;
    217258}
    218259
    219 /** Requests an echo message.
    220  *
    221  * Sends a packet with specified parameters to the target host and waits for
    222  * the reply upto the given timeout.
    223  * Blocks the caller until the reply or the timeout occurs.
    224  *
    225  * @param[in] id        The message identifier.
    226  * @param[in] sequence  The message sequence parameter.
    227  * @param[in] size      The message data length in bytes.
    228  * @param[in] timeout   The timeout in miliseconds.
    229  * @param[in] ttl       The time to live.
    230  * @param[in] tos       The type of service.
    231  * @param[in] dont_fragment The value indicating whether the datagram must not
    232  *                      be fragmented. Is used as a MTU discovery.
    233  * @param[in] addr      The target host address.
    234  * @param[in] addrlen   The torget host address length.
    235  * @return              ICMP_ECHO on success.
    236  * @return              ETIMEOUT if the reply has not arrived before the
    237  *                      timeout.
    238  * @return              ICMP type of the received error notification.
    239  * @return              EINVAL if the addrlen parameter is less or equal to
    240  *                      zero.
    241  * @return              ENOMEM if there is not enough memory left.
    242  * @return              EPARTY if there was an internal error.
     260/** Request an echo message.
     261 *
     262 * Send a packet with specified parameters to the target host
     263 * and wait for the reply upto the given timeout.
     264 * Block the caller until the reply or the timeout occurs.
     265 *
     266 * @param[in] id            Message identifier.
     267 * @param[in] sequence      Message sequence parameter.
     268 * @param[in] size          Message data length in bytes.
     269 * @param[in] timeout       Timeout in miliseconds.
     270 * @param[in] ttl           Time to live.
     271 * @param[in] tos           Type of service.
     272 * @param[in] dont_fragment Disable fragmentation.
     273 * @param[in] addr          Target host address.
     274 * @param[in] addrlen       Torget host address length.
     275 *
     276 * @return ICMP_ECHO on success.
     277 * @return ETIMEOUT if the reply has not arrived before the
     278 *         timeout.
     279 * @return ICMP type of the received error notification.
     280 * @return EINVAL if the addrlen parameter is less or equal to
     281 *         zero.
     282 * @return ENOMEM if there is not enough memory left.
     283 * @return EPARTY if there was an internal error.
     284 *
    243285 */
    244286static int icmp_echo(icmp_param_t id, icmp_param_t sequence, size_t size,
    245     mseconds_t timeout, ip_ttl_t ttl, ip_tos_t tos, int dont_fragment,
    246     const struct sockaddr * addr, socklen_t addrlen)
    247 {
    248         icmp_header_t *header;
    249         packet_t *packet;
    250         size_t length;
    251         uint8_t *data;
    252         icmp_reply_t *reply;
    253         int reply_key;
    254         int index;
    255         int rc;
    256 
     287    mseconds_t timeout, ip_ttl_t ttl, ip_tos_t tos, bool dont_fragment,
     288    const struct sockaddr *addr, socklen_t addrlen)
     289{
    257290        if (addrlen <= 0)
    258291                return EINVAL;
    259 
    260         length = (size_t) addrlen;
    261         /* TODO do not ask all the time */
    262         rc = ip_packet_size_req(icmp_globals.ip_phone, -1,
    263             &icmp_globals.packet_dimension);
    264         if (rc != EOK)
    265                 return rc;
    266 
    267         packet = packet_get_4_remote(icmp_globals.net_phone, size,
    268             icmp_globals.packet_dimension.addr_len,
    269             ICMP_HEADER_SIZE + icmp_globals.packet_dimension.prefix,
    270             icmp_globals.packet_dimension.suffix);
     292       
     293        size_t length = (size_t) addrlen;
     294       
     295        packet_t *packet = packet_get_4_remote(phone_net, size,
     296            icmp_dimension.addr_len, ICMP_HEADER_SIZE + icmp_dimension.prefix,
     297            icmp_dimension.suffix);
    271298        if (!packet)
    272299                return ENOMEM;
    273 
     300       
    274301        /* Prepare the requesting packet, set the destination address. */
    275         rc = packet_set_addr(packet, NULL, (const uint8_t *) addr, length);
    276         if (rc != EOK)
    277                 return icmp_release_and_return(packet, rc);
    278 
     302        int rc = packet_set_addr(packet, NULL, (const uint8_t *) addr, length);
     303        if (rc != EOK) {
     304                icmp_release(packet);
     305                return rc;
     306        }
     307       
    279308        /* Allocate space in the packet */
    280         data = (uint8_t *) packet_suffix(packet, size);
    281         if (!data)
    282                 return icmp_release_and_return(packet, ENOMEM);
    283 
     309        uint8_t *data = (uint8_t *) packet_suffix(packet, size);
     310        if (!data) {
     311                icmp_release(packet);
     312                return ENOMEM;
     313        }
     314       
    284315        /* Fill the data */
    285316        length = 0;
     
    289320        }
    290321        memcpy(data + length, ICMP_ECHO_TEXT, size - length);
    291 
     322       
    292323        /* Prefix the header */
    293         header = PACKET_PREFIX(packet, icmp_header_t);
    294         if (!header)
    295                 return icmp_release_and_return(packet, ENOMEM);
    296 
     324        icmp_header_t *header = PACKET_PREFIX(packet, icmp_header_t);
     325        if (!header) {
     326                icmp_release(packet);
     327                return ENOMEM;
     328        }
     329       
    297330        bzero(header, sizeof(*header));
    298331        header->un.echo.identifier = id;
    299332        header->un.echo.sequence_number = sequence;
    300 
     333       
    301334        /* Prepare the reply structure */
    302         reply = malloc(sizeof(*reply));
    303         if (!reply)
    304                 return icmp_release_and_return(packet, ENOMEM);
    305 
    306         fibril_mutex_initialize(&reply->mutex);
    307         fibril_mutex_lock(&reply->mutex);
     335        icmp_reply_t *reply = malloc(sizeof(icmp_reply_t));
     336        if (!reply) {
     337                icmp_release(packet);
     338                return ENOMEM;
     339        }
     340       
     341        reply->id = id;
     342        reply->sequence = sequence;
    308343        fibril_condvar_initialize(&reply->condvar);
    309         reply_key = ICMP_GET_REPLY_KEY(header->un.echo.identifier,
    310             header->un.echo.sequence_number);
    311         index = icmp_replies_add(&icmp_globals.replies, reply_key, reply);
    312         if (index < 0) {
    313                 free(reply);
    314                 return icmp_release_and_return(packet, index);
    315         }
    316 
    317         /* Unlock the globals so that we can wait for the reply */
    318         fibril_rwlock_write_unlock(&icmp_globals.lock);
    319 
     344       
     345        /* Add the reply to the replies hash table */
     346        fibril_mutex_lock(&reply_lock);
     347       
     348        unsigned long key[REPLY_KEYS] = {id, sequence};
     349        hash_table_insert(&replies, key, &reply->link);
     350       
    320351        /* Send the request */
    321352        icmp_send_packet(ICMP_ECHO, 0, packet, header, 0, ttl, tos,
    322353            dont_fragment);
    323 
     354       
    324355        /* Wait for the reply. Timeout in microseconds. */
    325         rc = fibril_condvar_wait_timeout(&reply->condvar, &reply->mutex,
     356        rc = fibril_condvar_wait_timeout(&reply->condvar, &reply_lock,
    326357            timeout * 1000);
    327358        if (rc == EOK)
    328359                rc = reply->result;
    329 
    330         /* Drop the reply mutex before locking the globals again */
    331         fibril_mutex_unlock(&reply->mutex);
    332         fibril_rwlock_write_lock(&icmp_globals.lock);
    333 
    334         /* Destroy the reply structure */
    335         icmp_replies_exclude_index(&icmp_globals.replies, index);
    336 
     360       
     361        /* Remove the reply from the replies hash table */
     362        hash_table_remove(&replies, key, REPLY_KEYS);
     363       
     364        fibril_mutex_unlock(&reply_lock);
     365       
     366        free(reply);
     367       
    337368        return rc;
    338369}
    339370
    340 static int icmp_destination_unreachable_msg_local(int icmp_phone,
    341     icmp_code_t code, icmp_param_t mtu, packet_t *packet)
    342 {
    343         icmp_header_t *header;
    344 
    345         header = icmp_prepare_packet(packet);
    346         if (!header)
    347                 return icmp_release_and_return(packet, ENOMEM);
    348 
     371static int icmp_destination_unreachable(icmp_code_t code, icmp_param_t mtu,
     372    packet_t *packet)
     373{
     374        icmp_header_t *header = icmp_prepare_packet(packet);
     375        if (!header) {
     376                icmp_release(packet);
     377                return ENOMEM;
     378        }
     379       
    349380        if (mtu)
    350381                header->un.frag.mtu = mtu;
    351 
     382       
    352383        return icmp_send_packet(ICMP_DEST_UNREACH, code, packet, header,
    353             SERVICE_ICMP, 0, 0, 0);
    354 }
    355 
    356 static int icmp_source_quench_msg_local(int icmp_phone, packet_t *packet)
    357 {
    358         icmp_header_t *header;
    359 
    360         header = icmp_prepare_packet(packet);
    361         if (!header)
    362                 return icmp_release_and_return(packet, ENOMEM);
    363 
     384            SERVICE_ICMP, 0, 0, false);
     385}
     386
     387static int icmp_source_quench(packet_t *packet)
     388{
     389        icmp_header_t *header = icmp_prepare_packet(packet);
     390        if (!header) {
     391                icmp_release(packet);
     392                return ENOMEM;
     393        }
     394       
    364395        return icmp_send_packet(ICMP_SOURCE_QUENCH, 0, packet, header,
    365             SERVICE_ICMP, 0, 0, 0);
    366 }
    367 
    368 static int icmp_time_exceeded_msg_local(int icmp_phone, icmp_code_t code,
     396            SERVICE_ICMP, 0, 0, false);
     397}
     398
     399static int icmp_time_exceeded(icmp_code_t code, packet_t *packet)
     400{
     401        icmp_header_t *header = icmp_prepare_packet(packet);
     402        if (!header) {
     403                icmp_release(packet);
     404                return ENOMEM;
     405        }
     406       
     407        return icmp_send_packet(ICMP_TIME_EXCEEDED, code, packet, header,
     408            SERVICE_ICMP, 0, 0, false);
     409}
     410
     411static int icmp_parameter_problem(icmp_code_t code, icmp_param_t pointer,
    369412    packet_t *packet)
    370413{
    371         icmp_header_t *header;
    372 
    373         header = icmp_prepare_packet(packet);
    374         if (!header)
    375                 return icmp_release_and_return(packet, ENOMEM);
    376 
    377         return icmp_send_packet(ICMP_TIME_EXCEEDED, code, packet, header,
    378             SERVICE_ICMP, 0, 0, 0);
    379 }
    380 
    381 static int icmp_parameter_problem_msg_local(int icmp_phone, icmp_code_t code,
    382     icmp_param_t pointer, packet_t *packet)
    383 {
    384         icmp_header_t *header;
    385 
    386         header = icmp_prepare_packet(packet);
    387         if (!header)
    388                 return icmp_release_and_return(packet, ENOMEM);
    389 
     414        icmp_header_t *header = icmp_prepare_packet(packet);
     415        if (!header) {
     416                icmp_release(packet);
     417                return ENOMEM;
     418        }
     419       
    390420        header->un.param.pointer = pointer;
    391421        return icmp_send_packet(ICMP_PARAMETERPROB, code, packet, header,
    392             SERVICE_ICMP, 0, 0, 0);
    393 }
    394 
    395 /** Tries to set the pending reply result as the received message type.
     422            SERVICE_ICMP, 0, 0, false);
     423}
     424
     425/** Try to set the pending reply result as the received message type.
    396426 *
    397427 * If the reply data is not present, the reply timed out and the other fibril
    398  * is already awake.
    399  * Releases the packet.
    400  *
    401  * @param[in] packet    The received reply message.
    402  * @param[in] header    The ICMP message header.
    403  * @param[in] type      The received reply message type.
    404  * @param[in] code      The received reply message code.
    405  */
    406 static void  icmp_process_echo_reply(packet_t *packet, icmp_header_t *header,
     428 * is already awake. The packet is released.
     429 *
     430 * @param[in] packet The received reply message.
     431 * @param[in] header The ICMP message header.
     432 * @param[in] type   The received reply message type.
     433 * @param[in] code   The received reply message code.
     434 *
     435 */
     436static void icmp_process_echo_reply(packet_t *packet, icmp_header_t *header,
    407437    icmp_type_t type, icmp_code_t code)
    408438{
    409         int reply_key;
    410         icmp_reply_t *reply;
    411 
    412         /* Compute the reply key */
    413         reply_key = ICMP_GET_REPLY_KEY(header->un.echo.identifier,
    414             header->un.echo.sequence_number);
    415         pq_release_remote(icmp_globals.net_phone, packet_get_id(packet));
    416 
     439        unsigned long key[REPLY_KEYS] =
     440            {header->un.echo.identifier, header->un.echo.sequence_number};
     441        icmp_release(packet);
     442       
    417443        /* Find the pending reply */
    418         fibril_rwlock_write_lock(&icmp_globals.lock);
    419         reply = icmp_replies_find(&icmp_globals.replies, reply_key);
    420         if (reply) {
     444        fibril_mutex_lock(&reply_lock);
     445       
     446        link_t *link = hash_table_find(&replies, key);
     447        if (link != NULL) {
     448                icmp_reply_t *reply =
     449                   hash_table_get_instance(link, icmp_reply_t, link);
     450               
    421451                reply->result = type;
    422452                fibril_condvar_signal(&reply->condvar);
    423453        }
    424         fibril_rwlock_write_unlock(&icmp_globals.lock);
    425 }
    426 
    427 /** Processes the received ICMP packet.
    428  *
    429  * Notifies the destination socket application.
    430  *
    431  * @param[in,out] packet The received packet.
    432  * @param[in] error     The packet error reporting service. Prefixes the
    433  *                      received packet.
    434  * @return              EOK on success.
    435  * @return              EINVAL if the packet is not valid.
    436  * @return              EINVAL if the stored packet address is not the an_addr_t.
    437  * @return              EINVAL if the packet does not contain any data.
    438  * @return              NO_DATA if the packet content is shorter than the user
    439  *                      datagram header.
    440  * @return              ENOMEM if there is not enough memory left.
    441  * @return              EADDRNOTAVAIL if the destination socket does not exist.
    442  * @return              Other error codes as defined for the
    443  *                      ip_client_process_packet() function.
     454       
     455        fibril_mutex_unlock(&reply_lock);
     456}
     457
     458/** Process the received ICMP packet.
     459 *
     460 * Notify the destination socket application.
     461 *
     462 * @param[in,out] packet Received packet.
     463 * @param[in]     error  Packet error reporting service to prefix
     464 *                       the received packet.
     465 *
     466 * @return EOK on success.
     467 * @return EINVAL if the packet is not valid.
     468 * @return EINVAL if the stored packet address is not the an_addr_t.
     469 * @return EINVAL if the packet does not contain any data.
     470 * @return NO_DATA if the packet content is shorter than the user
     471 *         datagram header.
     472 * @return ENOMEM if there is not enough memory left.
     473 * @return EADDRNOTAVAIL if the destination socket does not exist.
     474 * @return Other error codes as defined for the
     475 *         ip_client_process_packet() function.
     476 *
    444477 */
    445478static int icmp_process_packet(packet_t *packet, services_t error)
    446479{
    447         size_t length;
    448         uint8_t *src;
    449         int addrlen;
    450         int result;
    451         void *data;
    452         icmp_header_t *header;
    453480        icmp_type_t type;
    454481        icmp_code_t code;
     
    460487        case SERVICE_ICMP:
    461488                /* Process error */
    462                 result = icmp_client_process_packet(packet, &type, &code, NULL,
    463                     NULL);
    464                 if (result < 0)
    465                         return result;
    466                 length = (size_t) result;
     489                rc = icmp_client_process_packet(packet, &type, &code, NULL, NULL);
     490                if (rc < 0)
     491                        return rc;
     492               
    467493                /* Remove the error header */
    468                 rc = packet_trim(packet, length, 0);
     494                rc = packet_trim(packet, (size_t) rc, 0);
    469495                if (rc != EOK)
    470496                        return rc;
     497               
    471498                break;
    472499        default:
    473500                return ENOTSUP;
    474501        }
    475 
     502       
    476503        /* Get rid of the IP header */
    477         length = ip_client_header_length(packet);
     504        size_t length = ip_client_header_length(packet);
    478505        rc = packet_trim(packet, length, 0);
    479506        if (rc != EOK)
    480507                return rc;
    481 
     508       
    482509        length = packet_get_data_length(packet);
    483510        if (length <= 0)
    484511                return EINVAL;
    485 
     512       
    486513        if (length < ICMP_HEADER_SIZE)
    487514                return EINVAL;
    488 
    489         data = packet_get_data(packet);
     515       
     516        void *data = packet_get_data(packet);
    490517        if (!data)
    491518                return EINVAL;
    492 
     519       
    493520        /* Get ICMP header */
    494         header = (icmp_header_t *) data;
    495 
     521        icmp_header_t *header = (icmp_header_t *) data;
     522       
    496523        if (header->checksum) {
    497524                while (ICMP_CHECKSUM(header, length) != IP_CHECKSUM_ZERO) {
     
    507534                                }
    508535                        }
     536                       
    509537                        return EINVAL;
    510538                }
    511539        }
    512 
     540       
    513541        switch (header->type) {
    514542        case ICMP_ECHOREPLY:
     
    517545                else
    518546                        icmp_process_echo_reply(packet, header, ICMP_ECHO, 0);
    519 
     547               
    520548                return EOK;
    521 
     549       
    522550        case ICMP_ECHO:
    523551                if (error) {
     
    527555               
    528556                /* Do not send a reply if disabled */
    529                 if (icmp_globals.echo_replying) {
    530                         addrlen = packet_get_addr(packet, &src, NULL);
    531 
     557                if (echo_replying) {
     558                        uint8_t *src;
     559                        int addrlen = packet_get_addr(packet, &src, NULL);
     560                       
    532561                        /*
    533                          * Set both addresses to the source one (avoids the
     562                         * Set both addresses to the source one (avoid the
    534563                         * source address deletion before setting the
    535564                         * destination one).
     
    542571                                return EOK;
    543572                        }
    544 
     573                       
    545574                        return EINVAL;
    546575                }
    547 
     576               
    548577                return EPERM;
    549 
     578       
    550579        case ICMP_DEST_UNREACH:
    551580        case ICMP_SOURCE_QUENCH:
     
    560589        case ICMP_SKIP:
    561590        case ICMP_PHOTURIS:
    562                 ip_received_error_msg(icmp_globals.ip_phone, -1, packet,
     591                ip_received_error_msg(phone_ip, -1, packet,
    563592                    SERVICE_IP, SERVICE_ICMP);
    564593                return EOK;
    565 
     594       
    566595        default:
    567596                return ENOTSUP;
     
    569598}
    570599
    571 /** Processes the received ICMP packet.
    572  *
    573  * Is used as an entry point from the underlying IP module.
    574  * Releases the packet on error.
    575  *
    576  * @param device_id     The device identifier. Ignored parameter.
    577  * @param[in,out] packet The received packet.
    578  * @param receiver      The target service. Ignored parameter.
    579  * @param[in] error     The packet error reporting service. Prefixes the
    580  *                      received packet.
    581  * @return              EOK on success.
    582  * @return              Other error codes as defined for the
    583  *                      icmp_process_packet() function.
    584  */
    585 static int icmp_received_msg_local(device_id_t device_id, packet_t *packet,
    586     services_t receiver, services_t error)
    587 {
    588         int rc;
    589 
    590         rc = icmp_process_packet(packet, error);
    591         if (rc != EOK)
    592                 return icmp_release_and_return(packet, rc);
    593 
    594         return EOK;
    595 }
    596 
    597600/** Process IPC messages from the IP module
    598601 *
     
    603606static void icmp_receiver(ipc_callid_t iid, ipc_call_t *icall)
    604607{
     608        bool loop = true;
    605609        packet_t *packet;
    606610        int rc;
    607611       
    608         while (true) {
     612        while (loop) {
    609613                switch (IPC_GET_IMETHOD(*icall)) {
    610614                case NET_TL_RECEIVED:
    611                         rc = packet_translate_remote(icmp_globals.net_phone, &packet,
     615                        rc = packet_translate_remote(phone_net, &packet,
    612616                            IPC_GET_PACKET(*icall));
    613                         if (rc == EOK)
    614                                 rc = icmp_received_msg_local(IPC_GET_DEVICE(*icall), packet,
    615                                     SERVICE_ICMP, IPC_GET_ERROR(*icall));
     617                        if (rc == EOK) {
     618                                rc = icmp_process_packet(packet, IPC_GET_ERROR(*icall));
     619                                if (rc != EOK)
     620                                        icmp_release(packet);
     621                        }
    616622                       
    617623                        ipc_answer_0(iid, (sysarg_t) rc);
    618624                        break;
     625                case IPC_M_PHONE_HUNGUP:
     626                        loop = false;
     627                        continue;
    619628                default:
    620629                        ipc_answer_0(iid, (sysarg_t) ENOTSUP);
     
    649658        uint8_t *data;
    650659       
    651         fibril_rwlock_initialize(&icmp_globals.lock);
    652         fibril_rwlock_write_lock(&icmp_globals.lock);
    653         icmp_replies_initialize(&icmp_globals.replies);
    654         icmp_echo_data_initialize(&icmp_globals.echo_data);
    655        
    656         icmp_globals.net_phone = net_phone;
    657        
    658         icmp_globals.ip_phone = ip_bind_service(SERVICE_IP, IPPROTO_ICMP,
    659             SERVICE_ICMP, icmp_receiver);
    660         if (icmp_globals.ip_phone < 0) {
    661                 fibril_rwlock_write_unlock(&icmp_globals.lock);
    662                 return icmp_globals.ip_phone;
    663         }
    664        
    665         int rc = ip_packet_size_req(icmp_globals.ip_phone, -1,
    666             &icmp_globals.packet_dimension);
    667         if (rc != EOK) {
    668                 fibril_rwlock_write_unlock(&icmp_globals.lock);
     660        if (!hash_table_create(&replies, REPLY_BUCKETS, REPLY_KEYS, &reply_ops))
     661                return ENOMEM;
     662       
     663        fibril_mutex_initialize(&reply_lock);
     664        atomic_set(&icmp_client, 0);
     665       
     666        phone_net = net_phone;
     667        phone_ip = ip_bind_service(SERVICE_IP, IPPROTO_ICMP, SERVICE_ICMP,
     668            icmp_receiver);
     669        if (phone_ip < 0)
     670                return phone_ip;
     671       
     672        int rc = ip_packet_size_req(phone_ip, -1, &icmp_dimension);
     673        if (rc != EOK)
    669674                return rc;
    670         }
    671        
    672         icmp_globals.packet_dimension.prefix += ICMP_HEADER_SIZE;
    673         icmp_globals.packet_dimension.content -= ICMP_HEADER_SIZE;
    674        
    675         icmp_globals.error_reporting = NET_DEFAULT_ICMP_ERROR_REPORTING;
    676         icmp_globals.echo_replying = NET_DEFAULT_ICMP_ECHO_REPLYING;
     675       
     676        icmp_dimension.prefix += ICMP_HEADER_SIZE;
     677        icmp_dimension.content -= ICMP_HEADER_SIZE;
    677678       
    678679        /* Get configuration */
    679680        configuration = &names[0];
    680         rc = net_get_conf_req(icmp_globals.net_phone, &configuration, count,
    681             &data);
    682         if (rc != EOK) {
    683                 fibril_rwlock_write_unlock(&icmp_globals.lock);
     681        rc = net_get_conf_req(phone_net, &configuration, count, &data);
     682        if (rc != EOK)
    684683                return rc;
    685         }
    686684       
    687685        if (configuration) {
    688                 if (configuration[0].value) {
    689                         icmp_globals.error_reporting =
    690                             (configuration[0].value[0] == 'y');
    691                 }
    692                 if (configuration[1].value) {
    693                         icmp_globals.echo_replying =
    694                             (configuration[1].value[0] == 'y');
    695                 }
     686                if (configuration[0].value)
     687                        error_reporting = (configuration[0].value[0] == 'y');
     688               
     689                if (configuration[1].value)
     690                        echo_replying = (configuration[1].value[0] == 'y');
     691               
    696692                net_free_settings(configuration, data);
    697693        }
    698694       
    699         fibril_rwlock_write_unlock(&icmp_globals.lock);
    700695        return EOK;
    701696}
    702697
    703 /** Processes the generic client messages.
    704  *
    705  * @param[in] call      The message parameters.
    706  * @return              EOK on success.
    707  * @return              ENOTSUP if the message is not known.
    708  * @return              Other error codes as defined for the packet_translate()
    709  *                      function.
    710  * @return              Other error codes as defined for the
    711  *                      icmp_destination_unreachable_msg_local() function.
    712  * @return              Other error codes as defined for the
    713  *                      icmp_source_quench_msg_local() function.
    714  * @return              Other error codes as defined for the
    715  *                      icmp_time_exceeded_msg_local() function.
    716  * @return              Other error codes as defined for the
    717  *                      icmp_parameter_problem_msg_local() function.
    718  *
    719  * @see icmp_interface.h
    720  */
    721 static int icmp_process_message(ipc_call_t *call)
    722 {
     698/** Per-connection initialization
     699 *
     700 */
     701void tl_connection(void)
     702{
     703        icmp_id = (icmp_param_t) atomic_postinc(&icmp_client);
     704        icmp_seq = 1;
     705}
     706
     707/** Process the ICMP message.
     708 *
     709 * @param[in]  callid Message identifier.
     710 * @param[in]  call   Message parameters.
     711 * @param[out] answer Answer.
     712 * @param[out] count  Number of arguments of the answer.
     713 *
     714 * @return EOK on success.
     715 * @return ENOTSUP if the message is not known.
     716 * @return Other error codes as defined for the packet_translate()
     717 *         function.
     718 * @return Other error codes as defined for the
     719 *         icmp_destination_unreachable() function.
     720 * @return Other error codes as defined for the
     721 *         icmp_source_quench() function.
     722 * @return Other error codes as defined for the
     723 *         icmp_time_exceeded() function.
     724 * @return Other error codes as defined for the
     725 *         icmp_parameter_problem() function.
     726 *
     727 * @see icmp_remote.h
     728 * @see IS_NET_ICMP_MESSAGE()
     729 *
     730 */
     731int tl_message(ipc_callid_t callid, ipc_call_t *call,
     732    ipc_call_t *answer, size_t *count)
     733{
     734        struct sockaddr *addr;
     735        size_t size;
    723736        packet_t *packet;
    724737        int rc;
    725 
     738       
     739        *count = 0;
     740       
    726741        switch (IPC_GET_IMETHOD(*call)) {
     742        case NET_ICMP_ECHO:
     743                rc = async_data_write_accept((void **) &addr, false, 0, 0, 0, &size);
     744                if (rc != EOK)
     745                        return rc;
     746               
     747                rc = icmp_echo(icmp_id, icmp_seq, ICMP_GET_SIZE(*call),
     748                    ICMP_GET_TIMEOUT(*call), ICMP_GET_TTL(*call),
     749                    ICMP_GET_TOS(*call), ICMP_GET_DONT_FRAGMENT(*call),
     750                    addr, (socklen_t) size);
     751               
     752                free(addr);
     753                icmp_seq++;
     754                return rc;
     755       
    727756        case NET_ICMP_DEST_UNREACH:
    728                 rc = packet_translate_remote(icmp_globals.net_phone, &packet,
     757                rc = packet_translate_remote(phone_net, &packet,
    729758                    IPC_GET_PACKET(*call));
    730759                if (rc != EOK)
    731760                        return rc;
    732                 return icmp_destination_unreachable_msg_local(0,
    733                     ICMP_GET_CODE(*call), ICMP_GET_MTU(*call), packet);
     761               
     762                return icmp_destination_unreachable(ICMP_GET_CODE(*call),
     763                    ICMP_GET_MTU(*call), packet);
     764       
    734765        case NET_ICMP_SOURCE_QUENCH:
    735                 rc = packet_translate_remote(icmp_globals.net_phone, &packet,
     766                rc = packet_translate_remote(phone_net, &packet,
    736767                    IPC_GET_PACKET(*call));
    737768                if (rc != EOK)
    738769                        return rc;
    739                 return icmp_source_quench_msg_local(0, packet);
     770               
     771                return icmp_source_quench(packet);
     772       
    740773        case NET_ICMP_TIME_EXCEEDED:
    741                 rc = packet_translate_remote(icmp_globals.net_phone, &packet,
     774                rc = packet_translate_remote(phone_net, &packet,
    742775                    IPC_GET_PACKET(*call));
    743776                if (rc != EOK)
    744777                        return rc;
    745                 return icmp_time_exceeded_msg_local(0, ICMP_GET_CODE(*call),
    746                     packet);
     778               
     779                return icmp_time_exceeded(ICMP_GET_CODE(*call), packet);
     780       
    747781        case NET_ICMP_PARAMETERPROB:
    748                 rc = packet_translate_remote(icmp_globals.net_phone, &packet,
     782                rc = packet_translate_remote(phone_net, &packet,
    749783                    IPC_GET_PACKET(*call));
    750784                if (rc != EOK)
    751785                        return rc;
    752                 return icmp_parameter_problem_msg_local(0, ICMP_GET_CODE(*call),
     786               
     787                return icmp_parameter_problem(ICMP_GET_CODE(*call),
    753788                    ICMP_GET_POINTER(*call), packet);
    754         default:
    755                 return ENOTSUP;
    756         }
    757 }
    758 
    759 /** Assigns a new identifier for the connection.
    760  *
    761  * Fills the echo data parameter with the assigned values.
    762  *
    763  * @param[in,out] echo_data The echo data to be bound.
    764  * @return              Index of the inserted echo data.
    765  * @return              EBADMEM if the echo_data parameter is NULL.
    766  * @return              ENOTCONN if no free identifier have been found.
    767  */
    768 static int icmp_bind_free_id(icmp_echo_t *echo_data)
    769 {
    770         icmp_param_t index;
    771 
    772         if (!echo_data)
    773                 return EBADMEM;
    774 
    775         /* From the last used one */
    776         index = icmp_globals.last_used_id;
    777         do {
    778                 index++;
    779                 /* til the range end */
    780                 if (index >= ICMP_FREE_IDS_END) {
    781                         /* start from the range beginning */
    782                         index = ICMP_FREE_IDS_START - 1;
    783                         do {
    784                                 index++;
    785                                 /* til the last used one */
    786                                 if (index >= icmp_globals.last_used_id) {
    787                                         /* none found */
    788                                         return ENOTCONN;
    789                                 }
    790                         } while(icmp_echo_data_find(&icmp_globals.echo_data,
    791                             index) != NULL);
    792 
    793                         /* Found, break immediately */
    794                         break;
    795                 }
    796         } while (icmp_echo_data_find(&icmp_globals.echo_data, index) != NULL);
    797 
    798         echo_data->identifier = index;
    799         echo_data->sequence_number = 0;
    800 
    801         return icmp_echo_data_add(&icmp_globals.echo_data, index, echo_data);
    802 }
    803 
    804 /** Processes the client messages.
    805  *
    806  * Remembers the assigned identifier and sequence numbers.
    807  * Runs until the client module disconnects.
    808  *
    809  * @param[in] callid    The message identifier.
    810  * @param[in] call      The message parameters.
    811  * @return EOK.
    812  *
    813  * @see icmp_interface.h
    814  * @see icmp_api.h
    815  */
    816 static int icmp_process_client_messages(ipc_callid_t callid, ipc_call_t call)
    817 {
    818         bool keep_on_going = true;
    819         ipc_call_t answer;
    820         size_t answer_count;
    821         size_t length;
    822         struct sockaddr *addr;
    823         ipc_callid_t data_callid;
    824         icmp_echo_t *echo_data;
    825         int rc = EOK;
    826 
    827         /*
    828          * Accept the connection
    829          *  - Answer the first NET_ICMP_INIT call.
    830          */
    831         answer_count = 0;
    832 
    833         echo_data = (icmp_echo_t *) malloc(sizeof(*echo_data));
    834         if (!echo_data)
    835                 return ENOMEM;
    836 
    837         /* Assign a new identifier */
    838         fibril_rwlock_write_lock(&icmp_globals.lock);
    839         rc = icmp_bind_free_id(echo_data);
    840         fibril_rwlock_write_unlock(&icmp_globals.lock);
    841         if (rc < 0) {
    842                 free(echo_data);
    843                 return rc;
    844         }
    845 
    846         while (keep_on_going) {
    847                 /* Answer the call */
    848                 answer_call(callid, rc, &answer, answer_count);
    849 
    850                 /* Refresh data */
    851                 refresh_answer(&answer, &answer_count);
    852 
    853                 /* Get the next call */
    854                 callid = async_get_call(&call);
    855 
    856                 /* Process the call */
    857                 switch (IPC_GET_IMETHOD(call)) {
    858                 case IPC_M_PHONE_HUNGUP:
    859                         keep_on_going = false;
    860                         rc = EHANGUP;
    861                         break;
    862                
    863                 case NET_ICMP_ECHO:
    864                         if (!async_data_write_receive(&data_callid, &length)) {
    865                                 rc = EINVAL;
    866                                 break;
    867                         }
    868                        
    869                         addr = malloc(length);
    870                         if (!addr) {
    871                                 rc = ENOMEM;
    872                                 break;
    873                         }
    874                        
    875                         rc = async_data_write_finalize(data_callid, addr,
    876                             length);
    877                         if (rc != EOK) {
    878                                 free(addr);
    879                                 break;
    880                         }
    881 
    882                         fibril_rwlock_write_lock(&icmp_globals.lock);
    883                         rc = icmp_echo(echo_data->identifier,
    884                             echo_data->sequence_number, ICMP_GET_SIZE(call),
    885                             ICMP_GET_TIMEOUT(call), ICMP_GET_TTL(call),
    886                             ICMP_GET_TOS(call), ICMP_GET_DONT_FRAGMENT(call),
    887                             addr, (socklen_t) length);
    888                         fibril_rwlock_write_unlock(&icmp_globals.lock);
    889 
    890                         free(addr);
    891 
    892                         if (echo_data->sequence_number < UINT16_MAX)
    893                                 echo_data->sequence_number++;
    894                         else
    895                                 echo_data->sequence_number = 0;
    896 
    897                         break;
    898 
    899                 default:
    900                         rc = icmp_process_message(&call);
    901                 }
    902 
    903         }
    904 
    905         /* Release the identifier */
    906         fibril_rwlock_write_lock(&icmp_globals.lock);
    907         icmp_echo_data_exclude(&icmp_globals.echo_data, echo_data->identifier);
    908         fibril_rwlock_write_unlock(&icmp_globals.lock);
    909 
    910         return rc;
    911 }
    912 
    913 /** Processes the ICMP message.
    914  *
    915  * @param[in] callid    The message identifier.
    916  * @param[in] call      The message parameters.
    917  * @param[out] answer   The message answer parameters.
    918  * @param[out] answer_count The last parameter for the actual answer in the
    919  *                      answer parameter.
    920  * @return              EOK on success.
    921  * @return              ENOTSUP if the message is not known.
    922  *
    923  * @see icmp_interface.h
    924  * @see IS_NET_ICMP_MESSAGE()
    925  */
    926 int tl_module_message   (ipc_callid_t callid, ipc_call_t *call,
    927     ipc_call_t *answer, size_t *answer_count)
    928 {
    929         *answer_count = 0;
    930         switch (IPC_GET_IMETHOD(*call)) {
    931         case NET_ICMP_INIT:
    932                 return icmp_process_client_messages(callid, *call);
    933         default:
    934                 return icmp_process_message(call);
    935789        }
    936790       
  • uspace/srv/net/tl/tcp/tcp.c

    r9f3864a rf1938c6  
    6464#include <ip_interface.h>
    6565#include <icmp_client.h>
    66 #include <icmp_interface.h>
     66#include <icmp_remote.h>
    6767#include <net_interface.h>
    6868#include <socket_core.h>
     
    12041204}
    12051205
     1206/** Per-connection initialization
     1207 *
     1208 */
     1209void tl_connection(void)
     1210{
     1211}
     1212
    12061213/** Processes the TCP message.
    12071214 *
     
    12171224 * @see IS_NET_TCP_MESSAGE()
    12181225 */
    1219 int tl_module_message(ipc_callid_t callid, ipc_call_t *call,
     1226int tl_message(ipc_callid_t callid, ipc_call_t *call,
    12201227    ipc_call_t *answer, size_t *answer_count)
    12211228{
     
    24722479        tcp_globals.net_phone = net_phone;
    24732480       
    2474         tcp_globals.icmp_phone = icmp_connect_module(SERVICE_ICMP,
    2475             ICMP_CONNECT_TIMEOUT);
     2481        tcp_globals.icmp_phone = icmp_connect_module(ICMP_CONNECT_TIMEOUT);
    24762482        tcp_globals.ip_phone = ip_bind_service(SERVICE_IP, IPPROTO_TCP,
    24772483            SERVICE_TCP, tcp_receiver);
  • uspace/srv/net/tl/udp/udp.c

    r9f3864a rf1938c6  
    6161#include <ip_interface.h>
    6262#include <icmp_client.h>
    63 #include <icmp_interface.h>
     63#include <icmp_remote.h>
    6464#include <net_interface.h>
    6565#include <socket_core.h>
     
    393393        udp_globals.net_phone = net_phone;
    394394       
    395         udp_globals.icmp_phone = icmp_connect_module(SERVICE_ICMP,
    396             ICMP_CONNECT_TIMEOUT);
     395        udp_globals.icmp_phone = icmp_connect_module(ICMP_CONNECT_TIMEOUT);
    397396       
    398397        udp_globals.ip_phone = ip_bind_service(SERVICE_IP, IPPROTO_UDP,
     
    878877}
    879878
     879/** Per-connection initialization
     880 *
     881 */
     882void tl_connection(void)
     883{
     884}
     885
    880886/** Processes the UDP message.
    881887 *
     
    891897 * @see IS_NET_UDP_MESSAGE()
    892898 */
    893 int tl_module_message(ipc_callid_t callid, ipc_call_t *call,
     899int tl_message(ipc_callid_t callid, ipc_call_t *call,
    894900    ipc_call_t *answer, size_t *answer_count)
    895901{
Note: See TracChangeset for help on using the changeset viewer.