Changes in / [49d819b4:e06ef614] in mainline
- Files:
-
- 4 added
- 4 deleted
- 21 edited
Legend:
- Unmodified
- Added
- Removed
-
boot/Makefile.common
r49d819b4 re06ef614 106 106 $(USPACE_PATH)/srv/net/tl/tcp/tcp \ 107 107 $(USPACE_PATH)/srv/net/net/net \ 108 $(USPACE_PATH)/srv/net/netstart/netstart \ 108 109 $(USPACE_PATH)/srv/devman/devman 109 110 … … 134 135 $(USPACE_PATH)/app/tetris/tetris \ 135 136 $(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
r49d819b4 re06ef614 50 50 app/trace \ 51 51 app/top \ 52 app/netstart \53 52 app/netecho \ 54 53 app/nettest1 \ … … 87 86 srv/net/tl/tcp \ 88 87 srv/net/net \ 88 srv/net/netstart \ 89 89 drv/root 90 90 -
uspace/lib/c/include/ipc/services.h
r49d819b4 re06ef614 39 39 40 40 typedef enum { 41 SERVICE_NONE = 0, 42 SERVICE_LOAD, 41 SERVICE_LOAD = 1, 43 42 SERVICE_PCI, 44 43 SERVICE_VIDEO, -
uspace/lib/net/include/tl_local.h
r49d819b4 re06ef614 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 IPC43 * messages in an infinite loop.44 *45 * @param[in] client_connection The client connection processing function. The46 * module skeleton propagates its own one.47 * @returns EOK on successful module termination.48 * @returns Other error codes as defined for the module initialize49 * function.50 * @returns Other error codes as defined for the REGISTER_ME() macro51 * function.52 */53 39 extern int tl_module_message_standalone(ipc_callid_t, ipc_call_t *, 54 40 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 the63 * answer parameter.64 * @returns EOK on success.65 * @returns Other error codes as defined for the module's message66 * standalone function.67 */68 41 extern int tl_module_start_standalone(async_client_conn_t); 69 42 -
uspace/srv/net/net/net.c
r49d819b4 re06ef614 36 36 */ 37 37 38 #include "net.h"39 40 38 #include <async.h> 41 39 #include <ctype.h> … … 54 52 55 53 #include <net/modules.h> 56 #include <net/packet.h>57 #include <net/device.h>58 59 54 #include <adt/char_map.h> 60 55 #include <adt/generic_char_map.h> 61 56 #include <adt/measured_strings.h> 62 57 #include <adt/module_map.h> 63 58 #include <net/packet.h> 64 59 #include <netif_remote.h> 60 #include <net/device.h> 65 61 #include <nil_interface.h> 66 62 #include <net_interface.h> 67 63 #include <ip_interface.h> 68 64 69 /** Networking module name. */ 65 #include "net.h" 66 67 /** Networking module name. 68 * 69 */ 70 70 #define NAME "net" 71 71 72 /** File read buffer size. */ 72 /** File read buffer size. 73 * 74 */ 73 75 #define BUFFER_SIZE 256 74 76 75 /** Networking module global data. */ 77 /** Networking module global data. 78 * 79 */ 76 80 net_globals_t net_globals; 77 81 … … 96 100 measured_string_ref setting = 97 101 measured_string_create_bulk(value, 0); 102 98 103 if (!setting) 99 104 return ENOMEM; … … 201 206 unsigned int line_number = 0; 202 207 size_t index = 0; 203 while ( !ferror(cfg) && !feof(cfg)) {208 while ((!ferror(cfg)) && (!feof(cfg))) { 204 209 int read = fgetc(cfg); 205 210 if ((read > 0) && (read != '\n') && (read != '\r')) { … … 321 326 ipcarg_t phonehash; 322 327 323 if (ERROR_OCCURRED(net_initialize(client_connection)) ||324 ERROR_OCCURRED(REGISTER_ME(SERVICE_NETWORKING, &phonehash))){328 if (ERROR_OCCURRED(net_initialize(client_connection)) 329 || ERROR_OCCURRED(REGISTER_ME(SERVICE_NETWORKING, &phonehash))){ 325 330 pm_destroy(); 326 331 return ERROR_CODE; … … 374 379 size_t count, char **data) 375 380 { 376 if (! configuration || (count <= 0))381 if (!(configuration && (count > 0))) 377 382 return EINVAL; 378 383 … … 477 482 /* Inter-network layer startup */ 478 483 switch (netif->il->service) { 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;484 case SERVICE_IP: 485 ERROR_PROPAGATE(ip_device_req(netif->il->phone, netif->id, 486 internet_service)); 487 break; 488 default: 489 return ENOENT; 485 490 } 486 491 … … 506 511 ERROR_DECLARE; 507 512 508 const char *conf_files[] = { 509 "lo", 510 "ne2k" 511 }; 513 const char *conf_files[] = {"lo", "ne2k"}; 512 514 size_t count = sizeof(conf_files) / sizeof(char *); 513 515 … … 601 603 *answer_count = 0; 602 604 switch (IPC_GET_METHOD(*call)) { 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();605 case IPC_M_PHONE_HUNGUP: 606 return EOK; 607 case NET_NET_GET_DEVICE_CONF: 608 ERROR_PROPAGATE(measured_strings_receive(&strings, &data, 609 IPC_GET_COUNT(call))); 610 net_get_device_conf_req(0, IPC_GET_DEVICE(call), &strings, 611 IPC_GET_COUNT(call), NULL); 612 613 /* Strings should not contain received data anymore */ 614 free(data); 615 616 ERROR_CODE = measured_strings_reply(strings, IPC_GET_COUNT(call)); 617 free(strings); 618 return ERROR_CODE; 619 case NET_NET_GET_CONF: 620 ERROR_PROPAGATE(measured_strings_receive(&strings, &data, 621 IPC_GET_COUNT(call))); 622 net_get_conf_req(0, &strings, IPC_GET_COUNT(call), NULL); 623 624 /* Strings should not contain received data anymore */ 625 free(data); 626 627 ERROR_CODE = measured_strings_reply(strings, IPC_GET_COUNT(call)); 628 free(strings); 629 return ERROR_CODE; 630 case NET_NET_STARTUP: 631 return startup(); 630 632 } 631 633 return ENOTSUP; … … 659 661 int res = net_module_message(callid, &call, &answer, &answer_count); 660 662 661 /* End if told to either by the message or the processing result */663 /* End if said to either by the message or the processing result */ 662 664 if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) || (res == EHANGUP)) 663 665 return; -
uspace/srv/net/net/net.h
r49d819b4 re06ef614 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
r49d819b4 re06ef614 28 28 29 29 /** @addtogroup net 30 * @{30 * @{ 31 31 */ 32 32 33 33 /** @file 34 * Wrapper for the standalone networking module.34 * Wrapper for the standalone networking module. 35 35 */ 36 36 37 #include "net.h"37 #include <str.h> 38 38 39 #include <str.h>40 #include <adt/measured_strings.h>41 #include <adt/module_map.h>42 39 #include <ipc/ipc.h> 43 40 #include <ipc/net.h> 44 41 45 42 #include <ip_interface.h> 43 #include <adt/measured_strings.h> 44 #include <adt/module_map.h> 46 45 #include <packet_server.h> 47 46 48 /** Networking module global data. */ 47 #include "net.h" 48 49 /** Networking module global data. 50 */ 49 51 extern net_globals_t net_globals; 50 52 … … 58 60 * 59 61 */ 60 int net_initialize_build(async_client_conn_t client_connection) 61 { 62 int net_initialize_build(async_client_conn_t client_connection){ 62 63 ERROR_DECLARE; 63 64 -
uspace/srv/net/tl/icmp/icmp.c
r49d819b4 re06ef614 28 28 29 29 /** @addtogroup icmp 30 * @{30 * @{ 31 31 */ 32 32 33 33 /** @file 34 * ICMP module implementation. 35 * @see icmp.h 36 */ 37 38 #include "icmp.h" 39 #include "icmp_module.h" 34 * ICMP module implementation. 35 * @see icmp.h 36 */ 40 37 41 38 #include <async.h> … … 59 56 #include <net/ip_protocols.h> 60 57 #include <net/inet.h> 58 61 59 #include <net/modules.h> 62 #include <net/icmp_api.h>63 #include <net/icmp_codes.h>64 #include <net/icmp_common.h>65 66 60 #include <packet_client.h> 67 61 #include <packet_remote.h> 68 62 #include <net_checksum.h> 63 #include <net/icmp_api.h> 69 64 #include <icmp_client.h> 65 #include <net/icmp_codes.h> 66 #include <net/icmp_common.h> 70 67 #include <icmp_interface.h> 71 68 #include <il_interface.h> … … 77 74 #include <icmp_header.h> 78 75 79 /** ICMP module name. */ 76 #include "icmp.h" 77 #include "icmp_module.h" 78 79 /** ICMP module name. 80 */ 80 81 #define NAME "ICMP protocol" 81 82 82 /** Default ICMP error reporting. */ 83 /** Default ICMP error reporting. 84 */ 83 85 #define NET_DEFAULT_ICMP_ERROR_REPORTING true 84 86 85 /** Default ICMP echo replying. */ 87 /** Default ICMP echo replying. 88 */ 86 89 #define NET_DEFAULT_ICMP_ECHO_REPLYING true 87 90 88 /** Original datagram length in bytes transfered to the error notification 89 * message. 91 /** Original datagram length in bytes transfered to the error notification message. 90 92 */ 91 93 #define ICMP_KEEP_LENGTH 8 92 94 93 /** Free identifier numbers pool start. */ 95 /** Free identifier numbers pool start. 96 */ 94 97 #define ICMP_FREE_IDS_START 1 95 98 96 /** Free identifier numbers pool end. */ 99 /** Free identifier numbers pool end. 100 */ 97 101 #define ICMP_FREE_IDS_END UINT16_MAX 98 102 99 103 /** Computes the ICMP datagram checksum. 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." 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." 110 113 111 114 /** Computes an ICMP reply data key. 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. */ 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); 171 172 /** 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); 178 179 /** 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 */ 122 249 icmp_globals_t icmp_globals; 123 250 124 251 INT_MAP_IMPLEMENT(icmp_replies, icmp_reply_t); 252 125 253 INT_MAP_IMPLEMENT(icmp_echo_data, icmp_echo_t); 126 254 127 /** Releases the packet and returns the 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 } 220 221 /** Requests an echo message. 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 { 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){ 251 277 ERROR_DECLARE; 252 278 … … 254 280 packet_t packet; 255 281 size_t length; 256 uint8_t * data;282 uint8_t * data; 257 283 icmp_reply_ref reply; 258 284 int reply_key; … … 260 286 int index; 261 287 262 if (addrlen <= 0)288 if(addrlen <= 0){ 263 289 return EINVAL; 264 290 } 265 291 length = (size_t) addrlen; 266 292 // TODO do not ask all the time 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) 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){ 275 296 return ENOMEM; 297 } 276 298 277 299 // prepare the requesting packet 278 300 // set the destination address 279 if (ERROR_OCCURRED(packet_set_addr(packet, NULL, (const uint8_t *) addr, 280 length))) { 301 if(ERROR_OCCURRED(packet_set_addr(packet, NULL, (const uint8_t *) addr, length))){ 281 302 return icmp_release_and_return(packet, ERROR_CODE); 282 303 } 283 284 304 // allocate space in the packet 285 305 data = (uint8_t *) packet_suffix(packet, size); 286 if (!data)306 if(! data){ 287 307 return icmp_release_and_return(packet, ENOMEM); 288 308 } 289 309 // fill the data 290 310 length = 0; 291 while (size > length + sizeof(ICMP_ECHO_TEXT)){311 while(size > length + sizeof(ICMP_ECHO_TEXT)){ 292 312 memcpy(data + length, ICMP_ECHO_TEXT, sizeof(ICMP_ECHO_TEXT)); 293 313 length += sizeof(ICMP_ECHO_TEXT); 294 314 } 295 315 memcpy(data + length, ICMP_ECHO_TEXT, size - length); 296 297 316 // prefix the header 298 317 header = PACKET_PREFIX(packet, icmp_header_t); 299 if (!header)318 if(! header){ 300 319 return icmp_release_and_return(packet, ENOMEM); 301 320 } 302 321 bzero(header, sizeof(*header)); 303 322 header->un.echo.identifier = id; … … 306 325 // prepare the reply structure 307 326 reply = malloc(sizeof(*reply)); 308 if (!reply)327 if(! reply){ 309 328 return icmp_release_and_return(packet, ENOMEM); 310 329 } 311 330 fibril_mutex_initialize(&reply->mutex); 312 331 fibril_mutex_lock(&reply->mutex); 313 332 fibril_condvar_initialize(&reply->condvar); 314 reply_key = ICMP_GET_REPLY_KEY(header->un.echo.identifier, 315 header->un.echo.sequence_number); 333 reply_key = ICMP_GET_REPLY_KEY(header->un.echo.identifier, header->un.echo.sequence_number); 316 334 index = icmp_replies_add(&icmp_globals.replies, reply_key, reply); 317 if (index < 0){335 if(index < 0){ 318 336 free(reply); 319 337 return icmp_release_and_return(packet, index); … … 324 342 325 343 // send the request 326 icmp_send_packet(ICMP_ECHO, 0, packet, header, 0, ttl, tos, 327 dont_fragment); 344 icmp_send_packet(ICMP_ECHO, 0, packet, header, 0, ttl, tos, dont_fragment); 328 345 329 346 // wait for the reply 330 347 // timeout in microseconds 331 if (ERROR_OCCURRED(fibril_condvar_wait_timeout(&reply->condvar, 332 &reply->mutex, timeout * 1000))) { 348 if(ERROR_OCCURRED(fibril_condvar_wait_timeout(&reply->condvar, &reply->mutex, timeout * 1000))){ 333 349 result = ERROR_CODE; 334 } else{350 }else{ 335 351 // read the result 336 352 result = reply->result; … … 343 359 // destroy the reply structure 344 360 icmp_replies_exclude_index(&icmp_globals.replies, index); 345 346 361 return result; 347 362 } 348 363 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 { 364 int icmp_destination_unreachable_msg(int icmp_phone, icmp_code_t code, icmp_param_t mtu, packet_t packet){ 353 365 icmp_header_ref header; 354 366 355 367 header = icmp_prepare_packet(packet); 356 if (!header)368 if(! header){ 357 369 return icmp_release_and_return(packet, ENOMEM); 358 359 if (mtu)370 } 371 if(mtu){ 360 372 header->un.frag.mtu = mtu; 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 { 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){ 368 378 icmp_header_ref header; 369 379 370 380 header = icmp_prepare_packet(packet); 371 if (!header)381 if(! header){ 372 382 return icmp_release_and_return(packet, ENOMEM); 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 { 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){ 381 388 icmp_header_ref header; 382 389 383 390 header = icmp_prepare_packet(packet); 384 if (!header)391 if(! header){ 385 392 return icmp_release_and_return(packet, ENOMEM); 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 { 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){ 395 398 icmp_header_ref header; 396 399 397 400 header = icmp_prepare_packet(packet); 398 if (!header)401 if(! header){ 399 402 return icmp_release_and_return(packet, ENOMEM); 400 403 } 401 404 header->un.param.pointer = pointer; 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 { 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){ 415 435 ERROR_DECLARE; 416 436 417 measured_string_t names[] = { 418 { 419 (char *) "ICMP_ERROR_REPORTING", 420 20 421 }, 422 { 423 (char *) "ICMP_ECHO_REPLYING", 424 18 425 } 426 }; 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}}; 427 455 measured_string_ref configuration; 428 456 size_t count = sizeof(names) / sizeof(measured_string_t); 429 char * data;457 char * data; 430 458 431 459 fibril_rwlock_initialize(&icmp_globals.lock); … … 433 461 icmp_replies_initialize(&icmp_globals.replies); 434 462 icmp_echo_data_initialize(&icmp_globals.echo_data); 435 icmp_globals.ip_phone = ip_bind_service(SERVICE_IP, IPPROTO_ICMP, 436 SERVICE_ICMP, client_connection); 437 if (icmp_globals.ip_phone < 0) 463 icmp_globals.ip_phone = ip_bind_service(SERVICE_IP, IPPROTO_ICMP, SERVICE_ICMP, client_connection); 464 if(icmp_globals.ip_phone < 0){ 438 465 return icmp_globals.ip_phone; 439 440 ERROR_PROPAGATE(ip_packet_size_req(icmp_globals.ip_phone, -1, 441 &icmp_globals.packet_dimension)); 466 } 467 ERROR_PROPAGATE(ip_packet_size_req(icmp_globals.ip_phone, -1, &icmp_globals.packet_dimension)); 442 468 icmp_globals.packet_dimension.prefix += ICMP_HEADER_SIZE; 443 469 icmp_globals.packet_dimension.content -= ICMP_HEADER_SIZE; 444 470 // get configuration 445 471 icmp_globals.error_reporting = NET_DEFAULT_ICMP_ERROR_REPORTING; 446 472 icmp_globals.echo_replying = NET_DEFAULT_ICMP_ECHO_REPLYING; 447 448 // get configuration449 473 configuration = &names[0]; 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'); 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'); 456 478 } 457 if (configuration[1].value) { 458 icmp_globals.echo_replying = 459 (configuration[1].value[0] == 'y'); 479 if(configuration[1].value){ 480 icmp_globals.echo_replying = (configuration[1].value[0] == 'y'); 460 481 } 461 482 net_free_settings(configuration, data); 462 483 } 463 464 484 fibril_rwlock_write_unlock(&icmp_globals.lock); 465 485 return EOK; 466 486 } 467 487 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 { 488 int icmp_received_msg(device_id_t device_id, packet_t packet, services_t receiver, services_t error){ 521 489 ERROR_DECLARE; 522 490 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 523 501 size_t length; 524 uint8_t * src;502 uint8_t * src; 525 503 int addrlen; 526 504 int result; 527 void * data;505 void * data; 528 506 icmp_header_ref header; 529 507 icmp_type_t type; 530 508 icmp_code_t code; 531 509 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 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 } 549 526 // get rid of the ip header 550 527 length = ip_client_header_length(packet); … … 552 529 553 530 length = packet_get_data_length(packet); 554 if (length <= 0)531 if(length <= 0){ 555 532 return EINVAL; 556 557 if (length < ICMP_HEADER_SIZE)533 } 534 if(length < ICMP_HEADER_SIZE){ 558 535 return EINVAL; 559 536 } 560 537 data = packet_get_data(packet); 561 if (!data)538 if(! data){ 562 539 return EINVAL; 563 540 } 564 541 // get icmp header 565 542 header = (icmp_header_ref) data; 566 567 if (header->checksum){568 while (ICMP_CHECKSUM(header, length) != IP_CHECKSUM_ZERO){543 // checksum 544 if(header->checksum){ 545 while(ICMP_CHECKSUM(header, length) != IP_CHECKSUM_ZERO){ 569 546 // set the original message type on error notification 570 547 // type swap observed in Qemu 571 if (error){572 switch (header->type){573 case ICMP_ECHOREPLY:574 header->type = ICMP_ECHO;575 continue;548 if(error){ 549 switch(header->type){ 550 case ICMP_ECHOREPLY: 551 header->type = ICMP_ECHO; 552 continue; 576 553 } 577 554 } … … 579 556 } 580 557 } 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); 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); 564 } 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; 579 } 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); 594 596 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; 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){ 624 ERROR_DECLARE; 625 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)); 610 633 } 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 { 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){ 656 644 ERROR_DECLARE; 657 645 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 the672 * icmp_destination_unreachable_msg_local() function.673 * @returns Other error codes as defined for the674 * icmp_source_quench_msg_local() function.675 * @returns Other error codes as defined for the676 * icmp_time_exceeded_msg_local() function.677 * @returns Other error codes as defined for the678 * icmp_parameter_problem_msg_local() function.679 *680 * @see icmp_interface.h681 */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 one739 index = icmp_globals.last_used_id;740 do {741 index++;742 // til the range end743 if (index >= ICMP_FREE_IDS_END) {744 // start from the range beginning745 index = ICMP_FREE_IDS_START - 1;746 do {747 index++;748 // til the last used one749 if (index >= icmp_globals.last_used_id) {750 // none found751 return ENOTCONN;752 }753 } while(icmp_echo_data_find(&icmp_globals.echo_data,754 index) != NULL);755 756 // found, break immediately757 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.h777 * @see icmp_api.h778 */779 static int icmp_process_client_messages(ipc_callid_t callid, ipc_call_t call)780 {781 ERROR_DECLARE;782 783 646 bool keep_on_going = true; 647 // fibril_rwlock_t lock; 784 648 ipc_call_t answer; 785 649 int answer_count; 786 650 size_t length; 787 struct sockaddr * addr;651 struct sockaddr * addr; 788 652 ipc_callid_t data_callid; 789 653 icmp_echo_ref echo_data; … … 797 661 answer_count = 0; 798 662 663 // fibril_rwlock_initialize(&lock); 664 799 665 echo_data = (icmp_echo_ref) malloc(sizeof(*echo_data)); 800 if (!echo_data)666 if(! echo_data){ 801 667 return ENOMEM; 668 } 802 669 803 670 // assign a new identifier … … 805 672 res = icmp_bind_free_id(echo_data); 806 673 fibril_rwlock_write_unlock(&icmp_globals.lock); 807 if (res < 0){674 if(res < 0){ 808 675 free(echo_data); 809 676 return res; 810 677 } 811 678 812 while (keep_on_going) { 679 while(keep_on_going){ 680 813 681 // answer the call 814 682 answer_call(callid, res, &answer, answer_count); … … 821 689 822 690 // process the call 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; 691 switch(IPC_GET_METHOD(call)){ 692 case IPC_M_PHONE_HUNGUP: 693 keep_on_going = false; 694 res = EHANGUP; 832 695 break; 833 } 834 835 addr = malloc(length); 836 if (!addr) { 837 res = ENOMEM; 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); 838 721 break; 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); 722 default: 723 res = icmp_process_message(&call); 867 724 } 868 869 725 } 870 726 … … 873 729 icmp_echo_data_exclude(&icmp_globals.echo_data, echo_data->identifier); 874 730 fibril_rwlock_write_unlock(&icmp_globals.lock); 875 876 731 return res; 877 732 } 878 733 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 { 734 int icmp_process_message(ipc_call_t * call){ 896 735 ERROR_DECLARE; 897 736 898 737 packet_t packet; 899 738 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)); 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; 908 794 } 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 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 } 921 800 922 801 /** Default thread for new connections. 923 802 * 924 * @param[in] iid The initial message identifier.925 * @param[in] icall The initial message call structure.803 * @param[in] iid The initial message identifier. 804 * @param[in] icall The initial message call structure. 926 805 * 927 806 */ 928 static void tl_client_connection(ipc_callid_t iid, ipc_call_t * icall)807 static void tl_client_connection(ipc_callid_t iid, ipc_call_t * icall) 929 808 { 930 809 /* … … 934 813 ipc_answer_0(iid, EOK); 935 814 936 while 815 while(true) { 937 816 ipc_call_t answer; 938 817 int answer_count; … … 949 828 &answer_count); 950 829 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)) 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)) 957 832 return; 958 833 … … 964 839 /** Starts the module. 965 840 * 966 * @returns EOK on success. 967 * @returns Other error codes as defined for each specific module 968 * start function. 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 * 969 847 */ 970 848 int main(int argc, char *argv[]) … … 973 851 974 852 /* Start the module */ 975 ERROR_PROPAGATE(tl_module_start_standalone(tl_client_connection)); 853 if (ERROR_OCCURRED(tl_module_start_standalone(tl_client_connection))) 854 return ERROR_CODE; 855 976 856 return EOK; 977 857 } … … 979 859 /** @} 980 860 */ 981 -
uspace/srv/net/tl/icmp/icmp.h
r49d819b4 re06ef614 28 28 29 29 /** @addtogroup icmp 30 * @{30 * @{ 31 31 */ 32 32 33 33 /** @file 34 * ICMP module.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>44 43 #include <adt/int_map.h> 45 44 #include <icmp_header.h> 46 45 47 46 /** Type definition of the ICMP reply data. 48 * @see icmp_reply47 * @see icmp_reply 49 48 */ 50 typedef struct icmp_reply 49 typedef struct icmp_reply icmp_reply_t; 51 50 52 51 /** Type definition of the ICMP reply data pointer. 53 * @see icmp_reply52 * @see icmp_reply 54 53 */ 55 typedef icmp_reply_t * icmp_reply_ref;54 typedef icmp_reply_t * icmp_reply_ref; 56 55 57 56 /** Type definition of the ICMP global data. 58 * @see icmp_globals57 * @see icmp_globals 59 58 */ 60 typedef struct icmp_globals 59 typedef struct icmp_globals icmp_globals_t; 61 60 62 61 /** Pending replies map. 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. 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. 68 65 */ 69 66 INT_MAP_DECLARE(icmp_replies, icmp_reply_t); 70 67 71 68 /** Echo specific data map. 72 * 73 * The identifier is used in the future semi-remote calls instead of the ICMP 74 * phone. 69 * The identifier is used in the future semi-remote calls instead of the ICMP phone. 75 70 */ 76 71 INT_MAP_DECLARE(icmp_echo_data, icmp_echo_t); 77 72 78 /** ICMP reply data. */ 79 struct icmp_reply { 80 /** Reply result. */ 73 /** ICMP reply data. 74 */ 75 struct icmp_reply{ 76 /** Reply result. 77 */ 81 78 int result; 82 /** Safety lock. */ 79 /** Safety lock. 80 */ 83 81 fibril_mutex_t mutex; 84 /** Received or timeouted reply signaling. */ 82 /** Received or timeouted reply signaling. 83 */ 85 84 fibril_condvar_t condvar; 86 85 }; 87 86 88 /** ICMP global data. */ 89 struct icmp_globals { 90 /** IP module phone. */ 87 /** ICMP global data. 88 */ 89 struct icmp_globals{ 90 /** IP module phone. 91 */ 91 92 int ip_phone; 92 /** Packet dimension. */ 93 /** Packet dimension. 94 */ 93 95 packet_dimension_t packet_dimension; 94 /** Networking module phone. */ 96 /** Networking module phone. 97 */ 95 98 int net_phone; 96 /** Indicates whether ICMP error reporting is enabled. */ 99 /** Indicates whether ICMP error reporting is enabled. 100 */ 97 101 int error_reporting; 98 /** Indicates whether ICMP echo replying (ping) is enabled. */ 102 /** Indicates whether ICMP echo replying (ping) is enabled. 103 */ 99 104 int echo_replying; 100 /** The last used identifier number. */ 105 /** The last used identifier number. 106 */ 101 107 icmp_param_t last_used_id; 102 /** The budled modules assigned echo specific data. */ 108 /** The budled modules assigned echo specific data. 109 */ 103 110 icmp_echo_data_t echo_data; 104 /** Echo timeout locks. */ 111 /** Echo timeout locks. 112 */ 105 113 icmp_replies_t replies; 106 /** Safety lock. */ 114 /** Safety lock. 115 */ 107 116 fibril_rwlock_t lock; 108 117 }; … … 112 121 /** @} 113 122 */ 123 -
uspace/srv/net/tl/icmp/icmp_module.c
r49d819b4 re06ef614 28 28 29 29 /** @addtogroup icmp 30 * @{30 * @{ 31 31 */ 32 32 33 33 /** @file 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.c34 * 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"42 39 43 40 #include <async.h> … … 50 47 #include <net/packet.h> 51 48 #include <net_interface.h> 52 53 49 #include <tl_local.h> 54 50 55 /** ICMP module global data. */ 56 extern icmp_globals_t icmp_globals; 51 #include "icmp.h" 52 #include "icmp_module.h" 57 53 58 int tl_module_start_standalone(async_client_conn_t client_connection) 59 { 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){ 60 66 ERROR_DECLARE; 61 67 … … 64 70 async_set_client_connection(client_connection); 65 71 icmp_globals.net_phone = net_connect_module(); 66 if (icmp_globals.net_phone < 0)72 if(icmp_globals.net_phone < 0){ 67 73 return icmp_globals.net_phone; 68 74 } 69 75 ERROR_PROPAGATE(pm_init()); 70 if (ERROR_OCCURRED(icmp_initialize(client_connection)) ||71 ERROR_OCCURRED(REGISTER_ME(SERVICE_ICMP, &phonehash))){76 if(ERROR_OCCURRED(icmp_initialize(client_connection)) 77 || ERROR_OCCURRED(REGISTER_ME(SERVICE_ICMP, &phonehash))){ 72 78 pm_destroy(); 73 79 return ERROR_CODE; … … 80 86 } 81 87 82 int 83 tl_module_message_standalone(ipc_callid_t callid, ipc_call_t *call, 84 ipc_call_t *answer, int *answer_count) 85 { 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){ 86 97 return icmp_message_standalone(callid, call, answer, answer_count); 87 98 } … … 89 100 /** @} 90 101 */ 91 -
uspace/srv/net/tl/icmp/icmp_module.h
r49d819b4 re06ef614 28 28 29 29 /** @addtogroup icmp 30 * @{30 * @{ 31 31 */ 32 32 33 33 /** @file 34 * ICMP module functions.35 * The functions are used as ICMP module entry points.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 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 *); 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); 47 62 48 63 #endif -
uspace/srv/net/tl/tcp/tcp.c
r49d819b4 re06ef614 28 28 29 29 /** @addtogroup tcp 30 * @{30 * @{ 31 31 */ 32 32 33 33 /** @file 34 * TCP module implementation.35 * @see tcp.h34 * TCP module implementation. 35 * @see tcp.h 36 36 */ 37 38 #include "tcp.h"39 #include "tcp_header.h"40 #include "tcp_module.h"41 37 42 38 #include <assert.h> … … 76 72 #include <tl_interface.h> 77 73 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 * the possible overflow.112 * the possible overflow. 113 113 * 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. 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. 119 118 */ 120 119 #define IS_IN_INTERVAL_OVERFLOW(lower, value, higher_equal) \ … … 166 165 }; 167 166 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); 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); 224 245 225 246 /** TCP global data. */ 226 247 tcp_globals_t tcp_globals; 227 248 228 /** Initializes the TCP module.229 *230 * @param[in] client_connection The client connection processing function. The231 * module skeleton propagates its own one.232 * @returns EOK on success.233 * @returns ENOMEM if there is not enough memory left.234 */235 249 int tcp_initialize(async_client_conn_t client_connection) 236 250 { … … 300 314 size_t addrlen; 301 315 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); 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 } 318 335 } 319 336 … … 362 379 ntohs(header->destination_port), SOCKET_MAP_KEY_LISTENING, 363 380 0); 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 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 0, packet); 387 } 388 return EADDRNOTAVAIL; 389 } 390 } 374 391 printf("socket id %d\n", socket->socket_id); 375 392 socket_data = (tcp_socket_data_ref) socket->specific_data; … … 385 402 total_length = 0; 386 403 do { 387 fragments++;404 ++fragments; 388 405 length = packet_get_data_length(next_packet); 389 406 if (length <= 0) … … 404 421 405 422 if (error) 406 goto has_error_service;423 goto error; 407 424 408 425 if (socket_data->state == TCP_SOCKET_LISTEN) { 426 409 427 if (socket_data->pseudo_header) { 410 428 free(socket_data->pseudo_header); … … 446 464 } 447 465 448 has_error_service:466 error: 449 467 fibril_rwlock_read_unlock(&tcp_globals.lock); 450 468 … … 489 507 int 490 508 tcp_process_established(socket_core_ref socket, tcp_socket_data_ref socket_data, 491 tcp_header_ref header, packet_t packet, int fragments, size_t total_length) 509 tcp_header_ref header, packet_t packet, int fragments, 510 size_t total_length) 492 511 { 493 512 ERROR_DECLARE; … … 665 684 continue; 666 685 // at least partly following data? 667 } 668 if (IS_IN_INTERVAL_OVERFLOW(sequence_number,669 socket_data->next_incoming,new_sequence_number)) {686 } else if (IS_IN_INTERVAL_OVERFLOW( 687 sequence_number, socket_data->next_incoming, 688 new_sequence_number)) { 670 689 if (socket_data->next_incoming < 671 690 new_sequence_number) { … … 942 961 listening_socket = socket_port_find(&tcp_globals.sockets, 943 962 listening_port, SOCKET_MAP_KEY_LISTENING, 0); 944 if ( !listening_socket||963 if ((!listening_socket) || 945 964 (listening_socket->socket_id != listening_socket_id)) { 946 965 fibril_rwlock_write_unlock(&tcp_globals.lock); … … 1172 1191 if (number == socket_data->expected) { 1173 1192 // increase the counter 1174 socket_data->expected_count++;1193 ++socket_data->expected_count; 1175 1194 if (socket_data->expected_count == TCP_FAST_RETRANSMIT_COUNT) { 1176 1195 socket_data->expected_count = 1; … … 1181 1200 } 1182 1201 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) 1202 int tcp_message_standalone(ipc_callid_t callid, ipc_call_t * call, 1203 ipc_call_t * answer, int *answer_count) 1199 1204 { 1200 1205 ERROR_DECLARE; … … 1516 1521 socket = socket_port_find(&tcp_globals.sockets, timeout->port, 1517 1522 timeout->key, timeout->key_length); 1518 if (! socket || (socket->socket_id != timeout->socket_id))1523 if (!(socket && (socket->socket_id == timeout->socket_id))) 1519 1524 goto out; 1520 1525 … … 1527 1532 if (timeout->sequence_number) { 1528 1533 // increase the timeout counter; 1529 socket_data->timeout_count++;1534 ++socket_data->timeout_count; 1530 1535 if (socket_data->timeout_count == TCP_MAX_TIMEOUTS) { 1531 1536 // TODO release as connection lost … … 1739 1744 ERROR_OCCURRED(tcp_prepare_timeout(tcp_timeout, socket, socket_data, 1740 1745 0, TCP_SOCKET_INITIAL, NET_DEFAULT_TCP_INITIAL_TIMEOUT, false))) { 1746 1741 1747 socket_data->addr = NULL; 1742 1748 socket_data->addrlen = 0; 1743 1749 fibril_rwlock_write_lock(&tcp_globals.lock); 1750 1744 1751 } else { 1752 1745 1753 packet = tcp_get_packets_to_send(socket, socket_data); 1746 1754 if (packet) { … … 1868 1876 packet = pq_next(packet); 1869 1877 // overflow occurred ? 1870 if ( !packet&&1878 if ((!packet) && 1871 1879 (socket_data->last_outgoing > socket_data->next_outgoing)) { 1872 1880 printf("gpts overflow\n"); … … 2036 2044 int 2037 2045 tcp_recvfrom_message(socket_cores_ref local_sockets, int socket_id, int flags, 2038 size_t * addrlen)2046 size_t * addrlen) 2039 2047 { 2040 2048 ERROR_DECLARE; … … 2091 2099 int 2092 2100 tcp_send_message(socket_cores_ref local_sockets, int socket_id, int fragments, 2093 size_t * data_fragment_size, int flags)2101 size_t * data_fragment_size, int flags) 2094 2102 { 2095 2103 ERROR_DECLARE; … … 2130 2138 packet_dimension->content : socket_data->data_fragment_size); 2131 2139 2132 for (index = 0; index < fragments; index++) {2140 for (index = 0; index < fragments; ++index) { 2133 2141 // read the data fragment 2134 2142 result = tl_socket_read_packet_data(tcp_globals.net_phone, … … 2227 2235 2228 2236 int 2229 tcp_create_notification_packet(packet_t * packet, socket_core_ref socket,2237 tcp_create_notification_packet(packet_t * packet, socket_core_ref socket, 2230 2238 tcp_socket_data_ref socket_data, int synchronize, int finalize) 2231 2239 { … … 2263 2271 int 2264 2272 tcp_accept_message(socket_cores_ref local_sockets, int socket_id, 2265 int new_socket_id, size_t * data_fragment_size, size_t *addrlen)2273 int new_socket_id, size_t * data_fragment_size, size_t * addrlen) 2266 2274 { 2267 2275 ERROR_DECLARE; … … 2365 2373 } 2366 2374 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 */2373 2375 int tcp_release_and_return(packet_t packet, int result) 2374 2376 { … … 2379 2381 /** Default thread for new connections. 2380 2382 * 2381 * @param[in] iidThe initial message identifier.2382 * @param[in] icallThe initial message call structure.2383 * @param[in] iid The initial message identifier. 2384 * @param[in] icall The initial message call structure. 2383 2385 * 2384 2386 */ … … 2395 2397 int answer_count; 2396 2398 2397 /* Clear the answer structure */ 2399 /* 2400 Clear the answer structure 2401 */ 2398 2402 refresh_answer(&answer, &answer_count); 2399 2403 2400 /* Fetch the next message */ 2404 /* 2405 Fetch the next message 2406 */ 2401 2407 ipc_call_t call; 2402 2408 ipc_callid_t callid = async_get_call(&call); 2403 2409 2404 /* Process the message */ 2410 /* 2411 Process the message 2412 */ 2405 2413 int res = tl_module_message_standalone(callid, &call, &answer, 2406 2414 &answer_count); 2407 2415 2408 2416 /* 2409 * End if told to either by the message or the processing 2410 * result. 2417 End if said to either by the message or the processing result 2411 2418 */ 2412 2419 if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) || … … 2423 2430 /** Starts the module. 2424 2431 * 2425 * @returns EOK on success. 2426 * @returns Other error codes as defined for each specific module 2427 * start function. 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 * 2428 2438 */ 2429 2439 int -
uspace/srv/net/tl/tcp/tcp.h
r49d819b4 re06ef614 28 28 29 29 /** @addtogroup tcp 30 * @{30 * @{ 31 31 */ 32 32 33 33 /** @file 34 * TCP module.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 * @see tcp_globals49 */ 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 * @see tcp_socket_data54 */ 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 * @see tcp_socket_data59 */ 60 typedef tcp_socket_data_t * tcp_socket_data_ref;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 * @see tcp_operation64 */ 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 * @see tcp_operation69 */ 70 typedef tcp_operation_t * tcp_operation_ref;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 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 */ 79 enum tcp_socket_state{ 79 80 /** Initial. 80 * 81 * Not connected or bound. 81 * Not connected or bound. 82 82 */ 83 83 TCP_SOCKET_INITIAL, 84 85 84 /** Listening. 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. 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. 90 87 */ 91 88 TCP_SOCKET_LISTEN, 92 93 89 /** Connecting issued. 94 * 95 * A SYN has been sent, and TCP is awaiting the response SYN. 96 * Should continue to the TCP_SOCKET_ESTABLISHED state. 90 * A~SYN has been sent, and TCP is awaiting the response SYN. 91 * Should continue to the TCP_SOCKET_ESTABLISHED state. 97 92 */ 98 93 TCP_SOCKET_SYN_SENT, 99 100 94 /** Connecting received. 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. 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. 104 97 */ 105 98 TCP_SOCKET_SYN_RECEIVED, 106 107 99 /** Connected. 108 * 109 * The three-way handshake has been completed. 100 * The three-way handshake has been completed. 110 101 */ 111 102 TCP_SOCKET_ESTABLISHED, 112 113 103 /** Closing started. 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. 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. 121 108 */ 122 109 TCP_SOCKET_FIN_WAIT_1, 123 124 110 /** Closing confirmed. 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. 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. 129 114 */ 130 115 TCP_SOCKET_FIN_WAIT_2, 131 132 116 /** Closing. 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. 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. 138 120 */ 139 121 TCP_SOCKET_CLOSING, 140 141 122 /** Closing received. 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. 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. 147 126 */ 148 127 TCP_SOCKET_CLOSE_WAIT, 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. 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. 154 132 */ 155 133 TCP_SOCKET_LAST_ACK, 156 157 134 /** Closing finished. 158 * 159 * FINs have been received and ACK’d, and TCP is waiting two MSLs to 160 * remove the connection from the table. 135 * FINs have been received and ACK’d, and TCP is waiting two MSLs to remove the connection from the table. 161 136 */ 162 137 TCP_SOCKET_TIME_WAIT, 163 164 138 /** Closed. 165 * 166 * Imaginary, this indicates that a connection has been removed from 167 * the connection table. 139 * Imaginary, this indicates that a~connection has been removed from the connection table. 168 140 */ 169 141 TCP_SOCKET_CLOSED 170 142 }; 171 143 172 /** TCP operation data. */ 173 struct tcp_operation { 174 /** Operation result. */ 144 /** TCP operation data. 145 */ 146 struct tcp_operation{ 147 /** Operation result. 148 */ 175 149 int result; 176 /** Safety lock. */ 150 /** Safety lock. 151 */ 177 152 fibril_mutex_t mutex; 178 /** Operation result signaling. */ 153 /** Operation result signaling. 154 */ 179 155 fibril_condvar_t condvar; 180 156 }; 181 157 182 /** TCP socket specific data. */ 183 struct tcp_socket_data { 184 /** TCP socket state. */ 158 /** TCP socket specific data. 159 */ 160 struct tcp_socket_data{ 161 /** TCP socket state. 162 */ 185 163 tcp_socket_state_t state; 186 187 /** 188 * Data fragment size. 189 * Sending optimalization. 164 /** Data fragment size. 165 * Sending optimalization. 190 166 */ 191 167 size_t data_fragment_size; 192 193 /** Device identifier.*/168 /** Device identifier. 169 */ 194 170 device_id_t device_id; 195 196 /** 197 * Listening backlog. 198 * The maximal number of connected but not yet accepted sockets. 171 /** Listening backlog. 172 * The maximal number of connected but not yet accepted sockets. 199 173 */ 200 174 int backlog; 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. 175 // /** Segment size. 176 // */ 177 // size_t segment_size; 178 /** Parent listening socket identifier. 179 * Set if this socket is an accepted one. 208 180 */ 209 181 int listening_socket_id; 210 211 /** Treshold size in bytes.*/182 /** Treshold size in bytes. 183 */ 212 184 size_t treshold; 213 /** Window size in bytes. */ 185 /** Window size in bytes. 186 */ 214 187 size_t window; 215 /** Acknowledgement timeout. */ 188 /** Acknowledgement timeout. 189 */ 216 190 suseconds_t timeout; 217 /** Last acknowledged byte. */ 191 /** Last acknowledged byte. 192 */ 218 193 uint32_t acknowledged; 219 /** Next incoming sequence number. */ 194 /** Next incoming sequence number. 195 */ 220 196 uint32_t next_incoming; 221 /** Incoming FIN. */ 197 /** Incoming FIN. 198 */ 222 199 uint32_t fin_incoming; 223 /** Next outgoing sequence number. */ 200 /** Next outgoing sequence number. 201 */ 224 202 uint32_t next_outgoing; 225 /** Last outgoing sequence number. */ 203 /** Last outgoing sequence number. 204 */ 226 205 uint32_t last_outgoing; 227 /** Outgoing FIN. */ 206 /** Outgoing FIN. 207 */ 228 208 uint32_t fin_outgoing; 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. 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. 234 212 */ 235 213 uint32_t expected; 236 237 /** 238 * Expected sequence number counter. 239 * Counts the number of received notifications for the same sequence 240 * number. 214 /** Expected sequence number counter. 215 * Counts the number of received notifications for the same sequence number. 241 216 */ 242 217 int expected_count; 243 244 218 /** Incoming packet queue. 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. 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. 250 223 */ 251 224 packet_t incoming; 252 253 225 /** Outgoing packet queue. 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. 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. 260 230 */ 261 231 packet_t outgoing; 262 263 /** IP pseudo header.*/232 /** IP pseudo header. 233 */ 264 234 void *pseudo_header; 265 /** IP pseudo header length. */ 235 /** IP pseudo header length. 236 */ 266 237 size_t headerlen; 267 /** Remote host address. */ 268 struct sockaddr *addr; 269 /** Remote host address length. */ 238 /** Remote host address. 239 */ 240 struct sockaddr * addr; 241 /** Remote host address length. 242 */ 270 243 socklen_t addrlen; 271 /** Remote host port. */ 244 /** Remote host port. 245 */ 272 246 uint16_t dest_port; 273 /** Parent local sockets. */ 247 /** Parent local sockets. 248 */ 274 249 socket_cores_ref local_sockets; 275 276 250 /** Local sockets safety lock. 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. */ 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 */ 288 260 tcp_operation_t operation; 289 290 /** 291 * Timeouts in a row counter. 292 * If TCP_MAX_TIMEOUTS is reached, the connection is lost. 261 /** Timeouts in a row counter. 262 * If TCP_MAX_TIMEOUTS is reached, the connection is lost. 293 263 */ 294 264 int timeout_count; 295 265 }; 296 266 297 /** TCP global data. */ 298 struct tcp_globals { 299 /** Networking module phone. */ 267 /** TCP global data. 268 */ 269 struct tcp_globals{ 270 /** Networking module phone. 271 */ 300 272 int net_phone; 301 /** IP module phone. */ 273 /** IP module phone. 274 */ 302 275 int ip_phone; 303 /** ICMP module phone. */ 276 /** ICMP module phone. 277 */ 304 278 int icmp_phone; 305 /** Last used free port. */ 279 /** Last used free port. 280 */ 306 281 int last_used_port; 307 /** Active sockets. */ 282 /** Active sockets. 283 */ 308 284 socket_ports_t sockets; 309 /** Device packet dimensions. */ 285 /** Device packet dimensions. 286 */ 310 287 packet_dimensions_t dimensions; 311 312 /** 313 * Safety lock. 314 * Write lock is used only for adding or removing socket ports. 288 /** Safety lock. 289 * Write lock is used only for adding or removing socket ports. 315 290 */ 316 291 fibril_rwlock_t lock; … … 321 296 /** @} 322 297 */ 298 -
uspace/srv/net/tl/tcp/tcp_header.h
r49d819b4 re06ef614 28 28 29 29 /** @addtogroup tcp 30 * @{30 * @{ 31 31 */ 32 32 33 33 /** @file 34 * TCP header definition.35 * Based on the RFC793.36 */ 37 38 #ifndef NET_TCP_HEADER_H_39 #define NET_TCP_HEADER_H_34 * TCP header definition. 35 * Based on the RFC~793. 36 */ 37 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 #define TCP_HEADER_SIZE sizeof(tcp_header_t) 43 /** TCP header size in bytes. 44 */ 45 #define TCP_HEADER_SIZE sizeof(tcp_header_t) 45 46 46 47 /** Returns the actual TCP header length in bytes. 47 * @param[in] header The TCP packet header.48 */ 49 #define TCP_HEADER_LENGTH(header) ((header)->header_length * 4 U)48 * @param[in] header The TCP packet header. 49 */ 50 #define TCP_HEADER_LENGTH(header) ((header)->header_length * 4u) 50 51 51 52 /** Returns the TCP header length. 52 * @param[in] length The TCP header length in bytes.53 */ 54 #define TCP_COMPUTE_HEADER_LENGTH(length) ((uint8_t) ((length) / 4U))53 * @param[in] length The TCP header length in bytes. 54 */ 55 #define TCP_COMPUTE_HEADER_LENGTH(length) ((uint8_t) ((length) / 4u)) 55 56 56 57 /** Type definition of the transmission datagram header. 57 * @see tcp_header58 */ 59 typedef struct tcp_header 58 * @see tcp_header 59 */ 60 typedef struct tcp_header tcp_header_t; 60 61 61 62 /** Type definition of the transmission datagram header pointer. 62 * @see tcp_header63 */ 64 typedef tcp_header_t * tcp_header_ref;63 * @see tcp_header 64 */ 65 typedef tcp_header_t * tcp_header_ref; 65 66 66 67 /** Type definition of the transmission datagram header option. 67 * @see tcp_option68 */ 69 typedef struct tcp_option 68 * @see tcp_option 69 */ 70 typedef struct tcp_option tcp_option_t; 70 71 71 72 /** Type definition of the transmission datagram header option pointer. 72 * @see tcp_option 73 */ 74 typedef tcp_option_t *tcp_option_ref; 75 76 /** Type definition of the Maximum segment size TCP option. */ 77 typedef struct tcp_max_segment_size_option tcp_max_segment_size_option_t; 73 * @see tcp_option 74 */ 75 typedef tcp_option_t * tcp_option_ref; 76 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; 78 81 79 82 /** Type definition of the Maximum segment size TCP option pointer. 80 * @see tcp_max_segment_size_option 81 */ 82 typedef tcp_max_segment_size_option_t *tcp_max_segment_size_option_ref; 83 84 /** Transmission datagram header. */ 85 struct tcp_header { 83 * @see tcp_max_segment_size_option 84 */ 85 typedef tcp_max_segment_size_option_t * tcp_max_segment_size_option_ref; 86 87 /** Transmission datagram header. 88 */ 89 struct tcp_header{ 90 /** The source port number. 91 */ 86 92 uint16_t source_port; 93 /** The destination port number. 94 */ 87 95 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 */ 88 99 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 acknowledge 103 */ 89 104 uint32_t acknowledgement_number; 90 91 105 #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 */ 92 110 uint8_t header_length:4; 111 /** Four bits reserved for future use. 112 * Must be zero. 113 */ 93 114 uint8_t reserved1:4; 94 115 #else 116 /** Four bits reserved for future use. 117 * Must be zero. 118 */ 95 119 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 */ 96 124 uint8_t header_length:4; 97 125 #endif 98 99 126 #ifdef ARCH_IS_BIG_ENDIAN 127 /** Two bits reserved for future use. 128 * Must be zero. 129 */ 100 130 uint8_t reserved2:2; 131 /** Urgent Pointer field significant. 132 * @see tcp_header:urgent_pointer 133 */ 101 134 uint8_t urgent:1; 135 /** Acknowledgment field significant 136 * @see tcp_header:acknowledgement_number 137 */ 102 138 uint8_t acknowledge:1; 139 /** Push function. 140 */ 103 141 uint8_t push:1; 142 /** Reset the connection. 143 */ 104 144 uint8_t reset:1; 145 /** Synchronize the sequence numbers. 146 */ 105 147 uint8_t synchronize:1; 148 /** No more data from the sender. 149 */ 106 150 uint8_t finalize:1; 107 151 #else 152 /** No more data from the sender. 153 */ 108 154 uint8_t finalize:1; 155 /** Synchronize the sequence numbers. 156 */ 109 157 uint8_t synchronize:1; 158 /** Reset the connection. 159 */ 110 160 uint8_t reset:1; 161 /** Push function. 162 */ 111 163 uint8_t push:1; 164 /** Acknowledgment field significant. 165 * @see tcp_header:acknowledgement_number 166 */ 112 167 uint8_t acknowledge:1; 168 /** Urgent Pointer field significant. 169 * @see tcp_header:urgent_pointer 170 */ 113 171 uint8_t urgent:1; 172 /** Two bits reserved for future use. 173 * Must be zero. 174 */ 114 175 uint8_t reserved2:2; 115 176 #endif 116 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 */ 117 180 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 */ 118 190 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:urgent 195 */ 119 196 uint16_t urgent_pointer; 120 197 } __attribute__ ((packed)); 121 198 122 /** Transmission datagram header option. */ 123 struct tcp_option { 124 /** Option type. */ 199 /** Transmission datagram header option. 200 */ 201 struct tcp_option{ 202 /** Option type. 203 */ 125 204 uint8_t type; 126 /** Option length. */ 205 /** Option length. 206 */ 127 207 uint8_t length; 128 208 }; 129 209 130 /** Maximum segment size TCP option. */ 131 struct tcp_max_segment_size_option { 210 /** Maximum segment size TCP option. 211 */ 212 struct tcp_max_segment_size_option{ 132 213 /** TCP option. 133 * @see TCPOPT_MAX_SEGMENT_SIZE134 * @see TCPOPT_MAX_SEGMENT_SIZE_LENGTH214 * @see TCPOPT_MAX_SEGMENT_SIZE 215 * @see TCPOPT_MAX_SEGMENT_SIZE_LENGTH 135 216 */ 136 217 tcp_option_t option; 137 138 /** Maximum segment size in bytes.*/218 /** Maximum segment size in bytes. 219 */ 139 220 uint16_t max_segment_size; 140 221 } __attribute__ ((packed)); -
uspace/srv/net/tl/tcp/tcp_module.c
r49d819b4 re06ef614 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 37 * points. 38 * @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 points. 37 * @see module.c 39 38 */ 40 41 #include "tcp.h"42 #include "tcp_module.h"43 39 44 40 #include <async.h> … … 50 46 #include <net/ip_protocols.h> 51 47 #include <net/modules.h> 48 52 49 #include <net/packet.h> 53 50 #include <net_interface.h> 54 55 51 #include <ip_interface.h> 56 52 #include <tl_local.h> 57 53 58 /** TCP module global data. */ 59 extern tcp_globals_t tcp_globals; 54 #include "tcp.h" 55 #include "tcp_module.h" 60 56 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 */ 61 68 int tl_module_start_standalone(async_client_conn_t client_connection) 62 69 { … … 68 75 69 76 ipcarg_t phonehash; 70 if (ERROR_OCCURRED(tcp_initialize(client_connection)) ||71 ERROR_OCCURRED(REGISTER_ME(SERVICE_TCP, &phonehash))) {77 if (ERROR_OCCURRED(tcp_initialize(client_connection)) 78 || ERROR_OCCURRED(REGISTER_ME(SERVICE_TCP, &phonehash))) { 72 79 pm_destroy(); 73 80 return ERROR_CODE; … … 80 87 } 81 88 82 int 83 tl_module_message_standalone(ipc_callid_t callid, ipc_call_t *call, 84 ipc_call_t *answer, int *answer_count) 85 { 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){ 86 98 return tcp_message_standalone(callid, call, answer, answer_count); 87 99 } -
uspace/srv/net/tl/tcp/tcp_module.h
r49d819b4 re06ef614 28 28 29 29 /** @addtogroup tcp 30 * @{30 * @{ 31 31 */ 32 32 33 33 /** @file 34 * TCP module functions.35 * The functions are used as TCP module entry points.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 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 *); 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); 47 62 48 63 #endif -
uspace/srv/net/tl/udp/udp.c
r49d819b4 re06ef614 28 28 29 29 /** @addtogroup udp 30 * @{30 * @{ 31 31 */ 32 32 33 33 /** @file 34 * UDP module implementation. 35 * @see udp.h 36 */ 37 38 #include "udp.h" 39 #include "udp_header.h" 40 #include "udp_module.h" 34 * UDP module implementation. 35 * @see udp.h 36 */ 41 37 42 38 #include <async.h> … … 49 45 #include <ipc/tl.h> 50 46 #include <ipc/socket.h> 51 #include <adt/dynamic_fifo.h>52 47 #include <errno.h> 53 48 #include <err.h> … … 60 55 #include <net/modules.h> 61 56 57 #include <adt/dynamic_fifo.h> 62 58 #include <packet_client.h> 63 59 #include <packet_remote.h> … … 73 69 #include <tl_interface.h> 74 70 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 /** UDP global data. */ 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 */ 94 217 udp_globals_t udp_globals; 95 218 96 /** Initializes the UDP module.97 *98 * @param[in] client_connection The client connection processing function. The99 * module skeleton propagates its own one.100 * @returns EOK on success.101 * @returns ENOMEM if there is not enough memory left.102 */103 219 int udp_initialize(async_client_conn_t client_connection) 104 220 { … … 107 223 measured_string_t names[] = { 108 224 { 109 (char *) "UDP_CHECKSUM_COMPUTING",225 str_dup("UDP_CHECKSUM_COMPUTING"), 110 226 22 111 227 }, 112 228 { 113 (char *) "UDP_AUTOBINDING",229 str_dup("UDP_AUTOBINDING"), 114 230 15 115 231 } … … 117 233 measured_string_ref configuration; 118 234 size_t count = sizeof(names) / sizeof(measured_string_t); 119 char * data;235 char * data; 120 236 121 237 fibril_rwlock_initialize(&udp_globals.lock); … … 142 258 udp_globals.last_used_port = UDP_FREE_PORTS_START - 1; 143 259 260 // get configuration 144 261 udp_globals.checksum_computing = NET_DEFAULT_UDP_CHECKSUM_COMPUTING; 145 262 udp_globals.autobinding = NET_DEFAULT_UDP_AUTOBINDING; 146 147 // get configuration148 263 configuration = &names[0]; 149 264 ERROR_PROPAGATE(net_get_conf_req(udp_globals.net_phone, &configuration, … … 165 280 } 166 281 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) 282 int 283 udp_received_msg(device_id_t device_id, packet_t packet, services_t receiver, 284 services_t error) 174 285 { 175 pq_release_remote(udp_globals.net_phone, packet_get_id(packet)); 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 176 293 return result; 177 294 } 178 295 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) 296 int udp_process_packet(device_id_t device_id, packet_t packet, services_t error) 202 297 { 203 298 ERROR_DECLARE; … … 220 315 packet_dimension_ref packet_dimension; 221 316 222 switch(error) {223 case SERVICE_NONE:224 break;225 case SERVICE_ICMP:226 // ignore error227 // length = icmp_client_header_length(packet);228 // process error229 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);317 if (error) { 318 switch (error) { 319 case SERVICE_ICMP: 320 // ignore error 321 // length = icmp_client_header_length(packet); 322 // process error 323 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 } 240 335 } 241 336 … … 279 374 280 375 // compute header checksum if set 281 if (header->checksum && !error) {376 if (header->checksum && (!error)) { 282 377 result = packet_get_addr(packet, (uint8_t **) &src, 283 378 (uint8_t **) &dest); 284 if (result <= 0)379 if( result <= 0) 285 380 return udp_release_and_return(packet, result); 286 381 … … 301 396 302 397 do { 303 fragments++;398 ++ fragments; 304 399 length = packet_get_data_length(next_packet); 305 400 if (length <= 0) … … 376 471 } 377 472 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) 473 int 474 udp_message_standalone(ipc_callid_t callid, ipc_call_t * call, 475 ipc_call_t * answer, int * answer_count) 395 476 { 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; 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; 404 497 } 405 498 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 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 434 641 udp_sendto_message(socket_cores_ref local_sockets, int socket_id, 435 642 const struct sockaddr *addr, socklen_t addrlen, int fragments, … … 518 725 // prefix the udp header 519 726 header = PACKET_PREFIX(packet, udp_header_t); 520 if (!header)727 if(! header) 521 728 return udp_release_and_return(packet, ENOMEM); 522 729 523 730 bzero(header, sizeof(*header)); 524 731 // read the rest of the packet fragments 525 for (index = 1; index < fragments; index++) {732 for (index = 1; index < fragments; ++ index) { 526 733 result = tl_socket_read_packet_data(udp_globals.net_phone, 527 734 &next_packet, 0, packet_dimension, addr, addrlen); … … 577 784 } 578 785 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 786 int 599 787 udp_recvfrom_message(socket_cores_ref local_sockets, int socket_id, int flags, 600 788 size_t *addrlen) … … 642 830 643 831 // send the source address 644 ERROR_PROPAGATE(data_reply(addr, * addrlen));832 ERROR_PROPAGATE(data_reply(addr, * addrlen)); 645 833 646 834 // trim the header … … 658 846 } 659 847 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) 848 int udp_release_and_return(packet_t packet, int result) 671 849 { 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; 850 pq_release_remote(udp_globals.net_phone, packet_get_id(packet)); 851 return result; 848 852 } 849 853 … … 878 882 879 883 /* 880 * End if told to either by the message or the processing 881 * result. 884 * End if said to either by the message or the processing result 882 885 */ 883 886 if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) || … … 892 895 /** Starts the module. 893 896 * 894 * @returns EOK on success. 895 * @returns Other error codes as defined for each specific module 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 896 903 * start function. 897 904 */ -
uspace/srv/net/tl/udp/udp.h
r49d819b4 re06ef614 28 28 29 29 /** @addtogroup udp 30 * @{30 * @{ 31 31 */ 32 32 33 33 /** @file 34 * UDP module.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 * @see udp_globals45 * @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 struct udp_globals { 51 /** Networking module phone. */ 49 /** UDP global data. 50 */ 51 struct udp_globals{ 52 /** Networking module phone. 53 */ 52 54 int net_phone; 53 /** IP module phone. */ 55 /** IP module phone. 56 */ 54 57 int ip_phone; 55 /** ICMP module phone. */ 58 /** ICMP module phone. 59 */ 56 60 int icmp_phone; 57 /** Packet dimension. */ 61 /** Packet dimension. 62 */ 58 63 packet_dimension_t packet_dimension; 59 /** Indicates whether UDP checksum computing is enabled. */ 64 /** Indicates whether UDP checksum computing is enabled. 65 */ 60 66 int checksum_computing; 61 /** Indicates whether UDP autobnding on send is enabled. */ 67 /** Indicates whether UDP autobnding on send is enabled. 68 */ 62 69 int autobinding; 63 /** Last used free port. */ 70 /** Last used free port. 71 */ 64 72 int last_used_port; 65 /** Active sockets. */ 73 /** Active sockets. 74 */ 66 75 socket_ports_t sockets; 67 /** Device packet dimensions. */ 76 /** Device packet dimensions. 77 */ 68 78 packet_dimensions_t dimensions; 69 /** Safety lock. */ 79 /** Safety lock. 80 */ 70 81 fibril_rwlock_t lock; 71 82 }; … … 75 86 /** @} 76 87 */ 88 -
uspace/srv/net/tl/udp/udp_header.h
r49d819b4 re06ef614 28 28 29 29 /** @addtogroup udp 30 * @{30 * @{ 31 31 */ 32 32 33 33 /** @file 34 * UDP header definition.35 * Based on the RFC768.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 #define UDP_HEADER_SIZE sizeof(udp_header_t) 43 /** UDP header size in bytes. 44 */ 45 #define UDP_HEADER_SIZE sizeof(udp_header_t) 45 46 46 47 /** Type definition of the user datagram header. 47 * @see udp_header48 * @see udp_header 48 49 */ 49 typedef struct udp_header 50 typedef struct udp_header udp_header_t; 50 51 51 52 /** Type definition of the user datagram header pointer. 52 * @see udp_header53 * @see udp_header 53 54 */ 54 typedef udp_header_t * udp_header_ref;55 typedef udp_header_t * udp_header_ref; 55 56 56 /** User datagram header. */ 57 struct udp_header { 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 */ 58 63 uint16_t source_port; 64 /** Destination port has a meaning within the context of a particular internet destination address. 65 */ 59 66 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 */ 60 70 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 */ 61 77 uint16_t checksum; 62 78 } __attribute__ ((packed)); -
uspace/srv/net/tl/udp/udp_module.c
r49d819b4 re06ef614 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 37 * points. 38 * @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 points. 37 * @see module.c 39 38 */ 40 41 #include "udp.h"42 #include "udp_module.h"43 39 44 40 #include <async.h> … … 50 46 #include <net/modules.h> 51 47 #include <net/packet.h> 52 53 48 #include <net_interface.h> 54 49 #include <tl_local.h> 55 50 56 /** UDP module global data. */ 57 extern udp_globals_t udp_globals; 51 #include "udp.h" 52 #include "udp_module.h" 58 53 59 int tl_module_start_standalone(async_client_conn_t client_connection) 60 { 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){ 61 66 ERROR_DECLARE; 62 67 … … 65 70 async_set_client_connection(client_connection); 66 71 udp_globals.net_phone = net_connect_module(); 67 if (udp_globals.net_phone < 0)72 if(udp_globals.net_phone < 0){ 68 73 return udp_globals.net_phone; 69 74 } 70 75 ERROR_PROPAGATE(pm_init()); 71 if (ERROR_OCCURRED(udp_initialize(client_connection)) ||72 ERROR_OCCURRED(REGISTER_ME(SERVICE_UDP, &phonehash))){76 if(ERROR_OCCURRED(udp_initialize(client_connection)) 77 || ERROR_OCCURRED(REGISTER_ME(SERVICE_UDP, &phonehash))){ 73 78 pm_destroy(); 74 79 return ERROR_CODE; … … 81 86 } 82 87 83 int 84 tl_module_message_standalone(ipc_callid_t callid, ipc_call_t *call, 85 ipc_call_t *answer, int *answer_count) 86 { 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){ 87 97 return udp_message_standalone(callid, call, answer, answer_count); 88 98 } -
uspace/srv/net/tl/udp/udp_module.h
r49d819b4 re06ef614 28 28 29 29 /** @addtogroup udp 30 * @{30 * @{ 31 31 */ 32 32 33 33 /** @file 34 * UDP module functions.35 * The functions are used as UDP module entry points.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 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 *); 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); 47 62 48 63 #endif
Note:
See TracChangeset
for help on using the changeset viewer.