Changes in / [49d819b4:e06ef614] in mainline


Ignore:
Files:
4 added
4 deleted
21 edited

Legend:

Unmodified
Added
Removed
  • boot/Makefile.common

    r49d819b4 re06ef614  
    106106        $(USPACE_PATH)/srv/net/tl/tcp/tcp \
    107107        $(USPACE_PATH)/srv/net/net/net \
     108        $(USPACE_PATH)/srv/net/netstart/netstart \
    108109        $(USPACE_PATH)/srv/devman/devman
    109110       
     
    134135        $(USPACE_PATH)/app/tetris/tetris \
    135136        $(USPACE_PATH)/app/trace/trace \
    136         $(USPACE_PATH)/app/netstart/netstart \
    137137        $(USPACE_PATH)/app/nettest1/nettest1 \
    138138        $(USPACE_PATH)/app/nettest2/nettest2 \
  • uspace/Makefile

    r49d819b4 re06ef614  
    5050        app/trace \
    5151        app/top \
    52         app/netstart \
    5352        app/netecho \
    5453        app/nettest1 \
     
    8786        srv/net/tl/tcp \
    8887        srv/net/net \
     88        srv/net/netstart \
    8989        drv/root
    9090
  • uspace/lib/c/include/ipc/services.h

    r49d819b4 re06ef614  
    3939
    4040typedef enum {
    41         SERVICE_NONE = 0,
    42         SERVICE_LOAD,
     41        SERVICE_LOAD = 1,
    4342        SERVICE_PCI,
    4443        SERVICE_VIDEO,
  • uspace/lib/net/include/tl_local.h

    r49d819b4 re06ef614  
    3737#include <async.h>
    3838
    39 /** Starts the TL module.
    40  *
    41  * Initializes the client connection serving function, initializes the module,
    42  * registers the module service and starts the async manager, processing IPC
    43  * messages in an infinite loop.
    44  *
    45  * @param[in] client_connection The client connection processing function. The
    46  *                      module skeleton propagates its own one.
    47  * @returns             EOK on successful module termination.
    48  * @returns             Other error codes as defined for the module initialize
    49  *                      function.
    50  * @returns             Other error codes as defined for the REGISTER_ME() macro
    51  *                      function.
    52  */
    5339extern int tl_module_message_standalone(ipc_callid_t, ipc_call_t *,
    5440    ipc_call_t *, int *);
    55 
    56 
    57 /** Processes the TL module message.
    58  *
    59  * @param[in] callid    The message identifier.
    60  * @param[in] call      The message parameters.
    61  * @param[out] answer   The message answer parameters.
    62  * @param[out] answer_count The last parameter for the actual answer in the
    63  *                      answer parameter.
    64  * @returns             EOK on success.
    65  * @returns             Other error codes as defined for the module's message
    66  *                      standalone function.
    67  */
    6841extern int tl_module_start_standalone(async_client_conn_t);
    6942
  • uspace/srv/net/net/net.c

    r49d819b4 re06ef614  
    3636 */
    3737
    38 #include "net.h"
    39 
    4038#include <async.h>
    4139#include <ctype.h>
     
    5452
    5553#include <net/modules.h>
    56 #include <net/packet.h>
    57 #include <net/device.h>
    58 
    5954#include <adt/char_map.h>
    6055#include <adt/generic_char_map.h>
    6156#include <adt/measured_strings.h>
    6257#include <adt/module_map.h>
    63 
     58#include <net/packet.h>
    6459#include <netif_remote.h>
     60#include <net/device.h>
    6561#include <nil_interface.h>
    6662#include <net_interface.h>
    6763#include <ip_interface.h>
    6864
    69 /** Networking module name. */
     65#include "net.h"
     66
     67/** Networking module name.
     68 *
     69 */
    7070#define NAME  "net"
    7171
    72 /** File read buffer size. */
     72/** File read buffer size.
     73 *
     74 */
    7375#define BUFFER_SIZE  256
    7476
    75 /** Networking module global data. */
     77/** Networking module global data.
     78 *
     79 */
    7680net_globals_t net_globals;
    7781
     
    96100        measured_string_ref setting =
    97101            measured_string_create_bulk(value, 0);
     102       
    98103        if (!setting)
    99104                return ENOMEM;
     
    201206        unsigned int line_number = 0;
    202207        size_t index = 0;
    203         while (!ferror(cfg) && !feof(cfg)) {
     208        while ((!ferror(cfg)) && (!feof(cfg))) {
    204209                int read = fgetc(cfg);
    205210                if ((read > 0) && (read != '\n') && (read != '\r')) {
     
    321326        ipcarg_t phonehash;
    322327       
    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))){
    325330                pm_destroy();
    326331                return ERROR_CODE;
     
    374379    size_t count, char **data)
    375380{
    376         if (!configuration || (count <= 0))
     381        if (!(configuration && (count > 0)))
    377382                return EINVAL;
    378383       
     
    477482        /* Inter-network layer startup */
    478483        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;
    485490        }
    486491       
     
    506511        ERROR_DECLARE;
    507512       
    508         const char *conf_files[] = {
    509                 "lo",
    510                 "ne2k"
    511         };
     513        const char *conf_files[] = {"lo", "ne2k"};
    512514        size_t count = sizeof(conf_files) / sizeof(char *);
    513515       
     
    601603        *answer_count = 0;
    602604        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();
    630632        }
    631633        return ENOTSUP;
     
    659661                int res = net_module_message(callid, &call, &answer, &answer_count);
    660662               
    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 */
    662664                if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) || (res == EHANGUP))
    663665                        return;
  • uspace/srv/net/net/net.h

    r49d819b4 re06ef614  
    3636 */
    3737
    38 #ifndef NET_NET_H_
    39 #define NET_NET_H_
     38#ifndef __NET_NET_H__
     39#define __NET_NET_H__
    4040
    4141#include <ipc/ipc.h>
  • uspace/srv/net/net/net_standalone.c

    r49d819b4 re06ef614  
    2828
    2929/** @addtogroup net
    30  * @{
     30 *  @{
    3131 */
    3232
    3333/** @file
    34  * Wrapper for the standalone networking module.
     34 *  Wrapper for the standalone networking module.
    3535 */
    3636
    37 #include "net.h"
     37#include <str.h>
    3838
    39 #include <str.h>
    40 #include <adt/measured_strings.h>
    41 #include <adt/module_map.h>
    4239#include <ipc/ipc.h>
    4340#include <ipc/net.h>
    4441
    4542#include <ip_interface.h>
     43#include <adt/measured_strings.h>
     44#include <adt/module_map.h>
    4645#include <packet_server.h>
    4746
    48 /** Networking module global data. */
     47#include "net.h"
     48
     49/** Networking module global data.
     50 */
    4951extern net_globals_t net_globals;
    5052
     
    5860 *
    5961 */
    60 int net_initialize_build(async_client_conn_t client_connection)
    61 {
     62int net_initialize_build(async_client_conn_t client_connection){
    6263        ERROR_DECLARE;
    6364       
  • uspace/srv/net/tl/icmp/icmp.c

    r49d819b4 re06ef614  
    2828
    2929/** @addtogroup icmp
    30  * @{
     30 *  @{
    3131 */
    3232
    3333/** @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 */
    4037
    4138#include <async.h>
     
    5956#include <net/ip_protocols.h>
    6057#include <net/inet.h>
     58
    6159#include <net/modules.h>
    62 #include <net/icmp_api.h>
    63 #include <net/icmp_codes.h>
    64 #include <net/icmp_common.h>
    65 
    6660#include <packet_client.h>
    6761#include <packet_remote.h>
    6862#include <net_checksum.h>
     63#include <net/icmp_api.h>
    6964#include <icmp_client.h>
     65#include <net/icmp_codes.h>
     66#include <net/icmp_common.h>
    7067#include <icmp_interface.h>
    7168#include <il_interface.h>
     
    7774#include <icmp_header.h>
    7875
    79 /** ICMP module name. */
     76#include "icmp.h"
     77#include "icmp_module.h"
     78
     79/** ICMP module name.
     80 */
    8081#define NAME    "ICMP protocol"
    8182
    82 /** Default ICMP error reporting. */
     83/** Default ICMP error reporting.
     84 */
    8385#define NET_DEFAULT_ICMP_ERROR_REPORTING        true
    8486
    85 /** Default ICMP echo replying. */
     87/** Default ICMP echo replying.
     88 */
    8689#define NET_DEFAULT_ICMP_ECHO_REPLYING          true
    8790
    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.
    9092 */
    9193#define ICMP_KEEP_LENGTH        8
    9294
    93 /** Free identifier numbers pool start. */
     95/** Free identifier numbers pool start.
     96 */
    9497#define ICMP_FREE_IDS_START     1
    9598
    96 /** Free identifier numbers pool end. */
     99/** Free identifier numbers pool end.
     100 */
    97101#define ICMP_FREE_IDS_END       UINT16_MAX
    98102
    99103/** 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."
    110113
    111114/** 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 */
     131int 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 */
     146int 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 */
     157int 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 */
     170int 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 */
     177int 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 */
     198int 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 */
     207icmp_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 */
     224int 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 */
     236int 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 */
     245int icmp_bind_free_id(icmp_echo_ref echo_data);
     246
     247/** ICMP global data.
     248 */
    122249icmp_globals_t  icmp_globals;
    123250
    124251INT_MAP_IMPLEMENT(icmp_replies, icmp_reply_t);
     252
    125253INT_MAP_IMPLEMENT(icmp_echo_data, icmp_echo_t);
    126254
    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 {
     255int 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
     276int 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){
    251277        ERROR_DECLARE;
    252278
     
    254280        packet_t packet;
    255281        size_t length;
    256         uint8_t *data;
     282        uint8_t * data;
    257283        icmp_reply_ref reply;
    258284        int reply_key;
     
    260286        int index;
    261287
    262         if (addrlen <= 0)
     288        if(addrlen <= 0){
    263289                return EINVAL;
    264 
     290        }
    265291        length = (size_t) addrlen;
    266292        // 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){
    275296                return ENOMEM;
     297        }
    276298
    277299        // prepare the requesting packet
    278300        // 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))){
    281302                return icmp_release_and_return(packet, ERROR_CODE);
    282303        }
    283 
    284304        // allocate space in the packet
    285305        data = (uint8_t *) packet_suffix(packet, size);
    286         if (!data)
     306        if(! data){
    287307                return icmp_release_and_return(packet, ENOMEM);
    288 
     308        }
    289309        // fill the data
    290310        length = 0;
    291         while (size > length + sizeof(ICMP_ECHO_TEXT)) {
     311        while(size > length + sizeof(ICMP_ECHO_TEXT)){
    292312                memcpy(data + length, ICMP_ECHO_TEXT, sizeof(ICMP_ECHO_TEXT));
    293313                length += sizeof(ICMP_ECHO_TEXT);
    294314        }
    295315        memcpy(data + length, ICMP_ECHO_TEXT, size - length);
    296 
    297316        // prefix the header
    298317        header = PACKET_PREFIX(packet, icmp_header_t);
    299         if (!header)
     318        if(! header){
    300319                return icmp_release_and_return(packet, ENOMEM);
    301 
     320        }
    302321        bzero(header, sizeof(*header));
    303322        header->un.echo.identifier = id;
     
    306325        // prepare the reply structure
    307326        reply = malloc(sizeof(*reply));
    308         if (!reply)
     327        if(! reply){
    309328                return icmp_release_and_return(packet, ENOMEM);
    310 
     329        }
    311330        fibril_mutex_initialize(&reply->mutex);
    312331        fibril_mutex_lock(&reply->mutex);
    313332        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);
    316334        index = icmp_replies_add(&icmp_globals.replies, reply_key, reply);
    317         if (index < 0) {
     335        if(index < 0){
    318336                free(reply);
    319337                return icmp_release_and_return(packet, index);
     
    324342
    325343        // 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);
    328345
    329346        // wait for the reply
    330347        // 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))){
    333349                result = ERROR_CODE;
    334         } else {
     350        }else{
    335351                // read the result
    336352                result = reply->result;
     
    343359        // destroy the reply structure
    344360        icmp_replies_exclude_index(&icmp_globals.replies, index);
    345 
    346361        return result;
    347362}
    348363
    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 {
     364int icmp_destination_unreachable_msg(int icmp_phone, icmp_code_t code, icmp_param_t mtu, packet_t packet){
    353365        icmp_header_ref header;
    354366
    355367        header = icmp_prepare_packet(packet);
    356         if (!header)
     368        if(! header){
    357369                return icmp_release_and_return(packet, ENOMEM);
    358 
    359         if (mtu)
     370        }
     371        if(mtu){
    360372                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
     377int icmp_source_quench_msg(int icmp_phone, packet_t packet){
    368378        icmp_header_ref header;
    369379
    370380        header = icmp_prepare_packet(packet);
    371         if (!header)
     381        if(! header){
    372382                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
     387int icmp_time_exceeded_msg(int icmp_phone, icmp_code_t code, packet_t packet){
    381388        icmp_header_ref header;
    382389
    383390        header = icmp_prepare_packet(packet);
    384         if (!header)
     391        if(! header){
    385392                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
     397int icmp_parameter_problem_msg(int icmp_phone, icmp_code_t code, icmp_param_t pointer, packet_t packet){
    395398        icmp_header_ref header;
    396399
    397400        header = icmp_prepare_packet(packet);
    398         if (!header)
     401        if(! header){
    399402                return icmp_release_and_return(packet, ENOMEM);
    400 
     403        }
    401404        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
     408icmp_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
     434int 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){
    415435        ERROR_DECLARE;
    416436
    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
     451int 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}};
    427455        measured_string_ref configuration;
    428456        size_t count = sizeof(names) / sizeof(measured_string_t);
    429         char *data;
     457        char * data;
    430458
    431459        fibril_rwlock_initialize(&icmp_globals.lock);
     
    433461        icmp_replies_initialize(&icmp_globals.replies);
    434462        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){
    438465                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));
    442468        icmp_globals.packet_dimension.prefix += ICMP_HEADER_SIZE;
    443469        icmp_globals.packet_dimension.content -= ICMP_HEADER_SIZE;
    444 
     470        // get configuration
    445471        icmp_globals.error_reporting = NET_DEFAULT_ICMP_ERROR_REPORTING;
    446472        icmp_globals.echo_replying = NET_DEFAULT_ICMP_ECHO_REPLYING;
    447 
    448         // get configuration
    449473        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');
    456478                }
    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');
    460481                }
    461482                net_free_settings(configuration, data);
    462483        }
    463 
    464484        fibril_rwlock_write_unlock(&icmp_globals.lock);
    465485        return EOK;
    466486}
    467487
    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 {
     488int icmp_received_msg(device_id_t device_id, packet_t packet, services_t receiver, services_t error){
    521489        ERROR_DECLARE;
    522490
     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
     498int icmp_process_packet(packet_t packet, services_t error){
     499        ERROR_DECLARE;
     500
    523501        size_t length;
    524         uint8_t *src;
     502        uint8_t * src;
    525503        int addrlen;
    526504        int result;
    527         void *data;
     505        void * data;
    528506        icmp_header_ref header;
    529507        icmp_type_t type;
    530508        icmp_code_t code;
    531509
    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        }
    549526        // get rid of the ip header
    550527        length = ip_client_header_length(packet);
     
    552529
    553530        length = packet_get_data_length(packet);
    554         if (length <= 0)
     531        if(length <= 0){
    555532                return EINVAL;
    556 
    557         if (length < ICMP_HEADER_SIZE)
     533        }
     534        if(length < ICMP_HEADER_SIZE){
    558535                return EINVAL;
    559 
     536        }
    560537        data = packet_get_data(packet);
    561         if (!data)
     538        if(! data){
    562539                return EINVAL;
    563 
     540        }
    564541        // get icmp header
    565542        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){
    569546                        // set the original message type on error notification
    570547                        // 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;
    576553                                }
    577554                        }
     
    579556                }
    580557        }
    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);
    594596                        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
     602int 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
     623int 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));
    610633                        }
    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
     643int icmp_process_client_messages(ipc_callid_t callid, ipc_call_t call){
    656644        ERROR_DECLARE;
    657645
    658         if (ERROR_OCCURRED(icmp_process_packet(packet, error)))
    659                 return icmp_release_and_return(packet, ERROR_CODE);
    660 
    661         return EOK;
    662 }
    663 
    664 /** Processes the generic client messages.
    665  *
    666  * @param[in] call      The message parameters.
    667  * @returns             EOK on success.
    668  * @returns             ENOTSUP if the message is not known.
    669  * @returns             Other error codes as defined for the packet_translate()
    670  *                      function.
    671  * @returns             Other error codes as defined for the
    672  *                      icmp_destination_unreachable_msg_local() function.
    673  * @returns             Other error codes as defined for the
    674  *                      icmp_source_quench_msg_local() function.
    675  * @returns             Other error codes as defined for the
    676  *                      icmp_time_exceeded_msg_local() function.
    677  * @returns             Other error codes as defined for the
    678  *                      icmp_parameter_problem_msg_local() function.
    679  *
    680  * @see icmp_interface.h
    681  */
    682 static int icmp_process_message(ipc_call_t *call)
    683 {
    684         ERROR_DECLARE;
    685 
    686         packet_t packet;
    687 
    688         switch (IPC_GET_METHOD(*call)) {
    689         case NET_ICMP_DEST_UNREACH:
    690                 if (ERROR_NONE(packet_translate_remote(icmp_globals.net_phone,
    691                     &packet, IPC_GET_PACKET(call)))) {
    692                         ERROR_CODE = icmp_destination_unreachable_msg_local(0,
    693                             ICMP_GET_CODE(call), ICMP_GET_MTU(call), packet);
    694                 }
    695                 return ERROR_CODE;
    696         case NET_ICMP_SOURCE_QUENCH:
    697                 if (ERROR_NONE(packet_translate_remote(icmp_globals.net_phone,
    698                     &packet, IPC_GET_PACKET(call)))) {
    699                         ERROR_CODE = icmp_source_quench_msg_local(0, packet);
    700                 }
    701                 return ERROR_CODE;
    702         case NET_ICMP_TIME_EXCEEDED:
    703                 if (ERROR_NONE(packet_translate_remote(icmp_globals.net_phone,
    704                     &packet, IPC_GET_PACKET(call)))) {
    705                         ERROR_CODE = icmp_time_exceeded_msg_local(0,
    706                             ICMP_GET_CODE(call), packet);
    707                 }
    708                 return ERROR_CODE;
    709         case NET_ICMP_PARAMETERPROB:
    710                 if (ERROR_NONE(packet_translate_remote(icmp_globals.net_phone,
    711                     &packet, IPC_GET_PACKET(call)))) {
    712                         ERROR_CODE = icmp_parameter_problem_msg_local(0,
    713                             ICMP_GET_CODE(call), ICMP_GET_POINTER(call),
    714                             packet);
    715                 }
    716                 return ERROR_CODE;
    717         default:
    718                 return ENOTSUP;
    719         }
    720 }
    721 
    722 /** Assigns a new identifier for the connection.
    723  *
    724  * Fills the echo data parameter with the assigned values.
    725  *
    726  * @param[in,out] echo_data The echo data to be bound.
    727  * @returns             Index of the inserted echo data.
    728  * @returns             EBADMEM if the echo_data parameter is NULL.
    729  * @returns             ENOTCONN if no free identifier have been found.
    730  */
    731 static int icmp_bind_free_id(icmp_echo_ref echo_data)
    732 {
    733         icmp_param_t index;
    734 
    735         if (!echo_data)
    736                 return EBADMEM;
    737 
    738         // from the last used one
    739         index = icmp_globals.last_used_id;
    740         do {
    741                 index++;
    742                 // til the range end
    743                 if (index >= ICMP_FREE_IDS_END) {
    744                         // start from the range beginning
    745                         index = ICMP_FREE_IDS_START - 1;
    746                         do {
    747                                 index++;
    748                                 // til the last used one
    749                                 if (index >= icmp_globals.last_used_id) {
    750                                         // none found
    751                                         return ENOTCONN;
    752                                 }
    753                         } while(icmp_echo_data_find(&icmp_globals.echo_data,
    754                             index) != NULL);
    755 
    756                         // found, break immediately
    757                         break;
    758                 }
    759         } while(icmp_echo_data_find(&icmp_globals.echo_data, index) != NULL);
    760 
    761         echo_data->identifier = index;
    762         echo_data->sequence_number = 0;
    763 
    764         return icmp_echo_data_add(&icmp_globals.echo_data, index, echo_data);
    765 }
    766 
    767 /** Processes the client messages.
    768  *
    769  * Remembers the assigned identifier and sequence numbers.
    770  * Runs until the client module disconnects.
    771  *
    772  * @param[in] callid    The message identifier.
    773  * @param[in] call      The message parameters.
    774  * @returns EOK.
    775  *
    776  * @see icmp_interface.h
    777  * @see icmp_api.h
    778  */
    779 static int icmp_process_client_messages(ipc_callid_t callid, ipc_call_t call)
    780 {
    781         ERROR_DECLARE;
    782 
    783646        bool keep_on_going = true;
     647//      fibril_rwlock_t                 lock;
    784648        ipc_call_t answer;
    785649        int answer_count;
    786650        size_t length;
    787         struct sockaddr *addr;
     651        struct sockaddr * addr;
    788652        ipc_callid_t data_callid;
    789653        icmp_echo_ref echo_data;
     
    797661        answer_count = 0;
    798662
     663//      fibril_rwlock_initialize(&lock);
     664
    799665        echo_data = (icmp_echo_ref) malloc(sizeof(*echo_data));
    800         if (!echo_data)
     666        if(! echo_data){
    801667                return ENOMEM;
     668        }
    802669
    803670        // assign a new identifier
     
    805672        res = icmp_bind_free_id(echo_data);
    806673        fibril_rwlock_write_unlock(&icmp_globals.lock);
    807         if (res < 0) {
     674        if(res < 0){
    808675                free(echo_data);
    809676                return res;
    810677        }
    811678
    812         while (keep_on_going) {
     679        while(keep_on_going){
     680
    813681                // answer the call
    814682                answer_call(callid, res, &answer, answer_count);
     
    821689
    822690                // 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;
    832695                                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);
    838721                                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);
    867724                }
    868 
    869725        }
    870726
     
    873729        icmp_echo_data_exclude(&icmp_globals.echo_data, echo_data->identifier);
    874730        fibril_rwlock_write_unlock(&icmp_globals.lock);
    875 
    876731        return res;
    877732}
    878733
    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 {
     734int icmp_process_message(ipc_call_t * call){
    896735        ERROR_DECLARE;
    897736
    898737        packet_t packet;
    899738
    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
     765int 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
     770int 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;
    908794                }
    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}
    921800
    922801/** Default thread for new connections.
    923802 *
    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.
    926805 *
    927806 */
    928 static void tl_client_connection(ipc_callid_t iid, ipc_call_t *icall)
     807static void tl_client_connection(ipc_callid_t iid, ipc_call_t * icall)
    929808{
    930809        /*
     
    934813        ipc_answer_0(iid, EOK);
    935814       
    936         while (true) {
     815        while(true) {
    937816                ipc_call_t answer;
    938817                int answer_count;
     
    949828                    &answer_count);
    950829               
    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))
    957832                        return;
    958833               
     
    964839/** Starts the module.
    965840 *
    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 *
    969847 */
    970848int main(int argc, char *argv[])
     
    973851       
    974852        /* 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       
    976856        return EOK;
    977857}
     
    979859/** @}
    980860 */
    981 
  • uspace/srv/net/tl/icmp/icmp.h

    r49d819b4 re06ef614  
    2828
    2929/** @addtogroup icmp
    30  * @{
     30 *  @{
    3131 */
    3232
    3333/** @file
    34  * ICMP module.
     34 *  ICMP module.
    3535 */
    3636
    37 #ifndef NET_ICMP_H_
    38 #define NET_ICMP_H_
     37#ifndef __NET_ICMP_H__
     38#define __NET_ICMP_H__
    3939
    4040#include <fibril_synch.h>
    4141
    4242#include <net/icmp_codes.h>
    43 #include <net/packet.h>
    4443#include <adt/int_map.h>
    4544#include <icmp_header.h>
    4645
    4746/** Type definition of the ICMP reply data.
    48  * @see icmp_reply
     47 *  @see icmp_reply
    4948 */
    50 typedef struct icmp_reply icmp_reply_t;
     49typedef struct icmp_reply       icmp_reply_t;
    5150
    5251/** Type definition of the ICMP reply data pointer.
    53  * @see icmp_reply
     52 *  @see icmp_reply
    5453 */
    55 typedef icmp_reply_t *icmp_reply_ref;
     54typedef icmp_reply_t *  icmp_reply_ref;
    5655
    5756/** Type definition of the ICMP global data.
    58  * @see icmp_globals
     57 *  @see icmp_globals
    5958 */
    60 typedef struct icmp_globals icmp_globals_t;
     59typedef struct icmp_globals     icmp_globals_t;
    6160
    6261/** 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.
    6865 */
    6966INT_MAP_DECLARE(icmp_replies, icmp_reply_t);
    7067
    7168/** 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.
    7570 */
    7671INT_MAP_DECLARE(icmp_echo_data, icmp_echo_t);
    7772
    78 /** ICMP reply data. */
    79 struct icmp_reply {
    80         /** Reply result. */
     73/** ICMP reply data.
     74 */
     75struct icmp_reply{
     76        /** Reply result.
     77         */
    8178        int result;
    82         /** Safety lock. */
     79        /** Safety lock.
     80         */
    8381        fibril_mutex_t mutex;
    84         /** Received or timeouted reply signaling. */
     82        /** Received or timeouted reply signaling.
     83         */
    8584        fibril_condvar_t condvar;
    8685};
    8786
    88 /** ICMP global data. */
    89 struct icmp_globals {
    90         /** IP module phone. */
     87/** ICMP global data.
     88 */
     89struct  icmp_globals{
     90        /** IP module phone.
     91         */
    9192        int ip_phone;
    92         /** Packet dimension. */
     93        /** Packet dimension.
     94         */
    9395        packet_dimension_t packet_dimension;
    94         /** Networking module phone. */
     96        /** Networking module phone.
     97         */
    9598        int net_phone;
    96         /** Indicates whether ICMP error reporting is enabled. */
     99        /** Indicates whether ICMP error reporting is enabled.
     100         */
    97101        int error_reporting;
    98         /** Indicates whether ICMP echo replying (ping) is enabled. */
     102        /** Indicates whether ICMP echo replying (ping) is enabled.
     103         */
    99104        int echo_replying;
    100         /** The last used identifier number. */
     105        /** The last used identifier number.
     106         */
    101107        icmp_param_t last_used_id;
    102         /** The budled modules assigned echo specific data. */
     108        /** The budled modules assigned echo specific data.
     109         */
    103110        icmp_echo_data_t echo_data;
    104         /** Echo timeout locks. */
     111        /** Echo timeout locks.
     112         */
    105113        icmp_replies_t replies;
    106         /** Safety lock. */
     114        /** Safety lock.
     115         */
    107116        fibril_rwlock_t lock;
    108117};
     
    112121/** @}
    113122 */
     123
  • uspace/srv/net/tl/icmp/icmp_module.c

    r49d819b4 re06ef614  
    2828
    2929/** @addtogroup icmp
    30  * @{
     30 *  @{
    3131 */
    3232
    3333/** @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.c
     34 *  ICMP standalone module implementation.
     35 *  Contains skeleton module functions mapping.
     36 *  The functions are used by the module skeleton as module specific entry points.
     37 *  @see module.c
    3838 */
    39 
    40 #include "icmp.h"
    41 #include "icmp_module.h"
    4239
    4340#include <async.h>
     
    5047#include <net/packet.h>
    5148#include <net_interface.h>
    52 
    5349#include <tl_local.h>
    5450
    55 /** ICMP module global data. */
    56 extern icmp_globals_t icmp_globals;
     51#include "icmp.h"
     52#include "icmp_module.h"
    5753
    58 int tl_module_start_standalone(async_client_conn_t client_connection)
    59 {
     54/** ICMP module global data.
     55 */
     56extern 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 */
     65int tl_module_start_standalone(async_client_conn_t client_connection){
    6066        ERROR_DECLARE;
    6167
     
    6470        async_set_client_connection(client_connection);
    6571        icmp_globals.net_phone = net_connect_module();
    66         if (icmp_globals.net_phone < 0)
     72        if(icmp_globals.net_phone < 0){
    6773                return icmp_globals.net_phone;
    68 
     74        }
    6975        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))){
    7278                pm_destroy();
    7379                return ERROR_CODE;
     
    8086}
    8187
    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 */
     96int tl_module_message_standalone(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count){
    8697        return icmp_message_standalone(callid, call, answer, answer_count);
    8798}
     
    89100/** @}
    90101 */
    91 
  • uspace/srv/net/tl/icmp/icmp_module.h

    r49d819b4 re06ef614  
    2828
    2929/** @addtogroup icmp
    30  * @{
     30 *  @{
    3131 */
    3232
    3333/** @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.
    3636 */
    3737
    38 #ifndef NET_ICMP_MODULE_H_
    39 #define NET_ICMP_MODULE_H_
     38#ifndef __NET_ICMP_MODULE_H__
     39#define __NET_ICMP_MODULE_H__
    4040
    4141#include <async.h>
    4242#include <ipc/ipc.h>
    4343
    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 */
     49int 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 */
     61int icmp_message_standalone(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count);
    4762
    4863#endif
  • uspace/srv/net/tl/tcp/tcp.c

    r49d819b4 re06ef614  
    2828
    2929/** @addtogroup tcp
    30  * @{
     30 *  @{
    3131 */
    3232
    3333/** @file
    34  * TCP module implementation.
    35  * @see tcp.h
     34 *  TCP module implementation.
     35 *  @see tcp.h
    3636 */
    37 
    38 #include "tcp.h"
    39 #include "tcp_header.h"
    40 #include "tcp_module.h"
    4137
    4238#include <assert.h>
     
    7672#include <tl_interface.h>
    7773
     74#include "tcp.h"
     75#include "tcp_header.h"
     76#include "tcp_module.h"
     77
    7878/** TCP module name. */
    7979#define NAME    "TCP protocol"
     
    110110
    111111/** Returns a value indicating whether the value is in the interval respecting
    112  * the possible overflow.
     112 *  the possible overflow.
    113113 *
    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.
    119118 */
    120119#define IS_IN_INTERVAL_OVERFLOW(lower, value, higher_equal) \
     
    166165};
    167166
    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 */
     172int tcp_release_and_return(packet_t packet, int result);
     173
     174void tcp_prepare_operation_header(socket_core_ref socket,
     175    tcp_socket_data_ref socket_data, tcp_header_ref header, int synchronize,
     176    int finalize);
     177int 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);
     181void tcp_free_socket_data(socket_core_ref socket);
     182
     183int tcp_timeout(void *data);
     184
     185int tcp_release_after_timeout(void *data);
     186
     187int tcp_process_packet(device_id_t device_id, packet_t packet,
     188    services_t error);
     189int tcp_connect_core(socket_core_ref socket, socket_cores_ref local_sockets,
     190    struct sockaddr *addr, socklen_t addrlen);
     191int tcp_queue_prepare_packet(socket_core_ref socket,
     192    tcp_socket_data_ref socket_data, packet_t packet, size_t data_length);
     193int tcp_queue_packet(socket_core_ref socket, tcp_socket_data_ref socket_data,
     194    packet_t packet, size_t data_length);
     195packet_t tcp_get_packets_to_send(socket_core_ref socket,
     196    tcp_socket_data_ref socket_data);
     197void tcp_send_packets(device_id_t device_id, packet_t packet);
     198
     199void tcp_process_acknowledgement(socket_core_ref socket,
     200    tcp_socket_data_ref socket_data, tcp_header_ref header);
     201packet_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);
     204packet_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);
     207void tcp_retransmit_packet(socket_core_ref socket,
     208    tcp_socket_data_ref socket_data, size_t sequence_number);
     209int tcp_create_notification_packet(packet_t * packet, socket_core_ref socket,
     210    tcp_socket_data_ref socket_data, int synchronize, int finalize);
     211void tcp_refresh_socket_data(tcp_socket_data_ref socket_data);
     212
     213void tcp_initialize_socket_data(tcp_socket_data_ref socket_data);
     214
     215int 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);
     219int tcp_process_syn_sent(socket_core_ref socket,
     220    tcp_socket_data_ref socket_data, tcp_header_ref header, packet_t packet);
     221int tcp_process_syn_received(socket_core_ref socket,
     222    tcp_socket_data_ref socket_data, tcp_header_ref header, packet_t packet);
     223int 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);
     226int 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
     230int tcp_received_msg(device_id_t device_id, packet_t packet,
     231    services_t receiver, services_t error);
     232int tcp_process_client_messages(ipc_callid_t callid, ipc_call_t call);
     233
     234int tcp_listen_message(socket_cores_ref local_sockets, int socket_id,
     235    int backlog);
     236int tcp_connect_message(socket_cores_ref local_sockets, int socket_id,
     237    struct sockaddr *addr, socklen_t addrlen);
     238int tcp_recvfrom_message(socket_cores_ref local_sockets, int socket_id,
     239    int flags, size_t * addrlen);
     240int tcp_send_message(socket_cores_ref local_sockets, int socket_id,
     241    int fragments, size_t * data_fragment_size, int flags);
     242int tcp_accept_message(socket_cores_ref local_sockets, int socket_id,
     243    int new_socket_id, size_t * data_fragment_size, size_t * addrlen);
     244int tcp_close_message(socket_cores_ref local_sockets, int socket_id);
    224245
    225246/** TCP global data. */
    226247tcp_globals_t tcp_globals;
    227248
    228 /** Initializes the TCP module.
    229  *
    230  * @param[in] client_connection The client connection processing function. The
    231  *                      module skeleton propagates its own one.
    232  * @returns             EOK on success.
    233  * @returns             ENOMEM if there is not enough memory left.
    234  */
    235249int tcp_initialize(async_client_conn_t client_connection)
    236250{
     
    300314        size_t addrlen;
    301315
    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                }
    318335        }
    319336
     
    362379                    ntohs(header->destination_port), SOCKET_MAP_KEY_LISTENING,
    363380                    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        }
    374391        printf("socket id %d\n", socket->socket_id);
    375392        socket_data = (tcp_socket_data_ref) socket->specific_data;
     
    385402        total_length = 0;
    386403        do {
    387                 fragments++;
     404                ++fragments;
    388405                length = packet_get_data_length(next_packet);
    389406                if (length <= 0)
     
    404421
    405422        if (error)
    406                 goto has_error_service;
     423                goto error;
    407424       
    408425        if (socket_data->state == TCP_SOCKET_LISTEN) {
     426
    409427                if (socket_data->pseudo_header) {
    410428                        free(socket_data->pseudo_header);
     
    446464        }
    447465
    448 has_error_service:
     466error:
    449467        fibril_rwlock_read_unlock(&tcp_globals.lock);
    450468
     
    489507int
    490508tcp_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)
    492511{
    493512        ERROR_DECLARE;
     
    665684                                        continue;
    666685                                        // 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)) {
    670689                                        if (socket_data->next_incoming <
    671690                                            new_sequence_number) {
     
    942961        listening_socket = socket_port_find(&tcp_globals.sockets,
    943962            listening_port, SOCKET_MAP_KEY_LISTENING, 0);
    944         if (!listening_socket ||
     963        if ((!listening_socket) ||
    945964            (listening_socket->socket_id != listening_socket_id)) {
    946965                fibril_rwlock_write_unlock(&tcp_globals.lock);
     
    11721191        if (number == socket_data->expected) {
    11731192                // increase the counter
    1174                 socket_data->expected_count++;
     1193                ++socket_data->expected_count;
    11751194                if (socket_data->expected_count == TCP_FAST_RETRANSMIT_COUNT) {
    11761195                        socket_data->expected_count = 1;
     
    11811200}
    11821201
    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)
     1202int tcp_message_standalone(ipc_callid_t callid, ipc_call_t * call,
     1203    ipc_call_t * answer, int *answer_count)
    11991204{
    12001205        ERROR_DECLARE;
     
    15161521        socket = socket_port_find(&tcp_globals.sockets, timeout->port,
    15171522            timeout->key, timeout->key_length);
    1518         if (!socket || (socket->socket_id != timeout->socket_id))
     1523        if (!(socket && (socket->socket_id == timeout->socket_id)))
    15191524                goto out;
    15201525       
     
    15271532        if (timeout->sequence_number) {
    15281533                // increase the timeout counter;
    1529                 socket_data->timeout_count++;
     1534                ++socket_data->timeout_count;
    15301535                if (socket_data->timeout_count == TCP_MAX_TIMEOUTS) {
    15311536                        // TODO release as connection lost
     
    17391744            ERROR_OCCURRED(tcp_prepare_timeout(tcp_timeout, socket, socket_data,
    17401745            0, TCP_SOCKET_INITIAL, NET_DEFAULT_TCP_INITIAL_TIMEOUT, false))) {
     1746
    17411747                socket_data->addr = NULL;
    17421748                socket_data->addrlen = 0;
    17431749                fibril_rwlock_write_lock(&tcp_globals.lock);
     1750
    17441751        } else {
     1752
    17451753                packet = tcp_get_packets_to_send(socket, socket_data);
    17461754                if (packet) {
     
    18681876                packet = pq_next(packet);
    18691877                // overflow occurred ?
    1870                 if (!packet &&
     1878                if ((!packet) &&
    18711879                    (socket_data->last_outgoing > socket_data->next_outgoing)) {
    18721880                        printf("gpts overflow\n");
     
    20362044int
    20372045tcp_recvfrom_message(socket_cores_ref local_sockets, int socket_id, int flags,
    2038     size_t *addrlen)
     2046    size_t * addrlen)
    20392047{
    20402048        ERROR_DECLARE;
     
    20912099int
    20922100tcp_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)
    20942102{
    20952103        ERROR_DECLARE;
     
    21302138            packet_dimension->content : socket_data->data_fragment_size);
    21312139
    2132         for (index = 0; index < fragments; index++) {
     2140        for (index = 0; index < fragments; ++index) {
    21332141                // read the data fragment
    21342142                result = tl_socket_read_packet_data(tcp_globals.net_phone,
     
    22272235
    22282236int
    2229 tcp_create_notification_packet(packet_t *packet, socket_core_ref socket,
     2237tcp_create_notification_packet(packet_t * packet, socket_core_ref socket,
    22302238    tcp_socket_data_ref socket_data, int synchronize, int finalize)
    22312239{
     
    22632271int
    22642272tcp_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)
    22662274{
    22672275        ERROR_DECLARE;
     
    23652373}
    23662374
    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  */
    23732375int tcp_release_and_return(packet_t packet, int result)
    23742376{
     
    23792381/** Default thread for new connections.
    23802382 *
    2381  * @param[in] iid       The initial message identifier.
    2382  * @param[in] icall     The initial message call structure.
     2383 *  @param[in] iid The initial message identifier.
     2384 *  @param[in] icall The initial message call structure.
    23832385 *
    23842386 */
     
    23952397                int answer_count;
    23962398
    2397                 /* Clear the answer structure */
     2399                /*
     2400                   Clear the answer structure
     2401                 */
    23982402                refresh_answer(&answer, &answer_count);
    23992403
    2400                 /* Fetch the next message */
     2404                /*
     2405                   Fetch the next message
     2406                 */
    24012407                ipc_call_t call;
    24022408                ipc_callid_t callid = async_get_call(&call);
    24032409
    2404                 /* Process the message */
     2410                /*
     2411                   Process the message
     2412                 */
    24052413                int res = tl_module_message_standalone(callid, &call, &answer,
    24062414                    &answer_count);
    24072415
    24082416                /*
    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
    24112418                 */
    24122419                if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) ||
     
    24232430/** Starts the module.
    24242431 *
    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 *
    24282438 */
    24292439int
  • uspace/srv/net/tl/tcp/tcp.h

    r49d819b4 re06ef614  
    2828
    2929/** @addtogroup tcp
    30  * @{
     30 *  @{
    3131 */
    3232
    3333/** @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__
    3939
    4040#include <fibril_synch.h>
     
    4646
    4747/** Type definition of the TCP global data.
    48  * @see tcp_globals
    49  */
    50 typedef struct tcp_globals tcp_globals_t;
     48 *  @see tcp_globals
     49 */
     50typedef struct tcp_globals      tcp_globals_t;
    5151
    5252/** Type definition of the TCP socket specific data.
    53  * @see tcp_socket_data
    54  */
    55 typedef struct tcp_socket_data tcp_socket_data_t;
     53 *  @see tcp_socket_data
     54 */
     55typedef struct tcp_socket_data  tcp_socket_data_t;
    5656
    5757/** Type definition of the TCP socket specific data pointer.
    58  * @see tcp_socket_data
    59  */
    60 typedef tcp_socket_data_t *tcp_socket_data_ref;
     58 *  @see tcp_socket_data
     59 */
     60typedef tcp_socket_data_t *     tcp_socket_data_ref;
    6161
    6262/** Type definition of the TCP operation data.
    63  * @see tcp_operation
    64  */
    65 typedef struct tcp_operation tcp_operation_t;
     63 *  @see tcp_operation
     64 */
     65typedef struct tcp_operation    tcp_operation_t;
    6666
    6767/** Type definition of the TCP operation data pointer.
    68  * @see tcp_operation
    69  */
    70 typedef tcp_operation_t *tcp_operation_ref;
     68 *  @see tcp_operation
     69 */
     70typedef tcp_operation_t *       tcp_operation_ref;
    7171
    7272/** 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 */
     75typedef enum tcp_socket_state   tcp_socket_state_t;
     76
     77/** TCP socket state.
     78 */
     79enum tcp_socket_state{
    7980        /** Initial.
    80          *
    81          * Not connected or bound.
     81         *  Not connected or bound.
    8282         */
    8383        TCP_SOCKET_INITIAL,
    84        
    8584        /** 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.
    9087         */
    9188        TCP_SOCKET_LISTEN,
    92        
    9389        /** 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.
    9792         */
    9893        TCP_SOCKET_SYN_SENT,
    99        
    10094        /** 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.
    10497         */
    10598        TCP_SOCKET_SYN_RECEIVED,
    106        
    10799        /** Connected.
    108          *
    109          * The three-way handshake has been completed.
     100         *  The three-way handshake has been completed.
    110101         */
    111102        TCP_SOCKET_ESTABLISHED,
    112        
    113103        /** 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.
    121108         */
    122109        TCP_SOCKET_FIN_WAIT_1,
    123        
    124110        /** 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.
    129114         */
    130115        TCP_SOCKET_FIN_WAIT_2,
    131        
    132116        /** 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.
    138120         */
    139121        TCP_SOCKET_CLOSING,
    140        
    141122        /** 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.
    147126         */
    148127        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.
    154132         */
    155133        TCP_SOCKET_LAST_ACK,
    156        
    157134        /** 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.
    161136         */
    162137        TCP_SOCKET_TIME_WAIT,
    163        
    164138        /** 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.
    168140         */
    169141        TCP_SOCKET_CLOSED
    170142};
    171143
    172 /** TCP operation data. */
    173 struct tcp_operation {
    174         /** Operation result. */
     144/** TCP operation data.
     145 */
     146struct tcp_operation{
     147        /** Operation result.
     148         */
    175149        int result;
    176         /** Safety lock. */
     150        /** Safety lock.
     151         */
    177152        fibril_mutex_t mutex;
    178         /** Operation result signaling. */
     153        /** Operation result signaling.
     154         */
    179155        fibril_condvar_t condvar;
    180156};
    181157
    182 /** TCP socket specific data. */
    183 struct tcp_socket_data {
    184         /** TCP socket state. */
     158/** TCP socket specific data.
     159 */
     160struct tcp_socket_data{
     161        /** TCP socket state.
     162         */
    185163        tcp_socket_state_t state;
    186        
    187         /**
    188          * Data fragment size.
    189          * Sending optimalization.
     164        /** Data fragment size.
     165         *  Sending optimalization.
    190166         */
    191167        size_t data_fragment_size;
    192        
    193         /** Device identifier. */
     168        /** Device identifier.
     169        */
    194170        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.
    199173         */
    200174        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.
    208180         */
    209181        int listening_socket_id;
    210        
    211         /** Treshold size in bytes. */
     182        /** Treshold size in bytes.
     183        */
    212184        size_t treshold;
    213         /** Window size in bytes. */
     185        /** Window size in bytes.
     186         */
    214187        size_t window;
    215         /** Acknowledgement timeout. */
     188        /** Acknowledgement timeout.
     189         */
    216190        suseconds_t timeout;
    217         /** Last acknowledged byte. */
     191        /** Last acknowledged byte.
     192         */
    218193        uint32_t acknowledged;
    219         /** Next incoming sequence number. */
     194        /** Next incoming sequence number.
     195         */
    220196        uint32_t next_incoming;
    221         /** Incoming FIN. */
     197        /** Incoming FIN.
     198         */
    222199        uint32_t fin_incoming;
    223         /** Next outgoing sequence number. */
     200        /** Next outgoing sequence number.
     201         */
    224202        uint32_t next_outgoing;
    225         /** Last outgoing sequence number. */
     203        /** Last outgoing sequence number.
     204         */
    226205        uint32_t last_outgoing;
    227         /** Outgoing FIN. */
     206        /** Outgoing FIN.
     207         */
    228208        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.
    234212         */
    235213        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.
    241216         */
    242217        int expected_count;
    243        
    244218        /** 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.
    250223         */
    251224        packet_t incoming;
    252        
    253225        /** 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.
    260230         */
    261231        packet_t outgoing;
    262        
    263         /** IP pseudo header. */
     232        /** IP pseudo header.
     233        */
    264234        void *pseudo_header;
    265         /** IP pseudo header length. */
     235        /** IP pseudo header length.
     236         */
    266237        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         */
    270243        socklen_t addrlen;
    271         /** Remote host port. */
     244        /** Remote host port.
     245         */
    272246        uint16_t dest_port;
    273         /** Parent local sockets. */
     247        /** Parent local sockets.
     248         */
    274249        socket_cores_ref local_sockets;
    275        
    276250        /** 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         */
    288260        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.
    293263         */
    294264        int timeout_count;
    295265};
    296266
    297 /** TCP global data. */
    298 struct tcp_globals {
    299         /** Networking module phone. */
     267/** TCP global data.
     268 */
     269struct  tcp_globals{
     270        /** Networking module phone.
     271         */
    300272        int net_phone;
    301         /** IP module phone. */
     273        /** IP module phone.
     274         */
    302275        int ip_phone;
    303         /** ICMP module phone. */
     276        /** ICMP module phone.
     277         */
    304278        int icmp_phone;
    305         /** Last used free port. */
     279        /** Last used free port.
     280         */
    306281        int last_used_port;
    307         /** Active sockets. */
     282        /** Active sockets.
     283         */
    308284        socket_ports_t sockets;
    309         /** Device packet dimensions. */
     285        /** Device packet dimensions.
     286         */
    310287        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.
    315290         */
    316291        fibril_rwlock_t lock;
     
    321296/** @}
    322297 */
     298
  • uspace/srv/net/tl/tcp/tcp_header.h

    r49d819b4 re06ef614  
    2828
    2929/** @addtogroup tcp
    30  * @{
     30 *  @{
    3131 */
    3232
    3333/** @file
    34  * TCP header definition.
    35  * Based on the RFC 793.
    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__
    4040
    4141#include <sys/types.h>
    4242
    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)
    4546
    4647/** 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 * 4U)
     48 *  @param[in] header The TCP packet header.
     49 */
     50#define TCP_HEADER_LENGTH(header)               ((header)->header_length * 4u)
    5051
    5152/** 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))
    5556
    5657/** Type definition of the transmission datagram header.
    57  * @see tcp_header
    58  */
    59 typedef struct tcp_header tcp_header_t;
     58 *  @see tcp_header
     59 */
     60typedef struct tcp_header       tcp_header_t;
    6061
    6162/** Type definition of the transmission datagram header pointer.
    62  * @see tcp_header
    63  */
    64 typedef tcp_header_t *tcp_header_ref;
     63 *  @see tcp_header
     64 */
     65typedef tcp_header_t *          tcp_header_ref;
    6566
    6667/** Type definition of the transmission datagram header option.
    67  * @see tcp_option
    68  */
    69 typedef struct tcp_option tcp_option_t;
     68 *  @see tcp_option
     69 */
     70typedef struct tcp_option       tcp_option_t;
    7071
    7172/** 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 */
     75typedef tcp_option_t *          tcp_option_ref;
     76
     77/** Type definition of the Maximum segment size TCP option.
     78 *  @see ...
     79 */
     80typedef struct tcp_max_segment_size_option      tcp_max_segment_size_option_t;
    7881
    7982/** 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 */
     85typedef tcp_max_segment_size_option_t *         tcp_max_segment_size_option_ref;
     86
     87/** Transmission datagram header.
     88 */
     89struct tcp_header{
     90        /** The source port number.
     91         */
    8692        uint16_t source_port;
     93        /** The destination port number.
     94         */
    8795        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         */
    8899        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         */
    89104        uint32_t acknowledgement_number;
    90        
    91105#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         */
    92110        uint8_t header_length:4;
     111        /** Four bits reserved for future use.
     112         *  Must be zero.
     113         */
    93114        uint8_t reserved1:4;
    94115#else
     116        /** Four bits reserved for future use.
     117         *  Must be zero.
     118         */
    95119        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         */
    96124        uint8_t header_length:4;
    97125#endif
    98 
    99126#ifdef ARCH_IS_BIG_ENDIAN
     127        /** Two bits reserved for future use.
     128         *  Must be zero.
     129         */
    100130        uint8_t reserved2:2;
     131        /** Urgent Pointer field significant.
     132         *  @see tcp_header:urgent_pointer
     133         */
    101134        uint8_t urgent:1;
     135        /** Acknowledgment field significant
     136         *  @see tcp_header:acknowledgement_number
     137         */
    102138        uint8_t acknowledge:1;
     139        /** Push function.
     140         */
    103141        uint8_t push:1;
     142        /** Reset the connection.
     143         */
    104144        uint8_t reset:1;
     145        /** Synchronize the sequence numbers.
     146         */
    105147        uint8_t synchronize:1;
     148        /** No more data from the sender.
     149         */
    106150        uint8_t finalize:1;
    107151#else
     152        /** No more data from the sender.
     153         */
    108154        uint8_t finalize:1;
     155        /** Synchronize the sequence numbers.
     156         */
    109157        uint8_t synchronize:1;
     158        /** Reset the connection.
     159         */
    110160        uint8_t reset:1;
     161        /** Push function.
     162         */
    111163        uint8_t push:1;
     164        /** Acknowledgment field significant.
     165         *  @see tcp_header:acknowledgement_number
     166         */
    112167        uint8_t acknowledge:1;
     168        /** Urgent Pointer field significant.
     169         *  @see tcp_header:urgent_pointer
     170         */
    113171        uint8_t urgent:1;
     172        /** Two bits reserved for future use.
     173         *  Must be zero.
     174         */
    114175        uint8_t reserved2:2;
    115176#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         */
    117180        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         */
    118190        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         */
    119196        uint16_t urgent_pointer;
    120197} __attribute__ ((packed));
    121198
    122 /** Transmission datagram header option. */
    123 struct tcp_option {
    124         /** Option type. */
     199/** Transmission datagram header option.
     200 */
     201struct tcp_option{
     202        /** Option type.
     203         */
    125204        uint8_t type;
    126         /** Option length. */
     205        /** Option length.
     206         */
    127207        uint8_t length;
    128208};
    129209
    130 /** Maximum segment size TCP option. */
    131 struct tcp_max_segment_size_option {
     210/** Maximum segment size TCP option.
     211 */
     212struct tcp_max_segment_size_option{
    132213        /** TCP option.
    133          * @see TCPOPT_MAX_SEGMENT_SIZE
    134          * @see TCPOPT_MAX_SEGMENT_SIZE_LENGTH
     214         *  @see TCPOPT_MAX_SEGMENT_SIZE
     215         *  @see TCPOPT_MAX_SEGMENT_SIZE_LENGTH
    135216         */
    136217        tcp_option_t option;
    137        
    138         /** Maximum segment size in bytes. */
     218        /** Maximum segment size in bytes.
     219        */
    139220        uint16_t max_segment_size;
    140221} __attribute__ ((packed));
  • uspace/srv/net/tl/tcp/tcp_module.c

    r49d819b4 re06ef614  
    2828
    2929/** @addtogroup tcp
    30  * @{
     30 *  @{
    3131 */
    3232
    3333/** @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
    3938 */
    40 
    41 #include "tcp.h"
    42 #include "tcp_module.h"
    4339
    4440#include <async.h>
     
    5046#include <net/ip_protocols.h>
    5147#include <net/modules.h>
     48
    5249#include <net/packet.h>
    5350#include <net_interface.h>
    54 
    5551#include <ip_interface.h>
    5652#include <tl_local.h>
    5753
    58 /** TCP module global data. */
    59 extern tcp_globals_t tcp_globals;
     54#include "tcp.h"
     55#include "tcp_module.h"
    6056
     57/** TCP module global data.
     58 */
     59extern 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 */
    6168int tl_module_start_standalone(async_client_conn_t client_connection)
    6269{
     
    6875       
    6976        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))) {
    7279                pm_destroy();
    7380                return ERROR_CODE;
     
    8087}
    8188
    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 */
     97int tl_module_message_standalone(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count){
    8698        return tcp_message_standalone(callid, call, answer, answer_count);
    8799}
  • uspace/srv/net/tl/tcp/tcp_module.h

    r49d819b4 re06ef614  
    2828
    2929/** @addtogroup tcp
    30  * @{
     30 *  @{
    3131 */
    3232
    3333/** @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.
    3636 */
    3737
    38 #ifndef NET_TCP_MODULE_H_
    39 #define NET_TCP_MODULE_H_
     38#ifndef __NET_TCP_MODULE_H__
     39#define __NET_TCP_MODULE_H__
    4040
    4141#include <async.h>
    4242#include <ipc/ipc.h>
    4343
    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 */
     49extern 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 */
     61extern int tcp_message_standalone(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count);
    4762
    4863#endif
  • uspace/srv/net/tl/udp/udp.c

    r49d819b4 re06ef614  
    2828
    2929/** @addtogroup udp
    30  * @{
     30 *  @{
    3131 */
    3232
    3333/** @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 */
    4137
    4238#include <async.h>
     
    4945#include <ipc/tl.h>
    5046#include <ipc/socket.h>
    51 #include <adt/dynamic_fifo.h>
    5247#include <errno.h>
    5348#include <err.h>
     
    6055#include <net/modules.h>
    6156
     57#include <adt/dynamic_fifo.h>
    6258#include <packet_client.h>
    6359#include <packet_remote.h>
     
    7369#include <tl_interface.h>
    7470
     71#include "udp.h"
     72#include "udp_header.h"
     73#include "udp_module.h"
     74
    7575/** UDP module name. */
    7676#define NAME    "UDP protocol"
     
    9191#define UDP_FREE_PORTS_END              65535
    9292
    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 */
     107int
     108udp_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 */
     132int
     133udp_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 */
     141int 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 */
     156int 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 */
     185int
     186udp_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 */
     209int
     210udp_recvfrom_message(socket_cores_ref local_sockets, int socket_id, int flags,
     211    size_t * addrlen);
     212
     213/*@}*/
     214
     215/** UDP global data.
     216 */
    94217udp_globals_t udp_globals;
    95218
    96 /** Initializes the UDP module.
    97  *
    98  * @param[in] client_connection The client connection processing function. The
    99  *                      module skeleton propagates its own one.
    100  * @returns             EOK on success.
    101  * @returns             ENOMEM if there is not enough memory left.
    102  */
    103219int udp_initialize(async_client_conn_t client_connection)
    104220{
     
    107223        measured_string_t names[] = {
    108224                {
    109                         (char *) "UDP_CHECKSUM_COMPUTING",
     225                        str_dup("UDP_CHECKSUM_COMPUTING"),
    110226                        22
    111227                },
    112228                {
    113                         (char *) "UDP_AUTOBINDING",
     229                        str_dup("UDP_AUTOBINDING"),
    114230                        15
    115231                }
     
    117233        measured_string_ref configuration;
    118234        size_t count = sizeof(names) / sizeof(measured_string_t);
    119         char *data;
     235        char * data;
    120236
    121237        fibril_rwlock_initialize(&udp_globals.lock);
     
    142258        udp_globals.last_used_port = UDP_FREE_PORTS_START - 1;
    143259
     260        // get configuration
    144261        udp_globals.checksum_computing = NET_DEFAULT_UDP_CHECKSUM_COMPUTING;
    145262        udp_globals.autobinding = NET_DEFAULT_UDP_AUTOBINDING;
    146 
    147         // get configuration
    148263        configuration = &names[0];
    149264        ERROR_PROPAGATE(net_get_conf_req(udp_globals.net_phone, &configuration,
     
    165280}
    166281
    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)
     282int
     283udp_received_msg(device_id_t device_id, packet_t packet, services_t receiver,
     284    services_t error)
    174285{
    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
    176293        return result;
    177294}
    178295
    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)
     296int udp_process_packet(device_id_t device_id, packet_t packet, services_t error)
    202297{
    203298        ERROR_DECLARE;
     
    220315        packet_dimension_ref packet_dimension;
    221316
    222         switch (error) {
    223         case SERVICE_NONE:
    224                 break;
    225         case SERVICE_ICMP:
    226                 // ignore error
    227                 // length = icmp_client_header_length(packet);
    228                 // process error
    229                 result = icmp_client_process_packet(packet, &type,
    230                     &code, NULL, NULL);
    231                 if (result < 0)
    232                         return udp_release_and_return(packet, result);
    233                 length = (size_t) result;
    234                 if (ERROR_OCCURRED(packet_trim(packet, length, 0)))
    235                         return udp_release_and_return(packet,
    236                             ERROR_CODE);
    237                 break;
    238         default:
    239                 return udp_release_and_return(packet, ENOTSUP);
     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                }
    240335        }
    241336
     
    279374
    280375        // compute header checksum if set
    281         if (header->checksum && !error) {
     376        if (header->checksum && (!error)) {
    282377                result = packet_get_addr(packet, (uint8_t **) &src,
    283378                    (uint8_t **) &dest);
    284                 if (result <= 0)
     379                if( result <= 0)
    285380                        return udp_release_and_return(packet, result);
    286381
     
    301396
    302397        do {
    303                 fragments++;
     398                ++ fragments;
    304399                length = packet_get_data_length(next_packet);
    305400                if (length <= 0)
     
    376471}
    377472
    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)
     473int
     474udp_message_standalone(ipc_callid_t callid, ipc_call_t * call,
     475    ipc_call_t * answer, int * answer_count)
    395476{
    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;
    404497}
    405498
    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
     499int 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
     640int
    434641udp_sendto_message(socket_cores_ref local_sockets, int socket_id,
    435642    const struct sockaddr *addr, socklen_t addrlen, int fragments,
     
    518725        // prefix the udp header
    519726        header = PACKET_PREFIX(packet, udp_header_t);
    520         if (!header)
     727        if(! header)
    521728                return udp_release_and_return(packet, ENOMEM);
    522729
    523730        bzero(header, sizeof(*header));
    524731        // read the rest of the packet fragments
    525         for (index = 1; index < fragments; index++) {
     732        for (index = 1; index < fragments; ++ index) {
    526733                result = tl_socket_read_packet_data(udp_globals.net_phone,
    527734                    &next_packet, 0, packet_dimension, addr, addrlen);
     
    577784}
    578785
    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
     786int
    599787udp_recvfrom_message(socket_cores_ref local_sockets, int socket_id, int flags,
    600788    size_t *addrlen)
     
    642830
    643831        // send the source address
    644         ERROR_PROPAGATE(data_reply(addr, *addrlen));
     832        ERROR_PROPAGATE(data_reply(addr, * addrlen));
    645833
    646834        // trim the header
     
    658846}
    659847
    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)
     848int udp_release_and_return(packet_t packet, int result)
    671849{
    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;
    848852}
    849853
     
    878882               
    879883                /*
    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
    882885                 */
    883886                if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) ||
     
    892895/** Starts the module.
    893896 *
    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
    896903 *                      start function.
    897904 */
  • uspace/srv/net/tl/udp/udp.h

    r49d819b4 re06ef614  
    2828
    2929/** @addtogroup udp
    30  * @{
     30 *  @{
    3131 */
    3232
    3333/** @file
    34  * UDP module.
     34 *  UDP module.
    3535 */
    3636
    37 #ifndef NET_UDP_H_
    38 #define NET_UDP_H_
     37#ifndef __NET_UDP_H__
     38#define __NET_UDP_H__
    3939
    4040#include <fibril_synch.h>
     
    4343
    4444/** Type definition of the UDP global data.
    45  * @see udp_globals
     45 *  @see udp_globals
    4646 */
    47 typedef struct udp_globals udp_globals_t;
     47typedef struct udp_globals      udp_globals_t;
    4848
    49 /** UDP global data. */
    50 struct udp_globals {
    51         /** Networking module phone. */
     49/** UDP global data.
     50 */
     51struct  udp_globals{
     52        /** Networking module phone.
     53         */
    5254        int net_phone;
    53         /** IP module phone. */
     55        /** IP module phone.
     56         */
    5457        int ip_phone;
    55         /** ICMP module phone. */
     58        /** ICMP module phone.
     59         */
    5660        int icmp_phone;
    57         /** Packet dimension. */
     61        /** Packet dimension.
     62         */
    5863        packet_dimension_t packet_dimension;
    59         /** Indicates whether UDP checksum computing is enabled. */
     64        /** Indicates whether UDP checksum computing is enabled.
     65         */
    6066        int checksum_computing;
    61         /** Indicates whether UDP autobnding on send is enabled. */
     67        /** Indicates whether UDP autobnding on send is enabled.
     68         */
    6269        int autobinding;
    63         /** Last used free port. */
     70        /** Last used free port.
     71         */
    6472        int last_used_port;
    65         /** Active sockets. */
     73        /** Active sockets.
     74         */
    6675        socket_ports_t sockets;
    67         /** Device packet dimensions. */
     76        /** Device packet dimensions.
     77         */
    6878        packet_dimensions_t dimensions;
    69         /** Safety lock. */
     79        /** Safety lock.
     80         */
    7081        fibril_rwlock_t lock;
    7182};
     
    7586/** @}
    7687 */
     88
  • uspace/srv/net/tl/udp/udp_header.h

    r49d819b4 re06ef614  
    2828
    2929/** @addtogroup udp
    30  * @{
     30 *  @{
    3131 */
    3232
    3333/** @file
    34  * UDP header definition.
    35  * Based on the RFC 768.
     34 *  UDP header definition.
     35 *  Based on the RFC~768.
    3636 */
    3737
    38 #ifndef NET_UDP_HEADER_H_
    39 #define NET_UDP_HEADER_H_
     38#ifndef __NET_UDP_HEADER_H__
     39#define __NET_UDP_HEADER_H__
    4040
    4141#include <sys/types.h>
    4242
    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)
    4546
    4647/** Type definition of the user datagram header.
    47  * @see udp_header
     48 *  @see udp_header
    4849 */
    49 typedef struct udp_header udp_header_t;
     50typedef struct udp_header       udp_header_t;
    5051
    5152/** Type definition of the user datagram header pointer.
    52  * @see udp_header
     53 *  @see udp_header
    5354 */
    54 typedef udp_header_t *udp_header_ref;
     55typedef udp_header_t *          udp_header_ref;
    5556
    56 /** User datagram header. */
    57 struct udp_header {
     57/** User datagram header.
     58 */
     59struct 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         */
    5863        uint16_t source_port;
     64        /** Destination port has a meaning within the context of a particular internet destination address.
     65         */
    5966        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         */
    6070        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         */
    6177        uint16_t checksum;
    6278} __attribute__ ((packed));
  • uspace/srv/net/tl/udp/udp_module.c

    r49d819b4 re06ef614  
    2828
    2929/** @addtogroup udp
    30  * @{
     30 *  @{
    3131 */
    3232
    3333/** @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
    3938 */
    40 
    41 #include "udp.h"
    42 #include "udp_module.h"
    4339
    4440#include <async.h>
     
    5046#include <net/modules.h>
    5147#include <net/packet.h>
    52 
    5348#include <net_interface.h>
    5449#include <tl_local.h>
    5550
    56 /** UDP module global data. */
    57 extern udp_globals_t udp_globals;
     51#include "udp.h"
     52#include "udp_module.h"
    5853
    59 int tl_module_start_standalone(async_client_conn_t client_connection)
    60 {
     54/** UDP module global data.
     55 */
     56extern 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 */
     65int tl_module_start_standalone(async_client_conn_t client_connection){
    6166        ERROR_DECLARE;
    6267
     
    6570        async_set_client_connection(client_connection);
    6671        udp_globals.net_phone = net_connect_module();
    67         if (udp_globals.net_phone < 0)
     72        if(udp_globals.net_phone < 0){
    6873                return udp_globals.net_phone;
    69 
     74        }
    7075        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))){
    7378                pm_destroy();
    7479                return ERROR_CODE;
     
    8186}
    8287
    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 */
     96int tl_module_message_standalone(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count){
    8797        return udp_message_standalone(callid, call, answer, answer_count);
    8898}
  • uspace/srv/net/tl/udp/udp_module.h

    r49d819b4 re06ef614  
    2828
    2929/** @addtogroup udp
    30  * @{
     30 *  @{
    3131 */
    3232
    3333/** @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.
    3636 */
    3737
    38 #ifndef NET_UDP_MODULE_H_
    39 #define NET_UDP_MODULE_H_
     38#ifndef __NET_UDP_MODULE_H__
     39#define __NET_UDP_MODULE_H__
    4040
    4141#include <async.h>
    4242#include <ipc/ipc.h>
    4343
    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 */
     49extern 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 */
     61extern int udp_message_standalone(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count);
    4762
    4863#endif
Note: See TracChangeset for help on using the changeset viewer.