Changeset 50c06df in mainline


Ignore:
Timestamp:
2011-01-21T13:07:18Z (14 years ago)
Author:
Lubos Slovak <lubos.slovak@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
7d540c8
Parents:
e2b1548 (diff), 5d00e40 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merged development

Files:
1 deleted
16 edited
1 moved

Legend:

Unmodified
Added
Removed
  • kernel/generic/src/adt/avl.c

    re2b1548 r50c06df  
    723723void avltree_walk(avltree_t *t, avltree_walker_t walker, void *arg)
    724724{
    725         _avltree_walk(t->root, walker, arg);
     725        if (t->root)
     726                _avltree_walk(t->root, walker, arg);
    726727}
    727728
  • uspace/app/ping/ping.c

    re2b1548 r50c06df  
    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

    re2b1548 r50c06df  
    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/adt/hash_table.h

    re2b1548 r50c06df  
    4141typedef unsigned long hash_count_t;
    4242typedef unsigned long hash_index_t;
    43 typedef struct hash_table hash_table_t;
    44 typedef struct hash_table_operations hash_table_operations_t;
     43
     44/** Set of operations for hash table. */
     45typedef struct {
     46        /** Hash function.
     47         *
     48         * @param key Array of keys needed to compute hash index.
     49         *            All keys must be passed.
     50         *
     51         * @return Index into hash table.
     52         *
     53         */
     54        hash_index_t (*hash)(unsigned long key[]);
     55       
     56        /** Hash table item comparison function.
     57         *
     58         * @param key Array of keys that will be compared with item. It is
     59         *            not necessary to pass all keys.
     60         *
     61         * @return True if the keys match, false otherwise.
     62         *
     63         */
     64        int (*compare)(unsigned long key[], hash_count_t keys, link_t *item);
     65       
     66        /** Hash table item removal callback.
     67         *
     68         * @param item Item that was removed from the hash table.
     69         *
     70         */
     71        void (*remove_callback)(link_t *item);
     72} hash_table_operations_t;
    4573
    4674/** Hash table structure. */
    47 struct hash_table {
     75typedef struct {
    4876        link_t *entry;
    4977        hash_count_t entries;
    5078        hash_count_t max_keys;
    5179        hash_table_operations_t *op;
    52 };
    53 
    54 /** Set of operations for hash table. */
    55 struct hash_table_operations {
    56         /** Hash function.
    57          *
    58          * @param key   Array of keys needed to compute hash index. All keys
    59          *              must be passed.
    60          *
    61          * @return      Index into hash table.
    62          */
    63         hash_index_t (* hash)(unsigned long key[]);
    64        
    65         /** Hash table item comparison function.
    66          *
    67          * @param key   Array of keys that will be compared with item. It is
    68          *              not necessary to pass all keys.
    69          *
    70          * @return      true if the keys match, false otherwise.
    71          */
    72         int (*compare)(unsigned long key[], hash_count_t keys, link_t *item);
    73 
    74         /** Hash table item removal callback.
    75          *
    76          * @param item  Item that was removed from the hash table.
    77          */
    78         void (*remove_callback)(link_t *item);
    79 };
     80} hash_table_t;
    8081
    8182#define hash_table_get_instance(item, type, member) \
  • uspace/lib/c/include/ipc/icmp.h

    re2b1548 r50c06df  
    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

    re2b1548 r50c06df  
    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_header.h

    re2b1548 r50c06df  
    4545
    4646/** ICMP header size in bytes. */
    47 #define ICMP_HEADER_SIZE        sizeof(icmp_header_t)
    48 
    49 /** Type definition of the echo specific data.
    50  * @see icmp_echo
    51  */
    52 typedef struct icmp_echo icmp_echo_t;
     47#define ICMP_HEADER_SIZE  sizeof(icmp_header_t)
    5348
    5449/** Echo specific data. */
    55 struct icmp_echo {
     50typedef struct icmp_echo {
    5651        /** Message idintifier. */
    5752        icmp_param_t identifier;
    5853        /** Message sequence number. */
    5954        icmp_param_t sequence_number;
    60 } __attribute__ ((packed));
    61 
    62 /** Type definition of the internet control message header.
    63  * @see icmp_header
    64  */
    65 typedef struct icmp_header icmp_header_t;
     55} __attribute__((packed)) icmp_echo_t;
    6656
    6757/** Internet control message header. */
    68 struct icmp_header {
     58typedef struct icmp_header {
    6959        /** The type of the message. */
    7060        uint8_t type;
     
    8373         */
    8474        uint16_t checksum;
    85 
     75       
    8676        /** Message specific data. */
    8777        union {
    8878                /** Echo specific data. */
    89                 icmp_echo_t  echo;
     79                icmp_echo_t echo;
    9080                /** Proposed gateway value. */
    9181                in_addr_t gateway;
     
    10797                } param;
    10898        } un;
    109 } __attribute__ ((packed));
     99} __attribute__((packed)) icmp_header_t;
    110100
    111101#endif
  • uspace/lib/net/include/icmp_remote.h

    re2b1548 r50c06df  
    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

    re2b1548 r50c06df  
    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

    re2b1548 r50c06df  
    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

    re2b1548 r50c06df  
    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

    re2b1548 r50c06df  
    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/lib/usb/src/recognise.c

    re2b1548 r50c06df  
    203203                uint8_t cur_descr_len = current_descriptor[0];
    204204                uint8_t cur_descr_type = current_descriptor[1];
     205
     206                if (cur_descr_len == 0) {
     207                        return ENOENT;
     208                }
    205209               
    206210                position += cur_descr_len;
  • uspace/srv/net/il/ip/ip.c

    re2b1548 r50c06df  
    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

    re2b1548 r50c06df  
    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;
     125static packet_dimension_t icmp_dimension;
     126
     127/** ICMP client identification counter */
     128static atomic_t icmp_client;
     129
     130/** ICMP identifier and sequence number (client-specific) */
     131static fibril_local icmp_param_t icmp_id;
     132static fibril_local icmp_param_t icmp_seq;
     133
     134/** Reply hash table */
     135static fibril_mutex_t reply_lock;
     136static hash_table_t replies;
     137
     138static hash_index_t replies_hash(unsigned long key[])
     139{
     140        /*
     141         * ICMP identifier and sequence numbers
     142         * are 16-bit values.
     143         */
     144        hash_index_t index = ((key[0] & 0xffff) << 16) | (key[1] & 0xffff);
     145        return (index % REPLY_BUCKETS);
     146}
     147
     148static int replies_compare(unsigned long key[], hash_count_t keys, link_t *item)
     149{
     150        icmp_reply_t *reply =
     151            hash_table_get_instance(item, icmp_reply_t, link);
     152       
     153        if (keys == 1)
     154                return (reply->id == key[0]);
     155        else
     156                return ((reply->id == key[0]) && (reply->sequence == key[1]));
     157}
     158
     159static void replies_remove_callback(link_t *item)
     160{
     161}
     162
     163static hash_table_operations_t reply_ops = {
     164        .hash = replies_hash,
     165        .compare = replies_compare,
     166        .remove_callback = replies_remove_callback
     167};
     168
     169/** Release the packet and return the result.
     170 *
     171 * @param[in] packet Packet queue to be released.
     172 *
     173 */
     174static void icmp_release(packet_t *packet)
     175{
     176        pq_release_remote(phone_net, packet_get_id(packet));
     177}
     178
     179/** Send the ICMP message.
     180 *
     181 * Set the message type and code and compute the checksum.
    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;
     211       
     212        /*
     213         * The checksum needs to be calculated
     214         * with a virtual checksum field set to
     215         * zero.
     216         */
    168217        header->checksum = 0;
    169218        header->checksum = ICMP_CHECKSUM(header,
    170219            packet_get_data_length(packet));
    171220       
    172         rc = ip_client_prepare_packet(packet, IPPROTO_ICMP, ttl, tos,
     221        int rc = ip_client_prepare_packet(packet, IPPROTO_ICMP, ttl, tos,
    173222            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.
     223        if (rc != EOK) {
     224                icmp_release(packet);
     225                return rc;
     226        }
     227       
     228        return ip_send_msg(phone_ip, -1, packet, SERVICE_ICMP, error);
     229}
     230
     231/** Prepare the ICMP error packet.
     232 *
     233 * Truncate the original packet if longer than ICMP_KEEP_LENGTH bytes.
     234 * Prefix and return the ICMP header.
     235 *
     236 * @param[in,out] packet Original packet.
     237 *
    187238 * @return The prefixed ICMP header.
    188239 * @return NULL on errors.
     240 *
    189241 */
    190242static icmp_header_t *icmp_prepare_packet(packet_t *packet)
    191243{
    192         icmp_header_t *header;
    193         size_t header_length;
    194         size_t total_length;
    195 
    196         total_length = packet_get_data_length(packet);
     244        size_t total_length = packet_get_data_length(packet);
    197245        if (total_length <= 0)
    198246                return NULL;
    199 
    200         header_length = ip_client_header_length(packet);
     247       
     248        size_t header_length = ip_client_header_length(packet);
    201249        if (header_length <= 0)
    202250                return NULL;
    203 
     251       
    204252        /* Truncate if longer than 64 bits (without the IP header) */
    205253        if ((total_length > header_length + ICMP_KEEP_LENGTH) &&
    206254            (packet_trim(packet, 0,
    207             total_length - header_length - ICMP_KEEP_LENGTH) != EOK)) {
     255            total_length - header_length - ICMP_KEEP_LENGTH) != EOK))
    208256                return NULL;
    209         }
    210 
    211         header = PACKET_PREFIX(packet, icmp_header_t);
     257       
     258        icmp_header_t *header = PACKET_PREFIX(packet, icmp_header_t);
    212259        if (!header)
    213260                return NULL;
    214 
     261       
    215262        bzero(header, sizeof(*header));
    216263        return header;
    217264}
    218265
    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.
     266/** Request an echo message.
     267 *
     268 * Send a packet with specified parameters to the target host
     269 * and wait for the reply upto the given timeout.
     270 * Block the caller until the reply or the timeout occurs.
     271 *
     272 * @param[in] id            Message identifier.
     273 * @param[in] sequence      Message sequence parameter.
     274 * @param[in] size          Message data length in bytes.
     275 * @param[in] timeout       Timeout in miliseconds.
     276 * @param[in] ttl           Time to live.
     277 * @param[in] tos           Type of service.
     278 * @param[in] dont_fragment Disable fragmentation.
     279 * @param[in] addr          Target host address.
     280 * @param[in] addrlen       Torget host address length.
     281 *
     282 * @return ICMP_ECHO on success.
     283 * @return ETIMEOUT if the reply has not arrived before the
     284 *         timeout.
     285 * @return ICMP type of the received error notification.
     286 * @return EINVAL if the addrlen parameter is less or equal to
     287 *         zero.
     288 * @return ENOMEM if there is not enough memory left.
     289 *
    243290 */
    244291static 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 
     292    mseconds_t timeout, ip_ttl_t ttl, ip_tos_t tos, bool dont_fragment,
     293    const struct sockaddr *addr, socklen_t addrlen)
     294{
    257295        if (addrlen <= 0)
    258296                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);
     297       
     298        size_t length = (size_t) addrlen;
     299       
     300        packet_t *packet = packet_get_4_remote(phone_net, size,
     301            icmp_dimension.addr_len, ICMP_HEADER_SIZE + icmp_dimension.prefix,
     302            icmp_dimension.suffix);
    271303        if (!packet)
    272304                return ENOMEM;
    273 
     305       
    274306        /* 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 
     307        int rc = packet_set_addr(packet, NULL, (const uint8_t *) addr, length);
     308        if (rc != EOK) {
     309                icmp_release(packet);
     310                return rc;
     311        }
     312       
    279313        /* 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 
     314        uint8_t *data = (uint8_t *) packet_suffix(packet, size);
     315        if (!data) {
     316                icmp_release(packet);
     317                return ENOMEM;
     318        }
     319       
    284320        /* Fill the data */
    285321        length = 0;
     
    289325        }
    290326        memcpy(data + length, ICMP_ECHO_TEXT, size - length);
    291 
     327       
    292328        /* Prefix the header */
    293         header = PACKET_PREFIX(packet, icmp_header_t);
    294         if (!header)
    295                 return icmp_release_and_return(packet, ENOMEM);
    296 
    297         bzero(header, sizeof(*header));
     329        icmp_header_t *header = PACKET_PREFIX(packet, icmp_header_t);
     330        if (!header) {
     331                icmp_release(packet);
     332                return ENOMEM;
     333        }
     334       
     335        bzero(header, sizeof(icmp_header_t));
    298336        header->un.echo.identifier = id;
    299337        header->un.echo.sequence_number = sequence;
    300 
     338       
    301339        /* 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);
     340        icmp_reply_t *reply = malloc(sizeof(icmp_reply_t));
     341        if (!reply) {
     342                icmp_release(packet);
     343                return ENOMEM;
     344        }
     345       
     346        reply->id = id;
     347        reply->sequence = sequence;
    308348        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 
     349       
     350        /* Add the reply to the replies hash table */
     351        fibril_mutex_lock(&reply_lock);
     352       
     353        unsigned long key[REPLY_KEYS] = {id, sequence};
     354        hash_table_insert(&replies, key, &reply->link);
     355       
    320356        /* Send the request */
    321357        icmp_send_packet(ICMP_ECHO, 0, packet, header, 0, ttl, tos,
    322358            dont_fragment);
    323 
     359       
    324360        /* Wait for the reply. Timeout in microseconds. */
    325         rc = fibril_condvar_wait_timeout(&reply->condvar, &reply->mutex,
     361        rc = fibril_condvar_wait_timeout(&reply->condvar, &reply_lock,
    326362            timeout * 1000);
    327363        if (rc == EOK)
    328364                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 
     365       
     366        /* Remove the reply from the replies hash table */
     367        hash_table_remove(&replies, key, REPLY_KEYS);
     368       
     369        fibril_mutex_unlock(&reply_lock);
     370       
     371        free(reply);
     372       
    337373        return rc;
    338374}
    339375
    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 
     376static int icmp_destination_unreachable(icmp_code_t code, icmp_param_t mtu,
     377    packet_t *packet)
     378{
     379        icmp_header_t *header = icmp_prepare_packet(packet);
     380        if (!header) {
     381                icmp_release(packet);
     382                return ENOMEM;
     383        }
     384       
    349385        if (mtu)
    350386                header->un.frag.mtu = mtu;
    351 
     387       
    352388        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 
     389            SERVICE_ICMP, 0, 0, false);
     390}
     391
     392static int icmp_source_quench(packet_t *packet)
     393{
     394        icmp_header_t *header = icmp_prepare_packet(packet);
     395        if (!header) {
     396                icmp_release(packet);
     397                return ENOMEM;
     398        }
     399       
    364400        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,
     401            SERVICE_ICMP, 0, 0, false);
     402}
     403
     404static int icmp_time_exceeded(icmp_code_t code, packet_t *packet)
     405{
     406        icmp_header_t *header = icmp_prepare_packet(packet);
     407        if (!header) {
     408                icmp_release(packet);
     409                return ENOMEM;
     410        }
     411       
     412        return icmp_send_packet(ICMP_TIME_EXCEEDED, code, packet, header,
     413            SERVICE_ICMP, 0, 0, false);
     414}
     415
     416static int icmp_parameter_problem(icmp_code_t code, icmp_param_t pointer,
    369417    packet_t *packet)
    370418{
    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 
     419        icmp_header_t *header = icmp_prepare_packet(packet);
     420        if (!header) {
     421                icmp_release(packet);
     422                return ENOMEM;
     423        }
     424       
    390425        header->un.param.pointer = pointer;
    391426        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.
     427            SERVICE_ICMP, 0, 0, false);
     428}
     429
     430/** Try to set the pending reply result as the received message type.
    396431 *
    397432 * 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,
     433 * is already awake. The packet is released.
     434 *
     435 * @param[in] packet The received reply message.
     436 * @param[in] header The ICMP message header.
     437 * @param[in] type   The received reply message type.
     438 * @param[in] code   The received reply message code.
     439 *
     440 */
     441static void icmp_process_echo_reply(packet_t *packet, icmp_header_t *header,
    407442    icmp_type_t type, icmp_code_t code)
    408443{
    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 
     444        unsigned long key[REPLY_KEYS] =
     445            {header->un.echo.identifier, header->un.echo.sequence_number};
     446       
     447        /* The packet is no longer needed */
     448        icmp_release(packet);
     449       
    417450        /* 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) {
     451        fibril_mutex_lock(&reply_lock);
     452       
     453        link_t *link = hash_table_find(&replies, key);
     454        if (link != NULL) {
     455                icmp_reply_t *reply =
     456                   hash_table_get_instance(link, icmp_reply_t, link);
     457               
    421458                reply->result = type;
    422459                fibril_condvar_signal(&reply->condvar);
    423460        }
    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.
     461       
     462        fibril_mutex_unlock(&reply_lock);
     463}
     464
     465/** Process the received ICMP packet.
     466 *
     467 * Notify the destination socket application.
     468 *
     469 * @param[in,out] packet Received packet.
     470 * @param[in]     error  Packet error reporting service to prefix
     471 *                       the received packet.
     472 *
     473 * @return EOK on success.
     474 * @return EINVAL if the packet is not valid.
     475 * @return EINVAL if the stored packet address is not the an_addr_t.
     476 * @return EINVAL if the packet does not contain any data.
     477 * @return NO_DATA if the packet content is shorter than the user
     478 *         datagram header.
     479 * @return ENOMEM if there is not enough memory left.
     480 * @return EADDRNOTAVAIL if the destination socket does not exist.
     481 * @return Other error codes as defined for the
     482 *         ip_client_process_packet() function.
     483 *
    444484 */
    445485static int icmp_process_packet(packet_t *packet, services_t error)
    446486{
    447         size_t length;
    448         uint8_t *src;
    449         int addrlen;
    450         int result;
    451         void *data;
    452         icmp_header_t *header;
    453487        icmp_type_t type;
    454488        icmp_code_t code;
     
    460494        case SERVICE_ICMP:
    461495                /* 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;
     496                rc = icmp_client_process_packet(packet, &type, &code, NULL, NULL);
     497                if (rc < 0)
     498                        return rc;
     499               
    467500                /* Remove the error header */
    468                 rc = packet_trim(packet, length, 0);
     501                rc = packet_trim(packet, (size_t) rc, 0);
    469502                if (rc != EOK)
    470503                        return rc;
     504               
    471505                break;
    472506        default:
    473507                return ENOTSUP;
    474508        }
    475 
     509       
    476510        /* Get rid of the IP header */
    477         length = ip_client_header_length(packet);
     511        size_t length = ip_client_header_length(packet);
    478512        rc = packet_trim(packet, length, 0);
    479513        if (rc != EOK)
    480514                return rc;
    481 
     515       
    482516        length = packet_get_data_length(packet);
    483517        if (length <= 0)
    484518                return EINVAL;
    485 
     519       
    486520        if (length < ICMP_HEADER_SIZE)
    487521                return EINVAL;
    488 
    489         data = packet_get_data(packet);
     522       
     523        void *data = packet_get_data(packet);
    490524        if (!data)
    491525                return EINVAL;
    492 
     526       
    493527        /* Get ICMP header */
    494         header = (icmp_header_t *) data;
    495 
     528        icmp_header_t *header = (icmp_header_t *) data;
     529       
    496530        if (header->checksum) {
    497531                while (ICMP_CHECKSUM(header, length) != IP_CHECKSUM_ZERO) {
     
    507541                                }
    508542                        }
     543                       
    509544                        return EINVAL;
    510545                }
    511546        }
    512 
     547       
    513548        switch (header->type) {
    514549        case ICMP_ECHOREPLY:
     
    517552                else
    518553                        icmp_process_echo_reply(packet, header, ICMP_ECHO, 0);
    519 
     554               
    520555                return EOK;
    521 
     556       
    522557        case ICMP_ECHO:
    523558                if (error) {
     
    527562               
    528563                /* Do not send a reply if disabled */
    529                 if (icmp_globals.echo_replying) {
    530                         addrlen = packet_get_addr(packet, &src, NULL);
    531 
     564                if (echo_replying) {
     565                        uint8_t *src;
     566                        int addrlen = packet_get_addr(packet, &src, NULL);
     567                       
    532568                        /*
    533                          * Set both addresses to the source one (avoids the
     569                         * Set both addresses to the source one (avoid the
    534570                         * source address deletion before setting the
    535571                         * destination one).
     
    542578                                return EOK;
    543579                        }
    544 
     580                       
    545581                        return EINVAL;
    546582                }
    547 
     583               
    548584                return EPERM;
    549 
     585       
    550586        case ICMP_DEST_UNREACH:
    551587        case ICMP_SOURCE_QUENCH:
     
    560596        case ICMP_SKIP:
    561597        case ICMP_PHOTURIS:
    562                 ip_received_error_msg(icmp_globals.ip_phone, -1, packet,
     598                ip_received_error_msg(phone_ip, -1, packet,
    563599                    SERVICE_IP, SERVICE_ICMP);
    564600                return EOK;
    565 
     601       
    566602        default:
    567603                return ENOTSUP;
     
    569605}
    570606
    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 
    597607/** Process IPC messages from the IP module
    598608 *
     
    603613static void icmp_receiver(ipc_callid_t iid, ipc_call_t *icall)
    604614{
     615        bool loop = true;
    605616        packet_t *packet;
    606617        int rc;
    607618       
    608         while (true) {
     619        while (loop) {
    609620                switch (IPC_GET_IMETHOD(*icall)) {
    610621                case NET_TL_RECEIVED:
    611                         rc = packet_translate_remote(icmp_globals.net_phone, &packet,
     622                        rc = packet_translate_remote(phone_net, &packet,
    612623                            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));
     624                        if (rc == EOK) {
     625                                rc = icmp_process_packet(packet, IPC_GET_ERROR(*icall));
     626                                if (rc != EOK)
     627                                        icmp_release(packet);
     628                        }
    616629                       
    617630                        ipc_answer_0(iid, (sysarg_t) rc);
    618631                        break;
     632                case IPC_M_PHONE_HUNGUP:
     633                        loop = false;
     634                        continue;
    619635                default:
    620636                        ipc_answer_0(iid, (sysarg_t) ENOTSUP);
     
    649665        uint8_t *data;
    650666       
    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);
     667        if (!hash_table_create(&replies, REPLY_BUCKETS, REPLY_KEYS, &reply_ops))
     668                return ENOMEM;
     669       
     670        fibril_mutex_initialize(&reply_lock);
     671        atomic_set(&icmp_client, 0);
     672       
     673        phone_net = net_phone;
     674        phone_ip = ip_bind_service(SERVICE_IP, IPPROTO_ICMP, SERVICE_ICMP,
     675            icmp_receiver);
     676        if (phone_ip < 0)
     677                return phone_ip;
     678       
     679        int rc = ip_packet_size_req(phone_ip, -1, &icmp_dimension);
     680        if (rc != EOK)
    669681                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;
     682       
     683        icmp_dimension.prefix += ICMP_HEADER_SIZE;
     684        icmp_dimension.content -= ICMP_HEADER_SIZE;
    677685       
    678686        /* Get configuration */
    679687        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);
     688        rc = net_get_conf_req(phone_net, &configuration, count, &data);
     689        if (rc != EOK)
    684690                return rc;
    685         }
    686691       
    687692        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                 }
     693                if (configuration[0].value)
     694                        error_reporting = (configuration[0].value[0] == 'y');
     695               
     696                if (configuration[1].value)
     697                        echo_replying = (configuration[1].value[0] == 'y');
     698               
    696699                net_free_settings(configuration, data);
    697700        }
    698701       
    699         fibril_rwlock_write_unlock(&icmp_globals.lock);
    700702        return EOK;
    701703}
    702704
    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 {
     705/** Per-connection initialization
     706 *
     707 * Initialize client-specific global variables.
     708 *
     709 */
     710void tl_connection(void)
     711{
     712        icmp_id = (icmp_param_t) atomic_postinc(&icmp_client);
     713        icmp_seq = 1;
     714}
     715
     716/** Process the ICMP message.
     717 *
     718 * @param[in]  callid Message identifier.
     719 * @param[in]  call   Message parameters.
     720 * @param[out] answer Answer.
     721 * @param[out] count  Number of arguments of the answer.
     722 *
     723 * @return EOK on success.
     724 * @return ENOTSUP if the message is not known.
     725 * @return Other error codes as defined for the packet_translate()
     726 *         function.
     727 * @return Other error codes as defined for the
     728 *         icmp_destination_unreachable() function.
     729 * @return Other error codes as defined for the
     730 *         icmp_source_quench() function.
     731 * @return Other error codes as defined for the
     732 *         icmp_time_exceeded() function.
     733 * @return Other error codes as defined for the
     734 *         icmp_parameter_problem() function.
     735 *
     736 * @see icmp_remote.h
     737 * @see IS_NET_ICMP_MESSAGE()
     738 *
     739 */
     740int tl_message(ipc_callid_t callid, ipc_call_t *call,
     741    ipc_call_t *answer, size_t *count)
     742{
     743        struct sockaddr *addr;
     744        size_t size;
    723745        packet_t *packet;
    724746        int rc;
    725 
     747       
     748        *count = 0;
     749       
    726750        switch (IPC_GET_IMETHOD(*call)) {
     751        case NET_ICMP_ECHO:
     752                rc = async_data_write_accept((void **) &addr, false, 0, 0, 0, &size);
     753                if (rc != EOK)
     754                        return rc;
     755               
     756                rc = icmp_echo(icmp_id, icmp_seq, ICMP_GET_SIZE(*call),
     757                    ICMP_GET_TIMEOUT(*call), ICMP_GET_TTL(*call),
     758                    ICMP_GET_TOS(*call), ICMP_GET_DONT_FRAGMENT(*call),
     759                    addr, (socklen_t) size);
     760               
     761                free(addr);
     762                icmp_seq++;
     763                return rc;
     764       
    727765        case NET_ICMP_DEST_UNREACH:
    728                 rc = packet_translate_remote(icmp_globals.net_phone, &packet,
     766                rc = packet_translate_remote(phone_net, &packet,
    729767                    IPC_GET_PACKET(*call));
    730768                if (rc != EOK)
    731769                        return rc;
    732                 return icmp_destination_unreachable_msg_local(0,
    733                     ICMP_GET_CODE(*call), ICMP_GET_MTU(*call), packet);
     770               
     771                return icmp_destination_unreachable(ICMP_GET_CODE(*call),
     772                    ICMP_GET_MTU(*call), packet);
     773       
    734774        case NET_ICMP_SOURCE_QUENCH:
    735                 rc = packet_translate_remote(icmp_globals.net_phone, &packet,
     775                rc = packet_translate_remote(phone_net, &packet,
    736776                    IPC_GET_PACKET(*call));
    737777                if (rc != EOK)
    738778                        return rc;
    739                 return icmp_source_quench_msg_local(0, packet);
     779               
     780                return icmp_source_quench(packet);
     781       
    740782        case NET_ICMP_TIME_EXCEEDED:
    741                 rc = packet_translate_remote(icmp_globals.net_phone, &packet,
     783                rc = packet_translate_remote(phone_net, &packet,
    742784                    IPC_GET_PACKET(*call));
    743785                if (rc != EOK)
    744786                        return rc;
    745                 return icmp_time_exceeded_msg_local(0, ICMP_GET_CODE(*call),
    746                     packet);
     787               
     788                return icmp_time_exceeded(ICMP_GET_CODE(*call), packet);
     789       
    747790        case NET_ICMP_PARAMETERPROB:
    748                 rc = packet_translate_remote(icmp_globals.net_phone, &packet,
     791                rc = packet_translate_remote(phone_net, &packet,
    749792                    IPC_GET_PACKET(*call));
    750793                if (rc != EOK)
    751794                        return rc;
    752                 return icmp_parameter_problem_msg_local(0, ICMP_GET_CODE(*call),
     795               
     796                return icmp_parameter_problem(ICMP_GET_CODE(*call),
    753797                    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);
    935798        }
    936799       
  • uspace/srv/net/tl/tcp/tcp.c

    re2b1548 r50c06df  
    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

    re2b1548 r50c06df  
    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.