summaryrefslogblamecommitdiffstats
path: root/cpukit/include/rtems/tftp.h
blob: 6df3866711c8cd2c0e9460ef9118ecd7c7a50874 (plain) (tree)
1
2
3
4
5
6
7
8
9

                                           


        



                                                                    
  

                                                              


   
                                                   
                                                   








                                                                          
  










                                                                              

   

                     




                  
                   
                     
 




                                            

                                



                                                 
 
























































































































































































































































































































































































                                                                               




                  
/* SPDX-License-Identifier: BSD-2-Clause */

/**
 * @file
 *
 * @ingroup RTEMSImplTFTPFS
 *
 * @brief This header file provides interfaces and functions used to
 *   implement the TFTP file system.
 *
 * This file declares the public functions of the Trivial File
 * Transfer Protocol (TFTP) file system.
 */

/*
 * Copyright (C) 1998 W. Eric Norum <eric@norum.ca>
 * Copyright (C) 2022 embedded brains GmbH & Co. KG
 *
 * 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.
 */

#ifndef _RTEMS_TFTP_H
#define _RTEMS_TFTP_H

#ifdef __cplusplus
extern "C" {
#endif

#include <stdint.h>
#include <rtems/fs.h>

/**
 * @brief Do not call directly, use mount().
 *
 * @ingroup RTEMSImplTFTPFS
 *
 * Filesystem Mount table entry.
 */
int rtems_tftpfs_initialize(
  rtems_filesystem_mount_table_entry_t *mt_entry,
  const void *data
);

/**
 * @defgroup RTEMSAPITFTPFS Trivial File Transfer Protocol (TFTP) API
 *
 * @ingroup RTEMSAPIIO
 *
 * @brief The TFTP client library provides an API to read files from and
 *   to write files to remote servers using the Trivial File Transfer
 *   Protocol (TFTP).
 *
 * See the _RTEMS Filesystem Design Guide_ Chapter _Trivial FTP Client
 * Filesystem_.
 *
 * Usage as TFTP File System
 * =========================
 *
 * To open `/bootfiles/image` on `hostname` for reading:
 *
 *     fd = open ("/TFTP/hostname:bootfiles/image", O_RDONLY);
 *
 * The `TFTP` is the mount path and the `hostname` must be
 *
 * + an IPv4 address (like `127.0.0.1`) or
 * + the (full-qualified) name of an IPv4 host (acceptable to
 *  `gethostbyname()`)
 *
 * IPv6 is currently not supported. `bootfiles/image` is a path on the
 * TFTP server `hostname` where the file (here `image`) can be found.
 *
 * Usage of TFTP Client
 * ====================
 *
 * The pseudo-code below shows the principal usage for reading a file.
 *
 * @code
 *   int res;
 *   ssize_t bytes;
 *   void *tftp_handle;
 *   tftp_net_config config;
 *   const size_t buffer_size = 4000;
 *   char data_buffer[buffer_size];
 *
 *   tftp_initialize_net_config( &config );
 *   config.options.window_size = 1; // Set desired config values
 *
 *   res = tftp_open(
 *     "127.0.0.1",
 *     "filename.txt",
 *     true, // is_for_reading
 *     &config,
 *     &tftp_handle
 *   );
 *
 *   if ( res != 0 || tftp_handle == NULL ) {
 *     // Error
 *   }
 *
 *   // Use tftp_read() (probably in a loop) ...
 *   bytes = tftp_read(
 *     tftp_handle,
 *     data_buffer,
 *     buffer_size
 *   );
 *   // ... or use tftp_write() instead when the file is open for writing.
 *
 *   res = tftp_close( tftp_handle );
 *
 *   if ( res != 0 ) {
 *     // Error ... check! Especially when writing!
 *   }
 * @endcode
 *
 * @{
 */

/*
 * The functions below use of the TFTP client library standalone
 * - i.e. without going through the file system.
 */

/**
 * @brief This block size meets RFC 1350 and avoids the sending of
 *   the `blksize` option to the TFTP server.
 */
#define TFTP_RFC1350_BLOCK_SIZE 512

/**
 * @brief This window size avoids the sending of the `windowsize`
 *   option to the TFTP server.
 *
 * This effectively mimics the operation defined in RFC 1350 which
 * does not know any window size.
 */
#define TFTP_RFC1350_WINDOW_SIZE 1

/**
 * @brief This block size is suggested in RFC 2348 and is used as
 *   default if no different block size is provided.
 */
#define TFTP_DEFAULT_BLOCK_SIZE 1456

/**
 * @brief This window size is suggested in RFC 2348 and is used as
 *   default if no different window size is provided.
 */
#define TFTP_DEFAULT_WINDOW_SIZE 8

/**
 * @brief This structure represents TFTP options negotiated between
 *   client and server.
 *
 * RFC 2347 is the basis for the TFTP option.
 */
typedef struct tftp_options {
  /**
   * @brief This member represents the desired size of a data block.
   *
   * The TFTP blocksize option is introduced in RFC 2348.  It defines the
   * number of octets in the data packets transferred.  Valid values
   * range between 8 and 65464 octets, inclusive.  Values larger
   * than 1468 may cause packet fragmentation over standard Ethernet.
   * A value of 512 will prevent this option from being sent to
   * the server.
   *
   * The default value is 1456.
   */
  uint16_t block_size;

  /**
   * @brief This member represents the desired size of a window.
   *
   * The TFTP windowsize option is introduced in RFC 7440.  It defines the
   * number of data packets send before the receiver must send an
   * acknowledgment packet.  Valid values range between 1 and 65535
   * packets, inclusive.  Simple TFTP servers usually do not support this
   * option.  This option may negatively contribute to network
   * congestion.  This can be avoided by using a window size of 1.
   * A value of 1 will prevent this option from being sent to
   * the server.
   *
   * The default value is 8.
   */
  uint16_t window_size;
} tftp_options;

/**
 * @brief This structure represents configuration value used by the TFTP
 *   client.
 *
 * As defaults the values suggested in RFC 7440 are used.
 */
typedef struct tftp_net_config {
  /**
   * @brief This member defines how many attempts are made to send a
   *   network packet to the server.
   *
   * Repetitions occur when the server does not response to a packet
   * send by the client within a timeout period.  When the here defined
   * number of repetitions is reached and the server does still not
   * respond, the connection is considered broken and the file transfer
   * is ended with an error.
   *
   * The default value is 6.
   */
  uint16_t retransmissions;

  /**
   * @brief This member defines the port on which the server is listening
   *   for incoming connections.
   *
   * The default port number is 69.
   */
  uint16_t server_port;

  /**
   * @brief This member defines the maximum time in milliseconds the
   *   client waits for an answer packet from the server.
   *
   * If the time out is exceeded, the client will re-transmit the last
   * packet it send to the server.  In case @c window_size is larger one,
   * several packets may subject to re-transmission.
   *
   * Note that this timeout applies only after the first re-transmission
   * of a packet. The timeout till the first re-transmission is
   * @c first_timeout.
   *
   * The default value is 1000ms.
   */
  uint32_t timeout;

  /**
   * @brief This member defines the maximum time in milliseconds the
   *   client waits for the first answer packet from the server.
   *
   * The @c first_timeout is used instead of the regular @c timeout
   * for the first wait-period directly after the client sends a packet
   * for the first time to the server.  That is, this is the timeout
   * of the first re-transmission.  For any following re-transmissions
   * of the current packet the regular @c timeout is used.
   *
   * The default value is 400ms.
   */
  uint32_t first_timeout;

  /**
   * @brief This member represents the options to be sent to the server.
   *
   * These option values are sent to the server.  Yet, the server may
   *
   *   + ignore one or all options
   *   + ask the client to use a different value for an option
   *   + reject the whole request with an error
   *
   * If the server rejects a request with options, the current client
   * implementation will automatically send a second request without
   * options.  Hence, the user should be aware that the actual file
   * transfer may not use the option values specified here.
   */
  tftp_options options;
} tftp_net_config;

/**
 * @brief Set all members of a @c tftp_net_config structure to their
 *   default values.
 *
 * @param config references a @c tftp_net_config structure.
 *   The values are set to the defaults defined in
 *   @ref tftp_net_config "`type tftp_net_config`".
 */
void tftp_initialize_net_config(
  tftp_net_config *config
);

/**
 * @brief Opens and starts a TFTP client session to read or write a
 *   single file.
 *
 * This directive resolves the hostname or IP address, establishes a connection
 * to the TFTP server and initiates the data transfer.  It will not return
 * before an error is encountered or the TFTP server has responded to the
 * read or write request with a network packet.
 *
 * TFTP uses timeouts (of unspecified length).  It does not know keep-alive
 * messages.  If the client does not respond to the server in due time,
 * the server sets the connection faulty and drops it.  To avoid this
 * the user of this code must read or write enough data fast enough.
 *
 * "Enough data" means at least so much data which fills a single data
 * packet or all packets of a window if windows are used.  The data
 * can be read or written in anything from one single large chunk to
 * byte-by-byte pieces.  The point is, one cannot pause the reading
 * or writing for longer periods of time.
 *
 * @param hostname is the IPv4 address as string or the name of the TFTP
 *   server to connect to.
 * @param path is the pathname at the TFTP server side of the file to
 *   read or write.  According to RFC 1350 the path must be in
 *   NETASCII.  This is ASCII as defined in "USA Standard Code for
 *   Information Interchange" with the modifications specified in "Telnet
 *   Protocol Specification".
 * @param is_for_reading indicated whether the file is to be read or written.
 *   A value of @c true indicates that the file is intended to be read from
 *   the server.  A value of @c false indicates that the file is to be
 *   written to the server.
 * @param config either references a structure defining the configuration
 *   values for this file transfer or is @c NULL.  If it is @c NULL, default
 *   configuration values are used.  See @ref tftp_net_config
 *   "type tftp_net_config" for a description and the defaults values.
 *   This function copies the data so that the memory pointed to by
 *   @c config can be used for other purposes after the call returns.
 * @param[out] tftp_handle references a place where a handle of the connection
 *   can be stored.  On success a pointer to a handle is stored.  On failure
 *   (return value other than 0) a @c NULL pointer is stored.  This handle
 *   must be provided to all further calls to @c tftp_read(),
 *   @c tftp_write(), and @c tftp_close().
 *
 *   When this directive stores a non-NULL pointer in this place, a call
 *   to @c tftp_close() is mandatory to release allocated resources.
 *   This parameter cannot be @c NULL.
 *
 * @retval 0 When the client session was opened successfully.
 * @return Returns a POSIX @c errno value in case an error occurred.
 */
int tftp_open(
  const char  *hostname,
  const char  *path,
  bool   is_for_reading,
  const tftp_net_config *config,
  void **tftp_handle
);

/**
 * @brief Read data from a TFTP server.
 *
 * This directive attempts to read data from a TFTP connection open for
 * reading.
 *
 * Upon success, the buffer is always filled with @c count bytes of received
 * data with the exception when the end of the file has been reached.
 *
 * TFTP cannot recover from errors.  Once an error is reported, the
 * connection must be and can only be closed.
 *
 * @param tftp_handle is the reference returned by a call to tftp_open().
 *   The file must be opened for reading.
 * @param[out] buffer references a memory area into which the received
 *   data is written.
 * @param count defines the size of the @c buffer in bytes.
 *
 * @retval 0 The end of the file has been reached.  There is no more data.
 * @return If greater or equal to 0, returns the number of bytes written
 *   into the buffer.  If the return value is negative, an error occurred.
 *   In this case the negated value is a POSIX @c errno value.
 */
ssize_t tftp_read(
  void   *tftp_handle,
  void   *buffer,
  size_t  count
);

/**
 * @brief Write data to a TFTP server.
 *
 * This directive attempts to write data to a TFTP connection open for
 * writing.
 *
 * On a successful call, all data in the @c buffer will be used.  Yet, this
 * does not imply that all data is actually sent.  This depends on
 * whether a whole data packet or window can be filled.
 *
 * TFTP cannot recover from errors.  Once an error is reported, the connection
 * must be and can only be closed.
 *
 * @param tftp_handle is the reference returned by a call to tftp_open().
 *   The file must be opened for writing.
 * @param buffer references a memory area which contains the data to be
 *   sent.
 * @param count defines the size of the data in @c buffer in bytes.
 *
 * @return If greater or equal to 0, returns the number of bytes used
 *   from the buffer.  The value is always @c count on a successful call.
 *   If the return value is negative, an error occurred.  In this case
 *   the negated value is a POSIX @c errno value.
 */
ssize_t tftp_write(
  void       *tftp_handle,
  const void *buffer,
  size_t      count
);

/**
 * @brief Close a TFTP client connection.
 *
 * This directive sends all data which are still stored in a write buffer
 * to the server (if any), tells the server that the connection ends (if
 * required by RFC 1350) and releases any resources allocated at the
 * client side.
 *
 * @note Especially, when writing a file to the server, the return
 * code of `tftp_close()` should be checked.  Invoking
 * `tftp_close()` triggers the sending of the last -- not
 * completely filled -- data block.  This may fail the same way as any
 * `tftp_write()` may fail.  Therefore, an error returned by
 * `tftp_close()` likely indicates that the file was not
 * completely transferred.
 *
 * @param tftp_handle is the reference returned by a call to tftp_open().
 *   If this parameter is @c NULL, the directive call is a no-op.
 *
 * @retval 0 When the client session was closed successfully.
 * @return Returns a POSIX @c errno value in case an error occurred.
 */
int tftp_close(
  void *tftp_handle
);

/** @} */

#ifdef __cplusplus
}
#endif

#endif