/* SPDX-License-Identifier: BSD-2-Clause */ /** * @file * * @ingroup RTEMSTestSuiteTestsTFTPFS * * @brief This header file provides interfaces and functions used to * implement the UDP network fake for tftpfs tests. * * Definitions and declarations of data structures and functions. */ /* * Copyright (C) 2022 embedded brains GmbH (http://www.embedded-brains.de) * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include /* ssize_t */ #ifndef _TFTPFS_UDP_NETWORK_FAKE_H #define _TFTPFS_UDP_NETWORK_FAKE_H #ifdef __cplusplus extern "C" { #endif /** * @defgroup RTEMSTestSuiteTestsTFTPFS Test suite for libtftpsfs tests * * @ingroup RTEMSTestSuites * * @brief This test suite provides a tests for libtftpfs. * * There are some additional files relevant for the TFTP test suite: * * - `spec/build/testsuites/fstests/grp.yml`\n * This file specifies how the RTEMS WAF build system has to compile, link * and install all filesystem test suites. The TFTP test suite must * be mentioned in this file to be build. * * - `spec/build/testsuites/fstests/tftpfs.yml`\n * This file specifies how the RTEMS WAF build system has to compile, link * and install the TFTP test suite. * * - `Doxygen`\n * At variable `INPUT` the test suite is included to be processed by the * Doxygen documentation generator. * * See also the _RTEMS Filesystem Design Guide_ Chapter _Trivial FTP Client * Filesystem_. * * @{ */ #define TFTP_STD_PORT 69 #define TFTP_MAX_IP_ADDR_STRLEN (16 * 2 + 7 + 1) #define TFTP_MAX_ERROR_STRLEN 20 #define TFTP_MAX_OPTIONS_SIZE 40 /** * @brief IP address strings and server names resolved by network fake * functions like inet_aton() and gethostbyname(). */ #define TFTP_KNOWN_IPV4_ADDR0_STR "127.0.0.1" #define TFTP_KNOWN_IPV4_ADDR0_ARRAY 127, 0, 0, 1 #define TFTP_KNOWN_SERVER0_NAME "server.tftp" #define TFTP_KNOWN_SERVER0_IPV4 "10.7.0.2" #define TFTP_KNOWN_SERVER0_ARRAY 10, 7, 0, 2 /** * @brief The faked socket() function (i.e. socket interaction) must return * a file descriptor equal or larger than @c TFTP_FIRST_FD * or -1. */ #define TFTP_FIRST_FD 33333 typedef enum Tftp_Action_kind { TFTP_IA_KIND_SOCKET, TFTP_IA_KIND_CLOSE, TFTP_IA_KIND_BIND, TFTP_IA_KIND_SENDTO, TFTP_IA_KIND_RECVFROM } Tftp_Action_kind; typedef struct Tftp_Action { Tftp_Action_kind kind; union { struct { int domain; int type; int protocol; int result; } socket; struct { int fd; int result; } close; struct { int fd; int family; uint16_t port; const char *addr_str; int result; } bind; struct { int fd; const void *buf; size_t len; int flags; uint16_t dest_port; const char *dest_addr_str; int addrlen; ssize_t result; } sendto; struct { int fd; void *buf; size_t len; int flags; uint32_t timeout_ms; uint16_t src_port; char src_addr_str[TFTP_MAX_IP_ADDR_STRLEN]; int addrlen; ssize_t result; } recvfrom; } data; } Tftp_Action; /** * @brief Carry out interactions with TFTP client. * * @c Tftp_Interaction_fn() is called to * * * check that the fake network function has been called with the expected * arguments (in @c act) * * define values which shall be returned (to be stored in @c act) * * The function should not call @c T_assert_*() but use @c T_*(). * Otherwise, it is unlikely that the test can terminate the client in * @c teardown(). * * @param[in,out] act The actual arguments provided by the TFTP client * to the network function. Moreover, storage to store the results * to be returned to the TFTP client. * @param data Arbitrary data area allocated when the interaction is created * by @c _Tftp_Append_interaction() * * @retval true if the client behaved as expected. * @retval false if the test shall fail. */ typedef bool (*Tftp_Interaction_fn)( Tftp_Action *act, void *data ); typedef struct Tftp_Interaction Tftp_Interaction; typedef struct Tftp_Interaction { Tftp_Interaction *next; Tftp_Action_kind kind; Tftp_Interaction_fn fn; void *data[0]; } Tftp_Interaction; /** * @brief Initialize and free the singleton control object. * * Invoke @c _Tftp_Reset() in @c setup() and @c teardown() of the test. */ void _Tftp_Reset( void ); /** * @brief Create an interaction and append it to the sequence of expected * interactions. * * This allocates memory for an interaction and additional specific data * for the function @c fn() parameter @c data. The interaction is * initialized and appended at the end of the sequence of expected interactions. * If an error occurs a @c T_assert_*() macro is called. Hence, this function * never returns @c NULL. * * @param kind Defines which interaction is expected. Note that it cannot * happen that @c fn is called for a different network function. * @param fn A function which is called to handle the interaction. * See @c Tftp_Interaction_fn() * @param size The size of a memory area which is given to @c fn() as * @c data argument when it is invoked. This can be used to provide * private data to the function. * * @return A pointer to a memory area of size @c size. The same pointer * will be provided to @c fn as argument @c data when invoked. */ void *_Tftp_Append_interaction( Tftp_Action_kind kind, Tftp_Interaction_fn fn, size_t size ); /** * @brief Have all queued interactions been processed? * * At the end of a test, it should be checked whether all queued interactions * have been consumed by the TFTP client. * * @retval true All queued interactions have been processed. * @retval false At least one queued interactions has not yet been processed. */ bool _Tftp_Has_no_more_interactions( void ); /* * TFTP details from RFC1350, RFC2347, RFC2348 and RFC7440 * * Note: The RFCs require modes and options to be case in-sensitive. */ #define TFTP_MODE_NETASCII "netascii" #define TFTP_MODE_OCTET "octet" #define TFTP_OPTION_BLKSIZE "blksize" #define TFTP_OPTION_TIMEOUT "timeout" #define TFTP_OPTION_TSIZE "tsize" #define TFTP_OPTION_WINDOWSIZE "windowsize" #define TFTP_WINDOW_SIZE_MIN 1 #define TFTP_BLOCK_SIZE_MIN 8 #define TFTP_BLOCK_SIZE_MAX 65464 typedef enum Tftp_Opcode { TFTP_OPCODE_RRQ = 1, TFTP_OPCODE_WRQ = 2, TFTP_OPCODE_DATA = 3, TFTP_OPCODE_ACK = 4, TFTP_OPCODE_ERROR = 5, TFTP_OPCODE_OACK = 6, } Tftp_Opcode; typedef enum Tftp_Error_code { TFTP_ERROR_CODE_NOT_DEFINED = 0, TFTP_ERROR_CODE_NOT_FOUND = 1, TFTP_ERROR_CODE_NO_ACCESS = 2, TFTP_ERROR_CODE_DISK_FULL = 3, TFTP_ERROR_CODE_ILLEGAL = 4, TFTP_ERROR_CODE_UNKNOWN_ID = 5, TFTP_ERROR_CODE_FILE_EXISTS = 6, TFTP_ERROR_CODE_NO_USER = 7, TFTP_ERROR_CODE_OPTION_NEGO = 8, } Tftp_Error_code; typedef struct Tftp_Packet { uint16_t opcode; union { struct { char opts[0]; } rrq; struct { char opts[0]; } wrq; struct { uint16_t block_num; uint8_t bytes[0]; } data; struct { uint16_t block_num; } ack; struct { uint16_t error_code; char err_msg[0]; } error; struct { char opts[0]; } oack; } content; } Tftp_Packet; /** * @brief Provides a human readable description for an error code from an TFTP * error packet. * * @param error_code The error code from the TFTP error packet in host byte * order. * * @return A pointer to a string describing the error. If the error code is * unknown, a pointer to "Unknown error code" is returned. Do not change the * the string as a pointer to the very same string will be returned by future * calls. */ const char *_Tftp_Get_error_str( uint16_t error_code ); /** @} */ #ifdef __cplusplus } #endif #endif /* _TFTPFS_UDP_NETWORK_FAKE_H */