Changes in / [c979591b:4f380d06] in mainline
- Files:
-
- 2 added
- 3 deleted
- 26 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/generic/include/mm/page.h
rc979591b r4f380d06 37 37 38 38 #include <typedefs.h> 39 #include <proc/task.h>40 39 #include <mm/as.h> 41 40 #include <memstr.h> … … 63 62 extern uintptr_t hw_map(uintptr_t, size_t); 64 63 65 extern sysarg_t sys_page_find_mapping(uintptr_t, uintptr_t *);66 67 64 #endif 68 65 -
kernel/generic/include/syscall/syscall.h
rc979591b r4f380d06 59 59 SYS_AS_AREA_DESTROY, 60 60 61 SYS_PAGE_FIND_MAPPING,62 63 61 SYS_IPC_CALL_SYNC_FAST, 64 62 SYS_IPC_CALL_SYNC_SLOW, -
kernel/generic/src/adt/avl.c
rc979591b r4f380d06 723 723 void avltree_walk(avltree_t *t, avltree_walker_t walker, void *arg) 724 724 { 725 if (t->root) 726 _avltree_walk(t->root, walker, arg); 725 _avltree_walk(t->root, walker, arg); 727 726 } 728 727 -
kernel/generic/src/mm/page.c
rc979591b r4f380d06 60 60 61 61 #include <mm/page.h> 62 #include <genarch/mm/page_ht.h>63 #include <genarch/mm/page_pt.h>64 62 #include <arch/mm/page.h> 65 63 #include <arch/mm/asid.h> … … 72 70 #include <debug.h> 73 71 #include <arch.h> 74 #include <syscall/copy.h>75 #include <errno.h>76 72 77 73 /** Virtual operations for page subsystem. */ … … 177 173 } 178 174 179 /** Syscall wrapper for getting mapping of a virtual page.180 *181 * @retval EOK Everything went find, @p uspace_frame and @p uspace_node182 * 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 210 175 /** @} 211 176 */ -
kernel/generic/src/syscall/syscall.c
rc979591b r4f380d06 41 41 #include <proc/program.h> 42 42 #include <mm/as.h> 43 #include <mm/page.h>44 43 #include <print.h> 45 44 #include <arch.h> … … 145 144 (syshandler_t) sys_as_area_destroy, 146 145 147 /* Page mapping related syscalls. */148 (syshandler_t) sys_page_find_mapping,149 150 146 /* IPC related syscalls. */ 151 147 (syshandler_t) sys_ipc_call_sync_fast, -
uspace/app/ping/ping.c
rc979591b r4f380d06 340 340 config.dest_str, config.size, config.size); 341 341 342 int icmp_phone = icmp_connect_module( ICMP_CONNECT_TIMEOUT);342 int icmp_phone = icmp_connect_module(SERVICE_ICMP, ICMP_CONNECT_TIMEOUT); 343 343 if (icmp_phone < 0) { 344 344 fprintf(stderr, "%s: Unable to connect to ICMP service (%s)\n", NAME, -
uspace/app/tester/Makefile
rc979591b r4f380d06 53 53 loop/loop1.c \ 54 54 mm/malloc1.c \ 55 mm/mapping1.c \56 55 hw/misc/virtchar1.c \ 57 56 hw/serial/serial1.c -
uspace/app/tester/tester.c
rc979591b r4f380d06 62 62 #include "loop/loop1.def" 63 63 #include "mm/malloc1.def" 64 #include "mm/mapping1.def"65 64 #include "hw/serial/serial1.def" 66 65 #include "adt/usbaddrkeep.def" -
uspace/app/tester/tester.h
rc979591b r4f380d06 79 79 extern const char *test_loop1(void); 80 80 extern const char *test_malloc1(void); 81 extern const char *test_mapping1(void);82 81 extern const char *test_serial1(void); 83 82 extern const char *test_usbaddrkeep(void); -
uspace/app/virtusbkbd/keys.h
rc979591b r4f380d06 40 40 41 41 /** Maximum number of keys that can be pressed simultaneously. */ 42 #define KB_MAX_KEYS_AT_ONCE 642 #define KB_MAX_KEYS_AT_ONCE 4 43 43 44 44 /** Key code type. */ -
uspace/lib/c/generic/as.c
rc979591b r4f380d06 35 35 #include <as.h> 36 36 #include <libc.h> 37 #include <errno.h>38 37 #include <unistd.h> 39 38 #include <align.h> … … 129 128 } 130 129 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 157 130 /** @} 158 131 */ -
uspace/lib/c/generic/net/icmp_common.c
rc979591b r4f380d06 27 27 */ 28 28 29 /** @addtogroup libc 29 /** @addtogroup libc 30 30 * @{ 31 31 */ … … 38 38 #include <net/modules.h> 39 39 #include <net/icmp_common.h> 40 40 41 #include <ipc/services.h> 41 42 #include <ipc/icmp.h> 43 42 44 #include <sys/time.h> 43 45 #include <async.h> 44 46 45 /** Connect to the ICMP module.47 /** Connects to the ICMP module. 46 48 * 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. 53 54 */ 54 int icmp_connect_module(s useconds_t timeout)55 int icmp_connect_module(services_t service, suseconds_t timeout) 55 56 { 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; 57 64 } 58 65 -
uspace/lib/c/include/adt/hash_table.h
rc979591b r4f380d06 41 41 typedef unsigned long hash_count_t; 42 42 typedef 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; 43 typedef struct hash_table hash_table_t; 44 typedef struct hash_table_operations hash_table_operations_t; 73 45 74 46 /** Hash table structure. */ 75 typedef struct{47 struct hash_table { 76 48 link_t *entry; 77 49 hash_count_t entries; 78 50 hash_count_t max_keys; 79 51 hash_table_operations_t *op; 80 } hash_table_t; 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 }; 81 80 82 81 #define hash_table_get_instance(item, type, member) \ -
uspace/lib/c/include/as.h
rc979591b r4f380d06 47 47 extern void *set_maxheapsize(size_t mhs); 48 48 extern void * as_get_mappable_page(size_t sz); 49 extern int as_get_physical_mapping(void *address, uintptr_t *frame);50 49 51 50 #endif -
uspace/lib/c/include/ipc/icmp.h
rc979591b r4f380d06 33 33 /** @file 34 34 * ICMP module messages. 35 * @see icmp_ remote.h35 * @see icmp_interface.h 36 36 */ 37 37 … … 48 48 /** ICMP module messages. */ 49 49 typedef enum { 50 /** Send echo request. @see icmp_echo() */50 /** Sends echo request. @see icmp_echo() */ 51 51 NET_ICMP_ECHO = NET_ICMP_FIRST, 52 52 53 53 /** 54 * Send destination unreachable error message.54 * Sends destination unreachable error message. 55 55 * @see icmp_destination_unreachable_msg() 56 56 */ … … 58 58 59 59 /** 60 * Send source quench error message.60 * Sends source quench error message. 61 61 * @see icmp_source_quench_msg() 62 62 */ … … 64 64 65 65 /** 66 * Send time exceeded error message.66 * Sends time exceeded error message. 67 67 * @see icmp_time_exceeded_msg() 68 68 */ … … 70 70 71 71 /** 72 * Send parameter problem error message.72 * Sends parameter problem error message. 73 73 * @see icmp_parameter_problem_msg() 74 74 */ 75 NET_ICMP_PARAMETERPROB 76 } icmp_messages_t; 75 NET_ICMP_PARAMETERPROB, 76 77 /** Initializes new connection. */ 78 NET_ICMP_INIT 79 } icmp_messages; 77 80 78 81 /** @name ICMP specific message parameters definitions */ -
uspace/lib/c/include/net/icmp_common.h
rc979591b r4f380d06 41 41 #include <sys/time.h> 42 42 43 /** Default timeout for incoming connections in microseconds (1 sec). */44 #define ICMP_CONNECT_TIMEOUT 100000043 /** Default timeout for incoming connections in microseconds. */ 44 #define ICMP_CONNECT_TIMEOUT (1 * 1000 * 1000) 45 45 46 extern int icmp_connect_module(s useconds_t);46 extern int icmp_connect_module(services_t, suseconds_t); 47 47 48 48 #endif -
uspace/lib/net/include/icmp_header.h
rc979591b r4f380d06 45 45 46 46 /** 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 */ 52 typedef struct icmp_echo icmp_echo_t; 48 53 49 54 /** Echo specific data. */ 50 typedefstruct icmp_echo {55 struct icmp_echo { 51 56 /** Message idintifier. */ 52 57 icmp_param_t identifier; 53 58 /** Message sequence number. */ 54 59 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 */ 65 typedef struct icmp_header icmp_header_t; 56 66 57 67 /** Internet control message header. */ 58 typedefstruct icmp_header {68 struct icmp_header { 59 69 /** The type of the message. */ 60 70 uint8_t type; … … 73 83 */ 74 84 uint16_t checksum; 75 85 76 86 /** Message specific data. */ 77 87 union { 78 88 /** Echo specific data. */ 79 icmp_echo_t echo;89 icmp_echo_t echo; 80 90 /** Proposed gateway value. */ 81 91 in_addr_t gateway; … … 97 107 } param; 98 108 } un; 99 } __attribute__ ((packed)) icmp_header_t;109 } __attribute__ ((packed)); 100 110 101 111 #endif -
uspace/lib/net/include/tl_skel.h
rc979591b r4f380d06 61 61 extern int tl_initialize(int net_phone); 62 62 63 /** Per-connection module initialization.64 *65 * This has to be implemented in user code.66 *67 */68 extern void tl_connection(void);69 70 63 /** Process the transport layer module message. 71 64 * … … 81 74 * 82 75 */ 83 extern int tl_m essage(ipc_callid_t, ipc_call_t *,76 extern int tl_module_message(ipc_callid_t, ipc_call_t *, 84 77 ipc_call_t *, size_t *); 85 78 -
uspace/lib/net/tl/icmp_remote.c
rc979591b r4f380d06 33 33 /** @file 34 34 * ICMP interface implementation for remote modules. 35 * @see icmp_ remote.h35 * @see icmp_interface.h 36 36 */ 37 37 38 #include <icmp_ remote.h>38 #include <icmp_interface.h> 39 39 #include <net/modules.h> 40 40 #include <packet_client.h> -
uspace/lib/net/tl/tl_common.c
rc979591b r4f380d06 27 27 */ 28 28 29 /** @addtogroup libnet 29 /** @addtogroup libnet 30 30 * @{ 31 31 */ … … 39 39 #include <packet_client.h> 40 40 #include <packet_remote.h> 41 #include <icmp_ remote.h>41 #include <icmp_interface.h> 42 42 #include <ip_remote.h> 43 43 #include <ip_interface.h> -
uspace/lib/net/tl/tl_skel.c
rc979591b r4f380d06 56 56 ipc_answer_0(iid, EOK); 57 57 58 /* Per-connection initialization */59 tl_connection();60 61 58 while (true) { 62 59 ipc_call_t answer; … … 71 68 72 69 /* Process the message */ 73 int res = tl_message(callid, &call, &answer, &count); 70 int res = tl_module_message(callid, &call, &answer, 71 &count); 74 72 75 73 /* -
uspace/lib/usb/src/recognise.c
rc979591b r4f380d06 203 203 uint8_t cur_descr_len = current_descriptor[0]; 204 204 uint8_t cur_descr_type = current_descriptor[1]; 205 206 if (cur_descr_len == 0) {207 return ENOENT;208 }209 205 210 206 position += cur_descr_len; -
uspace/srv/net/il/ip/ip.c
rc979591b r4f380d06 67 67 #include <net_checksum.h> 68 68 #include <icmp_client.h> 69 #include <icmp_ remote.h>69 #include <icmp_interface.h> 70 70 #include <ip_client.h> 71 71 #include <ip_interface.h> -
uspace/srv/net/tl/icmp/icmp.c
rc979591b r4f380d06 33 33 /** @file 34 34 * ICMP module implementation. 35 * @see icmp.h 35 36 */ 36 37 … … 50 51 #include <byteorder.h> 51 52 #include <errno.h> 52 #include <adt/hash_table.h>53 53 54 54 #include <net/socket_codes.h> … … 64 64 #include <net_checksum.h> 65 65 #include <icmp_client.h> 66 #include <icmp_ remote.h>66 #include <icmp_interface.h> 67 67 #include <il_remote.h> 68 68 #include <ip_client.h> … … 73 73 #include <icmp_header.h> 74 74 75 /** ICMP module name */ 75 #include "icmp.h" 76 77 /** ICMP module name. */ 76 78 #define NAME "icmp" 77 79 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. 97 102 */ 98 103 #define ICMP_CHECKSUM(header, length) \ … … 100 105 101 106 /** 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. */ 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. 182 140 * 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 */ 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 203 162 /* 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 209 166 header->type = type; 210 167 header->code = code; 211 212 /*213 * The checksum needs to be calculated214 * with a virtual checksum field set to215 * zero.216 */217 168 header->checksum = 0; 218 169 header->checksum = ICMP_CHECKSUM(header, 219 170 packet_get_data_length(packet)); 220 171 221 intrc = ip_client_prepare_packet(packet, IPPROTO_ICMP, ttl, tos,172 rc = ip_client_prepare_packet(packet, IPPROTO_ICMP, ttl, tos, 222 173 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. 238 187 * @return The prefixed ICMP header. 239 188 * @return NULL on errors. 240 *241 189 */ 242 190 static icmp_header_t *icmp_prepare_packet(packet_t *packet) 243 191 { 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); 245 197 if (total_length <= 0) 246 198 return NULL; 247 248 size_theader_length = ip_client_header_length(packet);199 200 header_length = ip_client_header_length(packet); 249 201 if (header_length <= 0) 250 202 return NULL; 251 203 252 204 /* Truncate if longer than 64 bits (without the IP header) */ 253 205 if ((total_length > header_length + ICMP_KEEP_LENGTH) && 254 206 (packet_trim(packet, 0, 255 total_length - header_length - ICMP_KEEP_LENGTH) != EOK)) 207 total_length - header_length - ICMP_KEEP_LENGTH) != EOK)) { 256 208 return NULL; 257 258 icmp_header_t *header = PACKET_PREFIX(packet, icmp_header_t); 209 } 210 211 header = PACKET_PREFIX(packet, icmp_header_t); 259 212 if (!header) 260 213 return NULL; 261 214 262 215 bzero(header, sizeof(*header)); 263 216 return header; 264 217 } 265 218 266 /** Request an echo message.267 * 268 * Send a packet with specified parameters to the target host269 * and wait forthe 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] addr len Torget host address length.281 * 282 * @return 283 * @return 284 * 285 * @return 286 * @return 287 * 288 * @return 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. 290 243 */ 291 244 static 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 295 257 if (addrlen <= 0) 296 258 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); 303 271 if (!packet) 304 272 return ENOMEM; 305 273 306 274 /* 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 313 279 /* 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 320 284 /* Fill the data */ 321 285 length = 0; … … 325 289 } 326 290 memcpy(data + length, ICMP_ECHO_TEXT, size - length); 327 291 328 292 /* 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)); 336 298 header->un.echo.identifier = id; 337 299 header->un.echo.sequence_number = sequence; 338 300 339 301 /* 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); 348 308 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 356 320 /* Send the request */ 357 321 icmp_send_packet(ICMP_ECHO, 0, packet, header, 0, ttl, tos, 358 322 dont_fragment); 359 323 360 324 /* 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, 362 326 timeout * 1000); 363 327 if (rc == EOK) 364 328 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 373 337 return rc; 374 338 } 375 339 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 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 385 349 if (mtu) 386 350 header->un.frag.mtu = mtu; 387 351 388 352 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 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 400 364 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 368 static 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 412 377 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 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 425 390 header->un.param.pointer = pointer; 426 391 return icmp_send_packet(ICMP_PARAMETERPROB, code, packet, header, 427 SERVICE_ICMP, 0, 0, false);428 } 429 430 /** Tr yto 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. 431 396 * 432 397 * 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 */ 406 static void icmp_process_echo_reply(packet_t *packet, icmp_header_t *header, 442 407 icmp_type_t type, icmp_code_t code) 443 408 { 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 450 417 /* 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) { 458 421 reply->result = type; 459 422 fibril_condvar_signal(&reply->condvar); 460 423 } 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. 484 444 */ 485 445 static int icmp_process_packet(packet_t *packet, services_t error) 486 446 { 447 size_t length; 448 uint8_t *src; 449 int addrlen; 450 int result; 451 void *data; 452 icmp_header_t *header; 487 453 icmp_type_t type; 488 454 icmp_code_t code; … … 494 460 case SERVICE_ICMP: 495 461 /* 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; 500 467 /* Remove the error header */ 501 rc = packet_trim(packet, (size_t) rc, 0);468 rc = packet_trim(packet, length, 0); 502 469 if (rc != EOK) 503 470 return rc; 504 505 471 break; 506 472 default: 507 473 return ENOTSUP; 508 474 } 509 475 510 476 /* Get rid of the IP header */ 511 size_tlength = ip_client_header_length(packet);477 length = ip_client_header_length(packet); 512 478 rc = packet_trim(packet, length, 0); 513 479 if (rc != EOK) 514 480 return rc; 515 481 516 482 length = packet_get_data_length(packet); 517 483 if (length <= 0) 518 484 return EINVAL; 519 485 520 486 if (length < ICMP_HEADER_SIZE) 521 487 return EINVAL; 522 523 void *data = packet_get_data(packet);488 489 data = packet_get_data(packet); 524 490 if (!data) 525 491 return EINVAL; 526 492 527 493 /* Get ICMP header */ 528 icmp_header_t *header = (icmp_header_t *) data;529 494 header = (icmp_header_t *) data; 495 530 496 if (header->checksum) { 531 497 while (ICMP_CHECKSUM(header, length) != IP_CHECKSUM_ZERO) { … … 541 507 } 542 508 } 543 544 509 return EINVAL; 545 510 } 546 511 } 547 512 548 513 switch (header->type) { 549 514 case ICMP_ECHOREPLY: … … 552 517 else 553 518 icmp_process_echo_reply(packet, header, ICMP_ECHO, 0); 554 519 555 520 return EOK; 556 521 557 522 case ICMP_ECHO: 558 523 if (error) { … … 562 527 563 528 /* 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 568 532 /* 569 * Set both addresses to the source one (avoid the533 * Set both addresses to the source one (avoids the 570 534 * source address deletion before setting the 571 535 * destination one). … … 578 542 return EOK; 579 543 } 580 544 581 545 return EINVAL; 582 546 } 583 547 584 548 return EPERM; 585 549 586 550 case ICMP_DEST_UNREACH: 587 551 case ICMP_SOURCE_QUENCH: … … 596 560 case ICMP_SKIP: 597 561 case ICMP_PHOTURIS: 598 ip_received_error_msg( phone_ip, -1, packet,562 ip_received_error_msg(icmp_globals.ip_phone, -1, packet, 599 563 SERVICE_IP, SERVICE_ICMP); 600 564 return EOK; 601 565 602 566 default: 603 567 return ENOTSUP; … … 605 569 } 606 570 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 607 597 /** Process IPC messages from the IP module 608 598 * … … 613 603 static void icmp_receiver(ipc_callid_t iid, ipc_call_t *icall) 614 604 { 615 bool loop = true;616 605 packet_t *packet; 617 606 int rc; 618 607 619 while ( loop) {608 while (true) { 620 609 switch (IPC_GET_IMETHOD(*icall)) { 621 610 case NET_TL_RECEIVED: 622 rc = packet_translate_remote( phone_net, &packet,611 rc = packet_translate_remote(icmp_globals.net_phone, &packet, 623 612 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)); 629 616 630 617 ipc_answer_0(iid, (sysarg_t) rc); 631 618 break; 632 case IPC_M_PHONE_HUNGUP:633 loop = false;634 continue;635 619 default: 636 620 ipc_answer_0(iid, (sysarg_t) ENOTSUP); … … 665 649 uint8_t *data; 666 650 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); 681 669 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; 685 677 686 678 /* Get configuration */ 687 679 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); 690 684 return rc; 685 } 691 686 692 687 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 } 699 696 net_free_settings(configuration, data); 700 697 } 701 698 699 fibril_rwlock_write_unlock(&icmp_globals.lock); 702 700 return EOK; 703 701 } 704 702 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 */ 721 static int icmp_process_message(ipc_call_t *call) 722 { 745 723 packet_t *packet; 746 724 int rc; 747 748 *count = 0; 749 725 750 726 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 765 727 case NET_ICMP_DEST_UNREACH: 766 rc = packet_translate_remote( phone_net, &packet,728 rc = packet_translate_remote(icmp_globals.net_phone, &packet, 767 729 IPC_GET_PACKET(*call)); 768 730 if (rc != EOK) 769 731 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); 774 734 case NET_ICMP_SOURCE_QUENCH: 775 rc = packet_translate_remote( phone_net, &packet,735 rc = packet_translate_remote(icmp_globals.net_phone, &packet, 776 736 IPC_GET_PACKET(*call)); 777 737 if (rc != EOK) 778 738 return rc; 779 780 return icmp_source_quench(packet); 781 739 return icmp_source_quench_msg_local(0, packet); 782 740 case NET_ICMP_TIME_EXCEEDED: 783 rc = packet_translate_remote( phone_net, &packet,741 rc = packet_translate_remote(icmp_globals.net_phone, &packet, 784 742 IPC_GET_PACKET(*call)); 785 743 if (rc != EOK) 786 744 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); 790 747 case NET_ICMP_PARAMETERPROB: 791 rc = packet_translate_remote( phone_net, &packet,748 rc = packet_translate_remote(icmp_globals.net_phone, &packet, 792 749 IPC_GET_PACKET(*call)); 793 750 if (rc != EOK) 794 751 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 */ 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; 795 862 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 */ 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); 798 935 } 799 936 -
uspace/srv/net/tl/tcp/tcp.c
rc979591b r4f380d06 64 64 #include <ip_interface.h> 65 65 #include <icmp_client.h> 66 #include <icmp_ remote.h>66 #include <icmp_interface.h> 67 67 #include <net_interface.h> 68 68 #include <socket_core.h> … … 1204 1204 } 1205 1205 1206 /** Per-connection initialization1207 *1208 */1209 void tl_connection(void)1210 {1211 }1212 1213 1206 /** Processes the TCP message. 1214 1207 * … … 1224 1217 * @see IS_NET_TCP_MESSAGE() 1225 1218 */ 1226 int tl_m essage(ipc_callid_t callid, ipc_call_t *call,1219 int tl_module_message(ipc_callid_t callid, ipc_call_t *call, 1227 1220 ipc_call_t *answer, size_t *answer_count) 1228 1221 { … … 2479 2472 tcp_globals.net_phone = net_phone; 2480 2473 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); 2482 2476 tcp_globals.ip_phone = ip_bind_service(SERVICE_IP, IPPROTO_TCP, 2483 2477 SERVICE_TCP, tcp_receiver); -
uspace/srv/net/tl/udp/udp.c
rc979591b r4f380d06 61 61 #include <ip_interface.h> 62 62 #include <icmp_client.h> 63 #include <icmp_ remote.h>63 #include <icmp_interface.h> 64 64 #include <net_interface.h> 65 65 #include <socket_core.h> … … 393 393 udp_globals.net_phone = net_phone; 394 394 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); 396 397 397 398 udp_globals.ip_phone = ip_bind_service(SERVICE_IP, IPPROTO_UDP, … … 877 878 } 878 879 879 /** Per-connection initialization880 *881 */882 void tl_connection(void)883 {884 }885 886 880 /** Processes the UDP message. 887 881 * … … 897 891 * @see IS_NET_UDP_MESSAGE() 898 892 */ 899 int tl_m essage(ipc_callid_t callid, ipc_call_t *call,893 int tl_module_message(ipc_callid_t callid, ipc_call_t *call, 900 894 ipc_call_t *answer, size_t *answer_count) 901 895 {
Note:
See TracChangeset
for help on using the changeset viewer.