Changeset 49d819b4 in mainline
- Timestamp:
- 2010-11-02T23:15:18Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 7ae3d6f
- Parents:
- e06ef614 (diff), d0d1f4f (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - Files:
-
- 21 edited
- 4 moved
Legend:
- Unmodified
- Added
- Removed
-
boot/Makefile.common
re06ef614 r49d819b4 106 106 $(USPACE_PATH)/srv/net/tl/tcp/tcp \ 107 107 $(USPACE_PATH)/srv/net/net/net \ 108 $(USPACE_PATH)/srv/net/netstart/netstart \109 108 $(USPACE_PATH)/srv/devman/devman 110 109 … … 135 134 $(USPACE_PATH)/app/tetris/tetris \ 136 135 $(USPACE_PATH)/app/trace/trace \ 136 $(USPACE_PATH)/app/netstart/netstart \ 137 137 $(USPACE_PATH)/app/nettest1/nettest1 \ 138 138 $(USPACE_PATH)/app/nettest2/nettest2 \ -
uspace/Makefile
re06ef614 r49d819b4 50 50 app/trace \ 51 51 app/top \ 52 app/netstart \ 52 53 app/netecho \ 53 54 app/nettest1 \ … … 86 87 srv/net/tl/tcp \ 87 88 srv/net/net \ 88 srv/net/netstart \89 89 drv/root 90 90 -
uspace/app/netstart/Makefile
re06ef614 r49d819b4 28 28 # 29 29 30 USPACE_PREFIX = ../.. /..30 USPACE_PREFIX = ../.. 31 31 LIBS = $(LIBNET_PREFIX)/libnet.a 32 32 EXTRA_CFLAGS = -I$(LIBNET_PREFIX)/include … … 35 35 36 36 SOURCES = \ 37 netstart.c \ 38 self_test.c 37 netstart.c 39 38 40 39 include $(USPACE_PREFIX)/Makefile.common -
uspace/app/netstart/netstart.c
re06ef614 r49d819b4 32 32 33 33 /** @file 34 *35 34 * Start the networking subsystem. 36 * Perform networking self-test if executed37 * with the -s argument.38 *39 35 */ 40 36 … … 52 48 #include <net/modules.h> 53 49 54 #include "self_test.h"55 56 50 /** Start a module. 57 51 * 58 * @param[in] desc The module description 59 * @param[in] path The module absolute path. 60 * 61 * @returns true on succesful spanwning 62 * @returns false on failure 63 * 52 * @param[in] desc The module description 53 * @param[in] path The module absolute path. 54 * @returns True on succesful spanwning. 55 * @returns False on failure 64 56 */ 65 57 static bool spawn(const char *desc, const char *path) … … 86 78 ERROR_DECLARE; 87 79 88 /* Run self-tests */89 if ((argc > 1) && (str_cmp(argv[1], "-s") == 0))90 ERROR_PROPAGATE(self_test());91 92 80 if (!spawn("networking service", "/srv/net")) 93 81 return EINVAL; -
uspace/lib/c/include/ipc/services.h
re06ef614 r49d819b4 39 39 40 40 typedef enum { 41 SERVICE_LOAD = 1, 41 SERVICE_NONE = 0, 42 SERVICE_LOAD, 42 43 SERVICE_PCI, 43 44 SERVICE_VIDEO, -
uspace/lib/net/include/tl_local.h
re06ef614 r49d819b4 37 37 #include <async.h> 38 38 39 /** Starts the TL module. 40 * 41 * Initializes the client connection serving function, initializes the module, 42 * registers the module service and starts the async manager, processing IPC 43 * messages in an infinite loop. 44 * 45 * @param[in] client_connection The client connection processing function. The 46 * module skeleton propagates its own one. 47 * @returns EOK on successful module termination. 48 * @returns Other error codes as defined for the module initialize 49 * function. 50 * @returns Other error codes as defined for the REGISTER_ME() macro 51 * function. 52 */ 39 53 extern int tl_module_message_standalone(ipc_callid_t, ipc_call_t *, 40 54 ipc_call_t *, int *); 55 56 57 /** Processes the TL module message. 58 * 59 * @param[in] callid The message identifier. 60 * @param[in] call The message parameters. 61 * @param[out] answer The message answer parameters. 62 * @param[out] answer_count The last parameter for the actual answer in the 63 * answer parameter. 64 * @returns EOK on success. 65 * @returns Other error codes as defined for the module's message 66 * standalone function. 67 */ 41 68 extern int tl_module_start_standalone(async_client_conn_t); 42 69 -
uspace/srv/net/net/net.c
re06ef614 r49d819b4 36 36 */ 37 37 38 #include "net.h" 39 38 40 #include <async.h> 39 41 #include <ctype.h> … … 52 54 53 55 #include <net/modules.h> 56 #include <net/packet.h> 57 #include <net/device.h> 58 54 59 #include <adt/char_map.h> 55 60 #include <adt/generic_char_map.h> 56 61 #include <adt/measured_strings.h> 57 62 #include <adt/module_map.h> 58 #include <net/packet.h> 63 59 64 #include <netif_remote.h> 60 #include <net/device.h>61 65 #include <nil_interface.h> 62 66 #include <net_interface.h> 63 67 #include <ip_interface.h> 64 68 65 #include "net.h" 66 67 /** Networking module name. 68 * 69 */ 69 /** Networking module name. */ 70 70 #define NAME "net" 71 71 72 /** File read buffer size. 73 * 74 */ 72 /** File read buffer size. */ 75 73 #define BUFFER_SIZE 256 76 74 77 /** Networking module global data. 78 * 79 */ 75 /** Networking module global data. */ 80 76 net_globals_t net_globals; 81 77 … … 100 96 measured_string_ref setting = 101 97 measured_string_create_bulk(value, 0); 102 103 98 if (!setting) 104 99 return ENOMEM; … … 206 201 unsigned int line_number = 0; 207 202 size_t index = 0; 208 while ( (!ferror(cfg)) && (!feof(cfg))) {203 while (!ferror(cfg) && !feof(cfg)) { 209 204 int read = fgetc(cfg); 210 205 if ((read > 0) && (read != '\n') && (read != '\r')) { … … 326 321 ipcarg_t phonehash; 327 322 328 if (ERROR_OCCURRED(net_initialize(client_connection)) 329 || ERROR_OCCURRED(REGISTER_ME(SERVICE_NETWORKING, &phonehash))){323 if (ERROR_OCCURRED(net_initialize(client_connection)) || 324 ERROR_OCCURRED(REGISTER_ME(SERVICE_NETWORKING, &phonehash))) { 330 325 pm_destroy(); 331 326 return ERROR_CODE; … … 379 374 size_t count, char **data) 380 375 { 381 if (! (configuration && (count > 0)))376 if (!configuration || (count <= 0)) 382 377 return EINVAL; 383 378 … … 482 477 /* Inter-network layer startup */ 483 478 switch (netif->il->service) { 484 485 486 487 488 489 479 case SERVICE_IP: 480 ERROR_PROPAGATE(ip_device_req(netif->il->phone, netif->id, 481 internet_service)); 482 break; 483 default: 484 return ENOENT; 490 485 } 491 486 … … 511 506 ERROR_DECLARE; 512 507 513 const char *conf_files[] = {"lo", "ne2k"}; 508 const char *conf_files[] = { 509 "lo", 510 "ne2k" 511 }; 514 512 size_t count = sizeof(conf_files) / sizeof(char *); 515 513 … … 603 601 *answer_count = 0; 604 602 switch (IPC_GET_METHOD(*call)) { 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 603 case IPC_M_PHONE_HUNGUP: 604 return EOK; 605 case NET_NET_GET_DEVICE_CONF: 606 ERROR_PROPAGATE(measured_strings_receive(&strings, &data, 607 IPC_GET_COUNT(call))); 608 net_get_device_conf_req(0, IPC_GET_DEVICE(call), &strings, 609 IPC_GET_COUNT(call), NULL); 610 611 /* Strings should not contain received data anymore */ 612 free(data); 613 614 ERROR_CODE = measured_strings_reply(strings, IPC_GET_COUNT(call)); 615 free(strings); 616 return ERROR_CODE; 617 case NET_NET_GET_CONF: 618 ERROR_PROPAGATE(measured_strings_receive(&strings, &data, 619 IPC_GET_COUNT(call))); 620 net_get_conf_req(0, &strings, IPC_GET_COUNT(call), NULL); 621 622 /* Strings should not contain received data anymore */ 623 free(data); 624 625 ERROR_CODE = measured_strings_reply(strings, IPC_GET_COUNT(call)); 626 free(strings); 627 return ERROR_CODE; 628 case NET_NET_STARTUP: 629 return startup(); 632 630 } 633 631 return ENOTSUP; … … 661 659 int res = net_module_message(callid, &call, &answer, &answer_count); 662 660 663 /* End if said to either by the message or the processing result */661 /* End if told to either by the message or the processing result */ 664 662 if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) || (res == EHANGUP)) 665 663 return; -
uspace/srv/net/net/net.h
re06ef614 r49d819b4 36 36 */ 37 37 38 #ifndef __NET_NET_H__39 #define __NET_NET_H__38 #ifndef NET_NET_H_ 39 #define NET_NET_H_ 40 40 41 41 #include <ipc/ipc.h> -
uspace/srv/net/net/net_standalone.c
re06ef614 r49d819b4 28 28 29 29 /** @addtogroup net 30 * 30 * @{ 31 31 */ 32 32 33 33 /** @file 34 * 34 * Wrapper for the standalone networking module. 35 35 */ 36 36 37 #include "net.h" 38 37 39 #include <str.h> 38 40 #include <adt/measured_strings.h> 41 #include <adt/module_map.h> 39 42 #include <ipc/ipc.h> 40 43 #include <ipc/net.h> 41 44 42 45 #include <ip_interface.h> 43 #include <adt/measured_strings.h>44 #include <adt/module_map.h>45 46 #include <packet_server.h> 46 47 47 #include "net.h" 48 49 /** Networking module global data. 50 */ 48 /** Networking module global data. */ 51 49 extern net_globals_t net_globals; 52 50 … … 60 58 * 61 59 */ 62 int net_initialize_build(async_client_conn_t client_connection){ 60 int net_initialize_build(async_client_conn_t client_connection) 61 { 63 62 ERROR_DECLARE; 64 63 -
uspace/srv/net/tl/icmp/icmp.c
re06ef614 r49d819b4 28 28 29 29 /** @addtogroup icmp 30 * 30 * @{ 31 31 */ 32 32 33 33 /** @file 34 * ICMP module implementation. 35 * @see icmp.h 36 */ 34 * ICMP module implementation. 35 * @see icmp.h 36 */ 37 38 #include "icmp.h" 39 #include "icmp_module.h" 37 40 38 41 #include <async.h> … … 56 59 #include <net/ip_protocols.h> 57 60 #include <net/inet.h> 58 59 61 #include <net/modules.h> 62 #include <net/icmp_api.h> 63 #include <net/icmp_codes.h> 64 #include <net/icmp_common.h> 65 60 66 #include <packet_client.h> 61 67 #include <packet_remote.h> 62 68 #include <net_checksum.h> 63 #include <net/icmp_api.h>64 69 #include <icmp_client.h> 65 #include <net/icmp_codes.h>66 #include <net/icmp_common.h>67 70 #include <icmp_interface.h> 68 71 #include <il_interface.h> … … 74 77 #include <icmp_header.h> 75 78 76 #include "icmp.h" 77 #include "icmp_module.h" 78 79 /** ICMP module name. 80 */ 79 /** ICMP module name. */ 81 80 #define NAME "ICMP protocol" 82 81 83 /** Default ICMP error reporting. 84 */ 82 /** Default ICMP error reporting. */ 85 83 #define NET_DEFAULT_ICMP_ERROR_REPORTING true 86 84 87 /** Default ICMP echo replying. 88 */ 85 /** Default ICMP echo replying. */ 89 86 #define NET_DEFAULT_ICMP_ECHO_REPLYING true 90 87 91 /** Original datagram length in bytes transfered to the error notification message. 88 /** Original datagram length in bytes transfered to the error notification 89 * message. 92 90 */ 93 91 #define ICMP_KEEP_LENGTH 8 94 92 95 /** Free identifier numbers pool start. 96 */ 93 /** Free identifier numbers pool start. */ 97 94 #define ICMP_FREE_IDS_START 1 98 95 99 /** Free identifier numbers pool end. 100 */ 96 /** Free identifier numbers pool end. */ 101 97 #define ICMP_FREE_IDS_END UINT16_MAX 102 98 103 99 /** Computes the ICMP datagram checksum. 104 * @param[in,out] header The ICMP datagram header. 105 * @param[in] length The total datagram length. 106 * @returns The computed checksum. 107 */ 108 #define ICMP_CHECKSUM(header, length) htons(ip_checksum((uint8_t *) (header), (length))) 109 110 /** An echo request datagrams pattern. 111 */ 112 #define ICMP_ECHO_TEXT "Hello from HelenOS." 100 * 101 * @param[in,out] header The ICMP datagram header. 102 * @param[in] length The total datagram length. 103 * @returns The computed checksum. 104 */ 105 #define ICMP_CHECKSUM(header, length) \ 106 htons(ip_checksum((uint8_t *) (header), (length))) 107 108 /** An echo request datagrams pattern. */ 109 #define ICMP_ECHO_TEXT "Hello from HelenOS." 113 110 114 111 /** Computes an ICMP reply data key. 115 * @param[in] id The message identifier. 116 * @param[in] sequence The message sequence number. 117 * @returns The computed ICMP reply data key. 118 */ 119 #define ICMP_GET_REPLY_KEY(id, sequence) (((id) << 16) | (sequence &0xFFFF)) 120 121 /** Processes the received ICMP packet. 122 * Is used as an entry point from the underlying IP module. 123 * Releases the packet on error. 124 * @param device_id The device identifier. Ignored parameter. 125 * @param[in,out] packet The received packet. 126 * @param receiver The target service. Ignored parameter. 127 * @param[in] error The packet error reporting service. Prefixes the received packet. 128 * @returns EOK on success. 129 * @returns Other error codes as defined for the icmp_process_packet() function. 130 */ 131 int icmp_received_msg(device_id_t device_id, packet_t packet, services_t receiver, services_t error); 132 133 /** Processes the received ICMP packet. 134 * Notifies the destination socket application. 135 * @param[in,out] packet The received packet. 136 * @param[in] error The packet error reporting service. Prefixes the received packet. 137 * @returns EOK on success. 138 * @returns EINVAL if the packet is not valid. 139 * @returns EINVAL if the stored packet address is not the an_addr_t. 140 * @returns EINVAL if the packet does not contain any data. 141 * @returns NO_DATA if the packet content is shorter than the user datagram header. 142 * @returns ENOMEM if there is not enough memory left. 143 * @returns EADDRNOTAVAIL if the destination socket does not exist. 144 * @returns Other error codes as defined for the ip_client_process_packet() function. 145 */ 146 int icmp_process_packet(packet_t packet, services_t error); 147 148 /** Processes the client messages. 149 * Remembers the assigned identifier and sequence numbers. 150 * Runs until the client module disconnects. 151 * @param[in] callid The message identifier. 152 * @param[in] call The message parameters. 153 * @returns EOK. 154 * @see icmp_interface.h 155 * @see icmp_api.h 156 */ 157 int icmp_process_client_messages(ipc_callid_t callid, ipc_call_t call); 158 159 /** Processes the generic client messages. 160 * @param[in] call The message parameters. 161 * @returns EOK on success. 162 * @returns ENOTSUP if the message is not known. 163 * @returns Other error codes as defined for the packet_translate() function. 164 * @returns Other error codes as defined for the icmp_destination_unreachable_msg() function. 165 * @returns Other error codes as defined for the icmp_source_quench_msg() function. 166 * @returns Other error codes as defined for the icmp_time_exceeded_msg() function. 167 * @returns Other error codes as defined for the icmp_parameter_problem_msg() function. 168 * @see icmp_interface.h 169 */ 170 int icmp_process_message(ipc_call_t * call); 112 * 113 * @param[in] id The message identifier. 114 * @param[in] sequence The message sequence number. 115 * @returns The computed ICMP reply data key. 116 */ 117 #define ICMP_GET_REPLY_KEY(id, sequence) \ 118 (((id) << 16) | (sequence & 0xFFFF)) 119 120 121 /** ICMP global data. */ 122 icmp_globals_t icmp_globals; 123 124 INT_MAP_IMPLEMENT(icmp_replies, icmp_reply_t); 125 INT_MAP_IMPLEMENT(icmp_echo_data, icmp_echo_t); 171 126 172 127 /** Releases the packet and returns the result. 173 * @param[in] packet The packet queue to be released. 174 * @param[in] result The result to be returned. 175 * @returns The result parameter. 176 */ 177 int icmp_release_and_return(packet_t packet, int result); 128 * 129 * @param[in] packet The packet queue to be released. 130 * @param[in] result The result to be returned. 131 * @returns The result parameter. 132 */ 133 static int icmp_release_and_return(packet_t packet, int result) 134 { 135 pq_release_remote(icmp_globals.net_phone, packet_get_id(packet)); 136 return result; 137 } 138 139 /** Sends the ICMP message. 140 * 141 * Sets the message type and code and computes the checksum. 142 * Error messages are sent only if allowed in the configuration. 143 * Releases the packet on errors. 144 * 145 * @param[in] type The message type. 146 * @param[in] code The message code. 147 * @param[in] packet The message packet to be sent. 148 * @param[in] header The ICMP header. 149 * @param[in] error The error service to be announced. Should be 150 * SERVICE_ICMP or zero. 151 * @param[in] ttl The time to live. 152 * @param[in] tos The type of service. 153 * @param[in] dont_fragment The value indicating whether the datagram must not 154 * be fragmented. Is used as a MTU discovery. 155 * @returns EOK on success. 156 * @returns EPERM if the error message is not allowed. 157 */ 158 static int 159 icmp_send_packet(icmp_type_t type, icmp_code_t code, packet_t packet, 160 icmp_header_ref header, services_t error, ip_ttl_t ttl, ip_tos_t tos, 161 int dont_fragment) 162 { 163 ERROR_DECLARE; 164 165 // do not send an error if disabled 166 if (error && !icmp_globals.error_reporting) 167 return icmp_release_and_return(packet, EPERM); 168 169 header->type = type; 170 header->code = code; 171 header->checksum = 0; 172 header->checksum = ICMP_CHECKSUM(header, 173 packet_get_data_length(packet)); 174 if (ERROR_OCCURRED(ip_client_prepare_packet(packet, IPPROTO_ICMP, ttl, 175 tos, dont_fragment, 0))) { 176 return icmp_release_and_return(packet, ERROR_CODE); 177 } 178 179 return ip_send_msg(icmp_globals.ip_phone, -1, packet, SERVICE_ICMP, 180 error); 181 } 182 183 /** Prepares the ICMP error packet. 184 * 185 * Truncates the original packet if longer than ICMP_KEEP_LENGTH bytes. 186 * Prefixes and returns the ICMP header. 187 * 188 * @param[in,out] packet The original packet. 189 * @returns The prefixed ICMP header. 190 * @returns NULL on errors. 191 */ 192 static icmp_header_ref icmp_prepare_packet(packet_t packet) 193 { 194 icmp_header_ref header; 195 size_t header_length; 196 size_t total_length; 197 198 total_length = packet_get_data_length(packet); 199 if (total_length <= 0) 200 return NULL; 201 202 header_length = ip_client_header_length(packet); 203 if (header_length <= 0) 204 return NULL; 205 206 // truncate if longer than 64 bits (without the IP header) 207 if ((total_length > header_length + ICMP_KEEP_LENGTH) && 208 (packet_trim(packet, 0, 209 total_length - header_length - ICMP_KEEP_LENGTH) != EOK)) { 210 return NULL; 211 } 212 213 header = PACKET_PREFIX(packet, icmp_header_t); 214 if (!header) 215 return NULL; 216 217 bzero(header, sizeof(*header)); 218 return header; 219 } 178 220 179 221 /** Requests an echo message. 180 * Sends a packet with specified parameters to the target host and waits for the reply upto the given timeout. 181 * Blocks the caller until the reply or the timeout occurs. 182 * @param[in] id The message identifier. 183 * @param[in] sequence The message sequence parameter. 184 * @param[in] size The message data length in bytes. 185 * @param[in] timeout The timeout in miliseconds. 186 * @param[in] ttl The time to live. 187 * @param[in] tos The type of service. 188 * @param[in] dont_fragment The value indicating whether the datagram must not be fragmented. Is used as a MTU discovery. 189 * @param[in] addr The target host address. 190 * @param[in] addrlen The torget host address length. 191 * @returns ICMP_ECHO on success. 192 * @returns ETIMEOUT if the reply has not arrived before the timeout. 193 * @returns ICMP type of the received error notification. 194 * @returns EINVAL if the addrlen parameter is less or equal to zero (<=0). 195 * @returns ENOMEM if there is not enough memory left. 196 * @returns EPARTY if there was an internal error. 197 */ 198 int icmp_echo(icmp_param_t id, icmp_param_t sequence, size_t size, mseconds_t timeout, ip_ttl_t ttl, ip_tos_t tos, int dont_fragment, const struct sockaddr * addr, socklen_t addrlen); 199 200 /** Prepares the ICMP error packet. 201 * Truncates the original packet if longer than ICMP_KEEP_LENGTH bytes. 202 * Prefixes and returns the ICMP header. 203 * @param[in,out] packet The original packet. 204 * @returns The prefixed ICMP header. 205 * @returns NULL on errors. 206 */ 207 icmp_header_ref icmp_prepare_packet(packet_t packet); 208 209 /** Sends the ICMP message. 210 * Sets the message type and code and computes the checksum. 211 * Error messages are sent only if allowed in the configuration. 212 * Releases the packet on errors. 213 * @param[in] type The message type. 214 * @param[in] code The message code. 215 * @param[in] packet The message packet to be sent. 216 * @param[in] header The ICMP header. 217 * @param[in] error The error service to be announced. Should be SERVICE_ICMP or zero (0). 218 * @param[in] ttl The time to live. 219 * @param[in] tos The type of service. 220 * @param[in] dont_fragment The value indicating whether the datagram must not be fragmented. Is used as a MTU discovery. 221 * @returns EOK on success. 222 * @returns EPERM if the error message is not allowed. 223 */ 224 int icmp_send_packet(icmp_type_t type, icmp_code_t code, packet_t packet, icmp_header_ref header, services_t error, ip_ttl_t ttl, ip_tos_t tos, int dont_fragment); 225 226 /** Tries to set the pending reply result as the received message type. 227 * If the reply data is not present, the reply timed out and the other fibril 228 * is already awake. 229 * Releases the packet. 230 * @param[in] packet The received reply message. 231 * @param[in] header The ICMP message header. 232 * @param[in] type The received reply message type. 233 * @param[in] code The received reply message code. 234 * @returns EOK. 235 */ 236 int icmp_process_echo_reply(packet_t packet, icmp_header_ref header, icmp_type_t type, icmp_code_t code); 237 238 /** Assigns a new identifier for the connection. 239 * Fills the echo data parameter with the assigned values. 240 * @param[in,out] echo_data The echo data to be bound. 241 * @returns Index of the inserted echo data. 242 * @returns EBADMEM if the echo_data parameter is NULL. 243 * @returns ENOTCONN if no free identifier have been found. 244 */ 245 int icmp_bind_free_id(icmp_echo_ref echo_data); 246 247 /** ICMP global data. 248 */ 249 icmp_globals_t icmp_globals; 250 251 INT_MAP_IMPLEMENT(icmp_replies, icmp_reply_t); 252 253 INT_MAP_IMPLEMENT(icmp_echo_data, icmp_echo_t); 254 255 int icmp_echo_msg(int icmp_phone, size_t size, mseconds_t timeout, ip_ttl_t ttl, ip_tos_t tos, int dont_fragment, const struct sockaddr * addr, socklen_t addrlen){ 256 icmp_echo_ref echo_data; 257 int res; 258 259 fibril_rwlock_write_lock(&icmp_globals.lock); 260 // use the phone as the echo data index 261 echo_data = icmp_echo_data_find(&icmp_globals.echo_data, icmp_phone); 262 if(! echo_data){ 263 res = ENOENT; 264 }else{ 265 res = icmp_echo(echo_data->identifier, echo_data->sequence_number, size, timeout, ttl, tos, dont_fragment, addr, addrlen); 266 if(echo_data->sequence_number < UINT16_MAX){ 267 ++ echo_data->sequence_number; 268 }else{ 269 echo_data->sequence_number = 0; 270 } 271 } 272 fibril_rwlock_write_unlock(&icmp_globals.lock); 273 return res; 274 } 275 276 int icmp_echo(icmp_param_t id, icmp_param_t sequence, size_t size, mseconds_t timeout, ip_ttl_t ttl, ip_tos_t tos, int dont_fragment, const struct sockaddr * addr, socklen_t addrlen){ 222 * 223 * Sends a packet with specified parameters to the target host and waits for 224 * the reply upto the given timeout. 225 * Blocks the caller until the reply or the timeout occurs. 226 * 227 * @param[in] id The message identifier. 228 * @param[in] sequence The message sequence parameter. 229 * @param[in] size The message data length in bytes. 230 * @param[in] timeout The timeout in miliseconds. 231 * @param[in] ttl The time to live. 232 * @param[in] tos The type of service. 233 * @param[in] dont_fragment The value indicating whether the datagram must not 234 * be fragmented. Is used as a MTU discovery. 235 * @param[in] addr The target host address. 236 * @param[in] addrlen The torget host address length. 237 * @returns ICMP_ECHO on success. 238 * @returns ETIMEOUT if the reply has not arrived before the 239 * timeout. 240 * @returns ICMP type of the received error notification. 241 * @returns EINVAL if the addrlen parameter is less or equal to 242 * zero. 243 * @returns ENOMEM if there is not enough memory left. 244 * @returns EPARTY if there was an internal error. 245 */ 246 static int 247 icmp_echo(icmp_param_t id, icmp_param_t sequence, size_t size, 248 mseconds_t timeout, ip_ttl_t ttl, ip_tos_t tos, int dont_fragment, 249 const struct sockaddr * addr, socklen_t addrlen) 250 { 277 251 ERROR_DECLARE; 278 252 … … 280 254 packet_t packet; 281 255 size_t length; 282 uint8_t * 256 uint8_t *data; 283 257 icmp_reply_ref reply; 284 258 int reply_key; … … 286 260 int index; 287 261 288 if (addrlen <= 0){262 if (addrlen <= 0) 289 263 return EINVAL; 290 } 264 291 265 length = (size_t) addrlen; 292 266 // TODO do not ask all the time 293 ERROR_PROPAGATE(ip_packet_size_req(icmp_globals.ip_phone, -1, &icmp_globals.packet_dimension)); 294 packet = packet_get_4_remote(icmp_globals.net_phone, size, icmp_globals.packet_dimension.addr_len, ICMP_HEADER_SIZE + icmp_globals.packet_dimension.prefix, icmp_globals.packet_dimension.suffix); 295 if(! packet){ 267 ERROR_PROPAGATE(ip_packet_size_req(icmp_globals.ip_phone, -1, 268 &icmp_globals.packet_dimension)); 269 270 packet = packet_get_4_remote(icmp_globals.net_phone, size, 271 icmp_globals.packet_dimension.addr_len, 272 ICMP_HEADER_SIZE + icmp_globals.packet_dimension.prefix, 273 icmp_globals.packet_dimension.suffix); 274 if (!packet) 296 275 return ENOMEM; 297 }298 276 299 277 // prepare the requesting packet 300 278 // set the destination address 301 if(ERROR_OCCURRED(packet_set_addr(packet, NULL, (const uint8_t *) addr, length))){ 279 if (ERROR_OCCURRED(packet_set_addr(packet, NULL, (const uint8_t *) addr, 280 length))) { 302 281 return icmp_release_and_return(packet, ERROR_CODE); 303 282 } 283 304 284 // allocate space in the packet 305 285 data = (uint8_t *) packet_suffix(packet, size); 306 if (! data){286 if (!data) 307 287 return icmp_release_and_return(packet, ENOMEM); 308 } 288 309 289 // fill the data 310 290 length = 0; 311 while (size > length + sizeof(ICMP_ECHO_TEXT)){291 while (size > length + sizeof(ICMP_ECHO_TEXT)) { 312 292 memcpy(data + length, ICMP_ECHO_TEXT, sizeof(ICMP_ECHO_TEXT)); 313 293 length += sizeof(ICMP_ECHO_TEXT); 314 294 } 315 295 memcpy(data + length, ICMP_ECHO_TEXT, size - length); 296 316 297 // prefix the header 317 298 header = PACKET_PREFIX(packet, icmp_header_t); 318 if (! header){299 if (!header) 319 300 return icmp_release_and_return(packet, ENOMEM); 320 } 301 321 302 bzero(header, sizeof(*header)); 322 303 header->un.echo.identifier = id; … … 325 306 // prepare the reply structure 326 307 reply = malloc(sizeof(*reply)); 327 if (! reply){308 if (!reply) 328 309 return icmp_release_and_return(packet, ENOMEM); 329 } 310 330 311 fibril_mutex_initialize(&reply->mutex); 331 312 fibril_mutex_lock(&reply->mutex); 332 313 fibril_condvar_initialize(&reply->condvar); 333 reply_key = ICMP_GET_REPLY_KEY(header->un.echo.identifier, header->un.echo.sequence_number); 314 reply_key = ICMP_GET_REPLY_KEY(header->un.echo.identifier, 315 header->un.echo.sequence_number); 334 316 index = icmp_replies_add(&icmp_globals.replies, reply_key, reply); 335 if (index < 0){317 if (index < 0) { 336 318 free(reply); 337 319 return icmp_release_and_return(packet, index); … … 342 324 343 325 // send the request 344 icmp_send_packet(ICMP_ECHO, 0, packet, header, 0, ttl, tos, dont_fragment); 326 icmp_send_packet(ICMP_ECHO, 0, packet, header, 0, ttl, tos, 327 dont_fragment); 345 328 346 329 // wait for the reply 347 330 // timeout in microseconds 348 if(ERROR_OCCURRED(fibril_condvar_wait_timeout(&reply->condvar, &reply->mutex, timeout * 1000))){ 331 if (ERROR_OCCURRED(fibril_condvar_wait_timeout(&reply->condvar, 332 &reply->mutex, timeout * 1000))) { 349 333 result = ERROR_CODE; 350 } else{334 } else { 351 335 // read the result 352 336 result = reply->result; … … 359 343 // destroy the reply structure 360 344 icmp_replies_exclude_index(&icmp_globals.replies, index); 345 361 346 return result; 362 347 } 363 348 364 int icmp_destination_unreachable_msg(int icmp_phone, icmp_code_t code, icmp_param_t mtu, packet_t packet){ 349 static int 350 icmp_destination_unreachable_msg_local(int icmp_phone, icmp_code_t code, 351 icmp_param_t mtu, packet_t packet) 352 { 365 353 icmp_header_ref header; 366 354 367 355 header = icmp_prepare_packet(packet); 368 if (! header){356 if (!header) 369 357 return icmp_release_and_return(packet, ENOMEM); 370 } 371 if (mtu){358 359 if (mtu) 372 360 header->un.frag.mtu = mtu; 373 } 374 return icmp_send_packet(ICMP_DEST_UNREACH, code, packet, header, SERVICE_ICMP, 0, 0, 0); 375 } 376 377 int icmp_source_quench_msg(int icmp_phone, packet_t packet){ 361 362 return icmp_send_packet(ICMP_DEST_UNREACH, code, packet, header, 363 SERVICE_ICMP, 0, 0, 0); 364 } 365 366 static int icmp_source_quench_msg_local(int icmp_phone, packet_t packet) 367 { 378 368 icmp_header_ref header; 379 369 380 370 header = icmp_prepare_packet(packet); 381 if (! header){371 if (!header) 382 372 return icmp_release_and_return(packet, ENOMEM); 383 } 384 return icmp_send_packet(ICMP_SOURCE_QUENCH, 0, packet, header, SERVICE_ICMP, 0, 0, 0); 385 } 386 387 int icmp_time_exceeded_msg(int icmp_phone, icmp_code_t code, packet_t packet){ 373 374 return icmp_send_packet(ICMP_SOURCE_QUENCH, 0, packet, header, 375 SERVICE_ICMP, 0, 0, 0); 376 } 377 378 static int 379 icmp_time_exceeded_msg_local(int icmp_phone, icmp_code_t code, packet_t packet) 380 { 388 381 icmp_header_ref header; 389 382 390 383 header = icmp_prepare_packet(packet); 391 if (! header){384 if (!header) 392 385 return icmp_release_and_return(packet, ENOMEM); 393 } 394 return icmp_send_packet(ICMP_TIME_EXCEEDED, code, packet, header, SERVICE_ICMP, 0, 0, 0); 395 } 396 397 int icmp_parameter_problem_msg(int icmp_phone, icmp_code_t code, icmp_param_t pointer, packet_t packet){ 386 387 return icmp_send_packet(ICMP_TIME_EXCEEDED, code, packet, header, 388 SERVICE_ICMP, 0, 0, 0); 389 } 390 391 static int 392 icmp_parameter_problem_msg_local(int icmp_phone, icmp_code_t code, 393 icmp_param_t pointer, packet_t packet) 394 { 398 395 icmp_header_ref header; 399 396 400 397 header = icmp_prepare_packet(packet); 401 if (! header){398 if (!header) 402 399 return icmp_release_and_return(packet, ENOMEM); 403 } 400 404 401 header->un.param.pointer = pointer; 405 return icmp_send_packet(ICMP_PARAMETERPROB, code, packet, header, SERVICE_ICMP, 0, 0, 0); 406 } 407 408 icmp_header_ref icmp_prepare_packet(packet_t packet){ 409 icmp_header_ref header; 410 size_t header_length; 411 size_t total_length; 412 413 total_length = packet_get_data_length(packet); 414 if(total_length <= 0){ 415 return NULL; 416 } 417 header_length = ip_client_header_length(packet); 418 if(header_length <= 0){ 419 return NULL; 420 } 421 // truncate if longer than 64 bits (without the IP header) 422 if((total_length > header_length + ICMP_KEEP_LENGTH) 423 && (packet_trim(packet, 0, total_length - header_length - ICMP_KEEP_LENGTH) != EOK)){ 424 return NULL; 425 } 426 header = PACKET_PREFIX(packet, icmp_header_t); 427 if(! header){ 428 return NULL; 429 } 430 bzero(header, sizeof(*header)); 431 return header; 432 } 433 434 int icmp_send_packet(icmp_type_t type, icmp_code_t code, packet_t packet, icmp_header_ref header, services_t error, ip_ttl_t ttl, ip_tos_t tos, int dont_fragment){ 402 return icmp_send_packet(ICMP_PARAMETERPROB, code, packet, header, 403 SERVICE_ICMP, 0, 0, 0); 404 } 405 406 /** Initializes the ICMP module. 407 * 408 * @param[in] client_connection The client connection processing function. The 409 * module skeleton propagates its own one. 410 * @returns EOK on success. 411 * @returns ENOMEM if there is not enough memory left. 412 */ 413 int icmp_initialize(async_client_conn_t client_connection) 414 { 435 415 ERROR_DECLARE; 436 416 437 // do not send an error if disabled 438 if(error && (! icmp_globals.error_reporting)){ 439 return icmp_release_and_return(packet, EPERM); 440 } 441 header->type = type; 442 header->code = code; 443 header->checksum = 0; 444 header->checksum = ICMP_CHECKSUM(header, packet_get_data_length(packet)); 445 if(ERROR_OCCURRED(ip_client_prepare_packet(packet, IPPROTO_ICMP, ttl, tos, dont_fragment, 0))){ 446 return icmp_release_and_return(packet, ERROR_CODE); 447 } 448 return ip_send_msg(icmp_globals.ip_phone, -1, packet, SERVICE_ICMP, error); 449 } 450 451 int icmp_initialize(async_client_conn_t client_connection){ 452 ERROR_DECLARE; 453 454 measured_string_t names[] = {{str_dup("ICMP_ERROR_REPORTING"), 20}, {str_dup("ICMP_ECHO_REPLYING"), 18}}; 417 measured_string_t names[] = { 418 { 419 (char *) "ICMP_ERROR_REPORTING", 420 20 421 }, 422 { 423 (char *) "ICMP_ECHO_REPLYING", 424 18 425 } 426 }; 455 427 measured_string_ref configuration; 456 428 size_t count = sizeof(names) / sizeof(measured_string_t); 457 char * 429 char *data; 458 430 459 431 fibril_rwlock_initialize(&icmp_globals.lock); … … 461 433 icmp_replies_initialize(&icmp_globals.replies); 462 434 icmp_echo_data_initialize(&icmp_globals.echo_data); 463 icmp_globals.ip_phone = ip_bind_service(SERVICE_IP, IPPROTO_ICMP, SERVICE_ICMP, client_connection); 464 if(icmp_globals.ip_phone < 0){ 435 icmp_globals.ip_phone = ip_bind_service(SERVICE_IP, IPPROTO_ICMP, 436 SERVICE_ICMP, client_connection); 437 if (icmp_globals.ip_phone < 0) 465 438 return icmp_globals.ip_phone; 466 } 467 ERROR_PROPAGATE(ip_packet_size_req(icmp_globals.ip_phone, -1, &icmp_globals.packet_dimension)); 439 440 ERROR_PROPAGATE(ip_packet_size_req(icmp_globals.ip_phone, -1, 441 &icmp_globals.packet_dimension)); 468 442 icmp_globals.packet_dimension.prefix += ICMP_HEADER_SIZE; 469 443 icmp_globals.packet_dimension.content -= ICMP_HEADER_SIZE; 470 // get configuration 444 471 445 icmp_globals.error_reporting = NET_DEFAULT_ICMP_ERROR_REPORTING; 472 446 icmp_globals.echo_replying = NET_DEFAULT_ICMP_ECHO_REPLYING; 447 448 // get configuration 473 449 configuration = &names[0]; 474 ERROR_PROPAGATE(net_get_conf_req(icmp_globals.net_phone, &configuration, count, &data)); 475 if(configuration){ 476 if(configuration[0].value){ 477 icmp_globals.error_reporting = (configuration[0].value[0] == 'y'); 478 } 479 if(configuration[1].value){ 480 icmp_globals.echo_replying = (configuration[1].value[0] == 'y'); 450 ERROR_PROPAGATE(net_get_conf_req(icmp_globals.net_phone, &configuration, 451 count, &data)); 452 if (configuration) { 453 if (configuration[0].value) { 454 icmp_globals.error_reporting = 455 (configuration[0].value[0] == 'y'); 456 } 457 if (configuration[1].value) { 458 icmp_globals.echo_replying = 459 (configuration[1].value[0] == 'y'); 481 460 } 482 461 net_free_settings(configuration, data); 483 462 } 463 484 464 fibril_rwlock_write_unlock(&icmp_globals.lock); 485 465 return EOK; 486 466 } 487 467 488 int icmp_received_msg(device_id_t device_id, packet_t packet, services_t receiver, services_t error){ 468 /** Tries to set the pending reply result as the received message type. 469 * 470 * If the reply data is not present, the reply timed out and the other fibril 471 * is already awake. 472 * Releases the packet. 473 * 474 * @param[in] packet The received reply message. 475 * @param[in] header The ICMP message header. 476 * @param[in] type The received reply message type. 477 * @param[in] code The received reply message code. 478 */ 479 static void 480 icmp_process_echo_reply(packet_t packet, icmp_header_ref header, 481 icmp_type_t type, icmp_code_t code) 482 { 483 int reply_key; 484 icmp_reply_ref reply; 485 486 // compute the reply key 487 reply_key = ICMP_GET_REPLY_KEY(header->un.echo.identifier, 488 header->un.echo.sequence_number); 489 pq_release_remote(icmp_globals.net_phone, packet_get_id(packet)); 490 491 fibril_rwlock_write_lock(&icmp_globals.lock); 492 // find the pending reply 493 reply = icmp_replies_find(&icmp_globals.replies, reply_key); 494 if (reply) { 495 reply->result = type; 496 fibril_condvar_signal(&reply->condvar); 497 } 498 fibril_rwlock_write_unlock(&icmp_globals.lock); 499 } 500 501 /** Processes the received ICMP packet. 502 * 503 * Notifies the destination socket application. 504 * 505 * @param[in,out] packet The received packet. 506 * @param[in] error The packet error reporting service. Prefixes the 507 * received packet. 508 * @returns EOK on success. 509 * @returns EINVAL if the packet is not valid. 510 * @returns EINVAL if the stored packet address is not the an_addr_t. 511 * @returns EINVAL if the packet does not contain any data. 512 * @returns NO_DATA if the packet content is shorter than the user 513 * datagram header. 514 * @returns ENOMEM if there is not enough memory left. 515 * @returns EADDRNOTAVAIL if the destination socket does not exist. 516 * @returns Other error codes as defined for the 517 * ip_client_process_packet() function. 518 */ 519 static int icmp_process_packet(packet_t packet, services_t error) 520 { 489 521 ERROR_DECLARE; 490 522 491 if(ERROR_OCCURRED(icmp_process_packet(packet, error))){492 return icmp_release_and_return(packet, ERROR_CODE);493 }494 495 return EOK;496 }497 498 int icmp_process_packet(packet_t packet, services_t error){499 ERROR_DECLARE;500 501 523 size_t length; 502 uint8_t * 524 uint8_t *src; 503 525 int addrlen; 504 526 int result; 505 void * 527 void *data; 506 528 icmp_header_ref header; 507 529 icmp_type_t type; 508 530 icmp_code_t code; 509 531 510 if(error){ 511 switch(error){ 512 case SERVICE_ICMP: 513 // process error 514 result = icmp_client_process_packet(packet, &type, &code, NULL, NULL); 515 if(result < 0){ 516 return result; 517 } 518 length = (size_t) result; 519 // remove the error header 520 ERROR_PROPAGATE(packet_trim(packet, length, 0)); 521 break; 522 default: 523 return ENOTSUP; 524 } 525 } 532 switch (error) { 533 case SERVICE_NONE: 534 break; 535 case SERVICE_ICMP: 536 // process error 537 result = icmp_client_process_packet(packet, &type, &code, NULL, 538 NULL); 539 if (result < 0) 540 return result; 541 length = (size_t) result; 542 // remove the error header 543 ERROR_PROPAGATE(packet_trim(packet, length, 0)); 544 break; 545 default: 546 return ENOTSUP; 547 } 548 526 549 // get rid of the ip header 527 550 length = ip_client_header_length(packet); … … 529 552 530 553 length = packet_get_data_length(packet); 531 if (length <= 0){554 if (length <= 0) 532 555 return EINVAL; 533 } 534 if (length < ICMP_HEADER_SIZE){556 557 if (length < ICMP_HEADER_SIZE) 535 558 return EINVAL; 536 } 559 537 560 data = packet_get_data(packet); 538 if (! data){561 if (!data) 539 562 return EINVAL; 540 } 563 541 564 // get icmp header 542 565 header = (icmp_header_ref) data; 543 // checksum 544 if (header->checksum){545 while (ICMP_CHECKSUM(header, length) != IP_CHECKSUM_ZERO){566 567 if (header->checksum) { 568 while (ICMP_CHECKSUM(header, length) != IP_CHECKSUM_ZERO) { 546 569 // set the original message type on error notification 547 570 // type swap observed in Qemu 548 if (error){549 switch (header->type){550 551 552 571 if (error) { 572 switch (header->type) { 573 case ICMP_ECHOREPLY: 574 header->type = ICMP_ECHO; 575 continue; 553 576 } 554 577 } … … 556 579 } 557 580 } 558 switch(header->type){ 559 case ICMP_ECHOREPLY: 560 if(error){ 561 return icmp_process_echo_reply(packet, header, type, code); 562 }else{ 563 return icmp_process_echo_reply(packet, header, ICMP_ECHO, 0); 581 582 switch (header->type) { 583 case ICMP_ECHOREPLY: 584 if (error) 585 icmp_process_echo_reply(packet, header, type, code); 586 else 587 icmp_process_echo_reply(packet, header, ICMP_ECHO, 0); 588 589 return EOK; 590 591 case ICMP_ECHO: 592 if (error) { 593 icmp_process_echo_reply(packet, header, type, code); 594 return EOK; 595 } 596 597 // do not send a reply if disabled 598 if (icmp_globals.echo_replying) { 599 addrlen = packet_get_addr(packet, &src, NULL); 600 601 // set both addresses to the source one (avoids the 602 // source address deletion before setting the 603 // destination one) 604 if ((addrlen > 0) && (packet_set_addr(packet, src, src, 605 (size_t) addrlen) == EOK)) { 606 // send the reply 607 icmp_send_packet(ICMP_ECHOREPLY, 0, packet, 608 header, 0, 0, 0, 0); 609 return EOK; 564 610 } 565 case ICMP_ECHO: 566 if(error){ 567 return icmp_process_echo_reply(packet, header, type, code); 568 // do not send a reply if disabled 569 }else if(icmp_globals.echo_replying){ 570 addrlen = packet_get_addr(packet, &src, NULL); 571 if((addrlen > 0) 572 // set both addresses to the source one (avoids the source address deletion before setting the destination one) 573 && (packet_set_addr(packet, src, src, (size_t) addrlen) == EOK)){ 574 // send the reply 575 icmp_send_packet(ICMP_ECHOREPLY, 0, packet, header, 0, 0, 0, 0); 576 return EOK; 577 }else{ 578 return EINVAL; 611 612 return EINVAL; 613 } 614 615 return EPERM; 616 617 case ICMP_DEST_UNREACH: 618 case ICMP_SOURCE_QUENCH: 619 case ICMP_REDIRECT: 620 case ICMP_ALTERNATE_ADDR: 621 case ICMP_ROUTER_ADV: 622 case ICMP_ROUTER_SOL: 623 case ICMP_TIME_EXCEEDED: 624 case ICMP_PARAMETERPROB: 625 case ICMP_CONVERSION_ERROR: 626 case ICMP_REDIRECT_MOBILE: 627 case ICMP_SKIP: 628 case ICMP_PHOTURIS: 629 ip_received_error_msg(icmp_globals.ip_phone, -1, packet, 630 SERVICE_IP, SERVICE_ICMP); 631 return EOK; 632 633 default: 634 return ENOTSUP; 635 } 636 } 637 638 /** Processes the received ICMP packet. 639 * 640 * Is used as an entry point from the underlying IP module. 641 * Releases the packet on error. 642 * 643 * @param device_id The device identifier. Ignored parameter. 644 * @param[in,out] packet The received packet. 645 * @param receiver The target service. Ignored parameter. 646 * @param[in] error The packet error reporting service. Prefixes the 647 * received packet. 648 * @returns EOK on success. 649 * @returns Other error codes as defined for the 650 * icmp_process_packet() function. 651 */ 652 static int 653 icmp_received_msg_local(device_id_t device_id, packet_t packet, 654 services_t receiver, services_t error) 655 { 656 ERROR_DECLARE; 657 658 if (ERROR_OCCURRED(icmp_process_packet(packet, error))) 659 return icmp_release_and_return(packet, ERROR_CODE); 660 661 return EOK; 662 } 663 664 /** Processes the generic client messages. 665 * 666 * @param[in] call The message parameters. 667 * @returns EOK on success. 668 * @returns ENOTSUP if the message is not known. 669 * @returns Other error codes as defined for the packet_translate() 670 * function. 671 * @returns Other error codes as defined for the 672 * icmp_destination_unreachable_msg_local() function. 673 * @returns Other error codes as defined for the 674 * icmp_source_quench_msg_local() function. 675 * @returns Other error codes as defined for the 676 * icmp_time_exceeded_msg_local() function. 677 * @returns Other error codes as defined for the 678 * icmp_parameter_problem_msg_local() function. 679 * 680 * @see icmp_interface.h 681 */ 682 static int icmp_process_message(ipc_call_t *call) 683 { 684 ERROR_DECLARE; 685 686 packet_t packet; 687 688 switch (IPC_GET_METHOD(*call)) { 689 case NET_ICMP_DEST_UNREACH: 690 if (ERROR_NONE(packet_translate_remote(icmp_globals.net_phone, 691 &packet, IPC_GET_PACKET(call)))) { 692 ERROR_CODE = icmp_destination_unreachable_msg_local(0, 693 ICMP_GET_CODE(call), ICMP_GET_MTU(call), packet); 694 } 695 return ERROR_CODE; 696 case NET_ICMP_SOURCE_QUENCH: 697 if (ERROR_NONE(packet_translate_remote(icmp_globals.net_phone, 698 &packet, IPC_GET_PACKET(call)))) { 699 ERROR_CODE = icmp_source_quench_msg_local(0, packet); 700 } 701 return ERROR_CODE; 702 case NET_ICMP_TIME_EXCEEDED: 703 if (ERROR_NONE(packet_translate_remote(icmp_globals.net_phone, 704 &packet, IPC_GET_PACKET(call)))) { 705 ERROR_CODE = icmp_time_exceeded_msg_local(0, 706 ICMP_GET_CODE(call), packet); 707 } 708 return ERROR_CODE; 709 case NET_ICMP_PARAMETERPROB: 710 if (ERROR_NONE(packet_translate_remote(icmp_globals.net_phone, 711 &packet, IPC_GET_PACKET(call)))) { 712 ERROR_CODE = icmp_parameter_problem_msg_local(0, 713 ICMP_GET_CODE(call), ICMP_GET_POINTER(call), 714 packet); 715 } 716 return ERROR_CODE; 717 default: 718 return ENOTSUP; 719 } 720 } 721 722 /** Assigns a new identifier for the connection. 723 * 724 * Fills the echo data parameter with the assigned values. 725 * 726 * @param[in,out] echo_data The echo data to be bound. 727 * @returns Index of the inserted echo data. 728 * @returns EBADMEM if the echo_data parameter is NULL. 729 * @returns ENOTCONN if no free identifier have been found. 730 */ 731 static int icmp_bind_free_id(icmp_echo_ref echo_data) 732 { 733 icmp_param_t index; 734 735 if (!echo_data) 736 return EBADMEM; 737 738 // from the last used one 739 index = icmp_globals.last_used_id; 740 do { 741 index++; 742 // til the range end 743 if (index >= ICMP_FREE_IDS_END) { 744 // start from the range beginning 745 index = ICMP_FREE_IDS_START - 1; 746 do { 747 index++; 748 // til the last used one 749 if (index >= icmp_globals.last_used_id) { 750 // none found 751 return ENOTCONN; 579 752 } 580 }else{ 581 return EPERM; 582 } 583 case ICMP_DEST_UNREACH: 584 case ICMP_SOURCE_QUENCH: 585 case ICMP_REDIRECT: 586 case ICMP_ALTERNATE_ADDR: 587 case ICMP_ROUTER_ADV: 588 case ICMP_ROUTER_SOL: 589 case ICMP_TIME_EXCEEDED: 590 case ICMP_PARAMETERPROB: 591 case ICMP_CONVERSION_ERROR: 592 case ICMP_REDIRECT_MOBILE: 593 case ICMP_SKIP: 594 case ICMP_PHOTURIS: 595 ip_received_error_msg(icmp_globals.ip_phone, -1, packet, SERVICE_IP, SERVICE_ICMP); 596 return EOK; 597 default: 598 return ENOTSUP; 599 } 600 } 601 602 int icmp_process_echo_reply(packet_t packet, icmp_header_ref header, icmp_type_t type, icmp_code_t code){ 603 int reply_key; 604 icmp_reply_ref reply; 605 606 // compute the reply key 607 reply_key = ICMP_GET_REPLY_KEY(header->un.echo.identifier, header->un.echo.sequence_number); 608 pq_release_remote(icmp_globals.net_phone, packet_get_id(packet)); 609 // lock the globals 610 fibril_rwlock_write_lock(&icmp_globals.lock); 611 // find the pending reply 612 reply = icmp_replies_find(&icmp_globals.replies, reply_key); 613 if(reply){ 614 // set the result 615 reply->result = type; 616 // notify the waiting fibril 617 fibril_condvar_signal(&reply->condvar); 618 } 619 fibril_rwlock_write_unlock(&icmp_globals.lock); 620 return EOK; 621 } 622 623 int icmp_message_standalone(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count){ 753 } while(icmp_echo_data_find(&icmp_globals.echo_data, 754 index) != NULL); 755 756 // found, break immediately 757 break; 758 } 759 } while(icmp_echo_data_find(&icmp_globals.echo_data, index) != NULL); 760 761 echo_data->identifier = index; 762 echo_data->sequence_number = 0; 763 764 return icmp_echo_data_add(&icmp_globals.echo_data, index, echo_data); 765 } 766 767 /** Processes the client messages. 768 * 769 * Remembers the assigned identifier and sequence numbers. 770 * Runs until the client module disconnects. 771 * 772 * @param[in] callid The message identifier. 773 * @param[in] call The message parameters. 774 * @returns EOK. 775 * 776 * @see icmp_interface.h 777 * @see icmp_api.h 778 */ 779 static int icmp_process_client_messages(ipc_callid_t callid, ipc_call_t call) 780 { 624 781 ERROR_DECLARE; 625 782 626 packet_t packet;627 628 *answer_count = 0;629 switch(IPC_GET_METHOD(*call)){630 case NET_TL_RECEIVED:631 if(! ERROR_OCCURRED(packet_translate_remote(icmp_globals.net_phone, &packet, IPC_GET_PACKET(call)))){632 ERROR_CODE = icmp_received_msg(IPC_GET_DEVICE(call), packet, SERVICE_ICMP, IPC_GET_ERROR(call));633 }634 return ERROR_CODE;635 case NET_ICMP_INIT:636 return icmp_process_client_messages(callid, * call);637 default:638 return icmp_process_message(call);639 }640 return ENOTSUP;641 }642 643 int icmp_process_client_messages(ipc_callid_t callid, ipc_call_t call){644 ERROR_DECLARE;645 646 783 bool keep_on_going = true; 647 // fibril_rwlock_t lock;648 784 ipc_call_t answer; 649 785 int answer_count; 650 786 size_t length; 651 struct sockaddr * 787 struct sockaddr *addr; 652 788 ipc_callid_t data_callid; 653 789 icmp_echo_ref echo_data; … … 661 797 answer_count = 0; 662 798 663 // fibril_rwlock_initialize(&lock);664 665 799 echo_data = (icmp_echo_ref) malloc(sizeof(*echo_data)); 666 if (! echo_data){800 if (!echo_data) 667 801 return ENOMEM; 668 }669 802 670 803 // assign a new identifier … … 672 805 res = icmp_bind_free_id(echo_data); 673 806 fibril_rwlock_write_unlock(&icmp_globals.lock); 674 if (res < 0){807 if (res < 0) { 675 808 free(echo_data); 676 809 return res; 677 810 } 678 811 679 while(keep_on_going){ 680 812 while (keep_on_going) { 681 813 // answer the call 682 814 answer_call(callid, res, &answer, answer_count); … … 689 821 690 822 // process the call 691 switch(IPC_GET_METHOD(call)){ 692 case IPC_M_PHONE_HUNGUP: 693 keep_on_going = false; 694 res = EHANGUP; 823 switch (IPC_GET_METHOD(call)) { 824 case IPC_M_PHONE_HUNGUP: 825 keep_on_going = false; 826 res = EHANGUP; 827 break; 828 829 case NET_ICMP_ECHO: 830 if (!async_data_write_receive(&data_callid, &length)) { 831 res = EINVAL; 695 832 break; 696 case NET_ICMP_ECHO: 697 // fibril_rwlock_write_lock(&lock); 698 if(! async_data_write_receive(&data_callid, &length)){ 699 res = EINVAL; 700 }else{ 701 addr = malloc(length); 702 if(! addr){ 703 res = ENOMEM; 704 }else{ 705 if(! ERROR_OCCURRED(async_data_write_finalize(data_callid, addr, length))){ 706 fibril_rwlock_write_lock(&icmp_globals.lock); 707 res = icmp_echo(echo_data->identifier, echo_data->sequence_number, ICMP_GET_SIZE(call), ICMP_GET_TIMEOUT(call), ICMP_GET_TTL(call), ICMP_GET_TOS(call), ICMP_GET_DONT_FRAGMENT(call), addr, (socklen_t) length); 708 fibril_rwlock_write_unlock(&icmp_globals.lock); 709 free(addr); 710 if(echo_data->sequence_number < UINT16_MAX){ 711 ++ echo_data->sequence_number; 712 }else{ 713 echo_data->sequence_number = 0; 714 } 715 }else{ 716 res = ERROR_CODE; 717 } 718 } 719 } 720 // fibril_rwlock_write_unlock(&lock); 833 } 834 835 addr = malloc(length); 836 if (!addr) { 837 res = ENOMEM; 721 838 break; 722 default: 723 res = icmp_process_message(&call); 724 } 839 } 840 841 if (ERROR_OCCURRED(async_data_write_finalize( 842 data_callid, addr, length))) { 843 free(addr); 844 res = ERROR_CODE; 845 break; 846 } 847 848 fibril_rwlock_write_lock(&icmp_globals.lock); 849 res = icmp_echo(echo_data->identifier, 850 echo_data->sequence_number, ICMP_GET_SIZE(call), 851 ICMP_GET_TIMEOUT(call), ICMP_GET_TTL(call), 852 ICMP_GET_TOS(call), ICMP_GET_DONT_FRAGMENT(call), 853 addr, (socklen_t) length); 854 fibril_rwlock_write_unlock(&icmp_globals.lock); 855 856 free(addr); 857 858 if (echo_data->sequence_number < UINT16_MAX) 859 echo_data->sequence_number++; 860 else 861 echo_data->sequence_number = 0; 862 863 break; 864 865 default: 866 res = icmp_process_message(&call); 867 } 868 725 869 } 726 870 … … 729 873 icmp_echo_data_exclude(&icmp_globals.echo_data, echo_data->identifier); 730 874 fibril_rwlock_write_unlock(&icmp_globals.lock); 875 731 876 return res; 732 877 } 733 878 734 int icmp_process_message(ipc_call_t * call){ 879 /** Processes the ICMP message. 880 * 881 * @param[in] callid The message identifier. 882 * @param[in] call The message parameters. 883 * @param[out] answer The message answer parameters. 884 * @param[out] answer_count The last parameter for the actual answer in the 885 * answer parameter. 886 * @returns EOK on success. 887 * @returns ENOTSUP if the message is not known. 888 * 889 * @see icmp_interface.h 890 * @see IS_NET_ICMP_MESSAGE() 891 */ 892 int 893 icmp_message_standalone(ipc_callid_t callid, ipc_call_t *call, 894 ipc_call_t *answer, int *answer_count) 895 { 735 896 ERROR_DECLARE; 736 897 737 898 packet_t packet; 738 899 739 switch(IPC_GET_METHOD(*call)){ 740 case NET_ICMP_DEST_UNREACH: 741 if(! ERROR_OCCURRED(packet_translate_remote(icmp_globals.net_phone, &packet, IPC_GET_PACKET(call)))){ 742 ERROR_CODE = icmp_destination_unreachable_msg(0, ICMP_GET_CODE(call), ICMP_GET_MTU(call), packet); 743 } 744 return ERROR_CODE; 745 case NET_ICMP_SOURCE_QUENCH: 746 if(! ERROR_OCCURRED(packet_translate_remote(icmp_globals.net_phone, &packet, IPC_GET_PACKET(call)))){ 747 ERROR_CODE = icmp_source_quench_msg(0, packet); 748 } 749 return ERROR_CODE; 750 case NET_ICMP_TIME_EXCEEDED: 751 if(! ERROR_OCCURRED(packet_translate_remote(icmp_globals.net_phone, &packet, IPC_GET_PACKET(call)))){ 752 ERROR_CODE = icmp_time_exceeded_msg(0, ICMP_GET_CODE(call), packet); 753 } 754 return ERROR_CODE; 755 case NET_ICMP_PARAMETERPROB: 756 if(! ERROR_OCCURRED(packet_translate_remote(icmp_globals.net_phone, &packet, IPC_GET_PACKET(call)))){ 757 ERROR_CODE = icmp_parameter_problem_msg(0, ICMP_GET_CODE(call), ICMP_GET_POINTER(call), packet); 758 } 759 return ERROR_CODE; 760 default: 761 return ENOTSUP; 762 } 763 } 764 765 int icmp_release_and_return(packet_t packet, int result){ 766 pq_release_remote(icmp_globals.net_phone, packet_get_id(packet)); 767 return result; 768 } 769 770 int icmp_bind_free_id(icmp_echo_ref echo_data){ 771 icmp_param_t index; 772 773 if(! echo_data){ 774 return EBADMEM; 775 } 776 // from the last used one 777 index = icmp_globals.last_used_id; 778 do{ 779 ++ index; 780 // til the range end 781 if(index >= ICMP_FREE_IDS_END){ 782 // start from the range beginning 783 index = ICMP_FREE_IDS_START - 1; 784 do{ 785 ++ index; 786 // til the last used one 787 if(index >= icmp_globals.last_used_id){ 788 // none found 789 return ENOTCONN; 790 } 791 }while(icmp_echo_data_find(&icmp_globals.echo_data, index) != NULL); 792 // found, break immediately 793 break; 794 } 795 }while(icmp_echo_data_find(&icmp_globals.echo_data, index) != NULL); 796 echo_data->identifier = index; 797 echo_data->sequence_number = 0; 798 return icmp_echo_data_add(&icmp_globals.echo_data, index, echo_data); 799 } 900 *answer_count = 0; 901 switch (IPC_GET_METHOD(*call)) { 902 case NET_TL_RECEIVED: 903 if (ERROR_NONE(packet_translate_remote(icmp_globals.net_phone, 904 &packet, IPC_GET_PACKET(call)))) { 905 ERROR_CODE = 906 icmp_received_msg_local(IPC_GET_DEVICE(call), 907 packet, SERVICE_ICMP, IPC_GET_ERROR(call)); 908 } 909 return ERROR_CODE; 910 911 case NET_ICMP_INIT: 912 return icmp_process_client_messages(callid, * call); 913 914 default: 915 return icmp_process_message(call); 916 } 917 918 return ENOTSUP; 919 } 920 800 921 801 922 /** Default thread for new connections. 802 923 * 803 * 804 * 805 * 806 */ 807 static void tl_client_connection(ipc_callid_t iid, ipc_call_t * 924 * @param[in] iid The initial message identifier. 925 * @param[in] icall The initial message call structure. 926 * 927 */ 928 static void tl_client_connection(ipc_callid_t iid, ipc_call_t *icall) 808 929 { 809 930 /* … … 813 934 ipc_answer_0(iid, EOK); 814 935 815 while (true) {936 while (true) { 816 937 ipc_call_t answer; 817 938 int answer_count; … … 828 949 &answer_count); 829 950 830 /* End if said to either by the message or the processing result */ 831 if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) || (res == EHANGUP)) 951 /* 952 * End if told to either by the message or the processing 953 * result. 954 */ 955 if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) || 956 (res == EHANGUP)) 832 957 return; 833 958 … … 839 964 /** Starts the module. 840 965 * 841 * @param argc The count of the command line arguments. Ignored parameter. 842 * @param argv The command line parameters. Ignored parameter. 843 * 844 * @returns EOK on success. 845 * @returns Other error codes as defined for each specific module start function. 846 * 966 * @returns EOK on success. 967 * @returns Other error codes as defined for each specific module 968 * start function. 847 969 */ 848 970 int main(int argc, char *argv[]) … … 851 973 852 974 /* Start the module */ 853 if (ERROR_OCCURRED(tl_module_start_standalone(tl_client_connection))) 854 return ERROR_CODE; 855 975 ERROR_PROPAGATE(tl_module_start_standalone(tl_client_connection)); 856 976 return EOK; 857 977 } … … 859 979 /** @} 860 980 */ 981 -
uspace/srv/net/tl/icmp/icmp.h
re06ef614 r49d819b4 28 28 29 29 /** @addtogroup icmp 30 * 30 * @{ 31 31 */ 32 32 33 33 /** @file 34 * 34 * ICMP module. 35 35 */ 36 36 37 #ifndef __NET_ICMP_H__38 #define __NET_ICMP_H__37 #ifndef NET_ICMP_H_ 38 #define NET_ICMP_H_ 39 39 40 40 #include <fibril_synch.h> 41 41 42 42 #include <net/icmp_codes.h> 43 #include <net/packet.h> 43 44 #include <adt/int_map.h> 44 45 #include <icmp_header.h> 45 46 46 47 /** Type definition of the ICMP reply data. 47 * 48 * @see icmp_reply 48 49 */ 49 typedef struct icmp_reply 50 typedef struct icmp_reply icmp_reply_t; 50 51 51 52 /** Type definition of the ICMP reply data pointer. 52 * 53 * @see icmp_reply 53 54 */ 54 typedef icmp_reply_t * 55 typedef icmp_reply_t *icmp_reply_ref; 55 56 56 57 /** Type definition of the ICMP global data. 57 * 58 * @see icmp_globals 58 59 */ 59 typedef struct icmp_globals 60 typedef struct icmp_globals icmp_globals_t; 60 61 61 62 /** Pending replies map. 62 * Maps message identifiers to the pending replies. 63 * Sending fibril waits for its associated reply event. 64 * Receiving fibril sets the associated reply with the return value and signals the event. 63 * 64 * Maps message identifiers to the pending replies. 65 * Sending fibril waits for its associated reply event. 66 * Receiving fibril sets the associated reply with the return value and signals 67 * the event. 65 68 */ 66 69 INT_MAP_DECLARE(icmp_replies, icmp_reply_t); 67 70 68 71 /** Echo specific data map. 69 * The identifier is used in the future semi-remote calls instead of the ICMP phone. 72 * 73 * The identifier is used in the future semi-remote calls instead of the ICMP 74 * phone. 70 75 */ 71 76 INT_MAP_DECLARE(icmp_echo_data, icmp_echo_t); 72 77 73 /** ICMP reply data. 74 */ 75 struct icmp_reply{ 76 /** Reply result. 77 */ 78 /** ICMP reply data. */ 79 struct icmp_reply { 80 /** Reply result. */ 78 81 int result; 79 /** Safety lock. 80 */ 82 /** Safety lock. */ 81 83 fibril_mutex_t mutex; 82 /** Received or timeouted reply signaling. 83 */ 84 /** Received or timeouted reply signaling. */ 84 85 fibril_condvar_t condvar; 85 86 }; 86 87 87 /** ICMP global data. 88 */ 89 struct icmp_globals{ 90 /** IP module phone. 91 */ 88 /** ICMP global data. */ 89 struct icmp_globals { 90 /** IP module phone. */ 92 91 int ip_phone; 93 /** Packet dimension. 94 */ 92 /** Packet dimension. */ 95 93 packet_dimension_t packet_dimension; 96 /** Networking module phone. 97 */ 94 /** Networking module phone. */ 98 95 int net_phone; 99 /** Indicates whether ICMP error reporting is enabled. 100 */ 96 /** Indicates whether ICMP error reporting is enabled. */ 101 97 int error_reporting; 102 /** Indicates whether ICMP echo replying (ping) is enabled. 103 */ 98 /** Indicates whether ICMP echo replying (ping) is enabled. */ 104 99 int echo_replying; 105 /** The last used identifier number. 106 */ 100 /** The last used identifier number. */ 107 101 icmp_param_t last_used_id; 108 /** The budled modules assigned echo specific data. 109 */ 102 /** The budled modules assigned echo specific data. */ 110 103 icmp_echo_data_t echo_data; 111 /** Echo timeout locks. 112 */ 104 /** Echo timeout locks. */ 113 105 icmp_replies_t replies; 114 /** Safety lock. 115 */ 106 /** Safety lock. */ 116 107 fibril_rwlock_t lock; 117 108 }; … … 121 112 /** @} 122 113 */ 123 -
uspace/srv/net/tl/icmp/icmp_module.c
re06ef614 r49d819b4 28 28 29 29 /** @addtogroup icmp 30 * 30 * @{ 31 31 */ 32 32 33 33 /** @file 34 * 35 * 36 * 37 * 34 * ICMP standalone module implementation. 35 * Contains skeleton module functions mapping. 36 * The functions are used by the module skeleton as module specific entry points. 37 * @see module.c 38 38 */ 39 40 #include "icmp.h" 41 #include "icmp_module.h" 39 42 40 43 #include <async.h> … … 47 50 #include <net/packet.h> 48 51 #include <net_interface.h> 52 49 53 #include <tl_local.h> 50 54 51 #include "icmp.h" 52 #include "icmp_module.h" 55 /** ICMP module global data. */ 56 extern icmp_globals_t icmp_globals; 53 57 54 /** ICMP module global data. 55 */ 56 extern icmp_globals_t icmp_globals; 57 58 /** Starts the ICMP module. 59 * Initializes the client connection serving function, initializes the module, registers the module service and starts the async manager, processing IPC messages in an infinite loop. 60 * @param[in] client_connection The client connection processing function. The module skeleton propagates its own one. 61 * @returns EOK on successful module termination. 62 * @returns Other error codes as defined for the arp_initialize() function. 63 * @returns Other error codes as defined for the REGISTER_ME() macro function. 64 */ 65 int tl_module_start_standalone(async_client_conn_t client_connection){ 58 int tl_module_start_standalone(async_client_conn_t client_connection) 59 { 66 60 ERROR_DECLARE; 67 61 … … 70 64 async_set_client_connection(client_connection); 71 65 icmp_globals.net_phone = net_connect_module(); 72 if (icmp_globals.net_phone < 0){66 if (icmp_globals.net_phone < 0) 73 67 return icmp_globals.net_phone; 74 } 68 75 69 ERROR_PROPAGATE(pm_init()); 76 if (ERROR_OCCURRED(icmp_initialize(client_connection))77 || ERROR_OCCURRED(REGISTER_ME(SERVICE_ICMP, &phonehash))){70 if (ERROR_OCCURRED(icmp_initialize(client_connection)) || 71 ERROR_OCCURRED(REGISTER_ME(SERVICE_ICMP, &phonehash))) { 78 72 pm_destroy(); 79 73 return ERROR_CODE; … … 86 80 } 87 81 88 /** Processes the ICMP message. 89 * @param[in] callid The message identifier. 90 * @param[in] call The message parameters. 91 * @param[out] answer The message answer parameters. 92 * @param[out] answer_count The last parameter for the actual answer in the answer parameter. 93 * @returns EOK on success. 94 * @returns Other error codes as defined for the icmp_message() function. 95 */ 96 int tl_module_message_standalone(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count){ 82 int 83 tl_module_message_standalone(ipc_callid_t callid, ipc_call_t *call, 84 ipc_call_t *answer, int *answer_count) 85 { 97 86 return icmp_message_standalone(callid, call, answer, answer_count); 98 87 } … … 100 89 /** @} 101 90 */ 91 -
uspace/srv/net/tl/icmp/icmp_module.h
re06ef614 r49d819b4 28 28 29 29 /** @addtogroup icmp 30 * 30 * @{ 31 31 */ 32 32 33 33 /** @file 34 * 35 * 34 * ICMP module functions. 35 * The functions are used as ICMP module entry points. 36 36 */ 37 37 38 #ifndef __NET_ICMP_MODULE_H__39 #define __NET_ICMP_MODULE_H__38 #ifndef NET_ICMP_MODULE_H_ 39 #define NET_ICMP_MODULE_H_ 40 40 41 41 #include <async.h> 42 42 #include <ipc/ipc.h> 43 43 44 /** Initializes the ICMP module. 45 * @param[in] client_connection The client connection processing function. The module skeleton propagates its own one. 46 * @returns EOK on success. 47 * @returns ENOMEM if there is not enough memory left. 48 */ 49 int icmp_initialize(async_client_conn_t client_connection); 50 51 /** Processes the ICMP message. 52 * @param[in] callid The message identifier. 53 * @param[in] call The message parameters. 54 * @param[out] answer The message answer parameters. 55 * @param[out] answer_count The last parameter for the actual answer in the answer parameter. 56 * @returns EOK on success. 57 * @returns ENOTSUP if the message is not known. 58 * @see icmp_interface.h 59 * @see IS_NET_ICMP_MESSAGE() 60 */ 61 int icmp_message_standalone(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count); 44 extern int icmp_initialize(async_client_conn_t); 45 extern int icmp_message_standalone(ipc_callid_t, ipc_call_t *, ipc_call_t *, 46 int *); 62 47 63 48 #endif -
uspace/srv/net/tl/tcp/tcp.c
re06ef614 r49d819b4 28 28 29 29 /** @addtogroup tcp 30 * 30 * @{ 31 31 */ 32 32 33 33 /** @file 34 * 35 * 34 * TCP module implementation. 35 * @see tcp.h 36 36 */ 37 38 #include "tcp.h" 39 #include "tcp_header.h" 40 #include "tcp_module.h" 37 41 38 42 #include <assert.h> … … 72 76 #include <tl_interface.h> 73 77 74 #include "tcp.h"75 #include "tcp_header.h"76 #include "tcp_module.h"77 78 78 /** TCP module name. */ 79 79 #define NAME "TCP protocol" … … 110 110 111 111 /** Returns a value indicating whether the value is in the interval respecting 112 * 112 * the possible overflow. 113 113 * 114 * The high end and/or the value may overflow, be lower than the low value. 115 * @param[in] lower The last value before the interval. 116 * @param[in] value The value to be checked. 117 * @param[in] higher_equal The last value in the interval. 114 * The high end and/or the value may overflow, be lower than the low value. 115 * 116 * @param[in] lower The last value before the interval. 117 * @param[in] value The value to be checked. 118 * @param[in] higher_equal The last value in the interval. 118 119 */ 119 120 #define IS_IN_INTERVAL_OVERFLOW(lower, value, higher_equal) \ … … 165 166 }; 166 167 167 /** Releases the packet and returns the result. 168 * @param[in] packet The packet queue to be released. 169 * @param[in] result The result to be returned. 170 * @return The result parameter. 171 */ 172 int tcp_release_and_return(packet_t packet, int result); 173 174 void tcp_prepare_operation_header(socket_core_ref socket, 175 tcp_socket_data_ref socket_data, tcp_header_ref header, int synchronize, 176 int finalize); 177 int tcp_prepare_timeout(int (*timeout_function)(void *tcp_timeout_t), 178 socket_core_ref socket, tcp_socket_data_ref socket_data, 179 size_t sequence_number, tcp_socket_state_t state, suseconds_t timeout, 180 int globals_read_only); 181 void tcp_free_socket_data(socket_core_ref socket); 182 183 int tcp_timeout(void *data); 184 185 int tcp_release_after_timeout(void *data); 186 187 int tcp_process_packet(device_id_t device_id, packet_t packet, 188 services_t error); 189 int tcp_connect_core(socket_core_ref socket, socket_cores_ref local_sockets, 190 struct sockaddr *addr, socklen_t addrlen); 191 int tcp_queue_prepare_packet(socket_core_ref socket, 192 tcp_socket_data_ref socket_data, packet_t packet, size_t data_length); 193 int tcp_queue_packet(socket_core_ref socket, tcp_socket_data_ref socket_data, 194 packet_t packet, size_t data_length); 195 packet_t tcp_get_packets_to_send(socket_core_ref socket, 196 tcp_socket_data_ref socket_data); 197 void tcp_send_packets(device_id_t device_id, packet_t packet); 198 199 void tcp_process_acknowledgement(socket_core_ref socket, 200 tcp_socket_data_ref socket_data, tcp_header_ref header); 201 packet_t tcp_send_prepare_packet(socket_core_ref socket, 202 tcp_socket_data_ref socket_data, packet_t packet, size_t data_length, 203 size_t sequence_number); 204 packet_t tcp_prepare_copy(socket_core_ref socket, 205 tcp_socket_data_ref socket_data, packet_t packet, size_t data_length, 206 size_t sequence_number); 207 void tcp_retransmit_packet(socket_core_ref socket, 208 tcp_socket_data_ref socket_data, size_t sequence_number); 209 int tcp_create_notification_packet(packet_t * packet, socket_core_ref socket, 210 tcp_socket_data_ref socket_data, int synchronize, int finalize); 211 void tcp_refresh_socket_data(tcp_socket_data_ref socket_data); 212 213 void tcp_initialize_socket_data(tcp_socket_data_ref socket_data); 214 215 int tcp_process_listen(socket_core_ref listening_socket, 216 tcp_socket_data_ref listening_socket_data, tcp_header_ref header, 217 packet_t packet, struct sockaddr *src, struct sockaddr *dest, 218 size_t addrlen); 219 int tcp_process_syn_sent(socket_core_ref socket, 220 tcp_socket_data_ref socket_data, tcp_header_ref header, packet_t packet); 221 int tcp_process_syn_received(socket_core_ref socket, 222 tcp_socket_data_ref socket_data, tcp_header_ref header, packet_t packet); 223 int tcp_process_established(socket_core_ref socket, 224 tcp_socket_data_ref socket_data, tcp_header_ref header, packet_t packet, 225 int fragments, size_t total_length); 226 int tcp_queue_received_packet(socket_core_ref socket, 227 tcp_socket_data_ref socket_data, packet_t packet, int fragments, 228 size_t total_length); 229 230 int tcp_received_msg(device_id_t device_id, packet_t packet, 231 services_t receiver, services_t error); 232 int tcp_process_client_messages(ipc_callid_t callid, ipc_call_t call); 233 234 int tcp_listen_message(socket_cores_ref local_sockets, int socket_id, 235 int backlog); 236 int tcp_connect_message(socket_cores_ref local_sockets, int socket_id, 237 struct sockaddr *addr, socklen_t addrlen); 238 int tcp_recvfrom_message(socket_cores_ref local_sockets, int socket_id, 239 int flags, size_t * addrlen); 240 int tcp_send_message(socket_cores_ref local_sockets, int socket_id, 241 int fragments, size_t * data_fragment_size, int flags); 242 int tcp_accept_message(socket_cores_ref local_sockets, int socket_id, 243 int new_socket_id, size_t * data_fragment_size, size_t * addrlen); 244 int tcp_close_message(socket_cores_ref local_sockets, int socket_id); 168 static int tcp_release_and_return(packet_t, int); 169 static void tcp_prepare_operation_header(socket_core_ref, tcp_socket_data_ref, 170 tcp_header_ref, int synchronize, int); 171 static int tcp_prepare_timeout(int (*)(void *), socket_core_ref, 172 tcp_socket_data_ref, size_t, tcp_socket_state_t, suseconds_t, int); 173 static void tcp_free_socket_data(socket_core_ref); 174 175 static int tcp_timeout(void *); 176 177 static int tcp_release_after_timeout(void *); 178 179 static int tcp_process_packet(device_id_t, packet_t, services_t); 180 static int tcp_connect_core(socket_core_ref, socket_cores_ref, 181 struct sockaddr *, socklen_t); 182 static int tcp_queue_prepare_packet(socket_core_ref, tcp_socket_data_ref, 183 packet_t, size_t); 184 static int tcp_queue_packet(socket_core_ref, tcp_socket_data_ref, packet_t, 185 size_t); 186 static packet_t tcp_get_packets_to_send(socket_core_ref, tcp_socket_data_ref); 187 static void tcp_send_packets(device_id_t, packet_t); 188 189 static void tcp_process_acknowledgement(socket_core_ref, tcp_socket_data_ref, 190 tcp_header_ref); 191 static packet_t tcp_send_prepare_packet(socket_core_ref, tcp_socket_data_ref, 192 packet_t, size_t, size_t); 193 static packet_t tcp_prepare_copy(socket_core_ref, tcp_socket_data_ref, packet_t, 194 size_t, size_t); 195 /* static */ void tcp_retransmit_packet(socket_core_ref, tcp_socket_data_ref, 196 size_t); 197 static int tcp_create_notification_packet(packet_t *, socket_core_ref, 198 tcp_socket_data_ref, int, int); 199 static void tcp_refresh_socket_data(tcp_socket_data_ref); 200 201 static void tcp_initialize_socket_data(tcp_socket_data_ref); 202 203 static int tcp_process_listen(socket_core_ref, tcp_socket_data_ref, 204 tcp_header_ref, packet_t, struct sockaddr *, struct sockaddr *, size_t); 205 static int tcp_process_syn_sent(socket_core_ref, tcp_socket_data_ref, 206 tcp_header_ref, packet_t); 207 static int tcp_process_syn_received(socket_core_ref, tcp_socket_data_ref, 208 tcp_header_ref, packet_t); 209 static int tcp_process_established(socket_core_ref, tcp_socket_data_ref, 210 tcp_header_ref, packet_t, int, size_t); 211 static int tcp_queue_received_packet(socket_core_ref, tcp_socket_data_ref, 212 packet_t, int, size_t); 213 214 static int tcp_received_msg(device_id_t, packet_t, services_t, services_t); 215 static int tcp_process_client_messages(ipc_callid_t, ipc_call_t); 216 217 static int tcp_listen_message(socket_cores_ref, int, int); 218 static int tcp_connect_message(socket_cores_ref, int, struct sockaddr *, 219 socklen_t); 220 static int tcp_recvfrom_message(socket_cores_ref, int, int, size_t *); 221 static int tcp_send_message(socket_cores_ref, int, int, size_t *, int); 222 static int tcp_accept_message(socket_cores_ref, int, int, size_t *, size_t *); 223 static int tcp_close_message(socket_cores_ref, int); 245 224 246 225 /** TCP global data. */ 247 226 tcp_globals_t tcp_globals; 248 227 228 /** Initializes the TCP module. 229 * 230 * @param[in] client_connection The client connection processing function. The 231 * module skeleton propagates its own one. 232 * @returns EOK on success. 233 * @returns ENOMEM if there is not enough memory left. 234 */ 249 235 int tcp_initialize(async_client_conn_t client_connection) 250 236 { … … 314 300 size_t addrlen; 315 301 316 if (error) { 317 switch (error) { 318 case SERVICE_ICMP: 319 // process error 320 result = icmp_client_process_packet(packet, &type, 321 &code, NULL, NULL); 322 if (result < 0) 323 return tcp_release_and_return(packet, result); 324 325 length = (size_t) result; 326 if (ERROR_OCCURRED(packet_trim(packet, length, 0))) { 327 return tcp_release_and_return(packet, 328 ERROR_CODE); 329 } 330 break; 331 332 default: 333 return tcp_release_and_return(packet, ENOTSUP); 334 } 302 switch (error) { 303 case SERVICE_NONE: 304 break; 305 case SERVICE_ICMP: 306 // process error 307 result = icmp_client_process_packet(packet, &type, &code, NULL, 308 NULL); 309 if (result < 0) 310 return tcp_release_and_return(packet, result); 311 312 length = (size_t) result; 313 if (ERROR_OCCURRED(packet_trim(packet, length, 0))) 314 return tcp_release_and_return(packet, ERROR_CODE); 315 break; 316 default: 317 return tcp_release_and_return(packet, ENOTSUP); 335 318 } 336 319 … … 379 362 ntohs(header->destination_port), SOCKET_MAP_KEY_LISTENING, 380 363 0); 381 if (!socket) {382 if (tl_prepare_icmp_packet(tcp_globals.net_phone,383 tcp_globals.icmp_phone, packet, error) == EOK) {384 icmp_destination_unreachable_msg(385 tcp_globals.icmp_phone, ICMP_PORT_UNREACH,386 387 388 389 390 } 364 } 365 if (!socket) { 366 if (tl_prepare_icmp_packet(tcp_globals.net_phone, 367 tcp_globals.icmp_phone, packet, error) == EOK) { 368 icmp_destination_unreachable_msg(tcp_globals.icmp_phone, 369 ICMP_PORT_UNREACH, 0, packet); 370 } 371 return EADDRNOTAVAIL; 372 } 373 391 374 printf("socket id %d\n", socket->socket_id); 392 375 socket_data = (tcp_socket_data_ref) socket->specific_data; … … 402 385 total_length = 0; 403 386 do { 404 ++fragments;387 fragments++; 405 388 length = packet_get_data_length(next_packet); 406 389 if (length <= 0) … … 421 404 422 405 if (error) 423 goto error;406 goto has_error_service; 424 407 425 408 if (socket_data->state == TCP_SOCKET_LISTEN) { 426 427 409 if (socket_data->pseudo_header) { 428 410 free(socket_data->pseudo_header); … … 464 446 } 465 447 466 error:448 has_error_service: 467 449 fibril_rwlock_read_unlock(&tcp_globals.lock); 468 450 … … 507 489 int 508 490 tcp_process_established(socket_core_ref socket, tcp_socket_data_ref socket_data, 509 tcp_header_ref header, packet_t packet, int fragments, 510 size_t total_length) 491 tcp_header_ref header, packet_t packet, int fragments, size_t total_length) 511 492 { 512 493 ERROR_DECLARE; … … 684 665 continue; 685 666 // at least partly following data? 686 } else if (IS_IN_INTERVAL_OVERFLOW(687 sequence_number, socket_data->next_incoming,688 new_sequence_number)) {667 } 668 if (IS_IN_INTERVAL_OVERFLOW(sequence_number, 669 socket_data->next_incoming, new_sequence_number)) { 689 670 if (socket_data->next_incoming < 690 671 new_sequence_number) { … … 961 942 listening_socket = socket_port_find(&tcp_globals.sockets, 962 943 listening_port, SOCKET_MAP_KEY_LISTENING, 0); 963 if ( (!listening_socket)||944 if (!listening_socket || 964 945 (listening_socket->socket_id != listening_socket_id)) { 965 946 fibril_rwlock_write_unlock(&tcp_globals.lock); … … 1191 1172 if (number == socket_data->expected) { 1192 1173 // increase the counter 1193 ++socket_data->expected_count;1174 socket_data->expected_count++; 1194 1175 if (socket_data->expected_count == TCP_FAST_RETRANSMIT_COUNT) { 1195 1176 socket_data->expected_count = 1; … … 1200 1181 } 1201 1182 1202 int tcp_message_standalone(ipc_callid_t callid, ipc_call_t * call, 1203 ipc_call_t * answer, int *answer_count) 1183 /** Processes the TCP message. 1184 * 1185 * @param[in] callid The message identifier. 1186 * @param[in] call The message parameters. 1187 * @param[out] answer The message answer parameters. 1188 * @param[out] answer_count The last parameter for the actual answer in the 1189 * answer parameter. 1190 * @returns EOK on success. 1191 * @returns ENOTSUP if the message is not known. 1192 * 1193 * @see tcp_interface.h 1194 * @see IS_NET_TCP_MESSAGE() 1195 */ 1196 int 1197 tcp_message_standalone(ipc_callid_t callid, ipc_call_t *call, 1198 ipc_call_t *answer, int *answer_count) 1204 1199 { 1205 1200 ERROR_DECLARE; … … 1521 1516 socket = socket_port_find(&tcp_globals.sockets, timeout->port, 1522 1517 timeout->key, timeout->key_length); 1523 if (! (socket && (socket->socket_id == timeout->socket_id)))1518 if (!socket || (socket->socket_id != timeout->socket_id)) 1524 1519 goto out; 1525 1520 … … 1532 1527 if (timeout->sequence_number) { 1533 1528 // increase the timeout counter; 1534 ++socket_data->timeout_count;1529 socket_data->timeout_count++; 1535 1530 if (socket_data->timeout_count == TCP_MAX_TIMEOUTS) { 1536 1531 // TODO release as connection lost … … 1744 1739 ERROR_OCCURRED(tcp_prepare_timeout(tcp_timeout, socket, socket_data, 1745 1740 0, TCP_SOCKET_INITIAL, NET_DEFAULT_TCP_INITIAL_TIMEOUT, false))) { 1746 1747 1741 socket_data->addr = NULL; 1748 1742 socket_data->addrlen = 0; 1749 1743 fibril_rwlock_write_lock(&tcp_globals.lock); 1750 1751 1744 } else { 1752 1753 1745 packet = tcp_get_packets_to_send(socket, socket_data); 1754 1746 if (packet) { … … 1876 1868 packet = pq_next(packet); 1877 1869 // overflow occurred ? 1878 if ( (!packet)&&1870 if (!packet && 1879 1871 (socket_data->last_outgoing > socket_data->next_outgoing)) { 1880 1872 printf("gpts overflow\n"); … … 2044 2036 int 2045 2037 tcp_recvfrom_message(socket_cores_ref local_sockets, int socket_id, int flags, 2046 size_t * 2038 size_t *addrlen) 2047 2039 { 2048 2040 ERROR_DECLARE; … … 2099 2091 int 2100 2092 tcp_send_message(socket_cores_ref local_sockets, int socket_id, int fragments, 2101 size_t * 2093 size_t *data_fragment_size, int flags) 2102 2094 { 2103 2095 ERROR_DECLARE; … … 2138 2130 packet_dimension->content : socket_data->data_fragment_size); 2139 2131 2140 for (index = 0; index < fragments; ++index) {2132 for (index = 0; index < fragments; index++) { 2141 2133 // read the data fragment 2142 2134 result = tl_socket_read_packet_data(tcp_globals.net_phone, … … 2235 2227 2236 2228 int 2237 tcp_create_notification_packet(packet_t * 2229 tcp_create_notification_packet(packet_t *packet, socket_core_ref socket, 2238 2230 tcp_socket_data_ref socket_data, int synchronize, int finalize) 2239 2231 { … … 2271 2263 int 2272 2264 tcp_accept_message(socket_cores_ref local_sockets, int socket_id, 2273 int new_socket_id, size_t * data_fragment_size, size_t *addrlen)2265 int new_socket_id, size_t *data_fragment_size, size_t *addrlen) 2274 2266 { 2275 2267 ERROR_DECLARE; … … 2373 2365 } 2374 2366 2367 /** Releases the packet and returns the result. 2368 * 2369 * @param[in] packet The packet queue to be released. 2370 * @param[in] result The result to be returned. 2371 * @return The result parameter. 2372 */ 2375 2373 int tcp_release_and_return(packet_t packet, int result) 2376 2374 { … … 2381 2379 /** Default thread for new connections. 2382 2380 * 2383 * @param[in] iidThe initial message identifier.2384 * @param[in] icallThe initial message call structure.2381 * @param[in] iid The initial message identifier. 2382 * @param[in] icall The initial message call structure. 2385 2383 * 2386 2384 */ … … 2397 2395 int answer_count; 2398 2396 2399 /* 2400 Clear the answer structure 2401 */ 2397 /* Clear the answer structure */ 2402 2398 refresh_answer(&answer, &answer_count); 2403 2399 2404 /* 2405 Fetch the next message 2406 */ 2400 /* Fetch the next message */ 2407 2401 ipc_call_t call; 2408 2402 ipc_callid_t callid = async_get_call(&call); 2409 2403 2410 /* 2411 Process the message 2412 */ 2404 /* Process the message */ 2413 2405 int res = tl_module_message_standalone(callid, &call, &answer, 2414 2406 &answer_count); 2415 2407 2416 2408 /* 2417 End if said to either by the message or the processing result 2409 * End if told to either by the message or the processing 2410 * result. 2418 2411 */ 2419 2412 if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) || … … 2430 2423 /** Starts the module. 2431 2424 * 2432 * @param argc The count of the command line arguments. Ignored parameter. 2433 * @param argv The command line parameters. Ignored parameter. 2434 * 2435 * @returns EOK on success. 2436 * @returns Other error codes as defined for each specific module start function. 2437 * 2425 * @returns EOK on success. 2426 * @returns Other error codes as defined for each specific module 2427 * start function. 2438 2428 */ 2439 2429 int -
uspace/srv/net/tl/tcp/tcp.h
re06ef614 r49d819b4 28 28 29 29 /** @addtogroup tcp 30 * 30 * @{ 31 31 */ 32 32 33 33 /** @file 34 * 35 */ 36 37 #ifndef __NET_TCP_H__38 #define __NET_TCP_H__34 * TCP module. 35 */ 36 37 #ifndef NET_TCP_H_ 38 #define NET_TCP_H_ 39 39 40 40 #include <fibril_synch.h> … … 46 46 47 47 /** Type definition of the TCP global data. 48 * 49 */ 50 typedef struct tcp_globals 48 * @see tcp_globals 49 */ 50 typedef struct tcp_globals tcp_globals_t; 51 51 52 52 /** Type definition of the TCP socket specific data. 53 * 54 */ 55 typedef struct tcp_socket_data 53 * @see tcp_socket_data 54 */ 55 typedef struct tcp_socket_data tcp_socket_data_t; 56 56 57 57 /** Type definition of the TCP socket specific data pointer. 58 * 59 */ 60 typedef tcp_socket_data_t * 58 * @see tcp_socket_data 59 */ 60 typedef tcp_socket_data_t *tcp_socket_data_ref; 61 61 62 62 /** Type definition of the TCP operation data. 63 * 64 */ 65 typedef struct tcp_operation 63 * @see tcp_operation 64 */ 65 typedef struct tcp_operation tcp_operation_t; 66 66 67 67 /** Type definition of the TCP operation data pointer. 68 * 69 */ 70 typedef tcp_operation_t * 68 * @see tcp_operation 69 */ 70 typedef tcp_operation_t *tcp_operation_ref; 71 71 72 72 /** TCP socket state type definition. 73 * @see tcp_socket_state 74 */ 75 typedef enum tcp_socket_state tcp_socket_state_t; 76 77 /** TCP socket state. 78 */ 79 enum tcp_socket_state{ 73 * @see tcp_socket_state 74 */ 75 typedef enum tcp_socket_state tcp_socket_state_t; 76 77 /** TCP socket state. */ 78 enum tcp_socket_state { 80 79 /** Initial. 81 * Not connected or bound. 80 * 81 * Not connected or bound. 82 82 */ 83 83 TCP_SOCKET_INITIAL, 84 84 85 /** Listening. 85 * Awaiting a connection request from another TCP layer. 86 * When SYN is received a new bound socket in the TCP_SOCKET_SYN_RECEIVED state should be created. 86 * 87 * Awaiting a connection request from another TCP layer. 88 * When SYN is received a new bound socket in the 89 * TCP_SOCKET_SYN_RECEIVED state should be created. 87 90 */ 88 91 TCP_SOCKET_LISTEN, 92 89 93 /** Connecting issued. 90 * A~SYN has been sent, and TCP is awaiting the response SYN. 91 * Should continue to the TCP_SOCKET_ESTABLISHED state. 94 * 95 * A SYN has been sent, and TCP is awaiting the response SYN. 96 * Should continue to the TCP_SOCKET_ESTABLISHED state. 92 97 */ 93 98 TCP_SOCKET_SYN_SENT, 99 94 100 /** Connecting received. 95 * A~SYN has been received, a~SYN has been sent, and TCP is awaiting an ACK. 96 * Should continue to the TCP_SOCKET_ESTABLISHED state. 101 * 102 * A SYN has been received, a SYN has been sent, and TCP is awaiting an 103 * ACK. Should continue to the TCP_SOCKET_ESTABLISHED state. 97 104 */ 98 105 TCP_SOCKET_SYN_RECEIVED, 106 99 107 /** Connected. 100 * The three-way handshake has been completed. 108 * 109 * The three-way handshake has been completed. 101 110 */ 102 111 TCP_SOCKET_ESTABLISHED, 112 103 113 /** Closing started. 104 * The local application has issued a~CLOSE. 105 * TCP has sent a~FIN, and is awaiting an ACK or a~FIN. 106 * Should continue to the TCP_SOCKET_FIN_WAIT_2 state when an ACK is received. 107 * Should continue to the TCP_SOCKET_CLOSING state when a~FIN is received. 114 * 115 * The local application has issued a CLOSE. 116 * TCP has sent a FIN, and is awaiting an ACK or a FIN. 117 * Should continue to the TCP_SOCKET_FIN_WAIT_2 state when an ACK is 118 * received. 119 * Should continue to the TCP_SOCKET_CLOSING state when a FIN is 120 * received. 108 121 */ 109 122 TCP_SOCKET_FIN_WAIT_1, 123 110 124 /** Closing confirmed. 111 * A~FIN has been sent, and an ACK received. 112 * TCP is awaiting a~FIN from the remote TCP layer. 113 * Should continue to the TCP_SOCKET_CLOSING state. 125 * 126 * A FIN has been sent, and an ACK received. 127 * TCP is awaiting a~FIN from the remote TCP layer. 128 * Should continue to the TCP_SOCKET_CLOSING state. 114 129 */ 115 130 TCP_SOCKET_FIN_WAIT_2, 131 116 132 /** Closing. 117 * A FIN has been sent, a FIN has been received, and an ACK has been sent. 118 * TCP is awaiting an ACK for the FIN that was sent. 119 * Should continue to the TCP_SOCKET_TIME_WAIT state. 133 * 134 * A FIN has been sent, a FIN has been received, and an ACK has been 135 * sent. 136 * TCP is awaiting an ACK for the FIN that was sent. 137 * Should continue to the TCP_SOCKET_TIME_WAIT state. 120 138 */ 121 139 TCP_SOCKET_CLOSING, 140 122 141 /** Closing received. 123 * TCP has received a~FIN, and has sent an ACK. 124 * It is awaiting a~close request from the local application before sending a~FIN. 125 * Should continue to the TCP_SOCKET_SOCKET_LAST_ACK state. 142 * 143 * TCP has received a FIN, and has sent an ACK. 144 * It is awaiting a close request from the local application before 145 * sending a FIN. 146 * Should continue to the TCP_SOCKET_SOCKET_LAST_ACK state. 126 147 */ 127 148 TCP_SOCKET_CLOSE_WAIT, 128 /** 129 * A~FIN has been received, and an ACK and a~FIN have been sent. 130 * TCP is awaiting an ACK. 131 * Should continue to the TCP_SOCKET_TIME_WAIT state. 149 150 /** 151 * A FIN has been received, and an ACK and a FIN have been sent. 152 * TCP is awaiting an ACK. 153 * Should continue to the TCP_SOCKET_TIME_WAIT state. 132 154 */ 133 155 TCP_SOCKET_LAST_ACK, 156 134 157 /** Closing finished. 135 * FINs have been received and ACK’d, and TCP is waiting two MSLs to remove the connection from the table. 158 * 159 * FINs have been received and ACK’d, and TCP is waiting two MSLs to 160 * remove the connection from the table. 136 161 */ 137 162 TCP_SOCKET_TIME_WAIT, 163 138 164 /** Closed. 139 * Imaginary, this indicates that a~connection has been removed from the connection table. 165 * 166 * Imaginary, this indicates that a connection has been removed from 167 * the connection table. 140 168 */ 141 169 TCP_SOCKET_CLOSED 142 170 }; 143 171 144 /** TCP operation data. 145 */ 146 struct tcp_operation{ 147 /** Operation result. 148 */ 172 /** TCP operation data. */ 173 struct tcp_operation { 174 /** Operation result. */ 149 175 int result; 150 /** Safety lock. 151 */ 176 /** Safety lock. */ 152 177 fibril_mutex_t mutex; 153 /** Operation result signaling. 154 */ 178 /** Operation result signaling. */ 155 179 fibril_condvar_t condvar; 156 180 }; 157 181 158 /** TCP socket specific data. 159 */ 160 struct tcp_socket_data{ 161 /** TCP socket state. 162 */ 182 /** TCP socket specific data. */ 183 struct tcp_socket_data { 184 /** TCP socket state. */ 163 185 tcp_socket_state_t state; 164 /** Data fragment size. 165 * Sending optimalization. 186 187 /** 188 * Data fragment size. 189 * Sending optimalization. 166 190 */ 167 191 size_t data_fragment_size; 168 /** Device identifier.169 */192 193 /** Device identifier. */ 170 194 device_id_t device_id; 171 /** Listening backlog. 172 * The maximal number of connected but not yet accepted sockets. 195 196 /** 197 * Listening backlog. 198 * The maximal number of connected but not yet accepted sockets. 173 199 */ 174 200 int backlog; 175 // /** Segment size. 176 // */ 177 // size_t segment_size; 178 /** Parent listening socket identifier. 179 * Set if this socket is an accepted one. 201 202 // /** Segment size. */ 203 // size_t segment_size; 204 205 /** 206 * Parent listening socket identifier. 207 * Set if this socket is an accepted one. 180 208 */ 181 209 int listening_socket_id; 182 /** Treshold size in bytes.183 */210 211 /** Treshold size in bytes. */ 184 212 size_t treshold; 185 /** Window size in bytes. 186 */ 213 /** Window size in bytes. */ 187 214 size_t window; 188 /** Acknowledgement timeout. 189 */ 215 /** Acknowledgement timeout. */ 190 216 suseconds_t timeout; 191 /** Last acknowledged byte. 192 */ 217 /** Last acknowledged byte. */ 193 218 uint32_t acknowledged; 194 /** Next incoming sequence number. 195 */ 219 /** Next incoming sequence number. */ 196 220 uint32_t next_incoming; 197 /** Incoming FIN. 198 */ 221 /** Incoming FIN. */ 199 222 uint32_t fin_incoming; 200 /** Next outgoing sequence number. 201 */ 223 /** Next outgoing sequence number. */ 202 224 uint32_t next_outgoing; 203 /** Last outgoing sequence number. 204 */ 225 /** Last outgoing sequence number. */ 205 226 uint32_t last_outgoing; 206 /** Outgoing FIN. 207 */ 227 /** Outgoing FIN. */ 208 228 uint32_t fin_outgoing; 209 /** Expected sequence number by the remote host. 210 * The sequence number the other host expects. 211 * The notification is sent only upon a packet reecival. 229 230 /** 231 * Expected sequence number by the remote host. 232 * The sequence number the other host expects. 233 * The notification is sent only upon a packet reecival. 212 234 */ 213 235 uint32_t expected; 214 /** Expected sequence number counter. 215 * Counts the number of received notifications for the same sequence number. 236 237 /** 238 * Expected sequence number counter. 239 * Counts the number of received notifications for the same sequence 240 * number. 216 241 */ 217 242 int expected_count; 243 218 244 /** Incoming packet queue. 219 * Packets are buffered until received in the right order. 220 * The packets are excluded after successfully read. 221 * Packets are sorted by their starting byte. 222 * Packets metric is set as their data length. 245 * 246 * Packets are buffered until received in the right order. 247 * The packets are excluded after successfully read. 248 * Packets are sorted by their starting byte. 249 * Packets metric is set as their data length. 223 250 */ 224 251 packet_t incoming; 252 225 253 /** Outgoing packet queue. 226 * Packets are buffered until acknowledged by the remote host in the right order. 227 * The packets are excluded after acknowledged. 228 * Packets are sorted by their starting byte. 229 * Packets metric is set as their data length. 254 * 255 * Packets are buffered until acknowledged by the remote host in the 256 * right order. 257 * The packets are excluded after acknowledged. 258 * Packets are sorted by their starting byte. 259 * Packets metric is set as their data length. 230 260 */ 231 261 packet_t outgoing; 232 /** IP pseudo header.233 */262 263 /** IP pseudo header. */ 234 264 void *pseudo_header; 235 /** IP pseudo header length. 236 */ 265 /** IP pseudo header length. */ 237 266 size_t headerlen; 238 /** Remote host address. 239 */ 240 struct sockaddr * addr; 241 /** Remote host address length. 242 */ 267 /** Remote host address. */ 268 struct sockaddr *addr; 269 /** Remote host address length. */ 243 270 socklen_t addrlen; 244 /** Remote host port. 245 */ 271 /** Remote host port. */ 246 272 uint16_t dest_port; 247 /** Parent local sockets. 248 */ 273 /** Parent local sockets. */ 249 274 socket_cores_ref local_sockets; 275 250 276 /** Local sockets safety lock. 251 * May be locked for writing while holding the global lock for reading when changing the local sockets only. 252 * The global lock may to be locked only before locking the local lock. 253 * The global lock may be locked more weakly than the local lock. 254 * The global lock may be released before releasing the local lock. 255 * @see tcp_globals:lock 256 */ 257 fibril_rwlock_t * local_lock; 258 /** Pending operation data. 259 */ 277 * 278 * May be locked for writing while holding the global lock for reading 279 * when changing the local sockets only. 280 * The global lock may be locked only before locking the local lock. 281 * The global lock may be locked more weakly than the local lock. 282 * The global lock may be released before releasing the local lock. 283 * @see tcp_globals:lock 284 */ 285 fibril_rwlock_t *local_lock; 286 287 /** Pending operation data. */ 260 288 tcp_operation_t operation; 261 /** Timeouts in a row counter. 262 * If TCP_MAX_TIMEOUTS is reached, the connection is lost. 289 290 /** 291 * Timeouts in a row counter. 292 * If TCP_MAX_TIMEOUTS is reached, the connection is lost. 263 293 */ 264 294 int timeout_count; 265 295 }; 266 296 267 /** TCP global data. 268 */ 269 struct tcp_globals{ 270 /** Networking module phone. 271 */ 297 /** TCP global data. */ 298 struct tcp_globals { 299 /** Networking module phone. */ 272 300 int net_phone; 273 /** IP module phone. 274 */ 301 /** IP module phone. */ 275 302 int ip_phone; 276 /** ICMP module phone. 277 */ 303 /** ICMP module phone. */ 278 304 int icmp_phone; 279 /** Last used free port. 280 */ 305 /** Last used free port. */ 281 306 int last_used_port; 282 /** Active sockets. 283 */ 307 /** Active sockets. */ 284 308 socket_ports_t sockets; 285 /** Device packet dimensions. 286 */ 309 /** Device packet dimensions. */ 287 310 packet_dimensions_t dimensions; 288 /** Safety lock. 289 * Write lock is used only for adding or removing socket ports. 311 312 /** 313 * Safety lock. 314 * Write lock is used only for adding or removing socket ports. 290 315 */ 291 316 fibril_rwlock_t lock; … … 296 321 /** @} 297 322 */ 298 -
uspace/srv/net/tl/tcp/tcp_header.h
re06ef614 r49d819b4 28 28 29 29 /** @addtogroup tcp 30 * 30 * @{ 31 31 */ 32 32 33 33 /** @file 34 * 35 * Based on the RFC~793.34 * TCP header definition. 35 * Based on the RFC 793. 36 36 */ 37 37 38 #ifndef __NET_TCP_HEADER_H__39 #define __NET_TCP_HEADER_H__38 #ifndef NET_TCP_HEADER_H_ 39 #define NET_TCP_HEADER_H_ 40 40 41 41 #include <sys/types.h> 42 42 43 /** TCP header size in bytes. 44 */ 45 #define TCP_HEADER_SIZE sizeof(tcp_header_t) 43 /** TCP header size in bytes. */ 44 #define TCP_HEADER_SIZE sizeof(tcp_header_t) 46 45 47 46 /** Returns the actual TCP header length in bytes. 48 * 47 * @param[in] header The TCP packet header. 49 48 */ 50 #define TCP_HEADER_LENGTH(header) ((header)->header_length * 4 u)49 #define TCP_HEADER_LENGTH(header) ((header)->header_length * 4U) 51 50 52 51 /** Returns the TCP header length. 53 * 52 * @param[in] length The TCP header length in bytes. 54 53 */ 55 #define TCP_COMPUTE_HEADER_LENGTH(length) ((uint8_t) ((length) / 4u))54 #define TCP_COMPUTE_HEADER_LENGTH(length) ((uint8_t) ((length) / 4U)) 56 55 57 56 /** Type definition of the transmission datagram header. 58 * 57 * @see tcp_header 59 58 */ 60 typedef struct tcp_header 59 typedef struct tcp_header tcp_header_t; 61 60 62 61 /** Type definition of the transmission datagram header pointer. 63 * 62 * @see tcp_header 64 63 */ 65 typedef tcp_header_t * 64 typedef tcp_header_t *tcp_header_ref; 66 65 67 66 /** Type definition of the transmission datagram header option. 68 * 67 * @see tcp_option 69 68 */ 70 typedef struct tcp_option 69 typedef struct tcp_option tcp_option_t; 71 70 72 71 /** Type definition of the transmission datagram header option pointer. 73 * 72 * @see tcp_option 74 73 */ 75 typedef tcp_option_t * 74 typedef tcp_option_t *tcp_option_ref; 76 75 77 /** Type definition of the Maximum segment size TCP option. 78 * @see ... 79 */ 80 typedef struct tcp_max_segment_size_option tcp_max_segment_size_option_t; 76 /** Type definition of the Maximum segment size TCP option. */ 77 typedef struct tcp_max_segment_size_option tcp_max_segment_size_option_t; 81 78 82 79 /** Type definition of the Maximum segment size TCP option pointer. 83 * 80 * @see tcp_max_segment_size_option 84 81 */ 85 typedef tcp_max_segment_size_option_t * 82 typedef tcp_max_segment_size_option_t *tcp_max_segment_size_option_ref; 86 83 87 /** Transmission datagram header. 88 */ 89 struct tcp_header{ 90 /** The source port number. 91 */ 84 /** Transmission datagram header. */ 85 struct tcp_header { 92 86 uint16_t source_port; 93 /** The destination port number.94 */95 87 uint16_t destination_port; 96 /** The sequence number of the first data octet in this segment (except when SYN is present).97 * If SYN is present the sequence number is the initial sequence number (ISN) and the first data octet is ISN+1.98 */99 88 uint32_t sequence_number; 100 /** If the ACK control bit is set this field contains the value of the next sequence number the sender of the segment is expecting to receive.101 * Once a~connection is established this is always sent.102 * @see acknowledge103 */104 89 uint32_t acknowledgement_number; 90 105 91 #ifdef ARCH_IS_BIG_ENDIAN 106 /** The number of 32~bit words in the TCP Header.107 * This indicates where the data begins.108 * The TCP header (even one including options) is an integral number of 32~bits long.109 */110 92 uint8_t header_length:4; 111 /** Four bits reserved for future use.112 * Must be zero.113 */114 93 uint8_t reserved1:4; 115 94 #else 116 /** Four bits reserved for future use.117 * Must be zero.118 */119 95 uint8_t reserved1:4; 120 /** The number of 32~bit words in the TCP Header.121 * This indicates where the data begins.122 * The TCP header (even one including options) is an integral number of 32~bits long.123 */124 96 uint8_t header_length:4; 125 97 #endif 98 126 99 #ifdef ARCH_IS_BIG_ENDIAN 127 /** Two bits reserved for future use.128 * Must be zero.129 */130 100 uint8_t reserved2:2; 131 /** Urgent Pointer field significant.132 * @see tcp_header:urgent_pointer133 */134 101 uint8_t urgent:1; 135 /** Acknowledgment field significant136 * @see tcp_header:acknowledgement_number137 */138 102 uint8_t acknowledge:1; 139 /** Push function.140 */141 103 uint8_t push:1; 142 /** Reset the connection.143 */144 104 uint8_t reset:1; 145 /** Synchronize the sequence numbers.146 */147 105 uint8_t synchronize:1; 148 /** No more data from the sender.149 */150 106 uint8_t finalize:1; 151 107 #else 152 /** No more data from the sender.153 */154 108 uint8_t finalize:1; 155 /** Synchronize the sequence numbers.156 */157 109 uint8_t synchronize:1; 158 /** Reset the connection.159 */160 110 uint8_t reset:1; 161 /** Push function.162 */163 111 uint8_t push:1; 164 /** Acknowledgment field significant.165 * @see tcp_header:acknowledgement_number166 */167 112 uint8_t acknowledge:1; 168 /** Urgent Pointer field significant.169 * @see tcp_header:urgent_pointer170 */171 113 uint8_t urgent:1; 172 /** Two bits reserved for future use.173 * Must be zero.174 */175 114 uint8_t reserved2:2; 176 115 #endif 177 /** The number of data octets beginning with the one indicated in the acknowledgment field which the sender of this segment is willing to accept. 178 * @see tcp_header:acknowledge 179 */ 116 180 117 uint16_t window; 181 /** The checksum field is the 16~bit one's complement of the one's complement sum of all 16~bit words in the header and text.182 * If a~segment contains an odd number of header and text octets to be checksummed, the last octet is padded on the right with zeros to form a~16~bit word for checksum purposes.183 * The pad is not transmitted as part of the segment.184 * While computing the checksum, the checksum field itself is replaced with zeros.185 * The checksum also coves a~pseudo header conceptually.186 * The pseudo header conceptually prefixed to the TCP header contains the source address, the destination address, the protocol, and the TCP length.187 * This information gives protection against misrouted datagrams.188 * If the computed checksum is zero, it is transmitted as all ones (the equivalent in one's complement arithmetic).189 */190 118 uint16_t checksum; 191 /** This field communicates the current value of the urgent pointer as a~positive offset from the sequence number in this segment.192 * The urgent pointer points to the sequence number of the octet following the urgent data.193 * This field is only be interpreted in segments with the URG control bit set.194 * @see tcp_header:urgent195 */196 119 uint16_t urgent_pointer; 197 120 } __attribute__ ((packed)); 198 121 199 /** Transmission datagram header option. 200 */ 201 struct tcp_option{ 202 /** Option type. 203 */ 122 /** Transmission datagram header option. */ 123 struct tcp_option { 124 /** Option type. */ 204 125 uint8_t type; 205 /** Option length. 206 */ 126 /** Option length. */ 207 127 uint8_t length; 208 128 }; 209 129 210 /** Maximum segment size TCP option. 211 */ 212 struct tcp_max_segment_size_option{ 130 /** Maximum segment size TCP option. */ 131 struct tcp_max_segment_size_option { 213 132 /** TCP option. 214 * 215 * 133 * @see TCPOPT_MAX_SEGMENT_SIZE 134 * @see TCPOPT_MAX_SEGMENT_SIZE_LENGTH 216 135 */ 217 136 tcp_option_t option; 218 /** Maximum segment size in bytes.219 */137 138 /** Maximum segment size in bytes. */ 220 139 uint16_t max_segment_size; 221 140 } __attribute__ ((packed)); -
uspace/srv/net/tl/tcp/tcp_module.c
re06ef614 r49d819b4 28 28 29 29 /** @addtogroup tcp 30 * 30 * @{ 31 31 */ 32 32 33 33 /** @file 34 * TCP standalone module implementation. 35 * Contains skeleton module functions mapping. 36 * The functions are used by the module skeleton as module specific entry points. 37 * @see module.c 34 * TCP standalone module implementation. 35 * Contains skeleton module functions mapping. 36 * The functions are used by the module skeleton as module specific entry 37 * points. 38 * @see module.c 38 39 */ 40 41 #include "tcp.h" 42 #include "tcp_module.h" 39 43 40 44 #include <async.h> … … 46 50 #include <net/ip_protocols.h> 47 51 #include <net/modules.h> 48 49 52 #include <net/packet.h> 50 53 #include <net_interface.h> 54 51 55 #include <ip_interface.h> 52 56 #include <tl_local.h> 53 57 54 #include "tcp.h" 55 #include "tcp_module.h" 58 /** TCP module global data. */ 59 extern tcp_globals_t tcp_globals; 56 60 57 /** TCP module global data.58 */59 extern tcp_globals_t tcp_globals;60 61 /** Starts the TCP module.62 * Initializes the client connection serving function, initializes the module, registers the module service and starts the async manager, processing IPC messages in an infinite loop.63 * @param[in] client_connection The client connection processing function. The module skeleton propagates its own one.64 * @returns EOK on successful module termination.65 * @returns Other error codes as defined for the tcp_initialize() function.66 * @returns Other error codes as defined for the REGISTER_ME() macro function.67 */68 61 int tl_module_start_standalone(async_client_conn_t client_connection) 69 62 { … … 75 68 76 69 ipcarg_t phonehash; 77 if (ERROR_OCCURRED(tcp_initialize(client_connection)) 78 ||ERROR_OCCURRED(REGISTER_ME(SERVICE_TCP, &phonehash))) {70 if (ERROR_OCCURRED(tcp_initialize(client_connection)) || 71 ERROR_OCCURRED(REGISTER_ME(SERVICE_TCP, &phonehash))) { 79 72 pm_destroy(); 80 73 return ERROR_CODE; … … 87 80 } 88 81 89 /** Processes the TCP message. 90 * @param[in] callid The message identifier. 91 * @param[in] call The message parameters. 92 * @param[out] answer The message answer parameters. 93 * @param[out] answer_count The last parameter for the actual answer in the answer parameter. 94 * @returns EOK on success. 95 * @returns Other error codes as defined for the tcp_message() function. 96 */ 97 int tl_module_message_standalone(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count){ 82 int 83 tl_module_message_standalone(ipc_callid_t callid, ipc_call_t *call, 84 ipc_call_t *answer, int *answer_count) 85 { 98 86 return tcp_message_standalone(callid, call, answer, answer_count); 99 87 } -
uspace/srv/net/tl/tcp/tcp_module.h
re06ef614 r49d819b4 28 28 29 29 /** @addtogroup tcp 30 * 30 * @{ 31 31 */ 32 32 33 33 /** @file 34 * 35 * 34 * TCP module functions. 35 * The functions are used as TCP module entry points. 36 36 */ 37 37 38 #ifndef __NET_TCP_MODULE_H__39 #define __NET_TCP_MODULE_H__38 #ifndef NET_TCP_MODULE_H_ 39 #define NET_TCP_MODULE_H_ 40 40 41 41 #include <async.h> 42 42 #include <ipc/ipc.h> 43 43 44 /** Initializes the TCP module. 45 * @param[in] client_connection The client connection processing function. The module skeleton propagates its own one. 46 * @returns EOK on success. 47 * @returns ENOMEM if there is not enough memory left. 48 */ 49 extern int tcp_initialize(async_client_conn_t client_connection); 50 51 /** Processes the TCP message. 52 * @param[in] callid The message identifier. 53 * @param[in] call The message parameters. 54 * @param[out] answer The message answer parameters. 55 * @param[out] answer_count The last parameter for the actual answer in the answer parameter. 56 * @returns EOK on success. 57 * @returns ENOTSUP if the message is not known. 58 * @see tcp_interface.h 59 * @see IS_NET_TCP_MESSAGE() 60 */ 61 extern int tcp_message_standalone(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count); 44 extern int tcp_initialize(async_client_conn_t); 45 extern int tcp_message_standalone(ipc_callid_t, ipc_call_t *, ipc_call_t *, 46 int *); 62 47 63 48 #endif -
uspace/srv/net/tl/udp/udp.c
re06ef614 r49d819b4 28 28 29 29 /** @addtogroup udp 30 * 30 * @{ 31 31 */ 32 32 33 33 /** @file 34 * UDP module implementation. 35 * @see udp.h 36 */ 34 * UDP module implementation. 35 * @see udp.h 36 */ 37 38 #include "udp.h" 39 #include "udp_header.h" 40 #include "udp_module.h" 37 41 38 42 #include <async.h> … … 45 49 #include <ipc/tl.h> 46 50 #include <ipc/socket.h> 51 #include <adt/dynamic_fifo.h> 47 52 #include <errno.h> 48 53 #include <err.h> … … 55 60 #include <net/modules.h> 56 61 57 #include <adt/dynamic_fifo.h>58 62 #include <packet_client.h> 59 63 #include <packet_remote.h> … … 69 73 #include <tl_interface.h> 70 74 71 #include "udp.h"72 #include "udp_header.h"73 #include "udp_module.h"74 75 75 /** UDP module name. */ 76 76 #define NAME "UDP protocol" … … 91 91 #define UDP_FREE_PORTS_END 65535 92 92 93 /** Processes the received UDP packet queue. 94 * 95 * Is used as an entry point from the underlying IP module. 96 * Locks the global lock and calls udp_process_packet() function. 97 * 98 * @param[in] device_id The receiving device identifier. 99 * @param[in,out] packet The received packet queue. 100 * @param receiver The target service. Ignored parameter. 101 * @param[in] error The packet error reporting service. Prefixes the 102 * received packet. 103 * @returns EOK on success. 104 * @returns Other error codes as defined for the 105 * udp_process_packet() function. 106 */ 107 int 108 udp_received_msg(device_id_t device_id, packet_t packet, services_t receiver, 109 services_t error); 110 111 /** Processes the received UDP packet queue. 112 * 113 * Notifies the destination socket application. 114 * Releases the packet on error or sends an ICMP error notification. 115 * 116 * @param[in] device_id The receiving device identifier. 117 * @param[in,out] packet The received packet queue. 118 * @param[in] error The packet error reporting service. Prefixes the 119 * received packet. 120 * @returns EOK on success. 121 * @returns EINVAL if the packet is not valid. 122 * @returns EINVAL if the stored packet address is not the 123 * an_addr_t. 124 * @returns EINVAL if the packet does not contain any data. 125 * @returns NO_DATA if the packet content is shorter than the user 126 * datagram header. 127 * @returns ENOMEM if there is not enough memory left. 128 * @returns EADDRNOTAVAIL if the destination socket does not exist. 129 * @returns Other error codes as defined for the 130 * ip_client_process_packet() function. 131 */ 132 int 133 udp_process_packet(device_id_t device_id, packet_t packet, services_t error); 134 135 /** Releases the packet and returns the result. 136 * 137 * @param[in] packet The packet queue to be released. 138 * @param[in] result The result to be returned. 139 * @return The result parameter. 140 */ 141 int udp_release_and_return(packet_t packet, int result); 142 143 /** @name Socket messages processing functions 144 */ 145 /*@{*/ 146 147 /** Processes the socket client messages. 148 * 149 * Runs until the client module disconnects. 150 * 151 * @param[in] callid The message identifier. 152 * @param[in] call The message parameters. 153 * @returns EOK on success. 154 * @see socket.h 155 */ 156 int udp_process_client_messages(ipc_callid_t callid, ipc_call_t call); 157 158 /** Sends data from the socket to the remote address. 159 * 160 * Binds the socket to a free port if not already connected/bound. 161 * Handles the NET_SOCKET_SENDTO message. 162 * Supports AF_INET and AF_INET6 address families. 163 * 164 * @param[in,out] local_sockets The application local sockets. 165 * @param[in] socket_id Socket identifier. 166 * @param[in] addr The destination address. 167 * @param[in] addrlen The address length. 168 * @param[in] fragments The number of data fragments. 169 * @param[out] data_fragment_size The data fragment size in bytes. 170 * @param[in] flags Various send flags. 171 * @returns EOK on success. 172 * @returns EAFNOTSUPPORT if the address family is not supported. 173 * @returns ENOTSOCK if the socket is not found. 174 * @returns EINVAL if the address is invalid. 175 * @returns ENOTCONN if the sending socket is not and cannot be 176 * bound. 177 * @returns ENOMEM if there is not enough memory left. 178 * @returns Other error codes as defined for the 179 * socket_read_packet_data() function. 180 * @returns Other error codes as defined for the 181 * ip_client_prepare_packet() function. 182 * @returns Other error codes as defined for the ip_send_msg() 183 * function. 184 */ 185 int 186 udp_sendto_message(socket_cores_ref local_sockets, int socket_id, 187 const struct sockaddr * addr, socklen_t addrlen, int fragments, 188 size_t * data_fragment_size, int flags); 189 190 /** Receives data to the socket. 191 * 192 * Handles the NET_SOCKET_RECVFROM message. 193 * Replies the source address as well. 194 * 195 * @param[in] local_sockets The application local sockets. 196 * @param[in] socket_id Socket identifier. 197 * @param[in] flags Various receive flags. 198 * @param[out] addrlen The source address length. 199 * @returns The number of bytes received. 200 * @returns ENOTSOCK if the socket is not found. 201 * @returns NO_DATA if there are no received packets or data. 202 * @returns ENOMEM if there is not enough memory left. 203 * @returns EINVAL if the received address is not an IP address. 204 * @returns Other error codes as defined for the packet_translate() 205 * function. 206 * @returns Other error codes as defined for the data_reply() 207 * function. 208 */ 209 int 210 udp_recvfrom_message(socket_cores_ref local_sockets, int socket_id, int flags, 211 size_t * addrlen); 212 213 /*@}*/ 214 215 /** UDP global data. 216 */ 93 /** UDP global data. */ 217 94 udp_globals_t udp_globals; 218 95 96 /** Initializes the UDP module. 97 * 98 * @param[in] client_connection The client connection processing function. The 99 * module skeleton propagates its own one. 100 * @returns EOK on success. 101 * @returns ENOMEM if there is not enough memory left. 102 */ 219 103 int udp_initialize(async_client_conn_t client_connection) 220 104 { … … 223 107 measured_string_t names[] = { 224 108 { 225 str_dup("UDP_CHECKSUM_COMPUTING"),109 (char *) "UDP_CHECKSUM_COMPUTING", 226 110 22 227 111 }, 228 112 { 229 str_dup("UDP_AUTOBINDING"),113 (char *) "UDP_AUTOBINDING", 230 114 15 231 115 } … … 233 117 measured_string_ref configuration; 234 118 size_t count = sizeof(names) / sizeof(measured_string_t); 235 char * 119 char *data; 236 120 237 121 fibril_rwlock_initialize(&udp_globals.lock); … … 258 142 udp_globals.last_used_port = UDP_FREE_PORTS_START - 1; 259 143 260 // get configuration261 144 udp_globals.checksum_computing = NET_DEFAULT_UDP_CHECKSUM_COMPUTING; 262 145 udp_globals.autobinding = NET_DEFAULT_UDP_AUTOBINDING; 146 147 // get configuration 263 148 configuration = &names[0]; 264 149 ERROR_PROPAGATE(net_get_conf_req(udp_globals.net_phone, &configuration, … … 280 165 } 281 166 282 int 283 udp_received_msg(device_id_t device_id, packet_t packet, services_t receiver, 284 services_t error) 167 /** Releases the packet and returns the result. 168 * 169 * @param[in] packet The packet queue to be released. 170 * @param[in] result The result to be returned. 171 * @return The result parameter. 172 */ 173 static int udp_release_and_return(packet_t packet, int result) 285 174 { 286 int result; 287 288 fibril_rwlock_write_lock(&udp_globals.lock); 289 result = udp_process_packet(device_id, packet, error); 290 if (result != EOK) 291 fibril_rwlock_write_unlock(&udp_globals.lock); 292 175 pq_release_remote(udp_globals.net_phone, packet_get_id(packet)); 293 176 return result; 294 177 } 295 178 296 int udp_process_packet(device_id_t device_id, packet_t packet, services_t error) 179 /** Processes the received UDP packet queue. 180 * 181 * Notifies the destination socket application. 182 * Releases the packet on error or sends an ICMP error notification. 183 * 184 * @param[in] device_id The receiving device identifier. 185 * @param[in,out] packet The received packet queue. 186 * @param[in] error The packet error reporting service. Prefixes the 187 * received packet. 188 * @returns EOK on success. 189 * @returns EINVAL if the packet is not valid. 190 * @returns EINVAL if the stored packet address is not the 191 * an_addr_t. 192 * @returns EINVAL if the packet does not contain any data. 193 * @returns NO_DATA if the packet content is shorter than the user 194 * datagram header. 195 * @returns ENOMEM if there is not enough memory left. 196 * @returns EADDRNOTAVAIL if the destination socket does not exist. 197 * @returns Other error codes as defined for the 198 * ip_client_process_packet() function. 199 */ 200 static int 201 udp_process_packet(device_id_t device_id, packet_t packet, services_t error) 297 202 { 298 203 ERROR_DECLARE; … … 315 220 packet_dimension_ref packet_dimension; 316 221 317 if(error) {318 switch (error) {319 case SERVICE_ICMP:320 // ignore error321 // length = icmp_client_header_length(packet);322 // process error323 result = icmp_client_process_packet(packet, &type,324 &code, NULL, NULL);325 if (result < 0)326 return udp_release_and_return(packet, result);327 length = (size_t) result;328 if (ERROR_OCCURRED(packet_trim(packet, length, 0)))329 return udp_release_and_return(packet,330 ERROR_CODE);331 break;332 default:333 return udp_release_and_return(packet, ENOTSUP);334 }222 switch (error) { 223 case SERVICE_NONE: 224 break; 225 case SERVICE_ICMP: 226 // ignore error 227 // length = icmp_client_header_length(packet); 228 // process error 229 result = icmp_client_process_packet(packet, &type, 230 &code, NULL, NULL); 231 if (result < 0) 232 return udp_release_and_return(packet, result); 233 length = (size_t) result; 234 if (ERROR_OCCURRED(packet_trim(packet, length, 0))) 235 return udp_release_and_return(packet, 236 ERROR_CODE); 237 break; 238 default: 239 return udp_release_and_return(packet, ENOTSUP); 335 240 } 336 241 … … 374 279 375 280 // compute header checksum if set 376 if (header->checksum && (!error)) {281 if (header->checksum && !error) { 377 282 result = packet_get_addr(packet, (uint8_t **) &src, 378 283 (uint8_t **) &dest); 379 if (result <= 0)284 if (result <= 0) 380 285 return udp_release_and_return(packet, result); 381 286 … … 396 301 397 302 do { 398 ++ fragments;303 fragments++; 399 304 length = packet_get_data_length(next_packet); 400 305 if (length <= 0) … … 471 376 } 472 377 473 int 474 udp_message_standalone(ipc_callid_t callid, ipc_call_t * call, 475 ipc_call_t * answer, int * answer_count) 378 /** Processes the received UDP packet queue. 379 * 380 * Is used as an entry point from the underlying IP module. 381 * Locks the global lock and calls udp_process_packet() function. 382 * 383 * @param[in] device_id The receiving device identifier. 384 * @param[in,out] packet The received packet queue. 385 * @param receiver The target service. Ignored parameter. 386 * @param[in] error The packet error reporting service. Prefixes the 387 * received packet. 388 * @returns EOK on success. 389 * @returns Other error codes as defined for the 390 * udp_process_packet() function. 391 */ 392 static int 393 udp_received_msg(device_id_t device_id, packet_t packet, services_t receiver, 394 services_t error) 476 395 { 477 ERROR_DECLARE; 478 479 packet_t packet; 480 481 *answer_count = 0; 482 483 switch (IPC_GET_METHOD(*call)) { 484 case NET_TL_RECEIVED: 485 if (!ERROR_OCCURRED(packet_translate_remote( 486 udp_globals.net_phone, &packet, IPC_GET_PACKET(call)))) { 487 ERROR_CODE = udp_received_msg(IPC_GET_DEVICE(call), 488 packet, SERVICE_UDP, IPC_GET_ERROR(call)); 489 } 490 return ERROR_CODE; 491 492 case IPC_M_CONNECT_TO_ME: 493 return udp_process_client_messages(callid, * call); 494 } 495 496 return ENOTSUP; 396 int result; 397 398 fibril_rwlock_write_lock(&udp_globals.lock); 399 result = udp_process_packet(device_id, packet, error); 400 if (result != EOK) 401 fibril_rwlock_write_unlock(&udp_globals.lock); 402 403 return result; 497 404 } 498 405 499 int udp_process_client_messages(ipc_callid_t callid, ipc_call_t call) 500 { 501 int res; 502 bool keep_on_going = true; 503 socket_cores_t local_sockets; 504 int app_phone = IPC_GET_PHONE(&call); 505 struct sockaddr *addr; 506 int socket_id; 507 size_t addrlen; 508 size_t size; 509 ipc_call_t answer; 510 int answer_count; 511 packet_dimension_ref packet_dimension; 512 513 /* 514 * Accept the connection 515 * - Answer the first IPC_M_CONNECT_TO_ME call. 516 */ 517 res = EOK; 518 answer_count = 0; 519 520 // The client connection is only in one fibril and therefore no 521 // additional locks are needed. 522 523 socket_cores_initialize(&local_sockets); 524 525 while (keep_on_going) { 526 527 // answer the call 528 answer_call(callid, res, &answer, answer_count); 529 530 // refresh data 531 refresh_answer(&answer, &answer_count); 532 533 // get the next call 534 callid = async_get_call(&call); 535 536 // process the call 537 switch (IPC_GET_METHOD(call)) { 538 case IPC_M_PHONE_HUNGUP: 539 keep_on_going = false; 540 res = EHANGUP; 541 break; 542 543 case NET_SOCKET: 544 socket_id = SOCKET_GET_SOCKET_ID(call); 545 res = socket_create(&local_sockets, app_phone, NULL, 546 &socket_id); 547 SOCKET_SET_SOCKET_ID(answer, socket_id); 548 549 if (res != EOK) 550 break; 551 552 if (tl_get_ip_packet_dimension(udp_globals.ip_phone, 553 &udp_globals.dimensions, DEVICE_INVALID_ID, 554 &packet_dimension) == EOK) { 555 SOCKET_SET_DATA_FRAGMENT_SIZE(answer, 556 packet_dimension->content); 557 } 558 559 // SOCKET_SET_DATA_FRAGMENT_SIZE(answer, 560 // MAX_UDP_FRAGMENT_SIZE); 561 SOCKET_SET_HEADER_SIZE(answer, UDP_HEADER_SIZE); 562 answer_count = 3; 563 break; 564 565 case NET_SOCKET_BIND: 566 res = data_receive((void **) &addr, &addrlen); 567 if (res != EOK) 568 break; 569 fibril_rwlock_write_lock(&udp_globals.lock); 570 res = socket_bind(&local_sockets, &udp_globals.sockets, 571 SOCKET_GET_SOCKET_ID(call), addr, addrlen, 572 UDP_FREE_PORTS_START, UDP_FREE_PORTS_END, 573 udp_globals.last_used_port); 574 fibril_rwlock_write_unlock(&udp_globals.lock); 575 free(addr); 576 break; 577 578 case NET_SOCKET_SENDTO: 579 res = data_receive((void **) &addr, &addrlen); 580 if (res != EOK) 581 break; 582 583 fibril_rwlock_write_lock(&udp_globals.lock); 584 res = udp_sendto_message(&local_sockets, 585 SOCKET_GET_SOCKET_ID(call), addr, addrlen, 586 SOCKET_GET_DATA_FRAGMENTS(call), &size, 587 SOCKET_GET_FLAGS(call)); 588 SOCKET_SET_DATA_FRAGMENT_SIZE(answer, size); 589 590 if (res != EOK) 591 fibril_rwlock_write_unlock(&udp_globals.lock); 592 else 593 answer_count = 2; 594 595 free(addr); 596 break; 597 598 case NET_SOCKET_RECVFROM: 599 fibril_rwlock_write_lock(&udp_globals.lock); 600 res = udp_recvfrom_message(&local_sockets, 601 SOCKET_GET_SOCKET_ID(call), SOCKET_GET_FLAGS(call), 602 &addrlen); 603 fibril_rwlock_write_unlock(&udp_globals.lock); 604 605 if (res <= 0) 606 break; 607 608 SOCKET_SET_READ_DATA_LENGTH(answer, res); 609 SOCKET_SET_ADDRESS_LENGTH(answer, addrlen); 610 answer_count = 3; 611 res = EOK; 612 break; 613 614 case NET_SOCKET_CLOSE: 615 fibril_rwlock_write_lock(&udp_globals.lock); 616 res = socket_destroy(udp_globals.net_phone, 617 SOCKET_GET_SOCKET_ID(call), &local_sockets, 618 &udp_globals.sockets, NULL); 619 fibril_rwlock_write_unlock(&udp_globals.lock); 620 break; 621 622 case NET_SOCKET_GETSOCKOPT: 623 case NET_SOCKET_SETSOCKOPT: 624 default: 625 res = ENOTSUP; 626 break; 627 } 628 } 629 630 // release the application phone 631 ipc_hangup(app_phone); 632 633 // release all local sockets 634 socket_cores_release(udp_globals.net_phone, &local_sockets, 635 &udp_globals.sockets, NULL); 636 637 return res; 638 } 639 640 int 406 /** Sends data from the socket to the remote address. 407 * 408 * Binds the socket to a free port if not already connected/bound. 409 * Handles the NET_SOCKET_SENDTO message. 410 * Supports AF_INET and AF_INET6 address families. 411 * 412 * @param[in,out] local_sockets The application local sockets. 413 * @param[in] socket_id Socket identifier. 414 * @param[in] addr The destination address. 415 * @param[in] addrlen The address length. 416 * @param[in] fragments The number of data fragments. 417 * @param[out] data_fragment_size The data fragment size in bytes. 418 * @param[in] flags Various send flags. 419 * @returns EOK on success. 420 * @returns EAFNOTSUPPORT if the address family is not supported. 421 * @returns ENOTSOCK if the socket is not found. 422 * @returns EINVAL if the address is invalid. 423 * @returns ENOTCONN if the sending socket is not and cannot be 424 * bound. 425 * @returns ENOMEM if there is not enough memory left. 426 * @returns Other error codes as defined for the 427 * socket_read_packet_data() function. 428 * @returns Other error codes as defined for the 429 * ip_client_prepare_packet() function. 430 * @returns Other error codes as defined for the ip_send_msg() 431 * function. 432 */ 433 static int 641 434 udp_sendto_message(socket_cores_ref local_sockets, int socket_id, 642 435 const struct sockaddr *addr, socklen_t addrlen, int fragments, … … 725 518 // prefix the udp header 726 519 header = PACKET_PREFIX(packet, udp_header_t); 727 if (!header)520 if (!header) 728 521 return udp_release_and_return(packet, ENOMEM); 729 522 730 523 bzero(header, sizeof(*header)); 731 524 // read the rest of the packet fragments 732 for (index = 1; index < fragments; ++ index) {525 for (index = 1; index < fragments; index++) { 733 526 result = tl_socket_read_packet_data(udp_globals.net_phone, 734 527 &next_packet, 0, packet_dimension, addr, addrlen); … … 784 577 } 785 578 786 int 579 /** Receives data to the socket. 580 * 581 * Handles the NET_SOCKET_RECVFROM message. 582 * Replies the source address as well. 583 * 584 * @param[in] local_sockets The application local sockets. 585 * @param[in] socket_id Socket identifier. 586 * @param[in] flags Various receive flags. 587 * @param[out] addrlen The source address length. 588 * @returns The number of bytes received. 589 * @returns ENOTSOCK if the socket is not found. 590 * @returns NO_DATA if there are no received packets or data. 591 * @returns ENOMEM if there is not enough memory left. 592 * @returns EINVAL if the received address is not an IP address. 593 * @returns Other error codes as defined for the packet_translate() 594 * function. 595 * @returns Other error codes as defined for the data_reply() 596 * function. 597 */ 598 static int 787 599 udp_recvfrom_message(socket_cores_ref local_sockets, int socket_id, int flags, 788 600 size_t *addrlen) … … 830 642 831 643 // send the source address 832 ERROR_PROPAGATE(data_reply(addr, * 644 ERROR_PROPAGATE(data_reply(addr, *addrlen)); 833 645 834 646 // trim the header … … 846 658 } 847 659 848 int udp_release_and_return(packet_t packet, int result) 660 /** Processes the socket client messages. 661 * 662 * Runs until the client module disconnects. 663 * 664 * @param[in] callid The message identifier. 665 * @param[in] call The message parameters. 666 * @returns EOK on success. 667 * 668 * @see socket.h 669 */ 670 static int udp_process_client_messages(ipc_callid_t callid, ipc_call_t call) 849 671 { 850 pq_release_remote(udp_globals.net_phone, packet_get_id(packet)); 851 return result; 672 int res; 673 bool keep_on_going = true; 674 socket_cores_t local_sockets; 675 int app_phone = IPC_GET_PHONE(&call); 676 struct sockaddr *addr; 677 int socket_id; 678 size_t addrlen; 679 size_t size; 680 ipc_call_t answer; 681 int answer_count; 682 packet_dimension_ref packet_dimension; 683 684 /* 685 * Accept the connection 686 * - Answer the first IPC_M_CONNECT_TO_ME call. 687 */ 688 res = EOK; 689 answer_count = 0; 690 691 // The client connection is only in one fibril and therefore no 692 // additional locks are needed. 693 694 socket_cores_initialize(&local_sockets); 695 696 while (keep_on_going) { 697 698 // answer the call 699 answer_call(callid, res, &answer, answer_count); 700 701 // refresh data 702 refresh_answer(&answer, &answer_count); 703 704 // get the next call 705 callid = async_get_call(&call); 706 707 // process the call 708 switch (IPC_GET_METHOD(call)) { 709 case IPC_M_PHONE_HUNGUP: 710 keep_on_going = false; 711 res = EHANGUP; 712 break; 713 714 case NET_SOCKET: 715 socket_id = SOCKET_GET_SOCKET_ID(call); 716 res = socket_create(&local_sockets, app_phone, NULL, 717 &socket_id); 718 SOCKET_SET_SOCKET_ID(answer, socket_id); 719 720 if (res != EOK) 721 break; 722 723 if (tl_get_ip_packet_dimension(udp_globals.ip_phone, 724 &udp_globals.dimensions, DEVICE_INVALID_ID, 725 &packet_dimension) == EOK) { 726 SOCKET_SET_DATA_FRAGMENT_SIZE(answer, 727 packet_dimension->content); 728 } 729 730 // SOCKET_SET_DATA_FRAGMENT_SIZE(answer, 731 // MAX_UDP_FRAGMENT_SIZE); 732 SOCKET_SET_HEADER_SIZE(answer, UDP_HEADER_SIZE); 733 answer_count = 3; 734 break; 735 736 case NET_SOCKET_BIND: 737 res = data_receive((void **) &addr, &addrlen); 738 if (res != EOK) 739 break; 740 fibril_rwlock_write_lock(&udp_globals.lock); 741 res = socket_bind(&local_sockets, &udp_globals.sockets, 742 SOCKET_GET_SOCKET_ID(call), addr, addrlen, 743 UDP_FREE_PORTS_START, UDP_FREE_PORTS_END, 744 udp_globals.last_used_port); 745 fibril_rwlock_write_unlock(&udp_globals.lock); 746 free(addr); 747 break; 748 749 case NET_SOCKET_SENDTO: 750 res = data_receive((void **) &addr, &addrlen); 751 if (res != EOK) 752 break; 753 754 fibril_rwlock_write_lock(&udp_globals.lock); 755 res = udp_sendto_message(&local_sockets, 756 SOCKET_GET_SOCKET_ID(call), addr, addrlen, 757 SOCKET_GET_DATA_FRAGMENTS(call), &size, 758 SOCKET_GET_FLAGS(call)); 759 SOCKET_SET_DATA_FRAGMENT_SIZE(answer, size); 760 761 if (res != EOK) 762 fibril_rwlock_write_unlock(&udp_globals.lock); 763 else 764 answer_count = 2; 765 766 free(addr); 767 break; 768 769 case NET_SOCKET_RECVFROM: 770 fibril_rwlock_write_lock(&udp_globals.lock); 771 res = udp_recvfrom_message(&local_sockets, 772 SOCKET_GET_SOCKET_ID(call), SOCKET_GET_FLAGS(call), 773 &addrlen); 774 fibril_rwlock_write_unlock(&udp_globals.lock); 775 776 if (res <= 0) 777 break; 778 779 SOCKET_SET_READ_DATA_LENGTH(answer, res); 780 SOCKET_SET_ADDRESS_LENGTH(answer, addrlen); 781 answer_count = 3; 782 res = EOK; 783 break; 784 785 case NET_SOCKET_CLOSE: 786 fibril_rwlock_write_lock(&udp_globals.lock); 787 res = socket_destroy(udp_globals.net_phone, 788 SOCKET_GET_SOCKET_ID(call), &local_sockets, 789 &udp_globals.sockets, NULL); 790 fibril_rwlock_write_unlock(&udp_globals.lock); 791 break; 792 793 case NET_SOCKET_GETSOCKOPT: 794 case NET_SOCKET_SETSOCKOPT: 795 default: 796 res = ENOTSUP; 797 break; 798 } 799 } 800 801 // release the application phone 802 ipc_hangup(app_phone); 803 804 // release all local sockets 805 socket_cores_release(udp_globals.net_phone, &local_sockets, 806 &udp_globals.sockets, NULL); 807 808 return res; 809 } 810 811 /** Processes the UDP message. 812 * 813 * @param[in] callid The message identifier. 814 * @param[in] call The message parameters. 815 * @param[out] answer The message answer parameters. 816 * @param[out] answer_count The last parameter for the actual answer in the 817 * answer parameter. 818 * @returns EOK on success. 819 * @returns ENOTSUP if the message is not known. 820 * 821 * @see udp_interface.h 822 * @see IS_NET_UDP_MESSAGE() 823 */ 824 int 825 udp_message_standalone(ipc_callid_t callid, ipc_call_t *call, 826 ipc_call_t *answer, int *answer_count) 827 { 828 ERROR_DECLARE; 829 830 packet_t packet; 831 832 *answer_count = 0; 833 834 switch (IPC_GET_METHOD(*call)) { 835 case NET_TL_RECEIVED: 836 if (ERROR_NONE(packet_translate_remote(udp_globals.net_phone, 837 &packet, IPC_GET_PACKET(call)))) { 838 ERROR_CODE = udp_received_msg(IPC_GET_DEVICE(call), 839 packet, SERVICE_UDP, IPC_GET_ERROR(call)); 840 } 841 return ERROR_CODE; 842 843 case IPC_M_CONNECT_TO_ME: 844 return udp_process_client_messages(callid, * call); 845 } 846 847 return ENOTSUP; 852 848 } 853 849 … … 882 878 883 879 /* 884 * End if said to either by the message or the processing result 880 * End if told to either by the message or the processing 881 * result. 885 882 */ 886 883 if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) || … … 895 892 /** Starts the module. 896 893 * 897 * @param argc The count of the command line arguments. Ignored 898 * parameter. 899 * @param argv The command line parameters. Ignored parameter. 900 * 901 * @returns EOK on success. 902 * @returns Other error codes as defined for each specific module 894 * @returns EOK on success. 895 * @returns Other error codes as defined for each specific module 903 896 * start function. 904 897 */ -
uspace/srv/net/tl/udp/udp.h
re06ef614 r49d819b4 28 28 29 29 /** @addtogroup udp 30 * 30 * @{ 31 31 */ 32 32 33 33 /** @file 34 * 34 * UDP module. 35 35 */ 36 36 37 #ifndef __NET_UDP_H__38 #define __NET_UDP_H__37 #ifndef NET_UDP_H_ 38 #define NET_UDP_H_ 39 39 40 40 #include <fibril_synch.h> … … 43 43 44 44 /** Type definition of the UDP global data. 45 * 45 * @see udp_globals 46 46 */ 47 typedef struct udp_globals 47 typedef struct udp_globals udp_globals_t; 48 48 49 /** UDP global data. 50 */ 51 struct udp_globals{ 52 /** Networking module phone. 53 */ 49 /** UDP global data. */ 50 struct udp_globals { 51 /** Networking module phone. */ 54 52 int net_phone; 55 /** IP module phone. 56 */ 53 /** IP module phone. */ 57 54 int ip_phone; 58 /** ICMP module phone. 59 */ 55 /** ICMP module phone. */ 60 56 int icmp_phone; 61 /** Packet dimension. 62 */ 57 /** Packet dimension. */ 63 58 packet_dimension_t packet_dimension; 64 /** Indicates whether UDP checksum computing is enabled. 65 */ 59 /** Indicates whether UDP checksum computing is enabled. */ 66 60 int checksum_computing; 67 /** Indicates whether UDP autobnding on send is enabled. 68 */ 61 /** Indicates whether UDP autobnding on send is enabled. */ 69 62 int autobinding; 70 /** Last used free port. 71 */ 63 /** Last used free port. */ 72 64 int last_used_port; 73 /** Active sockets. 74 */ 65 /** Active sockets. */ 75 66 socket_ports_t sockets; 76 /** Device packet dimensions. 77 */ 67 /** Device packet dimensions. */ 78 68 packet_dimensions_t dimensions; 79 /** Safety lock. 80 */ 69 /** Safety lock. */ 81 70 fibril_rwlock_t lock; 82 71 }; … … 86 75 /** @} 87 76 */ 88 -
uspace/srv/net/tl/udp/udp_header.h
re06ef614 r49d819b4 28 28 29 29 /** @addtogroup udp 30 * 30 * @{ 31 31 */ 32 32 33 33 /** @file 34 * 35 * Based on the RFC~768.34 * UDP header definition. 35 * Based on the RFC 768. 36 36 */ 37 37 38 #ifndef __NET_UDP_HEADER_H__39 #define __NET_UDP_HEADER_H__38 #ifndef NET_UDP_HEADER_H_ 39 #define NET_UDP_HEADER_H_ 40 40 41 41 #include <sys/types.h> 42 42 43 /** UDP header size in bytes. 44 */ 45 #define UDP_HEADER_SIZE sizeof(udp_header_t) 43 /** UDP header size in bytes. */ 44 #define UDP_HEADER_SIZE sizeof(udp_header_t) 46 45 47 46 /** Type definition of the user datagram header. 48 * 47 * @see udp_header 49 48 */ 50 typedef struct udp_header 49 typedef struct udp_header udp_header_t; 51 50 52 51 /** Type definition of the user datagram header pointer. 53 * 52 * @see udp_header 54 53 */ 55 typedef udp_header_t * 54 typedef udp_header_t *udp_header_ref; 56 55 57 /** User datagram header. 58 */ 59 struct udp_header{ 60 /** Source Port is an optional field, when meaningful, it indicates the port of the sending process, and may be assumed to be the port to which a reply should be addressed in the absence of any other information. 61 * If not used, a value of zero is inserted. 62 */ 56 /** User datagram header. */ 57 struct udp_header { 63 58 uint16_t source_port; 64 /** Destination port has a meaning within the context of a particular internet destination address.65 */66 59 uint16_t destination_port; 67 /** Length is the length in octets of this user datagram including this header and the data.68 * This means the minimum value of the length is eight.69 */70 60 uint16_t total_length; 71 /** Checksum is the 16-bit one's complement of the one's complement sum of a pseudo header of information from the IP header, the UDP header, and the data, padded with zero octets at the end (if necessary) to make a multiple of two octets.72 * The pseudo header conceptually prefixed to the UDP header contains the source address, the destination address, the protocol, and the UDP length.73 * This information gives protection against misrouted datagrams.74 * If the computed checksum is zero, it is transmitted as all ones (the equivalent in one's complement arithmetic).75 * An all zero transmitted checksum value means that the transmitter generated no checksum (for debugging or for higher level protocols that don't care).76 */77 61 uint16_t checksum; 78 62 } __attribute__ ((packed)); -
uspace/srv/net/tl/udp/udp_module.c
re06ef614 r49d819b4 28 28 29 29 /** @addtogroup udp 30 * 30 * @{ 31 31 */ 32 32 33 33 /** @file 34 * UDP standalone module implementation. 35 * Contains skeleton module functions mapping. 36 * The functions are used by the module skeleton as module specific entry points. 37 * @see module.c 34 * UDP standalone module implementation. 35 * Contains skeleton module functions mapping. 36 * The functions are used by the module skeleton as module specific entry 37 * points. 38 * @see module.c 38 39 */ 40 41 #include "udp.h" 42 #include "udp_module.h" 39 43 40 44 #include <async.h> … … 46 50 #include <net/modules.h> 47 51 #include <net/packet.h> 52 48 53 #include <net_interface.h> 49 54 #include <tl_local.h> 50 55 51 #include "udp.h" 52 #include "udp_module.h" 56 /** UDP module global data. */ 57 extern udp_globals_t udp_globals; 53 58 54 /** UDP module global data. 55 */ 56 extern udp_globals_t udp_globals; 57 58 /** Starts the UDP module. 59 * Initializes the client connection serving function, initializes the module, registers the module service and starts the async manager, processing IPC messages in an infinite loop. 60 * @param[in] client_connection The client connection processing function. The module skeleton propagates its own one. 61 * @returns EOK on successful module termination. 62 * @returns Other error codes as defined for the udp_initialize() function. 63 * @returns Other error codes as defined for the REGISTER_ME() macro function. 64 */ 65 int tl_module_start_standalone(async_client_conn_t client_connection){ 59 int tl_module_start_standalone(async_client_conn_t client_connection) 60 { 66 61 ERROR_DECLARE; 67 62 … … 70 65 async_set_client_connection(client_connection); 71 66 udp_globals.net_phone = net_connect_module(); 72 if (udp_globals.net_phone < 0){67 if (udp_globals.net_phone < 0) 73 68 return udp_globals.net_phone; 74 } 69 75 70 ERROR_PROPAGATE(pm_init()); 76 if (ERROR_OCCURRED(udp_initialize(client_connection))77 || ERROR_OCCURRED(REGISTER_ME(SERVICE_UDP, &phonehash))){71 if (ERROR_OCCURRED(udp_initialize(client_connection)) || 72 ERROR_OCCURRED(REGISTER_ME(SERVICE_UDP, &phonehash))) { 78 73 pm_destroy(); 79 74 return ERROR_CODE; … … 86 81 } 87 82 88 /** Processes the UDP message. 89 * @param[in] callid The message identifier. 90 * @param[in] call The message parameters. 91 * @param[out] answer The message answer parameters. 92 * @param[out] answer_count The last parameter for the actual answer in the answer parameter. 93 * @returns EOK on success. 94 * @returns Other error codes as defined for the udp_message() function. 95 */ 96 int tl_module_message_standalone(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count){ 83 int 84 tl_module_message_standalone(ipc_callid_t callid, ipc_call_t *call, 85 ipc_call_t *answer, int *answer_count) 86 { 97 87 return udp_message_standalone(callid, call, answer, answer_count); 98 88 } -
uspace/srv/net/tl/udp/udp_module.h
re06ef614 r49d819b4 28 28 29 29 /** @addtogroup udp 30 * 30 * @{ 31 31 */ 32 32 33 33 /** @file 34 * 35 * 34 * UDP module functions. 35 * The functions are used as UDP module entry points. 36 36 */ 37 37 38 #ifndef __NET_UDP_MODULE_H__39 #define __NET_UDP_MODULE_H__38 #ifndef NET_UDP_MODULE_H_ 39 #define NET_UDP_MODULE_H_ 40 40 41 41 #include <async.h> 42 42 #include <ipc/ipc.h> 43 43 44 /** Initializes the UDP module. 45 * @param[in] client_connection The client connection processing function. The module skeleton propagates its own one. 46 * @returns EOK on success. 47 * @returns ENOMEM if there is not enough memory left. 48 */ 49 extern int udp_initialize(async_client_conn_t client_connection); 50 51 /** Processes the UDP message. 52 * @param[in] callid The message identifier. 53 * @param[in] call The message parameters. 54 * @param[out] answer The message answer parameters. 55 * @param[out] answer_count The last parameter for the actual answer in the answer parameter. 56 * @returns EOK on success. 57 * @returns ENOTSUP if the message is not known. 58 * @see udp_interface.h 59 * @see IS_NET_UDP_MESSAGE() 60 */ 61 extern int udp_message_standalone(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count); 44 extern int udp_initialize(async_client_conn_t); 45 extern int udp_message_standalone(ipc_callid_t, ipc_call_t *, ipc_call_t *, 46 int *); 62 47 63 48 #endif
Note:
See TracChangeset
for help on using the changeset viewer.