Changes in / [c979591b:4f380d06] in mainline


Ignore:
Files:
2 added
3 deleted
26 edited

Legend:

Unmodified
Added
Removed
  • kernel/generic/include/mm/page.h

    rc979591b r4f380d06  
    3737
    3838#include <typedefs.h>
    39 #include <proc/task.h>
    4039#include <mm/as.h>
    4140#include <memstr.h>
     
    6362extern uintptr_t hw_map(uintptr_t, size_t);
    6463
    65 extern sysarg_t sys_page_find_mapping(uintptr_t, uintptr_t *);
    66 
    6764#endif
    6865
  • kernel/generic/include/syscall/syscall.h

    rc979591b r4f380d06  
    5959        SYS_AS_AREA_DESTROY,
    6060       
    61         SYS_PAGE_FIND_MAPPING,
    62        
    6361        SYS_IPC_CALL_SYNC_FAST,
    6462        SYS_IPC_CALL_SYNC_SLOW,
  • kernel/generic/src/adt/avl.c

    rc979591b r4f380d06  
    723723void avltree_walk(avltree_t *t, avltree_walker_t walker, void *arg)
    724724{
    725         if (t->root)
    726                 _avltree_walk(t->root, walker, arg);
     725        _avltree_walk(t->root, walker, arg);
    727726}
    728727
  • kernel/generic/src/mm/page.c

    rc979591b r4f380d06  
    6060
    6161#include <mm/page.h>
    62 #include <genarch/mm/page_ht.h>
    63 #include <genarch/mm/page_pt.h>
    6462#include <arch/mm/page.h>
    6563#include <arch/mm/asid.h>
     
    7270#include <debug.h>
    7371#include <arch.h>
    74 #include <syscall/copy.h>
    75 #include <errno.h>
    7672
    7773/** Virtual operations for page subsystem. */
     
    177173}
    178174
    179 /** Syscall wrapper for getting mapping of a virtual page.
    180  *
    181  * @retval EOK Everything went find, @p uspace_frame and @p uspace_node
    182  *             contains correct values.
    183  * @retval ENOENT Virtual address has no mapping.
    184  */
    185 sysarg_t sys_page_find_mapping(uintptr_t virt_address,
    186     uintptr_t *uspace_frame)
    187 {
    188         mutex_lock(&AS->lock);
    189        
    190         pte_t *pte = page_mapping_find(AS, virt_address);
    191         if (!PTE_VALID(pte) || !PTE_PRESENT(pte)) {
    192                 mutex_unlock(&AS->lock);
    193                
    194                 return (sysarg_t) ENOENT;
    195         }
    196        
    197         uintptr_t phys_address = PTE_GET_FRAME(pte);
    198        
    199         mutex_unlock(&AS->lock);
    200        
    201         int rc = copy_to_uspace(uspace_frame,
    202             &phys_address, sizeof(phys_address));
    203         if (rc != EOK) {
    204                 return (sysarg_t) rc;
    205         }
    206        
    207         return EOK;
    208 }
    209 
    210175/** @}
    211176 */
  • kernel/generic/src/syscall/syscall.c

    rc979591b r4f380d06  
    4141#include <proc/program.h>
    4242#include <mm/as.h>
    43 #include <mm/page.h>
    4443#include <print.h>
    4544#include <arch.h>
     
    145144        (syshandler_t) sys_as_area_destroy,
    146145       
    147         /* Page mapping related syscalls. */
    148         (syshandler_t) sys_page_find_mapping,
    149        
    150146        /* IPC related syscalls. */
    151147        (syshandler_t) sys_ipc_call_sync_fast,
  • uspace/app/ping/ping.c

    rc979591b r4f380d06  
    340340            config.dest_str, config.size, config.size);
    341341       
    342         int icmp_phone = icmp_connect_module(ICMP_CONNECT_TIMEOUT);
     342        int icmp_phone = icmp_connect_module(SERVICE_ICMP, ICMP_CONNECT_TIMEOUT);
    343343        if (icmp_phone < 0) {
    344344                fprintf(stderr, "%s: Unable to connect to ICMP service (%s)\n", NAME,
  • uspace/app/tester/Makefile

    rc979591b r4f380d06  
    5353        loop/loop1.c \
    5454        mm/malloc1.c \
    55         mm/mapping1.c \
    5655        hw/misc/virtchar1.c \
    5756        hw/serial/serial1.c
  • uspace/app/tester/tester.c

    rc979591b r4f380d06  
    6262#include "loop/loop1.def"
    6363#include "mm/malloc1.def"
    64 #include "mm/mapping1.def"
    6564#include "hw/serial/serial1.def"
    6665#include "adt/usbaddrkeep.def"
  • uspace/app/tester/tester.h

    rc979591b r4f380d06  
    7979extern const char *test_loop1(void);
    8080extern const char *test_malloc1(void);
    81 extern const char *test_mapping1(void);
    8281extern const char *test_serial1(void);
    8382extern const char *test_usbaddrkeep(void);
  • uspace/app/virtusbkbd/keys.h

    rc979591b r4f380d06  
    4040
    4141/** Maximum number of keys that can be pressed simultaneously. */
    42 #define KB_MAX_KEYS_AT_ONCE 6
     42#define KB_MAX_KEYS_AT_ONCE 4
    4343
    4444/** Key code type. */
  • uspace/lib/c/generic/as.c

    rc979591b r4f380d06  
    3535#include <as.h>
    3636#include <libc.h>
    37 #include <errno.h>
    3837#include <unistd.h>
    3938#include <align.h>
     
    129128}
    130129
    131 /** Find mapping to physical address.
    132  *
    133  * @param address Virtual address in question (virtual).
    134  * @param[out] frame Frame address (physical).
    135  * @return Error code.
    136  * @retval EOK No error, @p frame holds the translation.
    137  * @retval ENOENT Mapping not found.
    138  */
    139 int as_get_physical_mapping(void *address, uintptr_t *frame)
    140 {
    141         uintptr_t tmp_frame;
    142         uintptr_t virt = (uintptr_t) address;
    143        
    144         int rc = (int) __SYSCALL2(SYS_PAGE_FIND_MAPPING,
    145             (sysarg_t) virt, (sysarg_t) &tmp_frame);
    146         if (rc != EOK) {
    147                 return rc;
    148         }
    149        
    150         if (frame != NULL) {
    151                 *frame = tmp_frame;
    152         }
    153        
    154         return EOK;
    155 }
    156 
    157130/** @}
    158131 */
  • uspace/lib/c/generic/net/icmp_common.c

    rc979591b r4f380d06  
    2727 */
    2828
    29 /** @addtogroup libc
     29/** @addtogroup libc 
    3030 *  @{
    3131 */
     
    3838#include <net/modules.h>
    3939#include <net/icmp_common.h>
     40
    4041#include <ipc/services.h>
    4142#include <ipc/icmp.h>
     43
    4244#include <sys/time.h>
    4345#include <async.h>
    4446
    45 /** Connect to the ICMP module.
     47/** Connects to the ICMP module.
    4648 *
    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  *
     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.
    5354 */
    54 int icmp_connect_module(suseconds_t timeout)
     55int icmp_connect_module(services_t service, suseconds_t timeout)
    5556{
    56         return connect_to_service_timeout(SERVICE_ICMP, timeout);
     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;
    5764}
    5865
  • uspace/lib/c/include/adt/hash_table.h

    rc979591b r4f380d06  
    4141typedef unsigned long hash_count_t;
    4242typedef unsigned long hash_index_t;
    43 
    44 /** Set of operations for hash table. */
    45 typedef 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;
     43typedef struct hash_table hash_table_t;
     44typedef struct hash_table_operations hash_table_operations_t;
    7345
    7446/** Hash table structure. */
    75 typedef struct {
     47struct hash_table {
    7648        link_t *entry;
    7749        hash_count_t entries;
    7850        hash_count_t max_keys;
    7951        hash_table_operations_t *op;
    80 } hash_table_t;
     52};
     53
     54/** Set of operations for hash table. */
     55struct 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};
    8180
    8281#define hash_table_get_instance(item, type, member) \
  • uspace/lib/c/include/as.h

    rc979591b r4f380d06  
    4747extern void *set_maxheapsize(size_t mhs);
    4848extern void * as_get_mappable_page(size_t sz);
    49 extern int as_get_physical_mapping(void *address, uintptr_t *frame);
    5049
    5150#endif
  • uspace/lib/c/include/ipc/icmp.h

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

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

    rc979591b r4f380d06  
    4545
    4646/** ICMP header size in bytes. */
    47 #define ICMP_HEADER_SIZE  sizeof(icmp_header_t)
     47#define ICMP_HEADER_SIZE        sizeof(icmp_header_t)
     48
     49/** Type definition of the echo specific data.
     50 * @see icmp_echo
     51 */
     52typedef struct icmp_echo icmp_echo_t;
    4853
    4954/** Echo specific data. */
    50 typedef struct icmp_echo {
     55struct icmp_echo {
    5156        /** Message idintifier. */
    5257        icmp_param_t identifier;
    5358        /** Message sequence number. */
    5459        icmp_param_t sequence_number;
    55 } __attribute__((packed)) icmp_echo_t;
     60} __attribute__ ((packed));
     61
     62/** Type definition of the internet control message header.
     63 * @see icmp_header
     64 */
     65typedef struct icmp_header icmp_header_t;
    5666
    5767/** Internet control message header. */
    58 typedef struct icmp_header {
     68struct icmp_header {
    5969        /** The type of the message. */
    6070        uint8_t type;
     
    7383         */
    7484        uint16_t checksum;
    75        
     85
    7686        /** Message specific data. */
    7787        union {
    7888                /** Echo specific data. */
    79                 icmp_echo_t echo;
     89                icmp_echo_t  echo;
    8090                /** Proposed gateway value. */
    8191                in_addr_t gateway;
     
    97107                } param;
    98108        } un;
    99 } __attribute__((packed)) icmp_header_t;
     109} __attribute__ ((packed));
    100110
    101111#endif
  • uspace/lib/net/include/tl_skel.h

    rc979591b r4f380d06  
    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  */
    68 extern void tl_connection(void);
    69 
    7063/** Process the transport layer module message.
    7164 *
     
    8174 *
    8275 */
    83 extern int tl_message(ipc_callid_t, ipc_call_t *,
     76extern int tl_module_message(ipc_callid_t, ipc_call_t *,
    8477    ipc_call_t *, size_t *);
    8578
  • uspace/lib/net/tl/icmp_remote.c

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

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

    rc979591b r4f380d06  
    5656        ipc_answer_0(iid, EOK);
    5757       
    58         /* Per-connection initialization */
    59         tl_connection();
    60        
    6158        while (true) {
    6259                ipc_call_t answer;
     
    7168               
    7269                /* Process the message */
    73                 int res = tl_message(callid, &call, &answer, &count);
     70                int res = tl_module_message(callid, &call, &answer,
     71                    &count);
    7472               
    7573                /*
  • uspace/lib/usb/src/recognise.c

    rc979591b r4f380d06  
    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                 }
    209205               
    210206                position += cur_descr_len;
  • uspace/srv/net/il/ip/ip.c

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

    rc979591b r4f380d06  
    3333/** @file
    3434 * ICMP module implementation.
     35 * @see icmp.h
    3536 */
    3637
     
    5051#include <byteorder.h>
    5152#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_remote.h>
     66#include <icmp_interface.h>
    6767#include <il_remote.h>
    6868#include <ip_client.h>
     
    7373#include <icmp_header.h>
    7474
    75 /** ICMP module name */
     75#include "icmp.h"
     76
     77/** ICMP module name. */
    7678#define NAME  "icmp"
    7779
    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  *
     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.
    97102 */
    98103#define ICMP_CHECKSUM(header, length) \
     
    100105
    101106/** An echo request datagrams pattern. */
    102 #define ICMP_ECHO_TEXT  "ICMP hello from HelenOS."
    103 
    104 /** ICMP reply data. */
    105 typedef 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 */
    121 static int phone_net = -1;
    122 static int phone_ip = -1;
    123 static bool error_reporting = true;
    124 static bool echo_replying = true;
    125 static packet_dimension_t icmp_dimension;
    126 
    127 /** ICMP client identification counter */
    128 static atomic_t icmp_client;
    129 
    130 /** ICMP identifier and sequence number (client-specific) */
    131 static fibril_local icmp_param_t icmp_id;
    132 static fibril_local icmp_param_t icmp_seq;
    133 
    134 /** Reply hash table */
    135 static fibril_mutex_t reply_lock;
    136 static hash_table_t replies;
    137 
    138 static 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 
    148 static 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 
    159 static void replies_remove_callback(link_t *item)
    160 {
    161 }
    162 
    163 static 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  */
    174 static 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.
     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. */
     120icmp_globals_t  icmp_globals;
     121
     122INT_MAP_IMPLEMENT(icmp_replies, icmp_reply_t);
     123INT_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 */
     131static 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.
    182140 * Error messages are sent only if allowed in the configuration.
    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  */
    199 static 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 {
     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 */
     156static 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
    203162        /* Do not send an error if disabled */
    204         if ((error) && (!error_reporting)) {
    205                 icmp_release(packet);
    206                 return EPERM;
    207         }
    208        
     163        if (error && !icmp_globals.error_reporting)
     164                return icmp_release_and_return(packet, EPERM);
     165
    209166        header->type = type;
    210167        header->code = code;
    211        
    212         /*
    213          * The checksum needs to be calculated
    214          * with a virtual checksum field set to
    215          * zero.
    216          */
    217168        header->checksum = 0;
    218169        header->checksum = ICMP_CHECKSUM(header,
    219170            packet_get_data_length(packet));
    220171       
    221         int rc = ip_client_prepare_packet(packet, IPPROTO_ICMP, ttl, tos,
     172        rc = ip_client_prepare_packet(packet, IPPROTO_ICMP, ttl, tos,
    222173            dont_fragment, 0);
    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  *
     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.
    238187 * @return The prefixed ICMP header.
    239188 * @return NULL on errors.
    240  *
    241189 */
    242190static icmp_header_t *icmp_prepare_packet(packet_t *packet)
    243191{
    244         size_t total_length = packet_get_data_length(packet);
     192        icmp_header_t *header;
     193        size_t header_length;
     194        size_t total_length;
     195
     196        total_length = packet_get_data_length(packet);
    245197        if (total_length <= 0)
    246198                return NULL;
    247        
    248         size_t header_length = ip_client_header_length(packet);
     199
     200        header_length = ip_client_header_length(packet);
    249201        if (header_length <= 0)
    250202                return NULL;
    251        
     203
    252204        /* Truncate if longer than 64 bits (without the IP header) */
    253205        if ((total_length > header_length + ICMP_KEEP_LENGTH) &&
    254206            (packet_trim(packet, 0,
    255             total_length - header_length - ICMP_KEEP_LENGTH) != EOK))
     207            total_length - header_length - ICMP_KEEP_LENGTH) != EOK)) {
    256208                return NULL;
    257        
    258         icmp_header_t *header = PACKET_PREFIX(packet, icmp_header_t);
     209        }
     210
     211        header = PACKET_PREFIX(packet, icmp_header_t);
    259212        if (!header)
    260213                return NULL;
    261        
     214
    262215        bzero(header, sizeof(*header));
    263216        return header;
    264217}
    265218
    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  *
     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.
    290243 */
    291244static int icmp_echo(icmp_param_t id, icmp_param_t sequence, size_t size,
    292     mseconds_t timeout, ip_ttl_t ttl, ip_tos_t tos, bool dont_fragment,
    293     const struct sockaddr *addr, socklen_t addrlen)
    294 {
     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
    295257        if (addrlen <= 0)
    296258                return EINVAL;
    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);
     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);
    303271        if (!packet)
    304272                return ENOMEM;
    305        
     273
    306274        /* Prepare the requesting packet, set the destination address. */
    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        
     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
    313279        /* Allocate space in the packet */
    314         uint8_t *data = (uint8_t *) packet_suffix(packet, size);
    315         if (!data) {
    316                 icmp_release(packet);
    317                 return ENOMEM;
    318         }
    319        
     280        data = (uint8_t *) packet_suffix(packet, size);
     281        if (!data)
     282                return icmp_release_and_return(packet, ENOMEM);
     283
    320284        /* Fill the data */
    321285        length = 0;
     
    325289        }
    326290        memcpy(data + length, ICMP_ECHO_TEXT, size - length);
    327        
     291
    328292        /* Prefix the 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));
     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));
    336298        header->un.echo.identifier = id;
    337299        header->un.echo.sequence_number = sequence;
    338        
     300
    339301        /* Prepare the reply structure */
    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;
     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);
    348308        fibril_condvar_initialize(&reply->condvar);
    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        
     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
    356320        /* Send the request */
    357321        icmp_send_packet(ICMP_ECHO, 0, packet, header, 0, ttl, tos,
    358322            dont_fragment);
    359        
     323
    360324        /* Wait for the reply. Timeout in microseconds. */
    361         rc = fibril_condvar_wait_timeout(&reply->condvar, &reply_lock,
     325        rc = fibril_condvar_wait_timeout(&reply->condvar, &reply->mutex,
    362326            timeout * 1000);
    363327        if (rc == EOK)
    364328                rc = reply->result;
    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        
     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
    373337        return rc;
    374338}
    375339
    376 static 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        
     340static 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
    385349        if (mtu)
    386350                header->un.frag.mtu = mtu;
    387        
     351
    388352        return icmp_send_packet(ICMP_DEST_UNREACH, code, packet, header,
    389             SERVICE_ICMP, 0, 0, false);
    390 }
    391 
    392 static 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        
     353            SERVICE_ICMP, 0, 0, 0);
     354}
     355
     356static 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
    400364        return icmp_send_packet(ICMP_SOURCE_QUENCH, 0, packet, header,
    401             SERVICE_ICMP, 0, 0, false);
    402 }
    403 
    404 static 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        
     365            SERVICE_ICMP, 0, 0, 0);
     366}
     367
     368static int icmp_time_exceeded_msg_local(int icmp_phone, icmp_code_t code,
     369    packet_t *packet)
     370{
     371        icmp_header_t *header;
     372
     373        header = icmp_prepare_packet(packet);
     374        if (!header)
     375                return icmp_release_and_return(packet, ENOMEM);
     376
    412377        return icmp_send_packet(ICMP_TIME_EXCEEDED, code, packet, header,
    413             SERVICE_ICMP, 0, 0, false);
    414 }
    415 
    416 static int icmp_parameter_problem(icmp_code_t code, icmp_param_t pointer,
    417     packet_t *packet)
    418 {
    419         icmp_header_t *header = icmp_prepare_packet(packet);
    420         if (!header) {
    421                 icmp_release(packet);
    422                 return ENOMEM;
    423         }
    424        
     378            SERVICE_ICMP, 0, 0, 0);
     379}
     380
     381static 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
    425390        header->un.param.pointer = pointer;
    426391        return icmp_send_packet(ICMP_PARAMETERPROB, code, packet, header,
    427             SERVICE_ICMP, 0, 0, false);
    428 }
    429 
    430 /** Try to set the pending reply result as the received message type.
     392            SERVICE_ICMP, 0, 0, 0);
     393}
     394
     395/** Tries to set the pending reply result as the received message type.
    431396 *
    432397 * If the reply data is not present, the reply timed out and the other fibril
    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  */
    441 static void icmp_process_echo_reply(packet_t *packet, icmp_header_t *header,
     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 */
     406static void  icmp_process_echo_reply(packet_t *packet, icmp_header_t *header,
    442407    icmp_type_t type, icmp_code_t code)
    443408{
    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        
     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
    450417        /* Find the pending 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                
     418        fibril_rwlock_write_lock(&icmp_globals.lock);
     419        reply = icmp_replies_find(&icmp_globals.replies, reply_key);
     420        if (reply) {
    458421                reply->result = type;
    459422                fibril_condvar_signal(&reply->condvar);
    460423        }
    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  *
     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.
    484444 */
    485445static int icmp_process_packet(packet_t *packet, services_t error)
    486446{
     447        size_t length;
     448        uint8_t *src;
     449        int addrlen;
     450        int result;
     451        void *data;
     452        icmp_header_t *header;
    487453        icmp_type_t type;
    488454        icmp_code_t code;
     
    494460        case SERVICE_ICMP:
    495461                /* Process error */
    496                 rc = icmp_client_process_packet(packet, &type, &code, NULL, NULL);
    497                 if (rc < 0)
    498                         return rc;
    499                
     462                result = icmp_client_process_packet(packet, &type, &code, NULL,
     463                    NULL);
     464                if (result < 0)
     465                        return result;
     466                length = (size_t) result;
    500467                /* Remove the error header */
    501                 rc = packet_trim(packet, (size_t) rc, 0);
     468                rc = packet_trim(packet, length, 0);
    502469                if (rc != EOK)
    503470                        return rc;
    504                
    505471                break;
    506472        default:
    507473                return ENOTSUP;
    508474        }
    509        
     475
    510476        /* Get rid of the IP header */
    511         size_t length = ip_client_header_length(packet);
     477        length = ip_client_header_length(packet);
    512478        rc = packet_trim(packet, length, 0);
    513479        if (rc != EOK)
    514480                return rc;
    515        
     481
    516482        length = packet_get_data_length(packet);
    517483        if (length <= 0)
    518484                return EINVAL;
    519        
     485
    520486        if (length < ICMP_HEADER_SIZE)
    521487                return EINVAL;
    522        
    523         void *data = packet_get_data(packet);
     488
     489        data = packet_get_data(packet);
    524490        if (!data)
    525491                return EINVAL;
    526        
     492
    527493        /* Get ICMP header */
    528         icmp_header_t *header = (icmp_header_t *) data;
    529        
     494        header = (icmp_header_t *) data;
     495
    530496        if (header->checksum) {
    531497                while (ICMP_CHECKSUM(header, length) != IP_CHECKSUM_ZERO) {
     
    541507                                }
    542508                        }
    543                        
    544509                        return EINVAL;
    545510                }
    546511        }
    547        
     512
    548513        switch (header->type) {
    549514        case ICMP_ECHOREPLY:
     
    552517                else
    553518                        icmp_process_echo_reply(packet, header, ICMP_ECHO, 0);
    554                
     519
    555520                return EOK;
    556        
     521
    557522        case ICMP_ECHO:
    558523                if (error) {
     
    562527               
    563528                /* Do not send a reply if disabled */
    564                 if (echo_replying) {
    565                         uint8_t *src;
    566                         int addrlen = packet_get_addr(packet, &src, NULL);
    567                        
     529                if (icmp_globals.echo_replying) {
     530                        addrlen = packet_get_addr(packet, &src, NULL);
     531
    568532                        /*
    569                          * Set both addresses to the source one (avoid the
     533                         * Set both addresses to the source one (avoids the
    570534                         * source address deletion before setting the
    571535                         * destination one).
     
    578542                                return EOK;
    579543                        }
    580                        
     544
    581545                        return EINVAL;
    582546                }
    583                
     547
    584548                return EPERM;
    585        
     549
    586550        case ICMP_DEST_UNREACH:
    587551        case ICMP_SOURCE_QUENCH:
     
    596560        case ICMP_SKIP:
    597561        case ICMP_PHOTURIS:
    598                 ip_received_error_msg(phone_ip, -1, packet,
     562                ip_received_error_msg(icmp_globals.ip_phone, -1, packet,
    599563                    SERVICE_IP, SERVICE_ICMP);
    600564                return EOK;
    601        
     565
    602566        default:
    603567                return ENOTSUP;
     
    605569}
    606570
     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 */
     585static 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
    607597/** Process IPC messages from the IP module
    608598 *
     
    613603static void icmp_receiver(ipc_callid_t iid, ipc_call_t *icall)
    614604{
    615         bool loop = true;
    616605        packet_t *packet;
    617606        int rc;
    618607       
    619         while (loop) {
     608        while (true) {
    620609                switch (IPC_GET_IMETHOD(*icall)) {
    621610                case NET_TL_RECEIVED:
    622                         rc = packet_translate_remote(phone_net, &packet,
     611                        rc = packet_translate_remote(icmp_globals.net_phone, &packet,
    623612                            IPC_GET_PACKET(*icall));
    624                         if (rc == EOK) {
    625                                 rc = icmp_process_packet(packet, IPC_GET_ERROR(*icall));
    626                                 if (rc != EOK)
    627                                         icmp_release(packet);
    628                         }
     613                        if (rc == EOK)
     614                                rc = icmp_received_msg_local(IPC_GET_DEVICE(*icall), packet,
     615                                    SERVICE_ICMP, IPC_GET_ERROR(*icall));
    629616                       
    630617                        ipc_answer_0(iid, (sysarg_t) rc);
    631618                        break;
    632                 case IPC_M_PHONE_HUNGUP:
    633                         loop = false;
    634                         continue;
    635619                default:
    636620                        ipc_answer_0(iid, (sysarg_t) ENOTSUP);
     
    665649        uint8_t *data;
    666650       
    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)
     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);
    681669                return rc;
    682        
    683         icmp_dimension.prefix += ICMP_HEADER_SIZE;
    684         icmp_dimension.content -= ICMP_HEADER_SIZE;
     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;
    685677       
    686678        /* Get configuration */
    687679        configuration = &names[0];
    688         rc = net_get_conf_req(phone_net, &configuration, count, &data);
    689         if (rc != EOK)
     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);
    690684                return rc;
     685        }
    691686       
    692687        if (configuration) {
    693                 if (configuration[0].value)
    694                         error_reporting = (configuration[0].value[0] == 'y');
    695                
    696                 if (configuration[1].value)
    697                         echo_replying = (configuration[1].value[0] == 'y');
    698                
     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                }
    699696                net_free_settings(configuration, data);
    700697        }
    701698       
     699        fibril_rwlock_write_unlock(&icmp_globals.lock);
    702700        return EOK;
    703701}
    704702
    705 /** Per-connection initialization
    706  *
    707  * Initialize client-specific global variables.
    708  *
    709  */
    710 void 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  */
    740 int 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;
     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 */
     721static int icmp_process_message(ipc_call_t *call)
     722{
    745723        packet_t *packet;
    746724        int rc;
    747        
    748         *count = 0;
    749        
     725
    750726        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        
    765727        case NET_ICMP_DEST_UNREACH:
    766                 rc = packet_translate_remote(phone_net, &packet,
     728                rc = packet_translate_remote(icmp_globals.net_phone, &packet,
    767729                    IPC_GET_PACKET(*call));
    768730                if (rc != EOK)
    769731                        return rc;
    770                
    771                 return icmp_destination_unreachable(ICMP_GET_CODE(*call),
    772                     ICMP_GET_MTU(*call), packet);
    773        
     732                return icmp_destination_unreachable_msg_local(0,
     733                    ICMP_GET_CODE(*call), ICMP_GET_MTU(*call), packet);
    774734        case NET_ICMP_SOURCE_QUENCH:
    775                 rc = packet_translate_remote(phone_net, &packet,
     735                rc = packet_translate_remote(icmp_globals.net_phone, &packet,
    776736                    IPC_GET_PACKET(*call));
    777737                if (rc != EOK)
    778738                        return rc;
    779                
    780                 return icmp_source_quench(packet);
    781        
     739                return icmp_source_quench_msg_local(0, packet);
    782740        case NET_ICMP_TIME_EXCEEDED:
    783                 rc = packet_translate_remote(phone_net, &packet,
     741                rc = packet_translate_remote(icmp_globals.net_phone, &packet,
    784742                    IPC_GET_PACKET(*call));
    785743                if (rc != EOK)
    786744                        return rc;
    787                
    788                 return icmp_time_exceeded(ICMP_GET_CODE(*call), packet);
    789        
     745                return icmp_time_exceeded_msg_local(0, ICMP_GET_CODE(*call),
     746                    packet);
    790747        case NET_ICMP_PARAMETERPROB:
    791                 rc = packet_translate_remote(phone_net, &packet,
     748                rc = packet_translate_remote(icmp_globals.net_phone, &packet,
    792749                    IPC_GET_PACKET(*call));
    793750                if (rc != EOK)
    794751                        return rc;
     752                return icmp_parameter_problem_msg_local(0, ICMP_GET_CODE(*call),
     753                    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 */
     768static 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 */
     816static 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;
    795862               
    796                 return icmp_parameter_problem(ICMP_GET_CODE(*call),
    797                     ICMP_GET_POINTER(*call), packet);
     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 */
     926int 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);
    798935        }
    799936       
  • uspace/srv/net/tl/tcp/tcp.c

    rc979591b r4f380d06  
    6464#include <ip_interface.h>
    6565#include <icmp_client.h>
    66 #include <icmp_remote.h>
     66#include <icmp_interface.h>
    6767#include <net_interface.h>
    6868#include <socket_core.h>
     
    12041204}
    12051205
    1206 /** Per-connection initialization
    1207  *
    1208  */
    1209 void tl_connection(void)
    1210 {
    1211 }
    1212 
    12131206/** Processes the TCP message.
    12141207 *
     
    12241217 * @see IS_NET_TCP_MESSAGE()
    12251218 */
    1226 int tl_message(ipc_callid_t callid, ipc_call_t *call,
     1219int tl_module_message(ipc_callid_t callid, ipc_call_t *call,
    12271220    ipc_call_t *answer, size_t *answer_count)
    12281221{
     
    24792472        tcp_globals.net_phone = net_phone;
    24802473       
    2481         tcp_globals.icmp_phone = icmp_connect_module(ICMP_CONNECT_TIMEOUT);
     2474        tcp_globals.icmp_phone = icmp_connect_module(SERVICE_ICMP,
     2475            ICMP_CONNECT_TIMEOUT);
    24822476        tcp_globals.ip_phone = ip_bind_service(SERVICE_IP, IPPROTO_TCP,
    24832477            SERVICE_TCP, tcp_receiver);
  • uspace/srv/net/tl/udp/udp.c

    rc979591b r4f380d06  
    6161#include <ip_interface.h>
    6262#include <icmp_client.h>
    63 #include <icmp_remote.h>
     63#include <icmp_interface.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(ICMP_CONNECT_TIMEOUT);
     395        udp_globals.icmp_phone = icmp_connect_module(SERVICE_ICMP,
     396            ICMP_CONNECT_TIMEOUT);
    396397       
    397398        udp_globals.ip_phone = ip_bind_service(SERVICE_IP, IPPROTO_UDP,
     
    877878}
    878879
    879 /** Per-connection initialization
    880  *
    881  */
    882 void tl_connection(void)
    883 {
    884 }
    885 
    886880/** Processes the UDP message.
    887881 *
     
    897891 * @see IS_NET_UDP_MESSAGE()
    898892 */
    899 int tl_message(ipc_callid_t callid, ipc_call_t *call,
     893int tl_module_message(ipc_callid_t callid, ipc_call_t *call,
    900894    ipc_call_t *answer, size_t *answer_count)
    901895{
Note: See TracChangeset for help on using the changeset viewer.