Changeset 49d819b4 in mainline


Ignore:
Timestamp:
2010-11-02T23:15:18Z (13 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
7ae3d6f
Parents:
e06ef614 (diff), d0d1f4f (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge from lp:~jakub/helenos/net.

Files:
21 edited
4 moved

Legend:

Unmodified
Added
Removed
  • boot/Makefile.common

    re06ef614 r49d819b4  
    106106        $(USPACE_PATH)/srv/net/tl/tcp/tcp \
    107107        $(USPACE_PATH)/srv/net/net/net \
    108         $(USPACE_PATH)/srv/net/netstart/netstart \
    109108        $(USPACE_PATH)/srv/devman/devman
    110109       
     
    135134        $(USPACE_PATH)/app/tetris/tetris \
    136135        $(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

    re06ef614 r49d819b4  
    5050        app/trace \
    5151        app/top \
     52        app/netstart \
    5253        app/netecho \
    5354        app/nettest1 \
     
    8687        srv/net/tl/tcp \
    8788        srv/net/net \
    88         srv/net/netstart \
    8989        drv/root
    9090
  • uspace/app/netstart/Makefile

    re06ef614 r49d819b4  
    2828#
    2929
    30 USPACE_PREFIX = ../../..
     30USPACE_PREFIX = ../..
    3131LIBS = $(LIBNET_PREFIX)/libnet.a
    3232EXTRA_CFLAGS = -I$(LIBNET_PREFIX)/include
     
    3535
    3636SOURCES = \
    37         netstart.c \
    38         self_test.c
     37        netstart.c
    3938
    4039include $(USPACE_PREFIX)/Makefile.common
  • uspace/app/netstart/netstart.c

    re06ef614 r49d819b4  
    3232
    3333/** @file
    34  *
    3534 * Start the networking subsystem.
    36  * Perform networking self-test if executed
    37  * with the -s argument.
    38  *
    3935 */
    4036
     
    5248#include <net/modules.h>
    5349
    54 #include "self_test.h"
    55 
    5650/** Start a module.
    5751 *
    58  * @param[in] desc The module description
    59  * @param[in] path The module absolute path.
    60  *
    61  * @returns true on succesful spanwning
    62  * @returns false on failure
    63  *
     52 * @param[in] desc      The module description
     53 * @param[in] path      The module absolute path.
     54 * @returns             True on succesful spanwning.
     55 * @returns             False on failure
    6456 */
    6557static bool spawn(const char *desc, const char *path)
     
    8678        ERROR_DECLARE;
    8779       
    88         /* Run self-tests */
    89         if ((argc > 1) && (str_cmp(argv[1], "-s") == 0))
    90                 ERROR_PROPAGATE(self_test());
    91        
    9280        if (!spawn("networking service", "/srv/net"))
    9381                return EINVAL;
  • uspace/lib/c/include/ipc/services.h

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

    re06ef614 r49d819b4  
    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 */
    3953extern int tl_module_message_standalone(ipc_callid_t, ipc_call_t *,
    4054    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 */
    4168extern int tl_module_start_standalone(async_client_conn_t);
    4269
  • uspace/srv/net/net/net.c

    re06ef614 r49d819b4  
    3636 */
    3737
     38#include "net.h"
     39
    3840#include <async.h>
    3941#include <ctype.h>
     
    5254
    5355#include <net/modules.h>
     56#include <net/packet.h>
     57#include <net/device.h>
     58
    5459#include <adt/char_map.h>
    5560#include <adt/generic_char_map.h>
    5661#include <adt/measured_strings.h>
    5762#include <adt/module_map.h>
    58 #include <net/packet.h>
     63
    5964#include <netif_remote.h>
    60 #include <net/device.h>
    6165#include <nil_interface.h>
    6266#include <net_interface.h>
    6367#include <ip_interface.h>
    6468
    65 #include "net.h"
    66 
    67 /** Networking module name.
    68  *
    69  */
     69/** Networking module name. */
    7070#define NAME  "net"
    7171
    72 /** File read buffer size.
    73  *
    74  */
     72/** File read buffer size. */
    7573#define BUFFER_SIZE  256
    7674
    77 /** Networking module global data.
    78  *
    79  */
     75/** Networking module global data. */
    8076net_globals_t net_globals;
    8177
     
    10096        measured_string_ref setting =
    10197            measured_string_create_bulk(value, 0);
    102        
    10398        if (!setting)
    10499                return ENOMEM;
     
    206201        unsigned int line_number = 0;
    207202        size_t index = 0;
    208         while ((!ferror(cfg)) && (!feof(cfg))) {
     203        while (!ferror(cfg) && !feof(cfg)) {
    209204                int read = fgetc(cfg);
    210205                if ((read > 0) && (read != '\n') && (read != '\r')) {
     
    326321        ipcarg_t phonehash;
    327322       
    328         if (ERROR_OCCURRED(net_initialize(client_connection))
    329             || ERROR_OCCURRED(REGISTER_ME(SERVICE_NETWORKING, &phonehash))){
     323        if (ERROR_OCCURRED(net_initialize(client_connection)) ||
     324            ERROR_OCCURRED(REGISTER_ME(SERVICE_NETWORKING, &phonehash))) {
    330325                pm_destroy();
    331326                return ERROR_CODE;
     
    379374    size_t count, char **data)
    380375{
    381         if (!(configuration && (count > 0)))
     376        if (!configuration || (count <= 0))
    382377                return EINVAL;
    383378       
     
    482477        /* Inter-network layer startup */
    483478        switch (netif->il->service) {
    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;
     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;
    490485        }
    491486       
     
    511506        ERROR_DECLARE;
    512507       
    513         const char *conf_files[] = {"lo", "ne2k"};
     508        const char *conf_files[] = {
     509                "lo",
     510                "ne2k"
     511        };
    514512        size_t count = sizeof(conf_files) / sizeof(char *);
    515513       
     
    603601        *answer_count = 0;
    604602        switch (IPC_GET_METHOD(*call)) {
    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();
     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();
    632630        }
    633631        return ENOTSUP;
     
    661659                int res = net_module_message(callid, &call, &answer, &answer_count);
    662660               
    663                 /* End if said to either by the message or the processing result */
     661                /* End if told to either by the message or the processing result */
    664662                if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) || (res == EHANGUP))
    665663                        return;
  • uspace/srv/net/net/net.h

    re06ef614 r49d819b4  
    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

    re06ef614 r49d819b4  
    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"
     38
    3739#include <str.h>
    38 
     40#include <adt/measured_strings.h>
     41#include <adt/module_map.h>
    3942#include <ipc/ipc.h>
    4043#include <ipc/net.h>
    4144
    4245#include <ip_interface.h>
    43 #include <adt/measured_strings.h>
    44 #include <adt/module_map.h>
    4546#include <packet_server.h>
    4647
    47 #include "net.h"
    48 
    49 /** Networking module global data.
    50  */
     48/** Networking module global data. */
    5149extern net_globals_t net_globals;
    5250
     
    6058 *
    6159 */
    62 int net_initialize_build(async_client_conn_t client_connection){
     60int net_initialize_build(async_client_conn_t client_connection)
     61{
    6362        ERROR_DECLARE;
    6463       
  • uspace/srv/net/tl/icmp/icmp.c

    re06ef614 r49d819b4  
    2828
    2929/** @addtogroup icmp
    30  *  @{
     30 * @{
    3131 */
    3232
    3333/** @file
    34  *  ICMP module implementation.
    35  *  @see icmp.h
    36  */
     34 * ICMP module implementation.
     35 * @see icmp.h
     36 */
     37
     38#include "icmp.h"
     39#include "icmp_module.h"
    3740
    3841#include <async.h>
     
    5659#include <net/ip_protocols.h>
    5760#include <net/inet.h>
    58 
    5961#include <net/modules.h>
     62#include <net/icmp_api.h>
     63#include <net/icmp_codes.h>
     64#include <net/icmp_common.h>
     65
    6066#include <packet_client.h>
    6167#include <packet_remote.h>
    6268#include <net_checksum.h>
    63 #include <net/icmp_api.h>
    6469#include <icmp_client.h>
    65 #include <net/icmp_codes.h>
    66 #include <net/icmp_common.h>
    6770#include <icmp_interface.h>
    6871#include <il_interface.h>
     
    7477#include <icmp_header.h>
    7578
    76 #include "icmp.h"
    77 #include "icmp_module.h"
    78 
    79 /** ICMP module name.
    80  */
     79/** ICMP module name. */
    8180#define NAME    "ICMP protocol"
    8281
    83 /** Default ICMP error reporting.
    84  */
     82/** Default ICMP error reporting. */
    8583#define NET_DEFAULT_ICMP_ERROR_REPORTING        true
    8684
    87 /** Default ICMP echo replying.
    88  */
     85/** Default ICMP echo replying. */
    8986#define NET_DEFAULT_ICMP_ECHO_REPLYING          true
    9087
    91 /** Original datagram length in bytes transfered to the error notification message.
     88/** Original datagram length in bytes transfered to the error notification
     89 * message.
    9290 */
    9391#define ICMP_KEEP_LENGTH        8
    9492
    95 /** Free identifier numbers pool start.
    96  */
     93/** Free identifier numbers pool start. */
    9794#define ICMP_FREE_IDS_START     1
    9895
    99 /** Free identifier numbers pool end.
    100  */
     96/** Free identifier numbers pool end. */
    10197#define ICMP_FREE_IDS_END       UINT16_MAX
    10298
    10399/** Computes the ICMP datagram checksum.
    104  *  @param[in,out] header The ICMP datagram header.
    105  *  @param[in] length The total datagram length.
    106  *  @returns The computed checksum.
    107  */
    108 #define ICMP_CHECKSUM(header, length)           htons(ip_checksum((uint8_t *) (header), (length)))
    109 
    110 /** An echo request datagrams pattern.
    111  */
    112 #define ICMP_ECHO_TEXT                                  "Hello from HelenOS."
     100 *
     101 * @param[in,out] header The ICMP datagram header.
     102 * @param[in] length    The total datagram length.
     103 * @returns             The computed checksum.
     104 */
     105#define ICMP_CHECKSUM(header, length) \
     106        htons(ip_checksum((uint8_t *) (header), (length)))
     107
     108/** An echo request datagrams pattern. */
     109#define ICMP_ECHO_TEXT          "Hello from HelenOS."
    113110
    114111/** Computes an ICMP reply data key.
    115  *  @param[in] id The message identifier.
    116  *  @param[in] sequence The message sequence number.
    117  *  @returns The computed ICMP reply data key.
    118  */
    119 #define ICMP_GET_REPLY_KEY(id, sequence)        (((id) << 16) | (sequence &0xFFFF))
    120 
    121 /** Processes the received ICMP packet.
    122  *  Is used as an entry point from the underlying IP module.
    123  *  Releases the packet on error.
    124  *  @param device_id The device identifier. Ignored parameter.
    125  *  @param[in,out] packet The received packet.
    126  *  @param receiver The target service. Ignored parameter.
    127  *  @param[in] error The packet error reporting service. Prefixes the received packet.
    128  *  @returns EOK on success.
    129  *  @returns Other error codes as defined for the icmp_process_packet() function.
    130  */
    131 int icmp_received_msg(device_id_t device_id, packet_t packet, services_t receiver, services_t error);
    132 
    133 /** Processes the received ICMP packet.
    134  *  Notifies the destination socket application.
    135  *  @param[in,out] packet The received packet.
    136  *  @param[in] error The packet error reporting service. Prefixes the received packet.
    137  *  @returns EOK on success.
    138  *  @returns EINVAL if the packet is not valid.
    139  *  @returns EINVAL if the stored packet address is not the an_addr_t.
    140  *  @returns EINVAL if the packet does not contain any data.
    141  *  @returns NO_DATA if the packet content is shorter than the user datagram header.
    142  *  @returns ENOMEM if there is not enough memory left.
    143  *  @returns EADDRNOTAVAIL if the destination socket does not exist.
    144  *  @returns Other error codes as defined for the ip_client_process_packet() function.
    145  */
    146 int icmp_process_packet(packet_t packet, services_t error);
    147 
    148 /** Processes the client messages.
    149  *  Remembers the assigned identifier and sequence numbers.
    150  *  Runs until the client module disconnects.
    151  *  @param[in] callid The message identifier.
    152  *  @param[in] call The message parameters.
    153  *  @returns EOK.
    154  *  @see icmp_interface.h
    155  *  @see icmp_api.h
    156  */
    157 int icmp_process_client_messages(ipc_callid_t callid, ipc_call_t call);
    158 
    159 /** Processes the generic client messages.
    160  *  @param[in] call The message parameters.
    161  *  @returns EOK on success.
    162  *  @returns ENOTSUP if the message is not known.
    163  *  @returns Other error codes as defined for the packet_translate() function.
    164  *  @returns Other error codes as defined for the icmp_destination_unreachable_msg() function.
    165  *  @returns Other error codes as defined for the icmp_source_quench_msg() function.
    166  *  @returns Other error codes as defined for the icmp_time_exceeded_msg() function.
    167  *  @returns Other error codes as defined for the icmp_parameter_problem_msg() function.
    168  *  @see icmp_interface.h
    169  */
    170 int icmp_process_message(ipc_call_t * call);
     112 *
     113 * @param[in] id        The message identifier.
     114 * @param[in] sequence  The message sequence number.
     115 * @returns             The computed ICMP reply data key.
     116 */
     117#define ICMP_GET_REPLY_KEY(id, sequence) \
     118        (((id) << 16) | (sequence & 0xFFFF))
     119
     120
     121/** ICMP global data. */
     122icmp_globals_t  icmp_globals;
     123
     124INT_MAP_IMPLEMENT(icmp_replies, icmp_reply_t);
     125INT_MAP_IMPLEMENT(icmp_echo_data, icmp_echo_t);
    171126
    172127/** Releases the packet and returns the result.
    173  *  @param[in] packet The packet queue to be released.
    174  *  @param[in] result The result to be returned.
    175  *  @returns The result parameter.
    176  */
    177 int icmp_release_and_return(packet_t packet, int result);
     128 *
     129 * @param[in] packet    The packet queue to be released.
     130 * @param[in] result    The result to be returned.
     131 * @returns             The result parameter.
     132 */
     133static 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 */
     158static int
     159icmp_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 */
     192static 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}
    178220
    179221/** Requests an echo message.
    180  *  Sends a packet with specified parameters to the target host and waits for the reply upto the given timeout.
    181  *  Blocks the caller until the reply or the timeout occurs.
    182  *  @param[in] id The message identifier.
    183  *  @param[in] sequence The message sequence parameter.
    184  *  @param[in] size The message data length in bytes.
    185  *  @param[in] timeout The timeout in miliseconds.
    186  *  @param[in] ttl The time to live.
    187  *  @param[in] tos The type of service.
    188  *  @param[in] dont_fragment The value indicating whether the datagram must not be fragmented. Is used as a MTU discovery.
    189  *  @param[in] addr The target host address.
    190  *  @param[in] addrlen The torget host address length.
    191  *  @returns ICMP_ECHO on success.
    192  *  @returns ETIMEOUT if the reply has not arrived before the timeout.
    193  *  @returns ICMP type of the received error notification.
    194  *  @returns EINVAL if the addrlen parameter is less or equal to zero (<=0).
    195  *  @returns ENOMEM if there is not enough memory left.
    196  *  @returns EPARTY if there was an internal error.
    197  */
    198 int icmp_echo(icmp_param_t id, icmp_param_t sequence, size_t size, mseconds_t timeout, ip_ttl_t ttl, ip_tos_t tos, int dont_fragment, const struct sockaddr * addr, socklen_t addrlen);
    199 
    200 /** Prepares the ICMP error packet.
    201  *  Truncates the original packet if longer than ICMP_KEEP_LENGTH bytes.
    202  *  Prefixes and returns the ICMP header.
    203  *  @param[in,out] packet The original packet.
    204  *  @returns The prefixed ICMP header.
    205  *  @returns NULL on errors.
    206  */
    207 icmp_header_ref icmp_prepare_packet(packet_t packet);
    208 
    209 /** Sends the ICMP message.
    210  *  Sets the message type and code and computes the checksum.
    211  *  Error messages are sent only if allowed in the configuration.
    212  *  Releases the packet on errors.
    213  *  @param[in] type The message type.
    214  *  @param[in] code The message code.
    215  *  @param[in] packet The message packet to be sent.
    216  *  @param[in] header The ICMP header.
    217  *  @param[in] error The error service to be announced. Should be SERVICE_ICMP or zero (0).
    218  *  @param[in] ttl The time to live.
    219  *  @param[in] tos The type of service.
    220  *  @param[in] dont_fragment The value indicating whether the datagram must not be fragmented. Is used as a MTU discovery.
    221  *  @returns EOK on success.
    222  *  @returns EPERM if the error message is not allowed.
    223  */
    224 int icmp_send_packet(icmp_type_t type, icmp_code_t code, packet_t packet, icmp_header_ref header, services_t error, ip_ttl_t ttl, ip_tos_t tos, int dont_fragment);
    225 
    226 /** Tries to set the pending reply result as the received message type.
    227  *  If the reply data is not present, the reply timed out and the other fibril
    228  *  is already awake.
    229  *  Releases the packet.
    230  *  @param[in] packet The received reply message.
    231  *  @param[in] header The ICMP message header.
    232  *  @param[in] type The received reply message type.
    233  *  @param[in] code The received reply message code.
    234  *  @returns EOK.
    235  */
    236 int icmp_process_echo_reply(packet_t packet, icmp_header_ref header, icmp_type_t type, icmp_code_t code);
    237 
    238 /** Assigns a new identifier for the connection.
    239  *  Fills the echo data parameter with the assigned values.
    240  *  @param[in,out] echo_data The echo data to be bound.
    241  *  @returns Index of the inserted echo data.
    242  *  @returns EBADMEM if the echo_data parameter is NULL.
    243  *  @returns ENOTCONN if no free identifier have been found.
    244  */
    245 int icmp_bind_free_id(icmp_echo_ref echo_data);
    246 
    247 /** ICMP global data.
    248  */
    249 icmp_globals_t  icmp_globals;
    250 
    251 INT_MAP_IMPLEMENT(icmp_replies, icmp_reply_t);
    252 
    253 INT_MAP_IMPLEMENT(icmp_echo_data, icmp_echo_t);
    254 
    255 int icmp_echo_msg(int icmp_phone, size_t size, mseconds_t timeout, ip_ttl_t ttl, ip_tos_t tos, int dont_fragment, const struct sockaddr * addr, socklen_t addrlen){
    256         icmp_echo_ref echo_data;
    257         int res;
    258 
    259         fibril_rwlock_write_lock(&icmp_globals.lock);
    260         // use the phone as the echo data index
    261         echo_data = icmp_echo_data_find(&icmp_globals.echo_data, icmp_phone);
    262         if(! echo_data){
    263                 res = ENOENT;
    264         }else{
    265                 res = icmp_echo(echo_data->identifier, echo_data->sequence_number, size, timeout, ttl, tos, dont_fragment, addr, addrlen);
    266                 if(echo_data->sequence_number < UINT16_MAX){
    267                         ++ echo_data->sequence_number;
    268                 }else{
    269                         echo_data->sequence_number = 0;
    270                 }
    271         }
    272         fibril_rwlock_write_unlock(&icmp_globals.lock);
    273         return res;
    274 }
    275 
    276 int icmp_echo(icmp_param_t id, icmp_param_t sequence, size_t size, mseconds_t timeout, ip_ttl_t ttl, ip_tos_t tos, int dont_fragment, const struct sockaddr * addr, socklen_t addrlen){
     222 *
     223 * Sends a packet with specified parameters to the target host and waits for
     224 * the reply upto the given timeout.
     225 * Blocks the caller until the reply or the timeout occurs.
     226 *
     227 * @param[in] id        The message identifier.
     228 * @param[in] sequence  The message sequence parameter.
     229 * @param[in] size      The message data length in bytes.
     230 * @param[in] timeout   The timeout in miliseconds.
     231 * @param[in] ttl       The time to live.
     232 * @param[in] tos       The type of service.
     233 * @param[in] dont_fragment The value indicating whether the datagram must not
     234 *                      be fragmented. Is used as a MTU discovery.
     235 * @param[in] addr      The target host address.
     236 * @param[in] addrlen   The torget host address length.
     237 * @returns             ICMP_ECHO on success.
     238 * @returns             ETIMEOUT if the reply has not arrived before the
     239 *                      timeout.
     240 * @returns             ICMP type of the received error notification.
     241 * @returns             EINVAL if the addrlen parameter is less or equal to
     242 *                      zero.
     243 * @returns             ENOMEM if there is not enough memory left.
     244 * @returns             EPARTY if there was an internal error.
     245 */
     246static int
     247icmp_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{
    277251        ERROR_DECLARE;
    278252
     
    280254        packet_t packet;
    281255        size_t length;
    282         uint8_t * data;
     256        uint8_t *data;
    283257        icmp_reply_ref reply;
    284258        int reply_key;
     
    286260        int index;
    287261
    288         if(addrlen <= 0){
     262        if (addrlen <= 0)
    289263                return EINVAL;
    290         }
     264
    291265        length = (size_t) addrlen;
    292266        // TODO do not ask all the time
    293         ERROR_PROPAGATE(ip_packet_size_req(icmp_globals.ip_phone, -1, &icmp_globals.packet_dimension));
    294         packet = packet_get_4_remote(icmp_globals.net_phone, size, icmp_globals.packet_dimension.addr_len, ICMP_HEADER_SIZE + icmp_globals.packet_dimension.prefix, icmp_globals.packet_dimension.suffix);
    295         if(! packet){
     267        ERROR_PROPAGATE(ip_packet_size_req(icmp_globals.ip_phone, -1,
     268            &icmp_globals.packet_dimension));
     269
     270        packet = packet_get_4_remote(icmp_globals.net_phone, size,
     271            icmp_globals.packet_dimension.addr_len,
     272            ICMP_HEADER_SIZE + icmp_globals.packet_dimension.prefix,
     273            icmp_globals.packet_dimension.suffix);
     274        if (!packet)
    296275                return ENOMEM;
    297         }
    298276
    299277        // prepare the requesting packet
    300278        // set the destination address
    301         if(ERROR_OCCURRED(packet_set_addr(packet, NULL, (const uint8_t *) addr, length))){
     279        if (ERROR_OCCURRED(packet_set_addr(packet, NULL, (const uint8_t *) addr,
     280            length))) {
    302281                return icmp_release_and_return(packet, ERROR_CODE);
    303282        }
     283
    304284        // allocate space in the packet
    305285        data = (uint8_t *) packet_suffix(packet, size);
    306         if(! data){
     286        if (!data)
    307287                return icmp_release_and_return(packet, ENOMEM);
    308         }
     288
    309289        // fill the data
    310290        length = 0;
    311         while(size > length + sizeof(ICMP_ECHO_TEXT)){
     291        while (size > length + sizeof(ICMP_ECHO_TEXT)) {
    312292                memcpy(data + length, ICMP_ECHO_TEXT, sizeof(ICMP_ECHO_TEXT));
    313293                length += sizeof(ICMP_ECHO_TEXT);
    314294        }
    315295        memcpy(data + length, ICMP_ECHO_TEXT, size - length);
     296
    316297        // prefix the header
    317298        header = PACKET_PREFIX(packet, icmp_header_t);
    318         if(! header){
     299        if (!header)
    319300                return icmp_release_and_return(packet, ENOMEM);
    320         }
     301
    321302        bzero(header, sizeof(*header));
    322303        header->un.echo.identifier = id;
     
    325306        // prepare the reply structure
    326307        reply = malloc(sizeof(*reply));
    327         if(! reply){
     308        if (!reply)
    328309                return icmp_release_and_return(packet, ENOMEM);
    329         }
     310
    330311        fibril_mutex_initialize(&reply->mutex);
    331312        fibril_mutex_lock(&reply->mutex);
    332313        fibril_condvar_initialize(&reply->condvar);
    333         reply_key = ICMP_GET_REPLY_KEY(header->un.echo.identifier, header->un.echo.sequence_number);
     314        reply_key = ICMP_GET_REPLY_KEY(header->un.echo.identifier,
     315            header->un.echo.sequence_number);
    334316        index = icmp_replies_add(&icmp_globals.replies, reply_key, reply);
    335         if(index < 0){
     317        if (index < 0) {
    336318                free(reply);
    337319                return icmp_release_and_return(packet, index);
     
    342324
    343325        // send the request
    344         icmp_send_packet(ICMP_ECHO, 0, packet, header, 0, ttl, tos, dont_fragment);
     326        icmp_send_packet(ICMP_ECHO, 0, packet, header, 0, ttl, tos,
     327            dont_fragment);
    345328
    346329        // wait for the reply
    347330        // timeout in microseconds
    348         if(ERROR_OCCURRED(fibril_condvar_wait_timeout(&reply->condvar, &reply->mutex, timeout * 1000))){
     331        if (ERROR_OCCURRED(fibril_condvar_wait_timeout(&reply->condvar,
     332            &reply->mutex, timeout * 1000))) {
    349333                result = ERROR_CODE;
    350         }else{
     334        } else {
    351335                // read the result
    352336                result = reply->result;
     
    359343        // destroy the reply structure
    360344        icmp_replies_exclude_index(&icmp_globals.replies, index);
     345
    361346        return result;
    362347}
    363348
    364 int icmp_destination_unreachable_msg(int icmp_phone, icmp_code_t code, icmp_param_t mtu, packet_t packet){
     349static int
     350icmp_destination_unreachable_msg_local(int icmp_phone, icmp_code_t code,
     351    icmp_param_t mtu, packet_t packet)
     352{
    365353        icmp_header_ref header;
    366354
    367355        header = icmp_prepare_packet(packet);
    368         if(! header){
     356        if (!header)
    369357                return icmp_release_and_return(packet, ENOMEM);
    370         }
    371         if(mtu){
     358
     359        if (mtu)
    372360                header->un.frag.mtu = mtu;
    373         }
    374         return icmp_send_packet(ICMP_DEST_UNREACH, code, packet, header, SERVICE_ICMP, 0, 0, 0);
    375 }
    376 
    377 int icmp_source_quench_msg(int icmp_phone, packet_t packet){
     361
     362        return icmp_send_packet(ICMP_DEST_UNREACH, code, packet, header,
     363            SERVICE_ICMP, 0, 0, 0);
     364}
     365
     366static int icmp_source_quench_msg_local(int icmp_phone, packet_t packet)
     367{
    378368        icmp_header_ref header;
    379369
    380370        header = icmp_prepare_packet(packet);
    381         if(! header){
     371        if (!header)
    382372                return icmp_release_and_return(packet, ENOMEM);
    383         }
    384         return icmp_send_packet(ICMP_SOURCE_QUENCH, 0, packet, header, SERVICE_ICMP, 0, 0, 0);
    385 }
    386 
    387 int icmp_time_exceeded_msg(int icmp_phone, icmp_code_t code, packet_t packet){
     373
     374        return icmp_send_packet(ICMP_SOURCE_QUENCH, 0, packet, header,
     375            SERVICE_ICMP, 0, 0, 0);
     376}
     377
     378static int
     379icmp_time_exceeded_msg_local(int icmp_phone, icmp_code_t code, packet_t packet)
     380{
    388381        icmp_header_ref header;
    389382
    390383        header = icmp_prepare_packet(packet);
    391         if(! header){
     384        if (!header)
    392385                return icmp_release_and_return(packet, ENOMEM);
    393         }
    394         return icmp_send_packet(ICMP_TIME_EXCEEDED, code, packet, header, SERVICE_ICMP, 0, 0, 0);
    395 }
    396 
    397 int icmp_parameter_problem_msg(int icmp_phone, icmp_code_t code, icmp_param_t pointer, packet_t packet){
     386
     387        return icmp_send_packet(ICMP_TIME_EXCEEDED, code, packet, header,
     388            SERVICE_ICMP, 0, 0, 0);
     389}
     390
     391static int
     392icmp_parameter_problem_msg_local(int icmp_phone, icmp_code_t code,
     393    icmp_param_t pointer, packet_t packet)
     394{
    398395        icmp_header_ref header;
    399396
    400397        header = icmp_prepare_packet(packet);
    401         if(! header){
     398        if (!header)
    402399                return icmp_release_and_return(packet, ENOMEM);
    403         }
     400
    404401        header->un.param.pointer = pointer;
    405         return icmp_send_packet(ICMP_PARAMETERPROB, code, packet, header, SERVICE_ICMP, 0, 0, 0);
    406 }
    407 
    408 icmp_header_ref icmp_prepare_packet(packet_t packet){
    409         icmp_header_ref header;
    410         size_t header_length;
    411         size_t total_length;
    412 
    413         total_length = packet_get_data_length(packet);
    414         if(total_length <= 0){
    415                 return NULL;
    416         }
    417         header_length = ip_client_header_length(packet);
    418         if(header_length <= 0){
    419                 return NULL;
    420         }
    421         // truncate if longer than 64 bits (without the IP header)
    422         if((total_length > header_length + ICMP_KEEP_LENGTH)
    423                 && (packet_trim(packet, 0, total_length - header_length - ICMP_KEEP_LENGTH) != EOK)){
    424                 return NULL;
    425         }
    426         header = PACKET_PREFIX(packet, icmp_header_t);
    427         if(! header){
    428                 return NULL;
    429         }
    430         bzero(header, sizeof(*header));
    431         return header;
    432 }
    433 
    434 int icmp_send_packet(icmp_type_t type, icmp_code_t code, packet_t packet, icmp_header_ref header, services_t error, ip_ttl_t ttl, ip_tos_t tos, int dont_fragment){
     402        return icmp_send_packet(ICMP_PARAMETERPROB, code, packet, header,
     403            SERVICE_ICMP, 0, 0, 0);
     404}
     405
     406/** Initializes the ICMP module.
     407 *
     408 * @param[in] client_connection The client connection processing function. The
     409 *                      module skeleton propagates its own one.
     410 * @returns             EOK on success.
     411 * @returns             ENOMEM if there is not enough memory left.
     412 */
     413int icmp_initialize(async_client_conn_t client_connection)
     414{
    435415        ERROR_DECLARE;
    436416
    437         // do not send an error if disabled
    438         if(error && (! icmp_globals.error_reporting)){
    439                 return icmp_release_and_return(packet, EPERM);
    440         }
    441         header->type = type;
    442         header->code = code;
    443         header->checksum = 0;
    444         header->checksum = ICMP_CHECKSUM(header, packet_get_data_length(packet));
    445         if(ERROR_OCCURRED(ip_client_prepare_packet(packet, IPPROTO_ICMP, ttl, tos, dont_fragment, 0))){
    446                 return icmp_release_and_return(packet, ERROR_CODE);
    447         }
    448         return ip_send_msg(icmp_globals.ip_phone, -1, packet, SERVICE_ICMP, error);
    449 }
    450 
    451 int icmp_initialize(async_client_conn_t client_connection){
    452         ERROR_DECLARE;
    453 
    454         measured_string_t names[] = {{str_dup("ICMP_ERROR_REPORTING"), 20}, {str_dup("ICMP_ECHO_REPLYING"), 18}};
     417        measured_string_t names[] = {
     418                {
     419                        (char *) "ICMP_ERROR_REPORTING",
     420                        20
     421                },
     422                {
     423                        (char *) "ICMP_ECHO_REPLYING",
     424                        18
     425                }
     426        };
    455427        measured_string_ref configuration;
    456428        size_t count = sizeof(names) / sizeof(measured_string_t);
    457         char * data;
     429        char *data;
    458430
    459431        fibril_rwlock_initialize(&icmp_globals.lock);
     
    461433        icmp_replies_initialize(&icmp_globals.replies);
    462434        icmp_echo_data_initialize(&icmp_globals.echo_data);
    463         icmp_globals.ip_phone = ip_bind_service(SERVICE_IP, IPPROTO_ICMP, SERVICE_ICMP, client_connection);
    464         if(icmp_globals.ip_phone < 0){
     435        icmp_globals.ip_phone = ip_bind_service(SERVICE_IP, IPPROTO_ICMP,
     436            SERVICE_ICMP, client_connection);
     437        if (icmp_globals.ip_phone < 0)
    465438                return icmp_globals.ip_phone;
    466         }
    467         ERROR_PROPAGATE(ip_packet_size_req(icmp_globals.ip_phone, -1, &icmp_globals.packet_dimension));
     439
     440        ERROR_PROPAGATE(ip_packet_size_req(icmp_globals.ip_phone, -1,
     441            &icmp_globals.packet_dimension));
    468442        icmp_globals.packet_dimension.prefix += ICMP_HEADER_SIZE;
    469443        icmp_globals.packet_dimension.content -= ICMP_HEADER_SIZE;
    470         // get configuration
     444
    471445        icmp_globals.error_reporting = NET_DEFAULT_ICMP_ERROR_REPORTING;
    472446        icmp_globals.echo_replying = NET_DEFAULT_ICMP_ECHO_REPLYING;
     447
     448        // get configuration
    473449        configuration = &names[0];
    474         ERROR_PROPAGATE(net_get_conf_req(icmp_globals.net_phone, &configuration, count, &data));
    475         if(configuration){
    476                 if(configuration[0].value){
    477                         icmp_globals.error_reporting = (configuration[0].value[0] == 'y');
    478                 }
    479                 if(configuration[1].value){
    480                         icmp_globals.echo_replying = (configuration[1].value[0] == 'y');
     450        ERROR_PROPAGATE(net_get_conf_req(icmp_globals.net_phone, &configuration,
     451            count, &data));
     452        if (configuration) {
     453                if (configuration[0].value) {
     454                        icmp_globals.error_reporting =
     455                            (configuration[0].value[0] == 'y');
     456                }
     457                if (configuration[1].value) {
     458                        icmp_globals.echo_replying =
     459                            (configuration[1].value[0] == 'y');
    481460                }
    482461                net_free_settings(configuration, data);
    483462        }
     463
    484464        fibril_rwlock_write_unlock(&icmp_globals.lock);
    485465        return EOK;
    486466}
    487467
    488 int icmp_received_msg(device_id_t device_id, packet_t packet, services_t receiver, services_t error){
     468/** Tries to set the pending reply result as the received message type.
     469 *
     470 * If the reply data is not present, the reply timed out and the other fibril
     471 * is already awake.
     472 * Releases the packet.
     473 *
     474 * @param[in] packet    The received reply message.
     475 * @param[in] header    The ICMP message header.
     476 * @param[in] type      The received reply message type.
     477 * @param[in] code      The received reply message code.
     478 */
     479static void
     480icmp_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 */
     519static int icmp_process_packet(packet_t packet, services_t error)
     520{
    489521        ERROR_DECLARE;
    490522
    491         if(ERROR_OCCURRED(icmp_process_packet(packet, error))){
    492                 return icmp_release_and_return(packet, ERROR_CODE);
    493         }
    494 
    495         return EOK;
    496 }
    497 
    498 int icmp_process_packet(packet_t packet, services_t error){
    499         ERROR_DECLARE;
    500 
    501523        size_t length;
    502         uint8_t * src;
     524        uint8_t *src;
    503525        int addrlen;
    504526        int result;
    505         void * data;
     527        void *data;
    506528        icmp_header_ref header;
    507529        icmp_type_t type;
    508530        icmp_code_t code;
    509531
    510         if(error){
    511                 switch(error){
    512                         case SERVICE_ICMP:
    513                                 // process error
    514                                 result = icmp_client_process_packet(packet, &type, &code, NULL, NULL);
    515                                 if(result < 0){
    516                                         return result;
    517                                 }
    518                                 length = (size_t) result;
    519                                 // remove the error header
    520                                 ERROR_PROPAGATE(packet_trim(packet, length, 0));
    521                                 break;
    522                         default:
    523                                 return ENOTSUP;
    524                 }
    525         }
     532        switch (error) {
     533        case SERVICE_NONE:
     534                break;
     535        case SERVICE_ICMP:
     536                // process error
     537                result = icmp_client_process_packet(packet, &type, &code, NULL,
     538                    NULL);
     539                if (result < 0)
     540                        return result;
     541                length = (size_t) result;
     542                // remove the error header
     543                ERROR_PROPAGATE(packet_trim(packet, length, 0));
     544                break;
     545        default:
     546                return ENOTSUP;
     547        }
     548
    526549        // get rid of the ip header
    527550        length = ip_client_header_length(packet);
     
    529552
    530553        length = packet_get_data_length(packet);
    531         if(length <= 0){
     554        if (length <= 0)
    532555                return EINVAL;
    533         }
    534         if(length < ICMP_HEADER_SIZE){
     556
     557        if (length < ICMP_HEADER_SIZE)
    535558                return EINVAL;
    536         }
     559
    537560        data = packet_get_data(packet);
    538         if(! data){
     561        if (!data)
    539562                return EINVAL;
    540         }
     563
    541564        // get icmp header
    542565        header = (icmp_header_ref) data;
    543         // checksum
    544         if(header->checksum){
    545                 while(ICMP_CHECKSUM(header, length) != IP_CHECKSUM_ZERO){
     566
     567        if (header->checksum) {
     568                while (ICMP_CHECKSUM(header, length) != IP_CHECKSUM_ZERO) {
    546569                        // set the original message type on error notification
    547570                        // type swap observed in Qemu
    548                         if(error){
    549                                 switch(header->type){
    550                                         case ICMP_ECHOREPLY:
    551                                                 header->type = ICMP_ECHO;
    552                                                 continue;
     571                        if (error) {
     572                                switch (header->type) {
     573                                case ICMP_ECHOREPLY:
     574                                        header->type = ICMP_ECHO;
     575                                        continue;
    553576                                }
    554577                        }
     
    556579                }
    557580        }
    558         switch(header->type){
    559                 case ICMP_ECHOREPLY:
    560                         if(error){
    561                                 return icmp_process_echo_reply(packet, header, type, code);
    562                         }else{
    563                                 return icmp_process_echo_reply(packet, header, ICMP_ECHO, 0);
     581
     582        switch (header->type) {
     583        case ICMP_ECHOREPLY:
     584                if (error)
     585                        icmp_process_echo_reply(packet, header, type, code);
     586                else
     587                        icmp_process_echo_reply(packet, header, ICMP_ECHO, 0);
     588
     589                return EOK;
     590
     591        case ICMP_ECHO:
     592                if (error) {
     593                        icmp_process_echo_reply(packet, header, type, code);
     594                        return EOK;
     595                }
     596               
     597                // do not send a reply if disabled
     598                if (icmp_globals.echo_replying) {
     599                        addrlen = packet_get_addr(packet, &src, NULL);
     600
     601                        // set both addresses to the source one (avoids the
     602                        // source address deletion before setting the
     603                        // destination one)
     604                        if ((addrlen > 0) && (packet_set_addr(packet, src, src,
     605                            (size_t) addrlen) == EOK)) {
     606                                // send the reply
     607                                icmp_send_packet(ICMP_ECHOREPLY, 0, packet,
     608                                    header, 0, 0, 0, 0);
     609                                return EOK;
    564610                        }
    565                 case ICMP_ECHO:
    566                         if(error){
    567                                 return icmp_process_echo_reply(packet, header, type, code);
    568                         // do not send a reply if disabled
    569                         }else if(icmp_globals.echo_replying){
    570                                 addrlen = packet_get_addr(packet, &src, NULL);
    571                                 if((addrlen > 0)
    572                                 // set both addresses to the source one (avoids the source address deletion before setting the destination one)
    573                                         && (packet_set_addr(packet, src, src, (size_t) addrlen) == EOK)){
    574                                         // send the reply
    575                                         icmp_send_packet(ICMP_ECHOREPLY, 0, packet, header, 0, 0, 0, 0);
    576                                         return EOK;
    577                                 }else{
    578                                         return EINVAL;
     611
     612                        return EINVAL;
     613                }
     614
     615                return EPERM;
     616
     617        case ICMP_DEST_UNREACH:
     618        case ICMP_SOURCE_QUENCH:
     619        case ICMP_REDIRECT:
     620        case ICMP_ALTERNATE_ADDR:
     621        case ICMP_ROUTER_ADV:
     622        case ICMP_ROUTER_SOL:
     623        case ICMP_TIME_EXCEEDED:
     624        case ICMP_PARAMETERPROB:
     625        case ICMP_CONVERSION_ERROR:
     626        case ICMP_REDIRECT_MOBILE:
     627        case ICMP_SKIP:
     628        case ICMP_PHOTURIS:
     629                ip_received_error_msg(icmp_globals.ip_phone, -1, packet,
     630                    SERVICE_IP, SERVICE_ICMP);
     631                return EOK;
     632
     633        default:
     634                return ENOTSUP;
     635        }
     636}
     637
     638/** Processes the received ICMP packet.
     639 *
     640 * Is used as an entry point from the underlying IP module.
     641 * Releases the packet on error.
     642 *
     643 * @param device_id     The device identifier. Ignored parameter.
     644 * @param[in,out] packet The received packet.
     645 * @param receiver      The target service. Ignored parameter.
     646 * @param[in] error     The packet error reporting service. Prefixes the
     647 *                      received packet.
     648 * @returns             EOK on success.
     649 * @returns             Other error codes as defined for the
     650 *                      icmp_process_packet() function.
     651 */
     652static int
     653icmp_received_msg_local(device_id_t device_id, packet_t packet,
     654    services_t receiver, services_t error)
     655{
     656        ERROR_DECLARE;
     657
     658        if (ERROR_OCCURRED(icmp_process_packet(packet, error)))
     659                return icmp_release_and_return(packet, ERROR_CODE);
     660
     661        return EOK;
     662}
     663
     664/** Processes the generic client messages.
     665 *
     666 * @param[in] call      The message parameters.
     667 * @returns             EOK on success.
     668 * @returns             ENOTSUP if the message is not known.
     669 * @returns             Other error codes as defined for the packet_translate()
     670 *                      function.
     671 * @returns             Other error codes as defined for the
     672 *                      icmp_destination_unreachable_msg_local() function.
     673 * @returns             Other error codes as defined for the
     674 *                      icmp_source_quench_msg_local() function.
     675 * @returns             Other error codes as defined for the
     676 *                      icmp_time_exceeded_msg_local() function.
     677 * @returns             Other error codes as defined for the
     678 *                      icmp_parameter_problem_msg_local() function.
     679 *
     680 * @see icmp_interface.h
     681 */
     682static 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 */
     731static 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;
    579752                                }
    580                         }else{
    581                                 return EPERM;
    582                         }
    583                 case ICMP_DEST_UNREACH:
    584                 case ICMP_SOURCE_QUENCH:
    585                 case ICMP_REDIRECT:
    586                 case ICMP_ALTERNATE_ADDR:
    587                 case ICMP_ROUTER_ADV:
    588                 case ICMP_ROUTER_SOL:
    589                 case ICMP_TIME_EXCEEDED:
    590                 case ICMP_PARAMETERPROB:
    591                 case ICMP_CONVERSION_ERROR:
    592                 case ICMP_REDIRECT_MOBILE:
    593                 case ICMP_SKIP:
    594                 case ICMP_PHOTURIS:
    595                         ip_received_error_msg(icmp_globals.ip_phone, -1, packet, SERVICE_IP, SERVICE_ICMP);
    596                         return EOK;
    597                 default:
    598                         return ENOTSUP;
    599         }
    600 }
    601 
    602 int icmp_process_echo_reply(packet_t packet, icmp_header_ref header, icmp_type_t type, icmp_code_t code){
    603         int reply_key;
    604         icmp_reply_ref reply;
    605 
    606         // compute the reply key
    607         reply_key = ICMP_GET_REPLY_KEY(header->un.echo.identifier, header->un.echo.sequence_number);
    608         pq_release_remote(icmp_globals.net_phone, packet_get_id(packet));
    609         // lock the globals
    610         fibril_rwlock_write_lock(&icmp_globals.lock);
    611         // find the pending reply
    612         reply = icmp_replies_find(&icmp_globals.replies, reply_key);
    613         if(reply){
    614                 // set the result
    615                 reply->result = type;
    616                 // notify the waiting fibril
    617                 fibril_condvar_signal(&reply->condvar);
    618         }
    619         fibril_rwlock_write_unlock(&icmp_globals.lock);
    620         return EOK;
    621 }
    622 
    623 int icmp_message_standalone(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count){
     753                        } while(icmp_echo_data_find(&icmp_globals.echo_data,
     754                            index) != NULL);
     755
     756                        // found, break immediately
     757                        break;
     758                }
     759        } while(icmp_echo_data_find(&icmp_globals.echo_data, index) != NULL);
     760
     761        echo_data->identifier = index;
     762        echo_data->sequence_number = 0;
     763
     764        return icmp_echo_data_add(&icmp_globals.echo_data, index, echo_data);
     765}
     766
     767/** Processes the client messages.
     768 *
     769 * Remembers the assigned identifier and sequence numbers.
     770 * Runs until the client module disconnects.
     771 *
     772 * @param[in] callid    The message identifier.
     773 * @param[in] call      The message parameters.
     774 * @returns EOK.
     775 *
     776 * @see icmp_interface.h
     777 * @see icmp_api.h
     778 */
     779static int icmp_process_client_messages(ipc_callid_t callid, ipc_call_t call)
     780{
    624781        ERROR_DECLARE;
    625782
    626         packet_t packet;
    627 
    628         *answer_count = 0;
    629         switch(IPC_GET_METHOD(*call)){
    630                 case NET_TL_RECEIVED:
    631                         if(! ERROR_OCCURRED(packet_translate_remote(icmp_globals.net_phone, &packet, IPC_GET_PACKET(call)))){
    632                                 ERROR_CODE = icmp_received_msg(IPC_GET_DEVICE(call), packet, SERVICE_ICMP, IPC_GET_ERROR(call));
    633                         }
    634                         return ERROR_CODE;
    635                 case NET_ICMP_INIT:
    636                         return icmp_process_client_messages(callid, * call);
    637                 default:
    638                         return icmp_process_message(call);
    639         }
    640         return ENOTSUP;
    641 }
    642 
    643 int icmp_process_client_messages(ipc_callid_t callid, ipc_call_t call){
    644         ERROR_DECLARE;
    645 
    646783        bool keep_on_going = true;
    647 //      fibril_rwlock_t                 lock;
    648784        ipc_call_t answer;
    649785        int answer_count;
    650786        size_t length;
    651         struct sockaddr * addr;
     787        struct sockaddr *addr;
    652788        ipc_callid_t data_callid;
    653789        icmp_echo_ref echo_data;
     
    661797        answer_count = 0;
    662798
    663 //      fibril_rwlock_initialize(&lock);
    664 
    665799        echo_data = (icmp_echo_ref) malloc(sizeof(*echo_data));
    666         if(! echo_data){
     800        if (!echo_data)
    667801                return ENOMEM;
    668         }
    669802
    670803        // assign a new identifier
     
    672805        res = icmp_bind_free_id(echo_data);
    673806        fibril_rwlock_write_unlock(&icmp_globals.lock);
    674         if(res < 0){
     807        if (res < 0) {
    675808                free(echo_data);
    676809                return res;
    677810        }
    678811
    679         while(keep_on_going){
    680 
     812        while (keep_on_going) {
    681813                // answer the call
    682814                answer_call(callid, res, &answer, answer_count);
     
    689821
    690822                // process the call
    691                 switch(IPC_GET_METHOD(call)){
    692                         case IPC_M_PHONE_HUNGUP:
    693                                 keep_on_going = false;
    694                                 res = EHANGUP;
     823                switch (IPC_GET_METHOD(call)) {
     824                case IPC_M_PHONE_HUNGUP:
     825                        keep_on_going = false;
     826                        res = EHANGUP;
     827                        break;
     828               
     829                case NET_ICMP_ECHO:
     830                        if (!async_data_write_receive(&data_callid, &length)) {
     831                                res = EINVAL;
    695832                                break;
    696                         case NET_ICMP_ECHO:
    697 //                              fibril_rwlock_write_lock(&lock);
    698                                 if(! async_data_write_receive(&data_callid, &length)){
    699                                         res = EINVAL;
    700                                 }else{
    701                                         addr = malloc(length);
    702                                         if(! addr){
    703                                                 res = ENOMEM;
    704                                         }else{
    705                                                 if(! ERROR_OCCURRED(async_data_write_finalize(data_callid, addr, length))){
    706                                                         fibril_rwlock_write_lock(&icmp_globals.lock);
    707                                                         res = icmp_echo(echo_data->identifier, echo_data->sequence_number, ICMP_GET_SIZE(call), ICMP_GET_TIMEOUT(call), ICMP_GET_TTL(call), ICMP_GET_TOS(call), ICMP_GET_DONT_FRAGMENT(call), addr, (socklen_t) length);
    708                                                         fibril_rwlock_write_unlock(&icmp_globals.lock);
    709                                                         free(addr);
    710                                                         if(echo_data->sequence_number < UINT16_MAX){
    711                                                                 ++ echo_data->sequence_number;
    712                                                         }else{
    713                                                                 echo_data->sequence_number = 0;
    714                                                         }
    715                                                 }else{
    716                                                         res = ERROR_CODE;
    717                                                 }
    718                                         }
    719                                 }
    720 //                              fibril_rwlock_write_unlock(&lock);
     833                        }
     834                       
     835                        addr = malloc(length);
     836                        if (!addr) {
     837                                res = ENOMEM;
    721838                                break;
    722                         default:
    723                                 res = icmp_process_message(&call);
    724                 }
     839                        }
     840                       
     841                        if (ERROR_OCCURRED(async_data_write_finalize(
     842                            data_callid, addr, length))) {
     843                                free(addr);
     844                                res = ERROR_CODE;
     845                                break;
     846                        }
     847
     848                        fibril_rwlock_write_lock(&icmp_globals.lock);
     849                        res = icmp_echo(echo_data->identifier,
     850                            echo_data->sequence_number, ICMP_GET_SIZE(call),
     851                            ICMP_GET_TIMEOUT(call), ICMP_GET_TTL(call),
     852                            ICMP_GET_TOS(call), ICMP_GET_DONT_FRAGMENT(call),
     853                            addr, (socklen_t) length);
     854                        fibril_rwlock_write_unlock(&icmp_globals.lock);
     855
     856                        free(addr);
     857
     858                        if (echo_data->sequence_number < UINT16_MAX)
     859                                echo_data->sequence_number++;
     860                        else
     861                                echo_data->sequence_number = 0;
     862
     863                        break;
     864
     865                default:
     866                        res = icmp_process_message(&call);
     867                }
     868
    725869        }
    726870
     
    729873        icmp_echo_data_exclude(&icmp_globals.echo_data, echo_data->identifier);
    730874        fibril_rwlock_write_unlock(&icmp_globals.lock);
     875
    731876        return res;
    732877}
    733878
    734 int icmp_process_message(ipc_call_t * call){
     879/** Processes the ICMP message.
     880 *
     881 * @param[in] callid    The message identifier.
     882 * @param[in] call      The message parameters.
     883 * @param[out] answer   The message answer parameters.
     884 * @param[out] answer_count The last parameter for the actual answer in the
     885 *                      answer parameter.
     886 * @returns             EOK on success.
     887 * @returns             ENOTSUP if the message is not known.
     888 *
     889 * @see icmp_interface.h
     890 * @see IS_NET_ICMP_MESSAGE()
     891 */
     892int
     893icmp_message_standalone(ipc_callid_t callid, ipc_call_t *call,
     894    ipc_call_t *answer, int *answer_count)
     895{
    735896        ERROR_DECLARE;
    736897
    737898        packet_t packet;
    738899
    739         switch(IPC_GET_METHOD(*call)){
    740                 case NET_ICMP_DEST_UNREACH:
    741                         if(! ERROR_OCCURRED(packet_translate_remote(icmp_globals.net_phone, &packet, IPC_GET_PACKET(call)))){
    742                                 ERROR_CODE = icmp_destination_unreachable_msg(0, ICMP_GET_CODE(call), ICMP_GET_MTU(call), packet);
    743                         }
    744                         return ERROR_CODE;
    745                 case NET_ICMP_SOURCE_QUENCH:
    746                         if(! ERROR_OCCURRED(packet_translate_remote(icmp_globals.net_phone, &packet, IPC_GET_PACKET(call)))){
    747                                 ERROR_CODE = icmp_source_quench_msg(0, packet);
    748                         }
    749                         return ERROR_CODE;
    750                 case NET_ICMP_TIME_EXCEEDED:
    751                         if(! ERROR_OCCURRED(packet_translate_remote(icmp_globals.net_phone, &packet, IPC_GET_PACKET(call)))){
    752                                 ERROR_CODE = icmp_time_exceeded_msg(0, ICMP_GET_CODE(call), packet);
    753                         }
    754                         return ERROR_CODE;
    755                 case NET_ICMP_PARAMETERPROB:
    756                         if(! ERROR_OCCURRED(packet_translate_remote(icmp_globals.net_phone, &packet, IPC_GET_PACKET(call)))){
    757                                 ERROR_CODE = icmp_parameter_problem_msg(0, ICMP_GET_CODE(call), ICMP_GET_POINTER(call), packet);
    758                         }
    759                         return ERROR_CODE;
    760                 default:
    761                         return ENOTSUP;
    762         }
    763 }
    764 
    765 int icmp_release_and_return(packet_t packet, int result){
    766         pq_release_remote(icmp_globals.net_phone, packet_get_id(packet));
    767         return result;
    768 }
    769 
    770 int icmp_bind_free_id(icmp_echo_ref echo_data){
    771         icmp_param_t index;
    772 
    773         if(! echo_data){
    774                 return EBADMEM;
    775         }
    776         // from the last used one
    777         index = icmp_globals.last_used_id;
    778         do{
    779                 ++ index;
    780                 // til the range end
    781                 if(index >= ICMP_FREE_IDS_END){
    782                         // start from the range beginning
    783                         index = ICMP_FREE_IDS_START - 1;
    784                         do{
    785                                 ++ index;
    786                                 // til the last used one
    787                                 if(index >= icmp_globals.last_used_id){
    788                                         // none found
    789                                         return ENOTCONN;
    790                                 }
    791                         }while(icmp_echo_data_find(&icmp_globals.echo_data, index) != NULL);
    792                         // found, break immediately
    793                         break;
    794                 }
    795         }while(icmp_echo_data_find(&icmp_globals.echo_data, index) != NULL);
    796         echo_data->identifier = index;
    797         echo_data->sequence_number = 0;
    798         return icmp_echo_data_add(&icmp_globals.echo_data, index, echo_data);
    799 }
     900        *answer_count = 0;
     901        switch (IPC_GET_METHOD(*call)) {
     902        case NET_TL_RECEIVED:
     903                if (ERROR_NONE(packet_translate_remote(icmp_globals.net_phone,
     904                    &packet, IPC_GET_PACKET(call)))) {
     905                        ERROR_CODE =
     906                            icmp_received_msg_local(IPC_GET_DEVICE(call),
     907                            packet, SERVICE_ICMP, IPC_GET_ERROR(call));
     908                }
     909                return ERROR_CODE;
     910       
     911        case NET_ICMP_INIT:
     912                return icmp_process_client_messages(callid, * call);
     913       
     914        default:
     915                return icmp_process_message(call);
     916        }
     917
     918        return ENOTSUP;
     919}
     920
    800921
    801922/** Default thread for new connections.
    802923 *
    803  *  @param[in] iid The initial message identifier.
    804  *  @param[in] icall The initial message call structure.
    805  *
    806  */
    807 static void tl_client_connection(ipc_callid_t iid, ipc_call_t * icall)
     924 * @param[in] iid The initial message identifier.
     925 * @param[in] icall The initial message call structure.
     926 *
     927 */
     928static void tl_client_connection(ipc_callid_t iid, ipc_call_t *icall)
    808929{
    809930        /*
     
    813934        ipc_answer_0(iid, EOK);
    814935       
    815         while(true) {
     936        while (true) {
    816937                ipc_call_t answer;
    817938                int answer_count;
     
    828949                    &answer_count);
    829950               
    830                 /* End if said to either by the message or the processing result */
    831                 if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) || (res == EHANGUP))
     951                /*
     952                 * End if told to either by the message or the processing
     953                 * result.
     954                 */
     955                if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) ||
     956                    (res == EHANGUP))
    832957                        return;
    833958               
     
    839964/** Starts the module.
    840965 *
    841  *  @param argc The count of the command line arguments. Ignored parameter.
    842  *  @param argv The command line parameters. Ignored parameter.
    843  *
    844  *  @returns EOK on success.
    845  *  @returns Other error codes as defined for each specific module start function.
    846  *
     966 * @returns             EOK on success.
     967 * @returns             Other error codes as defined for each specific module
     968 *                      start function.
    847969 */
    848970int main(int argc, char *argv[])
     
    851973       
    852974        /* Start the module */
    853         if (ERROR_OCCURRED(tl_module_start_standalone(tl_client_connection)))
    854                 return ERROR_CODE;
    855        
     975        ERROR_PROPAGATE(tl_module_start_standalone(tl_client_connection));
    856976        return EOK;
    857977}
     
    859979/** @}
    860980 */
     981
  • uspace/srv/net/tl/icmp/icmp.h

    re06ef614 r49d819b4  
    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>
    4344#include <adt/int_map.h>
    4445#include <icmp_header.h>
    4546
    4647/** Type definition of the ICMP reply data.
    47  *  @see icmp_reply
     48 * @see icmp_reply
    4849 */
    49 typedef struct icmp_reply       icmp_reply_t;
     50typedef struct icmp_reply icmp_reply_t;
    5051
    5152/** Type definition of the ICMP reply data pointer.
    52  *  @see icmp_reply
     53 * @see icmp_reply
    5354 */
    54 typedef icmp_reply_t *  icmp_reply_ref;
     55typedef icmp_reply_t *icmp_reply_ref;
    5556
    5657/** Type definition of the ICMP global data.
    57  *  @see icmp_globals
     58 * @see icmp_globals
    5859 */
    59 typedef struct icmp_globals     icmp_globals_t;
     60typedef struct icmp_globals icmp_globals_t;
    6061
    6162/** Pending replies map.
    62  *  Maps message identifiers to the pending replies.
    63  *  Sending fibril waits for its associated reply event.
    64  *  Receiving fibril sets the associated reply with the return value and signals the event.
     63 *
     64 * Maps message identifiers to the pending replies.
     65 * Sending fibril waits for its associated reply event.
     66 * Receiving fibril sets the associated reply with the return value and signals
     67 * the event.
    6568 */
    6669INT_MAP_DECLARE(icmp_replies, icmp_reply_t);
    6770
    6871/** Echo specific data map.
    69  *  The identifier is used in the future semi-remote calls instead of the ICMP phone.
     72 *
     73 * The identifier is used in the future semi-remote calls instead of the ICMP
     74 * phone.
    7075 */
    7176INT_MAP_DECLARE(icmp_echo_data, icmp_echo_t);
    7277
    73 /** ICMP reply data.
    74  */
    75 struct icmp_reply{
    76         /** Reply result.
    77          */
     78/** ICMP reply data. */
     79struct icmp_reply {
     80        /** Reply result. */
    7881        int result;
    79         /** Safety lock.
    80          */
     82        /** Safety lock. */
    8183        fibril_mutex_t mutex;
    82         /** Received or timeouted reply signaling.
    83          */
     84        /** Received or timeouted reply signaling. */
    8485        fibril_condvar_t condvar;
    8586};
    8687
    87 /** ICMP global data.
    88  */
    89 struct  icmp_globals{
    90         /** IP module phone.
    91          */
     88/** ICMP global data. */
     89struct icmp_globals {
     90        /** IP module phone. */
    9291        int ip_phone;
    93         /** Packet dimension.
    94          */
     92        /** Packet dimension. */
    9593        packet_dimension_t packet_dimension;
    96         /** Networking module phone.
    97          */
     94        /** Networking module phone. */
    9895        int net_phone;
    99         /** Indicates whether ICMP error reporting is enabled.
    100          */
     96        /** Indicates whether ICMP error reporting is enabled. */
    10197        int error_reporting;
    102         /** Indicates whether ICMP echo replying (ping) is enabled.
    103          */
     98        /** Indicates whether ICMP echo replying (ping) is enabled. */
    10499        int echo_replying;
    105         /** The last used identifier number.
    106          */
     100        /** The last used identifier number. */
    107101        icmp_param_t last_used_id;
    108         /** The budled modules assigned echo specific data.
    109          */
     102        /** The budled modules assigned echo specific data. */
    110103        icmp_echo_data_t echo_data;
    111         /** Echo timeout locks.
    112          */
     104        /** Echo timeout locks. */
    113105        icmp_replies_t replies;
    114         /** Safety lock.
    115          */
     106        /** Safety lock. */
    116107        fibril_rwlock_t lock;
    117108};
     
    121112/** @}
    122113 */
    123 
  • uspace/srv/net/tl/icmp/icmp_module.c

    re06ef614 r49d819b4  
    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"
    3942
    4043#include <async.h>
     
    4750#include <net/packet.h>
    4851#include <net_interface.h>
     52
    4953#include <tl_local.h>
    5054
    51 #include "icmp.h"
    52 #include "icmp_module.h"
     55/** ICMP module global data. */
     56extern icmp_globals_t icmp_globals;
    5357
    54 /** ICMP module global data.
    55  */
    56 extern icmp_globals_t   icmp_globals;
    57 
    58 /** Starts the ICMP module.
    59  *  Initializes the client connection serving function, initializes the module, registers the module service and starts the async manager, processing IPC messages in an infinite loop.
    60  *  @param[in] client_connection The client connection processing function. The module skeleton propagates its own one.
    61  *  @returns EOK on successful module termination.
    62  *  @returns Other error codes as defined for the arp_initialize() function.
    63  *  @returns Other error codes as defined for the REGISTER_ME() macro function.
    64  */
    65 int tl_module_start_standalone(async_client_conn_t client_connection){
     58int tl_module_start_standalone(async_client_conn_t client_connection)
     59{
    6660        ERROR_DECLARE;
    6761
     
    7064        async_set_client_connection(client_connection);
    7165        icmp_globals.net_phone = net_connect_module();
    72         if(icmp_globals.net_phone < 0){
     66        if (icmp_globals.net_phone < 0)
    7367                return icmp_globals.net_phone;
    74         }
     68
    7569        ERROR_PROPAGATE(pm_init());
    76         if(ERROR_OCCURRED(icmp_initialize(client_connection))
    77                 || ERROR_OCCURRED(REGISTER_ME(SERVICE_ICMP, &phonehash))){
     70        if (ERROR_OCCURRED(icmp_initialize(client_connection)) ||
     71            ERROR_OCCURRED(REGISTER_ME(SERVICE_ICMP, &phonehash))) {
    7872                pm_destroy();
    7973                return ERROR_CODE;
     
    8680}
    8781
    88 /** Processes the ICMP message.
    89  *  @param[in] callid The message identifier.
    90  *  @param[in] call The message parameters.
    91  *  @param[out] answer The message answer parameters.
    92  *  @param[out] answer_count The last parameter for the actual answer in the answer parameter.
    93  *  @returns EOK on success.
    94  *  @returns Other error codes as defined for the icmp_message() function.
    95  */
    96 int tl_module_message_standalone(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count){
     82int
     83tl_module_message_standalone(ipc_callid_t callid, ipc_call_t *call,
     84    ipc_call_t *answer, int *answer_count)
     85{
    9786        return icmp_message_standalone(callid, call, answer, answer_count);
    9887}
     
    10089/** @}
    10190 */
     91
  • uspace/srv/net/tl/icmp/icmp_module.h

    re06ef614 r49d819b4  
    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 /** Initializes the ICMP module.
    45  *  @param[in] client_connection The client connection processing function. The module skeleton propagates its own one.
    46  *  @returns EOK on success.
    47  *  @returns ENOMEM if there is not enough memory left.
    48  */
    49 int icmp_initialize(async_client_conn_t client_connection);
    50 
    51 /** Processes the ICMP message.
    52  *  @param[in] callid The message identifier.
    53  *  @param[in] call The message parameters.
    54  *  @param[out] answer The message answer parameters.
    55  *  @param[out] answer_count The last parameter for the actual answer in the answer parameter.
    56  *  @returns EOK on success.
    57  *  @returns ENOTSUP if the message is not known.
    58  *  @see icmp_interface.h
    59  *  @see IS_NET_ICMP_MESSAGE()
    60  */
    61 int icmp_message_standalone(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count);
     44extern int icmp_initialize(async_client_conn_t);
     45extern int icmp_message_standalone(ipc_callid_t, ipc_call_t *, ipc_call_t *,
     46    int *);
    6247
    6348#endif
  • uspace/srv/net/tl/tcp/tcp.c

    re06ef614 r49d819b4  
    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"
    3741
    3842#include <assert.h>
     
    7276#include <tl_interface.h>
    7377
    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  *  @param[in] lower The last value before the interval.
    116  *  @param[in] value The value to be checked.
    117  *  @param[in] higher_equal The last value in the interval.
     114 * The high end and/or the value may overflow, be lower than the low value.
     115 *
     116 * @param[in] lower     The last value before the interval.
     117 * @param[in] value     The value to be checked.
     118 * @param[in] higher_equal The last value in the interval.
    118119 */
    119120#define IS_IN_INTERVAL_OVERFLOW(lower, value, higher_equal) \
     
    165166};
    166167
    167 /** Releases the packet and returns the result.
    168  *  @param[in] packet The packet queue to be released.
    169  *  @param[in] result The result to be returned.
    170  *  @return The result parameter.
    171  */
    172 int tcp_release_and_return(packet_t packet, int result);
    173 
    174 void tcp_prepare_operation_header(socket_core_ref socket,
    175     tcp_socket_data_ref socket_data, tcp_header_ref header, int synchronize,
    176     int finalize);
    177 int tcp_prepare_timeout(int (*timeout_function)(void *tcp_timeout_t),
    178     socket_core_ref socket, tcp_socket_data_ref socket_data,
    179     size_t sequence_number, tcp_socket_state_t state, suseconds_t timeout,
    180     int globals_read_only);
    181 void tcp_free_socket_data(socket_core_ref socket);
    182 
    183 int tcp_timeout(void *data);
    184 
    185 int tcp_release_after_timeout(void *data);
    186 
    187 int tcp_process_packet(device_id_t device_id, packet_t packet,
    188     services_t error);
    189 int tcp_connect_core(socket_core_ref socket, socket_cores_ref local_sockets,
    190     struct sockaddr *addr, socklen_t addrlen);
    191 int tcp_queue_prepare_packet(socket_core_ref socket,
    192     tcp_socket_data_ref socket_data, packet_t packet, size_t data_length);
    193 int tcp_queue_packet(socket_core_ref socket, tcp_socket_data_ref socket_data,
    194     packet_t packet, size_t data_length);
    195 packet_t tcp_get_packets_to_send(socket_core_ref socket,
    196     tcp_socket_data_ref socket_data);
    197 void tcp_send_packets(device_id_t device_id, packet_t packet);
    198 
    199 void tcp_process_acknowledgement(socket_core_ref socket,
    200     tcp_socket_data_ref socket_data, tcp_header_ref header);
    201 packet_t tcp_send_prepare_packet(socket_core_ref socket,
    202     tcp_socket_data_ref socket_data, packet_t packet, size_t data_length,
    203     size_t sequence_number);
    204 packet_t tcp_prepare_copy(socket_core_ref socket,
    205     tcp_socket_data_ref socket_data, packet_t packet, size_t data_length,
    206     size_t sequence_number);
    207 void tcp_retransmit_packet(socket_core_ref socket,
    208     tcp_socket_data_ref socket_data, size_t sequence_number);
    209 int tcp_create_notification_packet(packet_t * packet, socket_core_ref socket,
    210     tcp_socket_data_ref socket_data, int synchronize, int finalize);
    211 void tcp_refresh_socket_data(tcp_socket_data_ref socket_data);
    212 
    213 void tcp_initialize_socket_data(tcp_socket_data_ref socket_data);
    214 
    215 int tcp_process_listen(socket_core_ref listening_socket,
    216     tcp_socket_data_ref listening_socket_data, tcp_header_ref header,
    217     packet_t packet, struct sockaddr *src, struct sockaddr *dest,
    218     size_t addrlen);
    219 int tcp_process_syn_sent(socket_core_ref socket,
    220     tcp_socket_data_ref socket_data, tcp_header_ref header, packet_t packet);
    221 int tcp_process_syn_received(socket_core_ref socket,
    222     tcp_socket_data_ref socket_data, tcp_header_ref header, packet_t packet);
    223 int tcp_process_established(socket_core_ref socket,
    224     tcp_socket_data_ref socket_data, tcp_header_ref header, packet_t packet,
    225     int fragments, size_t total_length);
    226 int tcp_queue_received_packet(socket_core_ref socket,
    227     tcp_socket_data_ref socket_data, packet_t packet, int fragments,
    228     size_t total_length);
    229 
    230 int tcp_received_msg(device_id_t device_id, packet_t packet,
    231     services_t receiver, services_t error);
    232 int tcp_process_client_messages(ipc_callid_t callid, ipc_call_t call);
    233 
    234 int tcp_listen_message(socket_cores_ref local_sockets, int socket_id,
    235     int backlog);
    236 int tcp_connect_message(socket_cores_ref local_sockets, int socket_id,
    237     struct sockaddr *addr, socklen_t addrlen);
    238 int tcp_recvfrom_message(socket_cores_ref local_sockets, int socket_id,
    239     int flags, size_t * addrlen);
    240 int tcp_send_message(socket_cores_ref local_sockets, int socket_id,
    241     int fragments, size_t * data_fragment_size, int flags);
    242 int tcp_accept_message(socket_cores_ref local_sockets, int socket_id,
    243     int new_socket_id, size_t * data_fragment_size, size_t * addrlen);
    244 int tcp_close_message(socket_cores_ref local_sockets, int socket_id);
     168static int tcp_release_and_return(packet_t, int);
     169static void tcp_prepare_operation_header(socket_core_ref, tcp_socket_data_ref,
     170    tcp_header_ref, int synchronize, int);
     171static int tcp_prepare_timeout(int (*)(void *), socket_core_ref,
     172    tcp_socket_data_ref, size_t, tcp_socket_state_t, suseconds_t, int);
     173static void tcp_free_socket_data(socket_core_ref);
     174
     175static int tcp_timeout(void *);
     176
     177static int tcp_release_after_timeout(void *);
     178
     179static int tcp_process_packet(device_id_t, packet_t, services_t);
     180static int tcp_connect_core(socket_core_ref, socket_cores_ref,
     181    struct sockaddr *, socklen_t);
     182static int tcp_queue_prepare_packet(socket_core_ref, tcp_socket_data_ref,
     183    packet_t, size_t);
     184static int tcp_queue_packet(socket_core_ref, tcp_socket_data_ref, packet_t,
     185    size_t);
     186static packet_t tcp_get_packets_to_send(socket_core_ref, tcp_socket_data_ref);
     187static void tcp_send_packets(device_id_t, packet_t);
     188
     189static void tcp_process_acknowledgement(socket_core_ref, tcp_socket_data_ref,
     190    tcp_header_ref);
     191static packet_t tcp_send_prepare_packet(socket_core_ref, tcp_socket_data_ref,
     192    packet_t, size_t, size_t);
     193static 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);
     197static int tcp_create_notification_packet(packet_t *, socket_core_ref,
     198    tcp_socket_data_ref, int, int);
     199static void tcp_refresh_socket_data(tcp_socket_data_ref);
     200
     201static void tcp_initialize_socket_data(tcp_socket_data_ref);
     202
     203static int tcp_process_listen(socket_core_ref, tcp_socket_data_ref,
     204    tcp_header_ref, packet_t, struct sockaddr *, struct sockaddr *, size_t);
     205static int tcp_process_syn_sent(socket_core_ref, tcp_socket_data_ref,
     206    tcp_header_ref, packet_t);
     207static int tcp_process_syn_received(socket_core_ref, tcp_socket_data_ref,
     208    tcp_header_ref, packet_t);
     209static int tcp_process_established(socket_core_ref, tcp_socket_data_ref,
     210    tcp_header_ref, packet_t, int, size_t);
     211static int tcp_queue_received_packet(socket_core_ref, tcp_socket_data_ref,
     212    packet_t, int, size_t);
     213
     214static int tcp_received_msg(device_id_t, packet_t, services_t, services_t);
     215static int tcp_process_client_messages(ipc_callid_t, ipc_call_t);
     216
     217static int tcp_listen_message(socket_cores_ref, int, int);
     218static int tcp_connect_message(socket_cores_ref, int, struct sockaddr *,
     219    socklen_t);
     220static int tcp_recvfrom_message(socket_cores_ref, int, int, size_t *);
     221static int tcp_send_message(socket_cores_ref, int, int, size_t *, int);
     222static int tcp_accept_message(socket_cores_ref, int, int, size_t *, size_t *);
     223static int tcp_close_message(socket_cores_ref, int);
    245224
    246225/** TCP global data. */
    247226tcp_globals_t tcp_globals;
    248227
     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 */
    249235int tcp_initialize(async_client_conn_t client_connection)
    250236{
     
    314300        size_t addrlen;
    315301
    316         if (error) {
    317                 switch (error) {
    318                 case SERVICE_ICMP:
    319                         // process error
    320                         result = icmp_client_process_packet(packet, &type,
    321                             &code, NULL, NULL);
    322                         if (result < 0)
    323                                 return tcp_release_and_return(packet, result);
    324 
    325                         length = (size_t) result;
    326                         if (ERROR_OCCURRED(packet_trim(packet, length, 0))) {
    327                                 return tcp_release_and_return(packet,
    328                                     ERROR_CODE);
    329                         }
    330                         break;
    331 
    332                 default:
    333                         return tcp_release_and_return(packet, ENOTSUP);
    334                 }
     302        switch (error) {
     303        case SERVICE_NONE:
     304                break;
     305        case SERVICE_ICMP:
     306                // process error
     307                result = icmp_client_process_packet(packet, &type, &code, NULL,
     308                    NULL);
     309                if (result < 0)
     310                        return tcp_release_and_return(packet, result);
     311
     312                length = (size_t) result;
     313                if (ERROR_OCCURRED(packet_trim(packet, length, 0)))
     314                        return tcp_release_and_return(packet, ERROR_CODE);
     315                break;
     316        default:
     317                return tcp_release_and_return(packet, ENOTSUP);
    335318        }
    336319
     
    379362                    ntohs(header->destination_port), SOCKET_MAP_KEY_LISTENING,
    380363                    0);
    381                 if (!socket) {
    382                         if (tl_prepare_icmp_packet(tcp_globals.net_phone,
    383                             tcp_globals.icmp_phone, packet, error) == EOK) {
    384                                 icmp_destination_unreachable_msg(
    385                                     tcp_globals.icmp_phone, ICMP_PORT_UNREACH,
    386                                     0, packet);
    387                         }
    388                         return EADDRNOTAVAIL;
    389                 }
    390         }
     364        }
     365        if (!socket) {
     366                if (tl_prepare_icmp_packet(tcp_globals.net_phone,
     367                    tcp_globals.icmp_phone, packet, error) == EOK) {
     368                        icmp_destination_unreachable_msg(tcp_globals.icmp_phone,
     369                            ICMP_PORT_UNREACH, 0, packet);
     370                }
     371                return EADDRNOTAVAIL;
     372        }
     373
    391374        printf("socket id %d\n", socket->socket_id);
    392375        socket_data = (tcp_socket_data_ref) socket->specific_data;
     
    402385        total_length = 0;
    403386        do {
    404                 ++fragments;
     387                fragments++;
    405388                length = packet_get_data_length(next_packet);
    406389                if (length <= 0)
     
    421404
    422405        if (error)
    423                 goto error;
     406                goto has_error_service;
    424407       
    425408        if (socket_data->state == TCP_SOCKET_LISTEN) {
    426 
    427409                if (socket_data->pseudo_header) {
    428410                        free(socket_data->pseudo_header);
     
    464446        }
    465447
    466 error:
     448has_error_service:
    467449        fibril_rwlock_read_unlock(&tcp_globals.lock);
    468450
     
    507489int
    508490tcp_process_established(socket_core_ref socket, tcp_socket_data_ref socket_data,
    509     tcp_header_ref header, packet_t packet, int fragments,
    510     size_t total_length)
     491    tcp_header_ref header, packet_t packet, int fragments, size_t total_length)
    511492{
    512493        ERROR_DECLARE;
     
    684665                                        continue;
    685666                                        // at least partly following data?
    686                                 } else if (IS_IN_INTERVAL_OVERFLOW(
    687                                     sequence_number, socket_data->next_incoming,
    688                                     new_sequence_number)) {
     667                                }
     668                                if (IS_IN_INTERVAL_OVERFLOW(sequence_number,
     669                                    socket_data->next_incoming, new_sequence_number)) {
    689670                                        if (socket_data->next_incoming <
    690671                                            new_sequence_number) {
     
    961942        listening_socket = socket_port_find(&tcp_globals.sockets,
    962943            listening_port, SOCKET_MAP_KEY_LISTENING, 0);
    963         if ((!listening_socket) ||
     944        if (!listening_socket ||
    964945            (listening_socket->socket_id != listening_socket_id)) {
    965946                fibril_rwlock_write_unlock(&tcp_globals.lock);
     
    11911172        if (number == socket_data->expected) {
    11921173                // increase the counter
    1193                 ++socket_data->expected_count;
     1174                socket_data->expected_count++;
    11941175                if (socket_data->expected_count == TCP_FAST_RETRANSMIT_COUNT) {
    11951176                        socket_data->expected_count = 1;
     
    12001181}
    12011182
    1202 int tcp_message_standalone(ipc_callid_t callid, ipc_call_t * call,
    1203     ipc_call_t * answer, int *answer_count)
     1183/** Processes the TCP message.
     1184 *
     1185 * @param[in] callid    The message identifier.
     1186 * @param[in] call      The message parameters.
     1187 * @param[out] answer   The message answer parameters.
     1188 * @param[out] answer_count The last parameter for the actual answer in the
     1189 *                      answer parameter.
     1190 * @returns             EOK on success.
     1191 * @returns             ENOTSUP if the message is not known.
     1192 *
     1193 * @see tcp_interface.h
     1194 * @see IS_NET_TCP_MESSAGE()
     1195 */
     1196int
     1197tcp_message_standalone(ipc_callid_t callid, ipc_call_t *call,
     1198    ipc_call_t *answer, int *answer_count)
    12041199{
    12051200        ERROR_DECLARE;
     
    15211516        socket = socket_port_find(&tcp_globals.sockets, timeout->port,
    15221517            timeout->key, timeout->key_length);
    1523         if (!(socket && (socket->socket_id == timeout->socket_id)))
     1518        if (!socket || (socket->socket_id != timeout->socket_id))
    15241519                goto out;
    15251520       
     
    15321527        if (timeout->sequence_number) {
    15331528                // increase the timeout counter;
    1534                 ++socket_data->timeout_count;
     1529                socket_data->timeout_count++;
    15351530                if (socket_data->timeout_count == TCP_MAX_TIMEOUTS) {
    15361531                        // TODO release as connection lost
     
    17441739            ERROR_OCCURRED(tcp_prepare_timeout(tcp_timeout, socket, socket_data,
    17451740            0, TCP_SOCKET_INITIAL, NET_DEFAULT_TCP_INITIAL_TIMEOUT, false))) {
    1746 
    17471741                socket_data->addr = NULL;
    17481742                socket_data->addrlen = 0;
    17491743                fibril_rwlock_write_lock(&tcp_globals.lock);
    1750 
    17511744        } else {
    1752 
    17531745                packet = tcp_get_packets_to_send(socket, socket_data);
    17541746                if (packet) {
     
    18761868                packet = pq_next(packet);
    18771869                // overflow occurred ?
    1878                 if ((!packet) &&
     1870                if (!packet &&
    18791871                    (socket_data->last_outgoing > socket_data->next_outgoing)) {
    18801872                        printf("gpts overflow\n");
     
    20442036int
    20452037tcp_recvfrom_message(socket_cores_ref local_sockets, int socket_id, int flags,
    2046     size_t * addrlen)
     2038    size_t *addrlen)
    20472039{
    20482040        ERROR_DECLARE;
     
    20992091int
    21002092tcp_send_message(socket_cores_ref local_sockets, int socket_id, int fragments,
    2101     size_t * data_fragment_size, int flags)
     2093    size_t *data_fragment_size, int flags)
    21022094{
    21032095        ERROR_DECLARE;
     
    21382130            packet_dimension->content : socket_data->data_fragment_size);
    21392131
    2140         for (index = 0; index < fragments; ++index) {
     2132        for (index = 0; index < fragments; index++) {
    21412133                // read the data fragment
    21422134                result = tl_socket_read_packet_data(tcp_globals.net_phone,
     
    22352227
    22362228int
    2237 tcp_create_notification_packet(packet_t * packet, socket_core_ref socket,
     2229tcp_create_notification_packet(packet_t *packet, socket_core_ref socket,
    22382230    tcp_socket_data_ref socket_data, int synchronize, int finalize)
    22392231{
     
    22712263int
    22722264tcp_accept_message(socket_cores_ref local_sockets, int socket_id,
    2273     int new_socket_id, size_t * data_fragment_size, size_t * addrlen)
     2265    int new_socket_id, size_t *data_fragment_size, size_t *addrlen)
    22742266{
    22752267        ERROR_DECLARE;
     
    23732365}
    23742366
     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 */
    23752373int tcp_release_and_return(packet_t packet, int result)
    23762374{
     
    23812379/** Default thread for new connections.
    23822380 *
    2383  *  @param[in] iid The initial message identifier.
    2384  *  @param[in] icall The initial message call structure.
     2381 * @param[in] iid       The initial message identifier.
     2382 * @param[in] icall     The initial message call structure.
    23852383 *
    23862384 */
     
    23972395                int answer_count;
    23982396
    2399                 /*
    2400                    Clear the answer structure
    2401                  */
     2397                /* Clear the answer structure */
    24022398                refresh_answer(&answer, &answer_count);
    24032399
    2404                 /*
    2405                    Fetch the next message
    2406                  */
     2400                /* Fetch the next message */
    24072401                ipc_call_t call;
    24082402                ipc_callid_t callid = async_get_call(&call);
    24092403
    2410                 /*
    2411                    Process the message
    2412                  */
     2404                /* Process the message */
    24132405                int res = tl_module_message_standalone(callid, &call, &answer,
    24142406                    &answer_count);
    24152407
    24162408                /*
    2417                    End if said to either by the message or the processing result
     2409                 * End if told to either by the message or the processing
     2410                 * result.
    24182411                 */
    24192412                if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) ||
     
    24302423/** Starts the module.
    24312424 *
    2432  *  @param argc The count of the command line arguments. Ignored parameter.
    2433  *  @param argv The command line parameters. Ignored parameter.
    2434  *
    2435  *  @returns EOK on success.
    2436  *  @returns Other error codes as defined for each specific module start function.
    2437  *
     2425 * @returns             EOK on success.
     2426 * @returns             Other error codes as defined for each specific module
     2427 *                      start function.
    24382428 */
    24392429int
  • uspace/srv/net/tl/tcp/tcp.h

    re06ef614 r49d819b4  
    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  */
    79 enum tcp_socket_state{
     73 * @see tcp_socket_state
     74 */
     75typedef enum tcp_socket_state tcp_socket_state_t;
     76
     77/** TCP socket state. */
     78enum tcp_socket_state {
    8079        /** Initial.
    81          *  Not connected or bound.
     80         *
     81         * Not connected or bound.
    8282         */
    8383        TCP_SOCKET_INITIAL,
     84       
    8485        /** Listening.
    85          *  Awaiting a connection request from another TCP layer.
    86          *  When SYN is received a new bound socket in the TCP_SOCKET_SYN_RECEIVED state should be created.
     86         *
     87         * Awaiting a connection request from another TCP layer.
     88         * When SYN is received a new bound socket in the
     89         * TCP_SOCKET_SYN_RECEIVED state should be created.
    8790         */
    8891        TCP_SOCKET_LISTEN,
     92       
    8993        /** Connecting issued.
    90          *  A~SYN has been sent, and TCP is awaiting the response SYN.
    91          *  Should continue to the TCP_SOCKET_ESTABLISHED state.
     94         *
     95         * A SYN has been sent, and TCP is awaiting the response SYN.
     96         * Should continue to the TCP_SOCKET_ESTABLISHED state.
    9297         */
    9398        TCP_SOCKET_SYN_SENT,
     99       
    94100        /** Connecting received.
    95          *  A~SYN has been received, a~SYN has been sent, and TCP is awaiting an ACK.
    96          *  Should continue to the TCP_SOCKET_ESTABLISHED state.
     101         *
     102         * A SYN has been received, a SYN has been sent, and TCP is awaiting an
     103         * ACK. Should continue to the TCP_SOCKET_ESTABLISHED state.
    97104         */
    98105        TCP_SOCKET_SYN_RECEIVED,
     106       
    99107        /** Connected.
    100          *  The three-way handshake has been completed.
     108         *
     109         * The three-way handshake has been completed.
    101110         */
    102111        TCP_SOCKET_ESTABLISHED,
     112       
    103113        /** Closing started.
    104          *  The local application has issued a~CLOSE.
    105          *  TCP has sent a~FIN, and is awaiting an ACK or a~FIN.
    106          *  Should continue to the TCP_SOCKET_FIN_WAIT_2 state when an ACK is received.
    107          *  Should continue to the TCP_SOCKET_CLOSING state when a~FIN is received.
     114         *
     115         * The local application has issued a CLOSE.
     116         * TCP has sent a FIN, and is awaiting an ACK or a FIN.
     117         * Should continue to the TCP_SOCKET_FIN_WAIT_2 state when an ACK is
     118         * received.
     119         * Should continue to the TCP_SOCKET_CLOSING state when a FIN is
     120         * received.
    108121         */
    109122        TCP_SOCKET_FIN_WAIT_1,
     123       
    110124        /** Closing confirmed.
    111          *  A~FIN has been sent, and an ACK received.
    112          *  TCP is awaiting a~FIN from the remote TCP layer.
    113          *  Should continue to the TCP_SOCKET_CLOSING state.
     125         *
     126         * A FIN has been sent, and an ACK received.
     127         * TCP is awaiting a~FIN from the remote TCP layer.
     128         * Should continue to the TCP_SOCKET_CLOSING state.
    114129         */
    115130        TCP_SOCKET_FIN_WAIT_2,
     131       
    116132        /** Closing.
    117          *  A FIN has been sent, a FIN has been received, and an ACK has been sent.
    118          *  TCP is awaiting an ACK for the FIN that was sent.
    119          *  Should continue to the TCP_SOCKET_TIME_WAIT state.
     133         *
     134         * A FIN has been sent, a FIN has been received, and an ACK has been
     135         * sent.
     136         * TCP is awaiting an ACK for the FIN that was sent.
     137         * Should continue to the TCP_SOCKET_TIME_WAIT state.
    120138         */
    121139        TCP_SOCKET_CLOSING,
     140       
    122141        /** Closing received.
    123          *  TCP has received a~FIN, and has sent an ACK.
    124          *  It is awaiting a~close request from the local application before sending a~FIN.
    125          *  Should continue to the TCP_SOCKET_SOCKET_LAST_ACK state.
     142         *
     143         * TCP has received a FIN, and has sent an ACK.
     144         * It is awaiting a close request from the local application before
     145         * sending a FIN.
     146         * Should continue to the TCP_SOCKET_SOCKET_LAST_ACK state.
    126147         */
    127148        TCP_SOCKET_CLOSE_WAIT,
    128         /**
    129          *  A~FIN has been received, and an ACK and a~FIN have been sent.
    130          *  TCP is awaiting an ACK.
    131          *  Should continue to the TCP_SOCKET_TIME_WAIT state.
     149       
     150        /**
     151         * A FIN has been received, and an ACK and a FIN have been sent.
     152         * TCP is awaiting an ACK.
     153         * Should continue to the TCP_SOCKET_TIME_WAIT state.
    132154         */
    133155        TCP_SOCKET_LAST_ACK,
     156       
    134157        /** Closing finished.
    135          *  FINs have been received and ACK’d, and TCP is waiting two MSLs to remove the connection from the table.
     158         *
     159         * FINs have been received and ACK’d, and TCP is waiting two MSLs to
     160         * remove the connection from the table.
    136161         */
    137162        TCP_SOCKET_TIME_WAIT,
     163       
    138164        /** Closed.
    139          *  Imaginary, this indicates that a~connection has been removed from the connection table.
     165         *
     166         * Imaginary, this indicates that a connection has been removed from
     167         * the connection table.
    140168         */
    141169        TCP_SOCKET_CLOSED
    142170};
    143171
    144 /** TCP operation data.
    145  */
    146 struct tcp_operation{
    147         /** Operation result.
    148          */
     172/** TCP operation data. */
     173struct tcp_operation {
     174        /** Operation result. */
    149175        int result;
    150         /** Safety lock.
    151          */
     176        /** Safety lock. */
    152177        fibril_mutex_t mutex;
    153         /** Operation result signaling.
    154          */
     178        /** Operation result signaling. */
    155179        fibril_condvar_t condvar;
    156180};
    157181
    158 /** TCP socket specific data.
    159  */
    160 struct tcp_socket_data{
    161         /** TCP socket state.
    162          */
     182/** TCP socket specific data. */
     183struct tcp_socket_data {
     184        /** TCP socket state. */
    163185        tcp_socket_state_t state;
    164         /** Data fragment size.
    165          *  Sending optimalization.
     186       
     187        /**
     188         * Data fragment size.
     189         * Sending optimalization.
    166190         */
    167191        size_t data_fragment_size;
    168         /** Device identifier.
    169         */
     192       
     193        /** Device identifier. */
    170194        device_id_t device_id;
    171         /** Listening backlog.
    172          *  The maximal number of connected but not yet accepted sockets.
     195       
     196        /**
     197         * Listening backlog.
     198         * The maximal number of connected but not yet accepted sockets.
    173199         */
    174200        int backlog;
    175 //      /** Segment size.
    176 //       */
    177 //      size_t                  segment_size;
    178         /** Parent listening socket identifier.
    179          *  Set if this socket is an accepted one.
     201       
     202//      /** Segment size. */
     203//      size_t segment_size;
     204
     205        /**
     206         * Parent listening socket identifier.
     207         * Set if this socket is an accepted one.
    180208         */
    181209        int listening_socket_id;
    182         /** Treshold size in bytes.
    183         */
     210       
     211        /** Treshold size in bytes. */
    184212        size_t treshold;
    185         /** Window size in bytes.
    186          */
     213        /** Window size in bytes. */
    187214        size_t window;
    188         /** Acknowledgement timeout.
    189          */
     215        /** Acknowledgement timeout. */
    190216        suseconds_t timeout;
    191         /** Last acknowledged byte.
    192          */
     217        /** Last acknowledged byte. */
    193218        uint32_t acknowledged;
    194         /** Next incoming sequence number.
    195          */
     219        /** Next incoming sequence number. */
    196220        uint32_t next_incoming;
    197         /** Incoming FIN.
    198          */
     221        /** Incoming FIN. */
    199222        uint32_t fin_incoming;
    200         /** Next outgoing sequence number.
    201          */
     223        /** Next outgoing sequence number. */
    202224        uint32_t next_outgoing;
    203         /** Last outgoing sequence number.
    204          */
     225        /** Last outgoing sequence number. */
    205226        uint32_t last_outgoing;
    206         /** Outgoing FIN.
    207          */
     227        /** Outgoing FIN. */
    208228        uint32_t fin_outgoing;
    209         /** Expected sequence number by the remote host.
    210          *  The sequence number the other host expects.
    211          *  The notification is sent only upon a packet reecival.
     229       
     230        /**
     231         * Expected sequence number by the remote host.
     232         * The sequence number the other host expects.
     233         * The notification is sent only upon a packet reecival.
    212234         */
    213235        uint32_t expected;
    214         /** Expected sequence number counter.
    215          *  Counts the number of received notifications for the same sequence number.
     236       
     237        /**
     238         * Expected sequence number counter.
     239         * Counts the number of received notifications for the same sequence
     240         * number.
    216241         */
    217242        int expected_count;
     243       
    218244        /** Incoming packet queue.
    219          *  Packets are buffered until received in the right order.
    220          *  The packets are excluded after successfully read.
    221          *  Packets are sorted by their starting byte.
    222          *  Packets metric is set as their data length.
     245         *
     246         * Packets are buffered until received in the right order.
     247         * The packets are excluded after successfully read.
     248         * Packets are sorted by their starting byte.
     249         * Packets metric is set as their data length.
    223250         */
    224251        packet_t incoming;
     252       
    225253        /** Outgoing packet queue.
    226          *  Packets are buffered until acknowledged by the remote host in the right order.
    227          *  The packets are excluded after acknowledged.
    228          *  Packets are sorted by their starting byte.
    229          *  Packets metric is set as their data length.
     254         *
     255         * Packets are buffered until acknowledged by the remote host in the
     256         * right order.
     257         * The packets are excluded after acknowledged.
     258         * Packets are sorted by their starting byte.
     259         * Packets metric is set as their data length.
    230260         */
    231261        packet_t outgoing;
    232         /** IP pseudo header.
    233         */
     262       
     263        /** IP pseudo header. */
    234264        void *pseudo_header;
    235         /** IP pseudo header length.
    236          */
     265        /** IP pseudo header length. */
    237266        size_t headerlen;
    238         /** Remote host address.
    239          */
    240         struct sockaddr * addr;
    241         /** Remote host address length.
    242          */
     267        /** Remote host address. */
     268        struct sockaddr *addr;
     269        /** Remote host address length. */
    243270        socklen_t addrlen;
    244         /** Remote host port.
    245          */
     271        /** Remote host port. */
    246272        uint16_t dest_port;
    247         /** Parent local sockets.
    248          */
     273        /** Parent local sockets. */
    249274        socket_cores_ref local_sockets;
     275       
    250276        /** Local sockets safety lock.
    251          *  May be locked for writing while holding the global lock for reading when changing the local sockets only.
    252          *  The global lock may to be locked only before locking the local lock.
    253          *  The global lock may be locked more weakly than the local lock.
    254          *  The global lock may be released before releasing the local lock.
    255          *  @see tcp_globals:lock
    256          */
    257         fibril_rwlock_t * local_lock;
    258         /** Pending operation data.
    259          */
     277         *
     278         * May be locked for writing while holding the global lock for reading
     279         * when changing the local sockets only.
     280         * The global lock may be locked only before locking the local lock.
     281         * The global lock may be locked more weakly than the local lock.
     282         * The global lock may be released before releasing the local lock.
     283         * @see tcp_globals:lock
     284         */
     285        fibril_rwlock_t *local_lock;
     286       
     287        /** Pending operation data. */
    260288        tcp_operation_t operation;
    261         /** Timeouts in a row counter.
    262          *  If TCP_MAX_TIMEOUTS is reached, the connection is lost.
     289       
     290        /**
     291         * Timeouts in a row counter.
     292         * If TCP_MAX_TIMEOUTS is reached, the connection is lost.
    263293         */
    264294        int timeout_count;
    265295};
    266296
    267 /** TCP global data.
    268  */
    269 struct  tcp_globals{
    270         /** Networking module phone.
    271          */
     297/** TCP global data. */
     298struct tcp_globals {
     299        /** Networking module phone. */
    272300        int net_phone;
    273         /** IP module phone.
    274          */
     301        /** IP module phone. */
    275302        int ip_phone;
    276         /** ICMP module phone.
    277          */
     303        /** ICMP module phone. */
    278304        int icmp_phone;
    279         /** Last used free port.
    280          */
     305        /** Last used free port. */
    281306        int last_used_port;
    282         /** Active sockets.
    283          */
     307        /** Active sockets. */
    284308        socket_ports_t sockets;
    285         /** Device packet dimensions.
    286          */
     309        /** Device packet dimensions. */
    287310        packet_dimensions_t dimensions;
    288         /** Safety lock.
    289          *  Write lock is used only for adding or removing socket ports.
     311       
     312        /**
     313         * Safety lock.
     314         * Write lock is used only for adding or removing socket ports.
    290315         */
    291316        fibril_rwlock_t lock;
     
    296321/** @}
    297322 */
    298 
  • uspace/srv/net/tl/tcp/tcp_header.h

    re06ef614 r49d819b4  
    2828
    2929/** @addtogroup tcp
    30  *  @{
     30 * @{
    3131 */
    3232
    3333/** @file
    34  *  TCP header definition.
    35  *  Based on the RFC~793.
     34 * TCP header definition.
     35 * Based on the RFC 793.
    3636 */
    3737
    38 #ifndef __NET_TCP_HEADER_H__
    39 #define __NET_TCP_HEADER_H__
     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  */
    45 #define TCP_HEADER_SIZE                 sizeof(tcp_header_t)
     43/** TCP header size in bytes. */
     44#define TCP_HEADER_SIZE                         sizeof(tcp_header_t)
    4645
    4746/** Returns the actual TCP header length in bytes.
    48  *  @param[in] header The TCP packet header.
     47 * @param[in] header The TCP packet header.
    4948 */
    50 #define TCP_HEADER_LENGTH(header)               ((header)->header_length * 4u)
     49#define TCP_HEADER_LENGTH(header)               ((header)->header_length * 4U)
    5150
    5251/** Returns the TCP header length.
    53  *  @param[in] length The TCP header length in bytes.
     52 * @param[in] length The TCP header length in bytes.
    5453 */
    55 #define TCP_COMPUTE_HEADER_LENGTH(length)               ((uint8_t) ((length) / 4u))
     54#define TCP_COMPUTE_HEADER_LENGTH(length)       ((uint8_t) ((length) / 4U))
    5655
    5756/** Type definition of the transmission datagram header.
    58  *  @see tcp_header
     57 * @see tcp_header
    5958 */
    60 typedef struct tcp_header       tcp_header_t;
     59typedef struct tcp_header tcp_header_t;
    6160
    6261/** Type definition of the transmission datagram header pointer.
    63  *  @see tcp_header
     62 * @see tcp_header
    6463 */
    65 typedef tcp_header_t *          tcp_header_ref;
     64typedef tcp_header_t *tcp_header_ref;
    6665
    6766/** Type definition of the transmission datagram header option.
    68  *  @see tcp_option
     67 * @see tcp_option
    6968 */
    70 typedef struct tcp_option       tcp_option_t;
     69typedef struct tcp_option tcp_option_t;
    7170
    7271/** Type definition of the transmission datagram header option pointer.
    73  *  @see tcp_option
     72 * @see tcp_option
    7473 */
    75 typedef tcp_option_t *          tcp_option_ref;
     74typedef tcp_option_t *tcp_option_ref;
    7675
    77 /** Type definition of the Maximum segment size TCP option.
    78  *  @see ...
    79  */
    80 typedef struct tcp_max_segment_size_option      tcp_max_segment_size_option_t;
     76/** Type definition of the Maximum segment size TCP option. */
     77typedef struct tcp_max_segment_size_option tcp_max_segment_size_option_t;
    8178
    8279/** Type definition of the Maximum segment size TCP option pointer.
    83  *  @see tcp_max_segment_size_option
     80 * @see tcp_max_segment_size_option
    8481 */
    85 typedef tcp_max_segment_size_option_t *         tcp_max_segment_size_option_ref;
     82typedef tcp_max_segment_size_option_t *tcp_max_segment_size_option_ref;
    8683
    87 /** Transmission datagram header.
    88  */
    89 struct tcp_header{
    90         /** The source port number.
    91          */
     84/** Transmission datagram header. */
     85struct tcp_header {
    9286        uint16_t source_port;
    93         /** The destination port number.
    94          */
    9587        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          */
    9988        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          */
    10489        uint32_t acknowledgement_number;
     90       
    10591#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          */
    11092        uint8_t header_length:4;
    111         /** Four bits reserved for future use.
    112          *  Must be zero.
    113          */
    11493        uint8_t reserved1:4;
    11594#else
    116         /** Four bits reserved for future use.
    117          *  Must be zero.
    118          */
    11995        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          */
    12496        uint8_t header_length:4;
    12597#endif
     98
    12699#ifdef ARCH_IS_BIG_ENDIAN
    127         /** Two bits reserved for future use.
    128          *  Must be zero.
    129          */
    130100        uint8_t reserved2:2;
    131         /** Urgent Pointer field significant.
    132          *  @see tcp_header:urgent_pointer
    133          */
    134101        uint8_t urgent:1;
    135         /** Acknowledgment field significant
    136          *  @see tcp_header:acknowledgement_number
    137          */
    138102        uint8_t acknowledge:1;
    139         /** Push function.
    140          */
    141103        uint8_t push:1;
    142         /** Reset the connection.
    143          */
    144104        uint8_t reset:1;
    145         /** Synchronize the sequence numbers.
    146          */
    147105        uint8_t synchronize:1;
    148         /** No more data from the sender.
    149          */
    150106        uint8_t finalize:1;
    151107#else
    152         /** No more data from the sender.
    153          */
    154108        uint8_t finalize:1;
    155         /** Synchronize the sequence numbers.
    156          */
    157109        uint8_t synchronize:1;
    158         /** Reset the connection.
    159          */
    160110        uint8_t reset:1;
    161         /** Push function.
    162          */
    163111        uint8_t push:1;
    164         /** Acknowledgment field significant.
    165          *  @see tcp_header:acknowledgement_number
    166          */
    167112        uint8_t acknowledge:1;
    168         /** Urgent Pointer field significant.
    169          *  @see tcp_header:urgent_pointer
    170          */
    171113        uint8_t urgent:1;
    172         /** Two bits reserved for future use.
    173          *  Must be zero.
    174          */
    175114        uint8_t reserved2:2;
    176115#endif
    177         /** The number of data octets beginning with the one indicated in the acknowledgment field which the sender of this segment is willing to accept.
    178          *  @see tcp_header:acknowledge
    179          */
     116
    180117        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          */
    190118        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          */
    196119        uint16_t urgent_pointer;
    197120} __attribute__ ((packed));
    198121
    199 /** Transmission datagram header option.
    200  */
    201 struct tcp_option{
    202         /** Option type.
    203          */
     122/** Transmission datagram header option. */
     123struct tcp_option {
     124        /** Option type. */
    204125        uint8_t type;
    205         /** Option length.
    206          */
     126        /** Option length. */
    207127        uint8_t length;
    208128};
    209129
    210 /** Maximum segment size TCP option.
    211  */
    212 struct tcp_max_segment_size_option{
     130/** Maximum segment size TCP option. */
     131struct tcp_max_segment_size_option {
    213132        /** TCP option.
    214          *  @see TCPOPT_MAX_SEGMENT_SIZE
    215          *  @see TCPOPT_MAX_SEGMENT_SIZE_LENGTH
     133         * @see TCPOPT_MAX_SEGMENT_SIZE
     134         * @see TCPOPT_MAX_SEGMENT_SIZE_LENGTH
    216135         */
    217136        tcp_option_t option;
    218         /** Maximum segment size in bytes.
    219         */
     137       
     138        /** Maximum segment size in bytes. */
    220139        uint16_t max_segment_size;
    221140} __attribute__ ((packed));
  • uspace/srv/net/tl/tcp/tcp_module.c

    re06ef614 r49d819b4  
    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 points.
    37  *  @see module.c
     34 * TCP standalone module implementation.
     35 * Contains skeleton module functions mapping.
     36 * The functions are used by the module skeleton as module specific entry
     37 * points.
     38 * @see module.c
    3839 */
     40
     41#include "tcp.h"
     42#include "tcp_module.h"
    3943
    4044#include <async.h>
     
    4650#include <net/ip_protocols.h>
    4751#include <net/modules.h>
    48 
    4952#include <net/packet.h>
    5053#include <net_interface.h>
     54
    5155#include <ip_interface.h>
    5256#include <tl_local.h>
    5357
    54 #include "tcp.h"
    55 #include "tcp_module.h"
     58/** TCP module global data. */
     59extern tcp_globals_t tcp_globals;
    5660
    57 /** TCP module global data.
    58  */
    59 extern tcp_globals_t    tcp_globals;
    60 
    61 /** Starts the TCP module.
    62  *  Initializes the client connection serving function, initializes the module, registers the module service and starts the async manager, processing IPC messages in an infinite loop.
    63  *  @param[in] client_connection The client connection processing function. The module skeleton propagates its own one.
    64  *  @returns EOK on successful module termination.
    65  *  @returns Other error codes as defined for the tcp_initialize() function.
    66  *  @returns Other error codes as defined for the REGISTER_ME() macro function.
    67  */
    6861int tl_module_start_standalone(async_client_conn_t client_connection)
    6962{
     
    7568       
    7669        ipcarg_t phonehash;
    77         if (ERROR_OCCURRED(tcp_initialize(client_connection))
    78             || ERROR_OCCURRED(REGISTER_ME(SERVICE_TCP, &phonehash))) {
     70        if (ERROR_OCCURRED(tcp_initialize(client_connection)) ||
     71            ERROR_OCCURRED(REGISTER_ME(SERVICE_TCP, &phonehash))) {
    7972                pm_destroy();
    8073                return ERROR_CODE;
     
    8780}
    8881
    89 /** Processes the TCP message.
    90  *  @param[in] callid The message identifier.
    91  *  @param[in] call The message parameters.
    92  *  @param[out] answer The message answer parameters.
    93  *  @param[out] answer_count The last parameter for the actual answer in the answer parameter.
    94  *  @returns EOK on success.
    95  *  @returns Other error codes as defined for the tcp_message() function.
    96  */
    97 int tl_module_message_standalone(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count){
     82int
     83tl_module_message_standalone(ipc_callid_t callid, ipc_call_t *call,
     84    ipc_call_t *answer, int *answer_count)
     85{
    9886        return tcp_message_standalone(callid, call, answer, answer_count);
    9987}
  • uspace/srv/net/tl/tcp/tcp_module.h

    re06ef614 r49d819b4  
    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 /** Initializes the TCP module.
    45  *  @param[in] client_connection The client connection processing function. The module skeleton propagates its own one.
    46  *  @returns EOK on success.
    47  *  @returns ENOMEM if there is not enough memory left.
    48  */
    49 extern int tcp_initialize(async_client_conn_t client_connection);
    50 
    51 /** Processes the TCP message.
    52  *  @param[in] callid The message identifier.
    53  *  @param[in] call The message parameters.
    54  *  @param[out] answer The message answer parameters.
    55  *  @param[out] answer_count The last parameter for the actual answer in the answer parameter.
    56  *  @returns EOK on success.
    57  *  @returns ENOTSUP if the message is not known.
    58  *  @see tcp_interface.h
    59  *  @see IS_NET_TCP_MESSAGE()
    60  */
    61 extern int tcp_message_standalone(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count);
     44extern int tcp_initialize(async_client_conn_t);
     45extern int tcp_message_standalone(ipc_callid_t, ipc_call_t *, ipc_call_t *,
     46    int *);
    6247
    6348#endif
  • uspace/srv/net/tl/udp/udp.c

    re06ef614 r49d819b4  
    2828
    2929/** @addtogroup udp
    30  *  @{
     30 * @{
    3131 */
    3232
    3333/** @file
    34  *  UDP module implementation.
    35  *  @see udp.h
    36  */
     34 * UDP module implementation.
     35 * @see udp.h
     36 */
     37
     38#include "udp.h"
     39#include "udp_header.h"
     40#include "udp_module.h"
    3741
    3842#include <async.h>
     
    4549#include <ipc/tl.h>
    4650#include <ipc/socket.h>
     51#include <adt/dynamic_fifo.h>
    4752#include <errno.h>
    4853#include <err.h>
     
    5560#include <net/modules.h>
    5661
    57 #include <adt/dynamic_fifo.h>
    5862#include <packet_client.h>
    5963#include <packet_remote.h>
     
    6973#include <tl_interface.h>
    7074
    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 /** Processes the received UDP packet queue.
    94  *
    95  *  Is used as an entry point from the underlying IP module.
    96  *  Locks the global lock and calls udp_process_packet() function.
    97  *
    98  *  @param[in] device_id The receiving device identifier.
    99  *  @param[in,out] packet The received packet queue.
    100  *  @param receiver     The target service. Ignored parameter.
    101  *  @param[in] error    The packet error reporting service. Prefixes the
    102  *                      received packet.
    103  *  @returns            EOK on success.
    104  *  @returns            Other error codes as defined for the
    105  *                      udp_process_packet() function.
    106  */
    107 int
    108 udp_received_msg(device_id_t device_id, packet_t packet, services_t receiver,
    109     services_t error);
    110 
    111 /** Processes the received UDP packet queue.
    112  *
    113  *  Notifies the destination socket application.
    114  *  Releases the packet on error or sends an ICMP error notification.
    115  *
    116  *  @param[in] device_id The receiving device identifier.
    117  *  @param[in,out] packet The received packet queue.
    118  *  @param[in] error    The packet error reporting service. Prefixes the
    119  *                      received packet.
    120  *  @returns            EOK on success.
    121  *  @returns            EINVAL if the packet is not valid.
    122  *  @returns            EINVAL if the stored packet address is not the
    123  *                      an_addr_t.
    124  *  @returns            EINVAL if the packet does not contain any data.
    125  *  @returns            NO_DATA if the packet content is shorter than the user
    126  *                      datagram header.
    127  *  @returns            ENOMEM if there is not enough memory left.
    128  *  @returns            EADDRNOTAVAIL if the destination socket does not exist.
    129  *  @returns            Other error codes as defined for the
    130  *                      ip_client_process_packet() function.
    131  */
    132 int
    133 udp_process_packet(device_id_t device_id, packet_t packet, services_t error);
    134 
    135 /** Releases the packet and returns the result.
    136  *
    137  *  @param[in] packet   The packet queue to be released.
    138  *  @param[in] result   The result to be returned.
    139  *  @return             The result parameter.
    140  */
    141 int udp_release_and_return(packet_t packet, int result);
    142 
    143 /** @name Socket messages processing functions
    144  */
    145 /*@{*/
    146 
    147 /** Processes the socket client messages.
    148  *
    149  *  Runs until the client module disconnects.
    150  *
    151  *  @param[in] callid   The message identifier.
    152  *  @param[in] call     The message parameters.
    153  *  @returns            EOK on success.
    154  *  @see                socket.h
    155  */
    156 int udp_process_client_messages(ipc_callid_t callid, ipc_call_t call);
    157 
    158 /** Sends data from the socket to the remote address.
    159  *
    160  *  Binds the socket to a free port if not already connected/bound.
    161  *  Handles the NET_SOCKET_SENDTO message.
    162  *  Supports AF_INET and AF_INET6 address families.
    163  *
    164  *  @param[in,out] local_sockets The application local sockets.
    165  *  @param[in] socket_id Socket identifier.
    166  *  @param[in] addr     The destination address.
    167  *  @param[in] addrlen  The address length.
    168  *  @param[in] fragments The number of data fragments.
    169  *  @param[out] data_fragment_size The data fragment size in bytes.
    170  *  @param[in] flags    Various send flags.
    171  *  @returns            EOK on success.
    172  *  @returns            EAFNOTSUPPORT if the address family is not supported.
    173  *  @returns            ENOTSOCK if the socket is not found.
    174  *  @returns            EINVAL if the address is invalid.
    175  *  @returns            ENOTCONN if the sending socket is not and cannot be
    176  *                      bound.
    177  *  @returns            ENOMEM if there is not enough memory left.
    178  *  @returns            Other error codes as defined for the
    179  *                      socket_read_packet_data() function.
    180  *  @returns            Other error codes as defined for the
    181  *                      ip_client_prepare_packet() function.
    182  *  @returns            Other error codes as defined for the ip_send_msg()
    183  *                      function.
    184  */
    185 int
    186 udp_sendto_message(socket_cores_ref local_sockets, int socket_id,
    187     const struct sockaddr * addr, socklen_t addrlen, int fragments,
    188     size_t * data_fragment_size, int flags);
    189 
    190 /** Receives data to the socket.
    191  *
    192  *  Handles the NET_SOCKET_RECVFROM message.
    193  *  Replies the source address as well.
    194  *
    195  *  @param[in] local_sockets The application local sockets.
    196  *  @param[in] socket_id Socket identifier.
    197  *  @param[in] flags    Various receive flags.
    198  *  @param[out] addrlen The source address length.
    199  *  @returns            The number of bytes received.
    200  *  @returns            ENOTSOCK if the socket is not found.
    201  *  @returns            NO_DATA if there are no received packets or data.
    202  *  @returns            ENOMEM if there is not enough memory left.
    203  *  @returns            EINVAL if the received address is not an IP address.
    204  *  @returns            Other error codes as defined for the packet_translate()
    205  *                      function.
    206  *  @returns            Other error codes as defined for the data_reply()
    207  *                      function.
    208  */
    209 int
    210 udp_recvfrom_message(socket_cores_ref local_sockets, int socket_id, int flags,
    211     size_t * addrlen);
    212 
    213 /*@}*/
    214 
    215 /** UDP global data.
    216  */
     93/** UDP global data.  */
    21794udp_globals_t udp_globals;
    21895
     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 */
    219103int udp_initialize(async_client_conn_t client_connection)
    220104{
     
    223107        measured_string_t names[] = {
    224108                {
    225                         str_dup("UDP_CHECKSUM_COMPUTING"),
     109                        (char *) "UDP_CHECKSUM_COMPUTING",
    226110                        22
    227111                },
    228112                {
    229                         str_dup("UDP_AUTOBINDING"),
     113                        (char *) "UDP_AUTOBINDING",
    230114                        15
    231115                }
     
    233117        measured_string_ref configuration;
    234118        size_t count = sizeof(names) / sizeof(measured_string_t);
    235         char * data;
     119        char *data;
    236120
    237121        fibril_rwlock_initialize(&udp_globals.lock);
     
    258142        udp_globals.last_used_port = UDP_FREE_PORTS_START - 1;
    259143
    260         // get configuration
    261144        udp_globals.checksum_computing = NET_DEFAULT_UDP_CHECKSUM_COMPUTING;
    262145        udp_globals.autobinding = NET_DEFAULT_UDP_AUTOBINDING;
     146
     147        // get configuration
    263148        configuration = &names[0];
    264149        ERROR_PROPAGATE(net_get_conf_req(udp_globals.net_phone, &configuration,
     
    280165}
    281166
    282 int
    283 udp_received_msg(device_id_t device_id, packet_t packet, services_t receiver,
    284     services_t error)
     167/** Releases the packet and returns the result.
     168 *
     169 * @param[in] packet    The packet queue to be released.
     170 * @param[in] result    The result to be returned.
     171 * @return              The result parameter.
     172 */
     173static int udp_release_and_return(packet_t packet, int result)
    285174{
    286         int result;
    287 
    288         fibril_rwlock_write_lock(&udp_globals.lock);
    289         result = udp_process_packet(device_id, packet, error);
    290         if (result != EOK)
    291                 fibril_rwlock_write_unlock(&udp_globals.lock);
    292 
     175        pq_release_remote(udp_globals.net_phone, packet_get_id(packet));
    293176        return result;
    294177}
    295178
    296 int udp_process_packet(device_id_t device_id, packet_t packet, services_t error)
     179/** Processes the received UDP packet queue.
     180 *
     181 * Notifies the destination socket application.
     182 * Releases the packet on error or sends an ICMP error notification.
     183 *
     184 * @param[in] device_id The receiving device identifier.
     185 * @param[in,out] packet The received packet queue.
     186 * @param[in] error     The packet error reporting service. Prefixes the
     187 *                      received packet.
     188 * @returns             EOK on success.
     189 * @returns             EINVAL if the packet is not valid.
     190 * @returns             EINVAL if the stored packet address is not the
     191 *                      an_addr_t.
     192 * @returns             EINVAL if the packet does not contain any data.
     193 * @returns             NO_DATA if the packet content is shorter than the user
     194 *                      datagram header.
     195 * @returns             ENOMEM if there is not enough memory left.
     196 * @returns             EADDRNOTAVAIL if the destination socket does not exist.
     197 * @returns             Other error codes as defined for the
     198 *                      ip_client_process_packet() function.
     199 */
     200static int
     201udp_process_packet(device_id_t device_id, packet_t packet, services_t error)
    297202{
    298203        ERROR_DECLARE;
     
    315220        packet_dimension_ref packet_dimension;
    316221
    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                 }
     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);
    335240        }
    336241
     
    374279
    375280        // compute header checksum if set
    376         if (header->checksum && (!error)) {
     281        if (header->checksum && !error) {
    377282                result = packet_get_addr(packet, (uint8_t **) &src,
    378283                    (uint8_t **) &dest);
    379                 if( result <= 0)
     284                if (result <= 0)
    380285                        return udp_release_and_return(packet, result);
    381286
     
    396301
    397302        do {
    398                 ++ fragments;
     303                fragments++;
    399304                length = packet_get_data_length(next_packet);
    400305                if (length <= 0)
     
    471376}
    472377
    473 int
    474 udp_message_standalone(ipc_callid_t callid, ipc_call_t * call,
    475     ipc_call_t * answer, int * answer_count)
     378/** Processes the received UDP packet queue.
     379 *
     380 * Is used as an entry point from the underlying IP module.
     381 * Locks the global lock and calls udp_process_packet() function.
     382 *
     383 * @param[in] device_id The receiving device identifier.
     384 * @param[in,out] packet The received packet queue.
     385 * @param receiver      The target service. Ignored parameter.
     386 * @param[in] error     The packet error reporting service. Prefixes the
     387 *                      received packet.
     388 * @returns             EOK on success.
     389 * @returns             Other error codes as defined for the
     390 *                      udp_process_packet() function.
     391 */
     392static int
     393udp_received_msg(device_id_t device_id, packet_t packet, services_t receiver,
     394    services_t error)
    476395{
    477         ERROR_DECLARE;
    478 
    479         packet_t packet;
    480 
    481         *answer_count = 0;
    482 
    483         switch (IPC_GET_METHOD(*call)) {
    484         case NET_TL_RECEIVED:
    485                 if (!ERROR_OCCURRED(packet_translate_remote(
    486                     udp_globals.net_phone, &packet, IPC_GET_PACKET(call)))) {
    487                         ERROR_CODE = udp_received_msg(IPC_GET_DEVICE(call),
    488                             packet, SERVICE_UDP, IPC_GET_ERROR(call));
    489                 }
    490                 return ERROR_CODE;
    491        
    492         case IPC_M_CONNECT_TO_ME:
    493                 return udp_process_client_messages(callid, * call);
    494         }
    495 
    496         return ENOTSUP;
     396        int result;
     397
     398        fibril_rwlock_write_lock(&udp_globals.lock);
     399        result = udp_process_packet(device_id, packet, error);
     400        if (result != EOK)
     401                fibril_rwlock_write_unlock(&udp_globals.lock);
     402
     403        return result;
    497404}
    498405
    499 int udp_process_client_messages(ipc_callid_t callid, ipc_call_t call)
    500 {
    501         int res;
    502         bool keep_on_going = true;
    503         socket_cores_t local_sockets;
    504         int app_phone = IPC_GET_PHONE(&call);
    505         struct sockaddr *addr;
    506         int socket_id;
    507         size_t addrlen;
    508         size_t size;
    509         ipc_call_t answer;
    510         int answer_count;
    511         packet_dimension_ref packet_dimension;
    512 
    513         /*
    514          * Accept the connection
    515          *  - Answer the first IPC_M_CONNECT_TO_ME call.
    516          */
    517         res = EOK;
    518         answer_count = 0;
    519 
    520         // The client connection is only in one fibril and therefore no
    521         // additional locks are needed.
    522 
    523         socket_cores_initialize(&local_sockets);
    524 
    525         while (keep_on_going) {
    526 
    527                 // answer the call
    528                 answer_call(callid, res, &answer, answer_count);
    529 
    530                 // refresh data
    531                 refresh_answer(&answer, &answer_count);
    532 
    533                 // get the next call
    534                 callid = async_get_call(&call);
    535 
    536                 // process the call
    537                 switch (IPC_GET_METHOD(call)) {
    538                 case IPC_M_PHONE_HUNGUP:
    539                         keep_on_going = false;
    540                         res = EHANGUP;
    541                         break;
    542 
    543                 case NET_SOCKET:
    544                         socket_id = SOCKET_GET_SOCKET_ID(call);
    545                         res = socket_create(&local_sockets, app_phone, NULL,
    546                             &socket_id);
    547                         SOCKET_SET_SOCKET_ID(answer, socket_id);
    548 
    549                         if (res != EOK)
    550                                 break;
    551                        
    552                         if (tl_get_ip_packet_dimension(udp_globals.ip_phone,
    553                             &udp_globals.dimensions, DEVICE_INVALID_ID,
    554                             &packet_dimension) == EOK) {
    555                                 SOCKET_SET_DATA_FRAGMENT_SIZE(answer,
    556                                     packet_dimension->content);
    557                         }
    558 
    559 //                      SOCKET_SET_DATA_FRAGMENT_SIZE(answer,
    560 //                          MAX_UDP_FRAGMENT_SIZE);
    561                         SOCKET_SET_HEADER_SIZE(answer, UDP_HEADER_SIZE);
    562                         answer_count = 3;
    563                         break;
    564 
    565                 case NET_SOCKET_BIND:
    566                         res = data_receive((void **) &addr, &addrlen);
    567                         if (res != EOK)
    568                                 break;
    569                         fibril_rwlock_write_lock(&udp_globals.lock);
    570                         res = socket_bind(&local_sockets, &udp_globals.sockets,
    571                             SOCKET_GET_SOCKET_ID(call), addr, addrlen,
    572                             UDP_FREE_PORTS_START, UDP_FREE_PORTS_END,
    573                             udp_globals.last_used_port);
    574                         fibril_rwlock_write_unlock(&udp_globals.lock);
    575                         free(addr);
    576                         break;
    577 
    578                 case NET_SOCKET_SENDTO:
    579                         res = data_receive((void **) &addr, &addrlen);
    580                         if (res != EOK)
    581                                 break;
    582 
    583                         fibril_rwlock_write_lock(&udp_globals.lock);
    584                         res = udp_sendto_message(&local_sockets,
    585                             SOCKET_GET_SOCKET_ID(call), addr, addrlen,
    586                             SOCKET_GET_DATA_FRAGMENTS(call), &size,
    587                             SOCKET_GET_FLAGS(call));
    588                         SOCKET_SET_DATA_FRAGMENT_SIZE(answer, size);
    589 
    590                         if (res != EOK)
    591                                 fibril_rwlock_write_unlock(&udp_globals.lock);
    592                         else
    593                                 answer_count = 2;
    594                        
    595                         free(addr);
    596                         break;
    597 
    598                 case NET_SOCKET_RECVFROM:
    599                         fibril_rwlock_write_lock(&udp_globals.lock);
    600                         res = udp_recvfrom_message(&local_sockets,
    601                              SOCKET_GET_SOCKET_ID(call), SOCKET_GET_FLAGS(call),
    602                              &addrlen);
    603                         fibril_rwlock_write_unlock(&udp_globals.lock);
    604 
    605                         if (res <= 0)
    606                                 break;
    607 
    608                         SOCKET_SET_READ_DATA_LENGTH(answer, res);
    609                         SOCKET_SET_ADDRESS_LENGTH(answer, addrlen);
    610                         answer_count = 3;
    611                         res = EOK;
    612                         break;
    613                        
    614                 case NET_SOCKET_CLOSE:
    615                         fibril_rwlock_write_lock(&udp_globals.lock);
    616                         res = socket_destroy(udp_globals.net_phone,
    617                             SOCKET_GET_SOCKET_ID(call), &local_sockets,
    618                             &udp_globals.sockets, NULL);
    619                         fibril_rwlock_write_unlock(&udp_globals.lock);
    620                         break;
    621 
    622                 case NET_SOCKET_GETSOCKOPT:
    623                 case NET_SOCKET_SETSOCKOPT:
    624                 default:
    625                         res = ENOTSUP;
    626                         break;
    627                 }
    628         }
    629 
    630         // release the application phone
    631         ipc_hangup(app_phone);
    632 
    633         // release all local sockets
    634         socket_cores_release(udp_globals.net_phone, &local_sockets,
    635             &udp_globals.sockets, NULL);
    636 
    637         return res;
    638 }
    639 
    640 int
     406/** Sends data from the socket to the remote address.
     407 *
     408 * Binds the socket to a free port if not already connected/bound.
     409 * Handles the NET_SOCKET_SENDTO message.
     410 * Supports AF_INET and AF_INET6 address families.
     411 *
     412 * @param[in,out] local_sockets The application local sockets.
     413 * @param[in] socket_id Socket identifier.
     414 * @param[in] addr      The destination address.
     415 * @param[in] addrlen   The address length.
     416 * @param[in] fragments The number of data fragments.
     417 * @param[out] data_fragment_size The data fragment size in bytes.
     418 * @param[in] flags     Various send flags.
     419 * @returns             EOK on success.
     420 * @returns             EAFNOTSUPPORT if the address family is not supported.
     421 * @returns             ENOTSOCK if the socket is not found.
     422 * @returns             EINVAL if the address is invalid.
     423 * @returns             ENOTCONN if the sending socket is not and cannot be
     424 *                      bound.
     425 * @returns             ENOMEM if there is not enough memory left.
     426 * @returns             Other error codes as defined for the
     427 *                      socket_read_packet_data() function.
     428 * @returns             Other error codes as defined for the
     429 *                      ip_client_prepare_packet() function.
     430 * @returns             Other error codes as defined for the ip_send_msg()
     431 *                      function.
     432 */
     433static int
    641434udp_sendto_message(socket_cores_ref local_sockets, int socket_id,
    642435    const struct sockaddr *addr, socklen_t addrlen, int fragments,
     
    725518        // prefix the udp header
    726519        header = PACKET_PREFIX(packet, udp_header_t);
    727         if(! header)
     520        if (!header)
    728521                return udp_release_and_return(packet, ENOMEM);
    729522
    730523        bzero(header, sizeof(*header));
    731524        // read the rest of the packet fragments
    732         for (index = 1; index < fragments; ++ index) {
     525        for (index = 1; index < fragments; index++) {
    733526                result = tl_socket_read_packet_data(udp_globals.net_phone,
    734527                    &next_packet, 0, packet_dimension, addr, addrlen);
     
    784577}
    785578
    786 int
     579/** Receives data to the socket.
     580 *
     581 * Handles the NET_SOCKET_RECVFROM message.
     582 * Replies the source address as well.
     583 *
     584 * @param[in] local_sockets The application local sockets.
     585 * @param[in] socket_id Socket identifier.
     586 * @param[in] flags     Various receive flags.
     587 * @param[out] addrlen  The source address length.
     588 * @returns             The number of bytes received.
     589 * @returns             ENOTSOCK if the socket is not found.
     590 * @returns             NO_DATA if there are no received packets or data.
     591 * @returns             ENOMEM if there is not enough memory left.
     592 * @returns             EINVAL if the received address is not an IP address.
     593 * @returns             Other error codes as defined for the packet_translate()
     594 *                      function.
     595 * @returns             Other error codes as defined for the data_reply()
     596 *                      function.
     597 */
     598static int
    787599udp_recvfrom_message(socket_cores_ref local_sockets, int socket_id, int flags,
    788600    size_t *addrlen)
     
    830642
    831643        // send the source address
    832         ERROR_PROPAGATE(data_reply(addr, * addrlen));
     644        ERROR_PROPAGATE(data_reply(addr, *addrlen));
    833645
    834646        // trim the header
     
    846658}
    847659
    848 int udp_release_and_return(packet_t packet, int result)
     660/** Processes the socket client messages.
     661 *
     662 * Runs until the client module disconnects.
     663 *
     664 * @param[in] callid    The message identifier.
     665 * @param[in] call      The message parameters.
     666 * @returns             EOK on success.
     667 *
     668 * @see socket.h
     669 */
     670static int udp_process_client_messages(ipc_callid_t callid, ipc_call_t call)
    849671{
    850         pq_release_remote(udp_globals.net_phone, packet_get_id(packet));
    851         return result;
     672        int res;
     673        bool keep_on_going = true;
     674        socket_cores_t local_sockets;
     675        int app_phone = IPC_GET_PHONE(&call);
     676        struct sockaddr *addr;
     677        int socket_id;
     678        size_t addrlen;
     679        size_t size;
     680        ipc_call_t answer;
     681        int answer_count;
     682        packet_dimension_ref packet_dimension;
     683
     684        /*
     685         * Accept the connection
     686         *  - Answer the first IPC_M_CONNECT_TO_ME call.
     687         */
     688        res = EOK;
     689        answer_count = 0;
     690
     691        // The client connection is only in one fibril and therefore no
     692        // additional locks are needed.
     693
     694        socket_cores_initialize(&local_sockets);
     695
     696        while (keep_on_going) {
     697
     698                // answer the call
     699                answer_call(callid, res, &answer, answer_count);
     700
     701                // refresh data
     702                refresh_answer(&answer, &answer_count);
     703
     704                // get the next call
     705                callid = async_get_call(&call);
     706
     707                // process the call
     708                switch (IPC_GET_METHOD(call)) {
     709                case IPC_M_PHONE_HUNGUP:
     710                        keep_on_going = false;
     711                        res = EHANGUP;
     712                        break;
     713
     714                case NET_SOCKET:
     715                        socket_id = SOCKET_GET_SOCKET_ID(call);
     716                        res = socket_create(&local_sockets, app_phone, NULL,
     717                            &socket_id);
     718                        SOCKET_SET_SOCKET_ID(answer, socket_id);
     719
     720                        if (res != EOK)
     721                                break;
     722                       
     723                        if (tl_get_ip_packet_dimension(udp_globals.ip_phone,
     724                            &udp_globals.dimensions, DEVICE_INVALID_ID,
     725                            &packet_dimension) == EOK) {
     726                                SOCKET_SET_DATA_FRAGMENT_SIZE(answer,
     727                                    packet_dimension->content);
     728                        }
     729
     730//                      SOCKET_SET_DATA_FRAGMENT_SIZE(answer,
     731//                          MAX_UDP_FRAGMENT_SIZE);
     732                        SOCKET_SET_HEADER_SIZE(answer, UDP_HEADER_SIZE);
     733                        answer_count = 3;
     734                        break;
     735
     736                case NET_SOCKET_BIND:
     737                        res = data_receive((void **) &addr, &addrlen);
     738                        if (res != EOK)
     739                                break;
     740                        fibril_rwlock_write_lock(&udp_globals.lock);
     741                        res = socket_bind(&local_sockets, &udp_globals.sockets,
     742                            SOCKET_GET_SOCKET_ID(call), addr, addrlen,
     743                            UDP_FREE_PORTS_START, UDP_FREE_PORTS_END,
     744                            udp_globals.last_used_port);
     745                        fibril_rwlock_write_unlock(&udp_globals.lock);
     746                        free(addr);
     747                        break;
     748
     749                case NET_SOCKET_SENDTO:
     750                        res = data_receive((void **) &addr, &addrlen);
     751                        if (res != EOK)
     752                                break;
     753
     754                        fibril_rwlock_write_lock(&udp_globals.lock);
     755                        res = udp_sendto_message(&local_sockets,
     756                            SOCKET_GET_SOCKET_ID(call), addr, addrlen,
     757                            SOCKET_GET_DATA_FRAGMENTS(call), &size,
     758                            SOCKET_GET_FLAGS(call));
     759                        SOCKET_SET_DATA_FRAGMENT_SIZE(answer, size);
     760
     761                        if (res != EOK)
     762                                fibril_rwlock_write_unlock(&udp_globals.lock);
     763                        else
     764                                answer_count = 2;
     765                       
     766                        free(addr);
     767                        break;
     768
     769                case NET_SOCKET_RECVFROM:
     770                        fibril_rwlock_write_lock(&udp_globals.lock);
     771                        res = udp_recvfrom_message(&local_sockets,
     772                             SOCKET_GET_SOCKET_ID(call), SOCKET_GET_FLAGS(call),
     773                             &addrlen);
     774                        fibril_rwlock_write_unlock(&udp_globals.lock);
     775
     776                        if (res <= 0)
     777                                break;
     778
     779                        SOCKET_SET_READ_DATA_LENGTH(answer, res);
     780                        SOCKET_SET_ADDRESS_LENGTH(answer, addrlen);
     781                        answer_count = 3;
     782                        res = EOK;
     783                        break;
     784                       
     785                case NET_SOCKET_CLOSE:
     786                        fibril_rwlock_write_lock(&udp_globals.lock);
     787                        res = socket_destroy(udp_globals.net_phone,
     788                            SOCKET_GET_SOCKET_ID(call), &local_sockets,
     789                            &udp_globals.sockets, NULL);
     790                        fibril_rwlock_write_unlock(&udp_globals.lock);
     791                        break;
     792
     793                case NET_SOCKET_GETSOCKOPT:
     794                case NET_SOCKET_SETSOCKOPT:
     795                default:
     796                        res = ENOTSUP;
     797                        break;
     798                }
     799        }
     800
     801        // release the application phone
     802        ipc_hangup(app_phone);
     803
     804        // release all local sockets
     805        socket_cores_release(udp_globals.net_phone, &local_sockets,
     806            &udp_globals.sockets, NULL);
     807
     808        return res;
     809}
     810
     811/** Processes the UDP message.
     812 *
     813 * @param[in] callid    The message identifier.
     814 * @param[in] call      The message parameters.
     815 * @param[out] answer   The message answer parameters.
     816 * @param[out] answer_count The last parameter for the actual answer in the
     817 *                      answer parameter.
     818 * @returns             EOK on success.
     819 * @returns             ENOTSUP if the message is not known.
     820 *
     821 * @see udp_interface.h
     822 * @see IS_NET_UDP_MESSAGE()
     823 */
     824int
     825udp_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;
    852848}
    853849
     
    882878               
    883879                /*
    884                  * End if said to either by the message or the processing result
     880                 * End if told to either by the message or the processing
     881                 * result.
    885882                 */
    886883                if ((IPC_GET_METHOD(call) == IPC_M_PHONE_HUNGUP) ||
     
    895892/** Starts the module.
    896893 *
    897  *  @param argc         The count of the command line arguments. Ignored
    898  *                      parameter.
    899  *  @param argv         The command line parameters. Ignored parameter.
    900  *
    901  *  @returns            EOK on success.
    902  *  @returns            Other error codes as defined for each specific module
     894 * @returns             EOK on success.
     895 * @returns             Other error codes as defined for each specific module
    903896 *                      start function.
    904897 */
  • uspace/srv/net/tl/udp/udp.h

    re06ef614 r49d819b4  
    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  */
    51 struct  udp_globals{
    52         /** Networking module phone.
    53          */
     49/** UDP global data. */
     50struct udp_globals {
     51        /** Networking module phone. */
    5452        int net_phone;
    55         /** IP module phone.
    56          */
     53        /** IP module phone. */
    5754        int ip_phone;
    58         /** ICMP module phone.
    59          */
     55        /** ICMP module phone. */
    6056        int icmp_phone;
    61         /** Packet dimension.
    62          */
     57        /** Packet dimension. */
    6358        packet_dimension_t packet_dimension;
    64         /** Indicates whether UDP checksum computing is enabled.
    65          */
     59        /** Indicates whether UDP checksum computing is enabled. */
    6660        int checksum_computing;
    67         /** Indicates whether UDP autobnding on send is enabled.
    68          */
     61        /** Indicates whether UDP autobnding on send is enabled. */
    6962        int autobinding;
    70         /** Last used free port.
    71          */
     63        /** Last used free port. */
    7264        int last_used_port;
    73         /** Active sockets.
    74          */
     65        /** Active sockets. */
    7566        socket_ports_t sockets;
    76         /** Device packet dimensions.
    77          */
     67        /** Device packet dimensions. */
    7868        packet_dimensions_t dimensions;
    79         /** Safety lock.
    80          */
     69        /** Safety lock. */
    8170        fibril_rwlock_t lock;
    8271};
     
    8675/** @}
    8776 */
    88 
  • uspace/srv/net/tl/udp/udp_header.h

    re06ef614 r49d819b4  
    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  */
    45 #define UDP_HEADER_SIZE                 sizeof(udp_header_t)
     43/** UDP header size in bytes. */
     44#define UDP_HEADER_SIZE         sizeof(udp_header_t)
    4645
    4746/** Type definition of the user datagram header.
    48  *  @see udp_header
     47 * @see udp_header
    4948 */
    50 typedef struct udp_header       udp_header_t;
     49typedef struct udp_header udp_header_t;
    5150
    5251/** Type definition of the user datagram header pointer.
    53  *  @see udp_header
     52 * @see udp_header
    5453 */
    55 typedef udp_header_t *          udp_header_ref;
     54typedef udp_header_t *udp_header_ref;
    5655
    57 /** User datagram header.
    58  */
    59 struct udp_header{
    60         /** Source Port is an optional field, when meaningful, it indicates the port of the sending process, and may be assumed to be the port to which a reply should be addressed in the absence of any other information.
    61          *  If not used, a value of zero is inserted.
    62          */
     56/** User datagram header. */
     57struct udp_header {
    6358        uint16_t source_port;
    64         /** Destination port has a meaning within the context of a particular internet destination address.
    65          */
    6659        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          */
    7060        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          */
    7761        uint16_t checksum;
    7862} __attribute__ ((packed));
  • uspace/srv/net/tl/udp/udp_module.c

    re06ef614 r49d819b4  
    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 points.
    37  *  @see module.c
     34 * UDP standalone module implementation.
     35 * Contains skeleton module functions mapping.
     36 * The functions are used by the module skeleton as module specific entry
     37 * points.
     38 * @see module.c
    3839 */
     40
     41#include "udp.h"
     42#include "udp_module.h"
    3943
    4044#include <async.h>
     
    4650#include <net/modules.h>
    4751#include <net/packet.h>
     52
    4853#include <net_interface.h>
    4954#include <tl_local.h>
    5055
    51 #include "udp.h"
    52 #include "udp_module.h"
     56/** UDP module global data. */
     57extern udp_globals_t udp_globals;
    5358
    54 /** UDP module global data.
    55  */
    56 extern udp_globals_t    udp_globals;
    57 
    58 /** Starts the UDP module.
    59  *  Initializes the client connection serving function, initializes the module, registers the module service and starts the async manager, processing IPC messages in an infinite loop.
    60  *  @param[in] client_connection The client connection processing function. The module skeleton propagates its own one.
    61  *  @returns EOK on successful module termination.
    62  *  @returns Other error codes as defined for the udp_initialize() function.
    63  *  @returns Other error codes as defined for the REGISTER_ME() macro function.
    64  */
    65 int tl_module_start_standalone(async_client_conn_t client_connection){
     59int tl_module_start_standalone(async_client_conn_t client_connection)
     60{
    6661        ERROR_DECLARE;
    6762
     
    7065        async_set_client_connection(client_connection);
    7166        udp_globals.net_phone = net_connect_module();
    72         if(udp_globals.net_phone < 0){
     67        if (udp_globals.net_phone < 0)
    7368                return udp_globals.net_phone;
    74         }
     69
    7570        ERROR_PROPAGATE(pm_init());
    76         if(ERROR_OCCURRED(udp_initialize(client_connection))
    77                 || ERROR_OCCURRED(REGISTER_ME(SERVICE_UDP, &phonehash))){
     71        if (ERROR_OCCURRED(udp_initialize(client_connection)) ||
     72            ERROR_OCCURRED(REGISTER_ME(SERVICE_UDP, &phonehash))) {
    7873                pm_destroy();
    7974                return ERROR_CODE;
     
    8681}
    8782
    88 /** Processes the UDP message.
    89  *  @param[in] callid The message identifier.
    90  *  @param[in] call The message parameters.
    91  *  @param[out] answer The message answer parameters.
    92  *  @param[out] answer_count The last parameter for the actual answer in the answer parameter.
    93  *  @returns EOK on success.
    94  *  @returns Other error codes as defined for the udp_message() function.
    95  */
    96 int tl_module_message_standalone(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count){
     83int
     84tl_module_message_standalone(ipc_callid_t callid, ipc_call_t *call,
     85    ipc_call_t *answer, int *answer_count)
     86{
    9787        return udp_message_standalone(callid, call, answer, answer_count);
    9888}
  • uspace/srv/net/tl/udp/udp_module.h

    re06ef614 r49d819b4  
    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 /** Initializes the UDP module.
    45  *  @param[in] client_connection The client connection processing function. The module skeleton propagates its own one.
    46  *  @returns EOK on success.
    47  *  @returns ENOMEM if there is not enough memory left.
    48  */
    49 extern int udp_initialize(async_client_conn_t client_connection);
    50 
    51 /** Processes the UDP message.
    52  *  @param[in] callid The message identifier.
    53  *  @param[in] call The message parameters.
    54  *  @param[out] answer The message answer parameters.
    55  *  @param[out] answer_count The last parameter for the actual answer in the answer parameter.
    56  *  @returns EOK on success.
    57  *  @returns ENOTSUP if the message is not known.
    58  *  @see udp_interface.h
    59  *  @see IS_NET_UDP_MESSAGE()
    60  */
    61 extern int udp_message_standalone(ipc_callid_t callid, ipc_call_t * call, ipc_call_t * answer, int * answer_count);
     44extern int udp_initialize(async_client_conn_t);
     45extern int udp_message_standalone(ipc_callid_t, ipc_call_t *, ipc_call_t *,
     46    int *);
    6247
    6348#endif
Note: See TracChangeset for help on using the changeset viewer.