Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:17

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup RTEMSImplTFTPFS
0007  *
0008  * @brief This source file contains the implementation of
0009  *   a Trivial File Transfer Protocol (TFTP) client library.
0010  *
0011  * The code in this file provides the ability to read files from and
0012  * to write files to remote servers using the Trivial File Transfer
0013  * Protocol (TFTP). It is used by the @ref tftpfs.c "TFTP file system" and
0014  * tested through its test suite. The
0015  * following RFCs are implemented:
0016  *
0017  *   + RFC 1350 "The TFTP Protocol (Revision 2)"
0018  *   + RFC 2347 "TFTP Option Extension"
0019  *   + RFC 2348 "TFTP Blocksize Option"
0020  *   + RFC 7440 "TFTP Windowsize Option"
0021  */
0022 
0023 /*
0024  * Copyright (C) 1998 W. Eric Norum <eric@norum.ca>
0025  * Copyright (C) 2012, 2022 embedded brains GmbH & Co. KG
0026  *
0027  * Redistribution and use in source and binary forms, with or without
0028  * modification, are permitted provided that the following conditions
0029  * are met:
0030  * 1. Redistributions of source code must retain the above copyright
0031  *    notice, this list of conditions and the following disclaimer.
0032  * 2. Redistributions in binary form must reproduce the above copyright
0033  *    notice, this list of conditions and the following disclaimer in the
0034  *    documentation and/or other materials provided with the distribution.
0035  *
0036  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0037  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0038  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0039  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0040  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0041  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0042  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0043  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0044  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0045  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0046  * POSSIBILITY OF SUCH DAMAGE.
0047  */
0048 
0049 #ifdef HAVE_CONFIG_H
0050 #include "config.h"
0051 #endif
0052 
0053 #include <stdio.h>
0054 #include <stdlib.h>
0055 #include <inttypes.h>
0056 #include <errno.h>
0057 #include <malloc.h>
0058 #include <string.h>
0059 #include <unistd.h>
0060 #include <fcntl.h>
0061 #include <rtems.h>
0062 #include <rtems/tftp.h>
0063 #include <sys/types.h>
0064 #include <sys/socket.h>
0065 #include <netinet/in.h>
0066 #include <arpa/inet.h>
0067 #include <netdb.h>
0068 
0069 #include "tftp_driver.h"
0070 
0071 /*
0072  * Range of UDP ports to try
0073  */
0074 #define UDP_PORT_BASE        3180
0075 
0076 /*
0077  * Default limits
0078  */
0079 #define PACKET_FIRST_TIMEOUT_MILLISECONDS  400L
0080 #define TFTP_WINDOW_SIZE_MIN               1
0081 #define TFTP_BLOCK_SIZE_MIN                8
0082 #define TFTP_BLOCK_SIZE_MAX                65464
0083 
0084 #define TFTP_BLOCK_SIZE_OPTION             "blksize"
0085 #define TFTP_WINDOW_SIZE_OPTION            "windowsize"
0086 #define TFTP_DECIMAL_BASE                  10
0087 
0088 #define TFTP_DEFAULT_SERVER_PORT           69
0089 
0090 /*
0091  * These values are suggested by RFC 7440.
0092  */
0093 #define TFTP_RFC7440_DATA_RETRANSMISSIONS  6
0094 #define TFTP_RFC7440_TIMEOUT_MILLISECONDS  1000
0095 
0096 /*
0097  * TFTP opcodes
0098  */
0099 #define TFTP_OPCODE_RRQ     1
0100 #define TFTP_OPCODE_WRQ     2
0101 #define TFTP_OPCODE_DATA    3
0102 #define TFTP_OPCODE_ACK     4
0103 #define TFTP_OPCODE_ERROR   5
0104 #define TFTP_OPCODE_OACK    6
0105 
0106 /*
0107  * TFTP error codes
0108  */
0109 #define TFTP_ERROR_CODE_NOT_DEFINED 0
0110 #define TFTP_ERROR_CODE_NOT_FOUND   1
0111 #define TFTP_ERROR_CODE_NO_ACCESS   2
0112 #define TFTP_ERROR_CODE_DISK_FULL   3
0113 #define TFTP_ERROR_CODE_ILLEGAL     4
0114 #define TFTP_ERROR_CODE_UNKNOWN_ID  5
0115 #define TFTP_ERROR_CODE_FILE_EXISTS 6
0116 #define TFTP_ERROR_CODE_NO_USER     7
0117 #define TFTP_ERROR_CODE_OPTION_NEGO 8
0118 
0119 /*
0120  * Special return values for process_*_packet() functions
0121  * (other return values are POSIX errors)
0122  */
0123 #define GOT_EXPECTED_PACKET 0
0124 #define GOT_DUPLICATE_OF_CURRENT_PACKET -1
0125 #define GOT_OLD_PACKET -2
0126 #define GOT_FIRST_OUT_OF_ORDER_PACKET -3
0127 
0128 /*
0129  * Special argument value for getPacket()
0130  */
0131 #define GET_PACKET_DONT_WAIT -1
0132 
0133 /*
0134  * Special return value for prepare_*_packet_for_sending() functions
0135  * (other return values are the length of the packet to be send)
0136  */
0137 #define DO_NOT_SEND_PACKET 0
0138 
0139 #define PKT_SIZE_FROM_BLK_SIZE(_blksize) ((_blksize) + 2 * sizeof (uint16_t))
0140 #define BLK_SIZE_FROM_PKT_SIZE(_pktsize) ((_pktsize) - 2 * sizeof (uint16_t))
0141 #define MUST_SEND_OPTIONS(_options) (\
0142     (_options).block_size  != TFTP_RFC1350_BLOCK_SIZE || \
0143     (_options).window_size != TFTP_RFC1350_WINDOW_SIZE )
0144 
0145 /*
0146  * Packets transferred between machines
0147  */
0148 union tftpPacket {
0149     /*
0150      * RRQ/WRQ packet
0151      */
0152     struct tftpRWRQ {
0153         uint16_t      opcode;
0154         char          filename_mode[];
0155     } tftpRWRQ;
0156 
0157     /*
0158      * DATA packet
0159      */
0160     struct tftpDATA {
0161         uint16_t      opcode;
0162         uint16_t      blocknum;
0163         uint8_t       data[];
0164     } tftpDATA;
0165 
0166     /*
0167      * ACK packet
0168      */
0169     struct tftpACK {
0170         uint16_t      opcode;
0171         uint16_t      blocknum;
0172     } tftpACK;
0173 
0174     /*
0175      * OACK packet
0176      */
0177     struct tftpOACK {
0178         uint16_t      opcode;
0179         char          options[];
0180     } tftpOACK;
0181 
0182     /*
0183      * ERROR packet
0184      */
0185     struct tftpERROR {
0186         uint16_t      opcode;
0187         uint16_t      errorCode;
0188         char          errorMessage[];
0189     } tftpERROR;
0190 };
0191 
0192 /*
0193  * State of each TFTP stream
0194  */
0195 struct tftpStream {
0196     /*
0197      * Buffer for storing packets for sending and receiving.  Can point
0198      * to the same address when only one buffer is needed for reading.
0199      */
0200     union tftpPacket *receive_buf;
0201     union tftpPacket *send_buf;
0202 
0203     /*
0204      * Current block number - i.e. the block currently send or received
0205      */
0206     uint16_t      blocknum;
0207 
0208     /*
0209      * Size of the data area in a DATA single packet.
0210      */
0211     size_t block_size;
0212 
0213     /*
0214      * The maximum size of a packet.  It depends linearly on the block_size.
0215      * The receive_buf and (the packets in) the send_buf are of this size.
0216      */
0217     size_t packet_size;
0218 
0219     /*
0220      * The number of packets which can be stored in the send buffer.
0221      * During option negotiation and for reading a file from the server
0222      * only a buffer for a single packet is needed.  In those cases, this
0223      * value is always one.  When a file is written to the server,
0224      * the value equals the window size:
0225      *     send_buf_size_in_pkts == server_options.window_size
0226      *
0227      * Packet N is stored in
0228      *     send_buf + packet_size * (N % send_buf_size_in_pkts)
0229      */
0230     uint16_t send_buf_size_in_pkts;
0231 
0232     /*
0233      * When writing files with windowsize > 1, the number of the completely
0234      * filled packet with the highest block number in the send buffer.
0235      * When the user calls write(), the data will be written into
0236      * the block after this one.
0237      */
0238     uint16_t blocknum_last_filled;
0239 
0240     /*
0241      * When writing files with windowsize > 1, the number of the packet
0242      * which is the last one in the whole file (i.e. the user
0243      * called close()).  This block is never full (but maybe empty).
0244      */
0245     uint16_t blocknum_eof_block;
0246 
0247     /*
0248      * Data transfer socket
0249      */
0250     int                 socket;
0251     struct sockaddr_in  myAddress;
0252     struct sockaddr_in  farAddress;
0253 
0254     /*
0255      * Indices into buffer
0256      * In case of sending a file with windowsize > 1, these values apply
0257      * only to the packet with the highest number in the send buffer
0258      * (blocknum_last_filled + 1).
0259      */
0260     int     nleft;
0261     int     nused;
0262 
0263     /*
0264      * Flags
0265      */
0266     int     firstReply;
0267     bool    at_eof;
0268     bool    is_for_reading;
0269 
0270     /*
0271      * Function pointers and members for use by communicate_with_server().
0272      */
0273     ssize_t (*prepare_packet_for_sending) (
0274         struct tftpStream *tp,
0275         bool force_retransmission,
0276         union tftpPacket **send_buf,
0277         bool *wait_for_packet_reception,
0278         const void *create_packet_data
0279     );
0280     int (*process_data_packet) (struct tftpStream *tp, ssize_t len);
0281     int (*process_ack_packet) (struct tftpStream *tp, ssize_t len);
0282     int (*process_oack_packet) (struct tftpStream *tp, ssize_t len);
0283     int (*process_error_packet) (struct tftpStream *tp, ssize_t len);
0284     int retransmission_error_code;
0285     bool ignore_out_of_order_packets;
0286     int32_t blocknum_of_first_packet_of_window;
0287     int error;
0288 
0289     /*
0290      * Configuration and TFTP options
0291      *
0292      *     * config.options are options desired by the user (i.e. the values
0293      *       send to the server).
0294      *     * server_options are the options agreed by the server
0295      *       (the option values actually used for the transfer of data).
0296      */
0297     tftp_net_config config;
0298     tftp_options server_options;
0299 };
0300 
0301 /*
0302  * Forward declaration cannot be avoided.
0303  */
0304 static ssize_t prepare_data_packet_for_sending (
0305     struct tftpStream *tp,
0306     bool force_retransmission,
0307     union tftpPacket **send_buf,
0308     bool *wait_for_packet_reception,
0309     const void *path_name
0310 );
0311 static ssize_t prepare_ack_packet_for_sending (
0312     struct tftpStream *tp,
0313     bool force_retransmission,
0314     union tftpPacket **send_buf,
0315     bool *wait_for_packet_reception,
0316     const void *path_name
0317 );
0318 
0319 /*
0320  * Calculate the address of packet N in the send buffer
0321  */
0322 static union tftpPacket *get_send_buffer_packet (
0323     struct tftpStream *tp,
0324     uint16_t packet_num
0325 )
0326 {
0327     return (union tftpPacket *) ( ( (char *) tp->send_buf) + tp->packet_size *
0328         (packet_num % tp->send_buf_size_in_pkts) );
0329 }
0330 
0331 /*
0332  * Create read or write request
0333  */
0334 static size_t create_request (
0335     union tftpPacket *send_buf,
0336     size_t data_size,
0337     bool is_for_reading,
0338     const char *path,
0339     const tftp_options *options
0340 )
0341 {
0342   size_t res_size;
0343   char *cur = send_buf->tftpRWRQ.filename_mode;
0344 
0345   send_buf->tftpRWRQ.opcode = htons (
0346       is_for_reading ? TFTP_OPCODE_RRQ : TFTP_OPCODE_WRQ
0347   );
0348 
0349   res_size = snprintf (cur, data_size, "%s%c%s", path, 0, "octet");
0350   if (res_size >= data_size) {
0351      return -1;
0352   }
0353   res_size++;
0354   data_size -= res_size;
0355   cur += res_size;
0356 
0357   if (options->block_size != TFTP_RFC1350_BLOCK_SIZE) {
0358       res_size = snprintf (
0359           cur,
0360           data_size,
0361           "%s%c%"PRIu16,
0362           TFTP_BLOCK_SIZE_OPTION,
0363           0,
0364           options->block_size
0365       );
0366       if (res_size >= data_size) {
0367           return -1;
0368       }
0369       res_size++;
0370       data_size -= res_size;
0371       cur += res_size;
0372   }
0373 
0374   if (options->window_size != TFTP_RFC1350_WINDOW_SIZE) {
0375       res_size = snprintf (
0376           cur,
0377           data_size,
0378           "%s%c%"PRIu16,
0379           TFTP_WINDOW_SIZE_OPTION,
0380           0,
0381           options->window_size
0382       );
0383       if (res_size >= data_size) {
0384           return -1;
0385       }
0386       res_size++;
0387       data_size -= res_size;
0388       cur += res_size;
0389   }
0390 
0391   return cur - (char *)send_buf;
0392 }
0393 
0394 static bool parse_decimal_number (
0395     char **pos,
0396     size_t *remain,
0397     long min,
0398     long max,
0399     uint16_t *variable
0400 )
0401 {
0402     long value;
0403     const char *start = *pos;
0404     if (*remain < 2) {
0405         return false;
0406     }
0407     value = strtoul(start, pos, TFTP_DECIMAL_BASE);
0408     if (value < min || value > max || **pos != 0) {
0409         return false;
0410     }
0411     *variable = (uint16_t) value;
0412     (*pos)++;
0413     *remain -= *pos - start;
0414 
0415     return true;
0416 }
0417 
0418 /*
0419  * Map error message
0420  */
0421 static int tftpErrno (uint16_t error_code)
0422 {
0423     unsigned int tftpError;
0424     static const int errorMap[] = {
0425         EINVAL,
0426         ENOENT,
0427         EPERM,
0428         ENOSPC,
0429         EINVAL,
0430         ENXIO,
0431         EEXIST,
0432         ESRCH,
0433         ENOTSUP, /* Error: Option negotiation failed (RFC 2347) */
0434     };
0435 
0436     tftpError = ntohs (error_code);
0437     if (tftpError < (sizeof errorMap / sizeof errorMap[0]))
0438         return errorMap[tftpError];
0439     else
0440         return 1000 + tftpError;
0441 }
0442 
0443 /*
0444  * Parse options from an OACK packet
0445  */
0446 static bool parse_options (
0447     union tftpPacket *receive_buf,
0448     size_t packet_size,
0449     tftp_options *options_in,
0450     tftp_options *options_out
0451 )
0452 {
0453     char *pos = receive_buf->tftpOACK.options;
0454     size_t remain   = packet_size - sizeof (receive_buf->tftpOACK.opcode);
0455 
0456     /*
0457      * Make sure there is a 0 byte in the end before comparing strings
0458      */
0459     if (remain > 0 && pos[remain - 1] != 0) {
0460         return false;
0461     }
0462 
0463     while (remain > 0) {
0464       if (strcasecmp(pos, TFTP_BLOCK_SIZE_OPTION) == 0 &&
0465           options_in->block_size != TFTP_RFC1350_BLOCK_SIZE) {
0466           remain -= sizeof (TFTP_BLOCK_SIZE_OPTION);
0467           pos    += sizeof (TFTP_BLOCK_SIZE_OPTION);
0468           if (!parse_decimal_number (
0469               &pos,
0470               &remain,
0471               TFTP_BLOCK_SIZE_MIN,
0472               options_in->block_size,
0473               &options_out->block_size)) {
0474               return false;
0475           };
0476 
0477       } else if (strcasecmp(pos, TFTP_WINDOW_SIZE_OPTION) == 0 &&
0478           options_in->window_size != TFTP_RFC1350_WINDOW_SIZE) {
0479           remain -= sizeof (TFTP_WINDOW_SIZE_OPTION);
0480           pos    += sizeof (TFTP_WINDOW_SIZE_OPTION);
0481           if (!parse_decimal_number (
0482               &pos,
0483               &remain,
0484               TFTP_WINDOW_SIZE_MIN,
0485               options_in->window_size,
0486               &options_out->window_size)) {
0487               return false;
0488           };
0489 
0490       } else {
0491          return false; /* Unknown option */
0492       }
0493     }
0494 
0495     return true;
0496 }
0497 
0498 /*
0499  * Send an error message
0500  */
0501 static void send_error (
0502     struct tftpStream *tp,
0503     struct sockaddr_in *to,
0504     uint8_t error_code,
0505     const char *error_message
0506 )
0507 {
0508     int len;
0509     struct {
0510         uint16_t      opcode;
0511         uint16_t      errorCode;
0512         char          errorMessage[80];
0513     } msg;
0514 
0515     /*
0516      * Create the error packet (Unknown transfer ID).
0517      */
0518     msg.opcode = htons (TFTP_OPCODE_ERROR);
0519     msg.errorCode = htons (error_code);
0520     len = snprintf (msg.errorMessage, sizeof (msg.errorMessage), error_message);
0521     if (len >= sizeof (msg.errorMessage)) {
0522       len = sizeof (msg.errorMessage) - 1;
0523     }
0524     len += sizeof (msg.opcode) + sizeof (msg.errorCode) + 1;
0525 
0526     /*
0527      * Send it
0528      *
0529      * Ignoring result because error packets are sent once and maybe lost.
0530      */
0531     (void) sendto (tp->socket, (char *)&msg, len, 0, (struct sockaddr *)to, sizeof *to);
0532 }
0533 
0534 /*
0535  * Send a message to make the other end shut up
0536  */
0537 static void sendStifle (struct tftpStream *tp, struct sockaddr_in *to)
0538 {
0539     send_error (tp, to, TFTP_ERROR_CODE_UNKNOWN_ID, "GO AWAY");
0540 }
0541 
0542 /*
0543  * Wait for a packet
0544  */
0545 static ssize_t
0546 getPacket (struct tftpStream *tp, int retryCount)
0547 {
0548     ssize_t len;
0549     struct timeval tv;
0550     int flags = 0;
0551 
0552     if (retryCount == GET_PACKET_DONT_WAIT) {
0553         flags = MSG_DONTWAIT;
0554     } else if (retryCount == 0) {
0555         tv.tv_sec = tp->config.first_timeout / 1000L;
0556         tv.tv_usec = (tp->config.first_timeout % 1000L) * 1000L;
0557         /*
0558          * Ignoring result because all possible errors indicate wrong
0559          * arguments and these arguments are OK as tested by test suite.
0560          */
0561         (void) setsockopt (tp->socket, SOL_SOCKET, SO_RCVTIMEO, &tv,
0562             sizeof tv);
0563     } else {
0564         tv.tv_sec = tp->config.timeout / 1000L;
0565         tv.tv_usec = (tp->config.timeout % 1000L) * 1000L;
0566         /*
0567          * Ignoring result because all possible errors indicate wrong
0568          * arguments and these arguments are OK as tested by test suite.
0569          */
0570         (void) setsockopt (tp->socket, SOL_SOCKET, SO_RCVTIMEO, &tv,
0571             sizeof tv);
0572     }
0573     for (;;) {
0574         union {
0575             struct sockaddr s;
0576             struct sockaddr_in i;
0577         } from;
0578         socklen_t fromlen = sizeof from;
0579         len = recvfrom (tp->socket,
0580             tp->receive_buf,
0581             tp->packet_size,
0582             flags,
0583             &from.s,
0584             &fromlen
0585         );
0586         if (len < 0)
0587             break;
0588         if (from.i.sin_addr.s_addr == tp->farAddress.sin_addr.s_addr) {
0589             if (tp->firstReply) {
0590                 tp->firstReply = 0;
0591                 tp->farAddress.sin_port = from.i.sin_port;
0592             }
0593             if (tp->farAddress.sin_port == from.i.sin_port)
0594                 break;
0595         }
0596 
0597         /*
0598          * Packet is from someone with whom we are
0599          * not interested.  Tell them to go away.
0600          */
0601         sendStifle (tp, &from.i);
0602     }
0603     if (retryCount != GET_PACKET_DONT_WAIT) {
0604         tv.tv_sec = 0;
0605         tv.tv_usec = 0;
0606         /*
0607          * Ignoring result because all possible errors indicate wrong
0608          * arguments and these arguments are OK as tested by test suite.
0609          */
0610         (void) setsockopt (tp->socket, SOL_SOCKET, SO_RCVTIMEO, &tv,
0611             sizeof tv);
0612     }
0613     return len;
0614 }
0615 
0616 static int process_unexpected_packet (struct tftpStream *tp, ssize_t len)
0617 {
0618     (void) len;
0619     send_error (
0620         tp,
0621         &tp->farAddress,
0622         TFTP_ERROR_CODE_ILLEGAL,
0623         "Got packet with unexpected opcode from server"
0624     );
0625     return EPROTO;
0626 }
0627 
0628 static int process_malformed_packet (struct tftpStream *tp, ssize_t len)
0629 {
0630     (void) len;
0631     send_error (
0632         tp,
0633         &tp->farAddress,
0634         TFTP_ERROR_CODE_ILLEGAL,
0635         "Got malformed packet from server"
0636     );
0637     return EPROTO;
0638 }
0639 
0640 static int process_error_packet (struct tftpStream *tp, ssize_t len)
0641 {
0642     (void) len;
0643     return tftpErrno (tp->receive_buf->tftpERROR.errorCode);
0644 }
0645 
0646 /*
0647  * When an RRQ or a WRQ with options is sent and the server responds with
0648  * an error, this function will trigger a re-sent of an RRQ or WRQ
0649  * without options (falling back to old RFC1350).
0650  *
0651  * If someone wants to change the implementation to force using options
0652  * (i.e. prevent fallback to RFC1350), at least these points must be
0653  * considered:
0654  *
0655  *     * Use `process_error_packet()` instead of
0656  *       `process_error_packet_option_negotiation()`
0657  *     * React to DATA and ACK packets, which are an immediate response to
0658  *       an RRQ or a WRQ with options, with an error packet.
0659  *     * Check the option values in the OACK whether they are in the
0660  *       desired range.
0661  */
0662 static int process_error_packet_option_negotiation (
0663     struct tftpStream *tp, ssize_t len
0664 )
0665 {
0666     (void) len;
0667     /*
0668      * Setting tp->config.options causes an RRQ or a WRQ to be created without
0669      * options.
0670      * Setting tp->server_option is defensive programming as these fields
0671      * should already have these values.
0672      */
0673     tp->config.options.block_size  = TFTP_RFC1350_BLOCK_SIZE;
0674     tp->config.options.window_size = TFTP_RFC1350_WINDOW_SIZE;
0675     tp->server_options.block_size  = TFTP_RFC1350_BLOCK_SIZE;
0676     tp->server_options.window_size = TFTP_RFC1350_WINDOW_SIZE;
0677 
0678     tp->process_error_packet = process_error_packet;
0679     /*
0680      * GOT_FIRST_OUT_OF_ORDER_PACKET will trigger a re-send of the RRQ or WRQ.
0681      */
0682     return GOT_FIRST_OUT_OF_ORDER_PACKET;
0683 }
0684 
0685 static int process_data_packet (struct tftpStream *tp, ssize_t len)
0686 {
0687     ssize_t plen;
0688     int32_t pkt_blocknum;
0689     union tftpPacket *send_buf;
0690 
0691     if (len < sizeof (tp->receive_buf->tftpACK)) {
0692         return process_malformed_packet (tp, len);
0693     }
0694     pkt_blocknum = (int32_t) ntohs (tp->receive_buf->tftpACK.blocknum);
0695     if (pkt_blocknum == 0) {
0696         return process_malformed_packet (tp, len);
0697     }
0698 
0699     /*
0700      * In case of reading a file from the server:
0701      * If the latest ACK packet(s) did not reach the server, the server
0702      * starts the window from the last ACK it received.  This if-clause
0703      * ensures, the client sends an ACK after having seen `windowsize`
0704      * packets.
0705      */
0706     if (pkt_blocknum < tp->blocknum_of_first_packet_of_window &&
0707         pkt_blocknum >= (int32_t) tp->blocknum + 1 -
0708             (int32_t) tp->server_options.window_size) {
0709         tp->blocknum_of_first_packet_of_window = pkt_blocknum;
0710     }
0711     if (!tp->ignore_out_of_order_packets &&
0712        pkt_blocknum > (int32_t) tp->blocknum + 1) {
0713         tp->ignore_out_of_order_packets = true;
0714         return GOT_FIRST_OUT_OF_ORDER_PACKET;
0715     } else if (pkt_blocknum == (int32_t) tp->blocknum) {
0716       /*
0717        * In case of reading a file from the server:
0718        * If the last ACK packet send by the client did not reach the
0719        * server, the server re-sends all packets of the window.  In this
0720        * case, the client must re-send the ACK packet after having
0721        * received the last packet of the window (even through it has
0722        * already received that packet before).
0723        * GOT_OLD_PACKET would wrongly suppress this.
0724        */
0725       return GOT_DUPLICATE_OF_CURRENT_PACKET;
0726     } else if (pkt_blocknum != (int32_t) tp->blocknum + 1) {
0727         return GOT_OLD_PACKET;
0728     }
0729     tp->ignore_out_of_order_packets = false;
0730 
0731     tp->blocknum++;
0732     tp->nused = 0; /* Only for 2nd, 3rd, 4th DATA packet received */
0733     tp->nleft = BLK_SIZE_FROM_PKT_SIZE (len);
0734     tp->at_eof = (tp->nleft < tp->server_options.block_size);
0735     /*
0736      * After the last DATA packet, the client must send a final ACK
0737      */
0738     if (tp->at_eof) {
0739         plen = prepare_ack_packet_for_sending (tp, true, &send_buf, NULL, NULL);
0740 
0741         /*
0742          * Send it. Errors during send will not matter for this last ACK.
0743          */
0744         (void) sendto (
0745             tp->socket,
0746             send_buf,
0747             plen,
0748             0,
0749             (struct sockaddr *) &tp->farAddress,
0750             sizeof (tp->farAddress)
0751         );
0752     }
0753     tp->prepare_packet_for_sending = prepare_ack_packet_for_sending;
0754     return GOT_EXPECTED_PACKET;
0755 }
0756 
0757 static int process_ack_packet (struct tftpStream *tp, ssize_t len)
0758 {
0759     uint16_t blocknum_ack;
0760     if (len < sizeof (tp->receive_buf->tftpACK)) {
0761         return process_malformed_packet (tp, len);
0762     }
0763     blocknum_ack = ntohs (tp->receive_buf->tftpACK.blocknum);
0764     if ((int32_t) blocknum_ack == tp->blocknum_of_first_packet_of_window - 1 &&
0765         blocknum_ack != 0
0766     ) {
0767         tp->blocknum = tp->blocknum_of_first_packet_of_window;
0768         return GOT_DUPLICATE_OF_CURRENT_PACKET;
0769     }
0770     if ((int32_t) blocknum_ack < tp->blocknum_of_first_packet_of_window ||
0771         blocknum_ack > tp->blocknum_last_filled) {
0772         return GOT_OLD_PACKET;
0773     }
0774     tp->blocknum = blocknum_ack + 1;
0775     tp->blocknum_of_first_packet_of_window = (int32_t) tp->blocknum;
0776     tp->prepare_packet_for_sending = prepare_data_packet_for_sending;
0777     return GOT_EXPECTED_PACKET;
0778 }
0779 
0780 static ssize_t prepare_data_packet_for_sending (
0781     struct tftpStream *tp,
0782     bool force_retransmission,
0783     union tftpPacket **send_buf,
0784     bool *wait_for_packet_reception,
0785     const void *not_used
0786 )
0787 {
0788     (void) not_used;
0789     ssize_t len;
0790     *send_buf = get_send_buffer_packet (tp, tp->blocknum);
0791 
0792     len = PKT_SIZE_FROM_BLK_SIZE (
0793         (tp->blocknum == tp->blocknum_eof_block) ? tp->nused : tp->block_size
0794     );
0795     (*send_buf)->tftpDATA.opcode   = htons (TFTP_OPCODE_DATA);
0796     (*send_buf)->tftpDATA.blocknum = htons (tp->blocknum);
0797 
0798     /*
0799      * If the client sends the last packet of a window,
0800      * it must wait for an ACK and - in case no ACK is received - begin
0801      * a retransmission with the first packet of the window.
0802      * Note that the last DATA block for the whole transfer is also
0803      * a "last packet of a window".
0804      */
0805     if ((int32_t) tp->blocknum + 1 >=
0806         tp->blocknum_of_first_packet_of_window + tp->send_buf_size_in_pkts ||
0807         tp->blocknum == tp->blocknum_eof_block) {
0808         tp->blocknum = (uint16_t) tp->blocknum_of_first_packet_of_window;
0809     } else {
0810         tp->blocknum++;
0811         *wait_for_packet_reception = false;
0812     }
0813 
0814     tp->process_data_packet  = process_unexpected_packet;
0815     tp->process_ack_packet   = process_ack_packet;
0816     tp->process_oack_packet  = process_unexpected_packet;
0817     tp->process_error_packet = process_error_packet;
0818 
0819     /*
0820      * Our last packet won't necessarily be acknowledged!
0821      */
0822     if (tp->blocknum == tp->blocknum_eof_block) {
0823         tp->retransmission_error_code = 0;
0824     }
0825 
0826     return len;
0827 }
0828 
0829 static ssize_t prepare_ack_packet_for_sending (
0830     struct tftpStream *tp,
0831     bool force_retransmission,
0832     union tftpPacket **send_buf,
0833     bool *wait_for_packet_reception,
0834     const void *path_name
0835 )
0836 {
0837     (void) wait_for_packet_reception;
0838     if (!force_retransmission &&
0839         tp->blocknum_of_first_packet_of_window - 1 +
0840         (int32_t) tp->server_options.window_size > (int32_t) tp->blocknum) {
0841       return DO_NOT_SEND_PACKET;
0842     }
0843     tp->blocknum_of_first_packet_of_window = (int32_t) tp->blocknum + 1;
0844 
0845     /*
0846      * Create the acknowledgement
0847      */
0848     *send_buf = tp->send_buf;
0849     (*send_buf)->tftpACK.opcode   = htons (TFTP_OPCODE_ACK);
0850     (*send_buf)->tftpACK.blocknum = htons (tp->blocknum);
0851 
0852     tp->process_data_packet  = process_data_packet;
0853     tp->process_ack_packet   = process_unexpected_packet;
0854     tp->process_oack_packet  = process_unexpected_packet;
0855     tp->process_error_packet = process_error_packet;
0856 
0857     return sizeof (tp->send_buf->tftpACK);
0858 }
0859 
0860 static int process_oack_packet (struct tftpStream *tp, ssize_t len)
0861 {
0862     if (!parse_options(tp->receive_buf,
0863         len,
0864         &tp->config.options,
0865         &tp->server_options)) {
0866         send_error (
0867             tp,
0868             &tp->farAddress,
0869             TFTP_ERROR_CODE_OPTION_NEGO,
0870             "Bad options, option values or malformed OACK packet"
0871         );
0872         return EPROTO;
0873     }
0874     if (tp->is_for_reading) {
0875         /*
0876          * Since no DATA packet has been received yet, tell
0877          * tftp_read() there is no data left.
0878          */
0879         tp->nleft = 0;
0880         tp->prepare_packet_for_sending = prepare_ack_packet_for_sending;
0881     } else {
0882         tp->blocknum_of_first_packet_of_window = 1;
0883         tp->blocknum = (uint16_t) tp->blocknum_of_first_packet_of_window;
0884         tp->prepare_packet_for_sending = prepare_data_packet_for_sending;
0885     }
0886     return GOT_EXPECTED_PACKET;
0887 }
0888 
0889 static ssize_t prepare_request_packet_for_sending (
0890     struct tftpStream *tp,
0891     bool force_retransmission,
0892     union tftpPacket **send_buf,
0893     bool *wait_for_packet_reception,
0894     const void *path_name
0895 )
0896 {
0897     (void) wait_for_packet_reception;
0898     ssize_t len;
0899     *send_buf = tp->send_buf;
0900     len = create_request (
0901         *send_buf,
0902         tp->block_size,
0903         tp->is_for_reading,
0904         path_name,
0905         &tp->config.options
0906     );
0907 
0908     if (len < 0) {
0909         tp->error = ENAMETOOLONG;
0910     } else {
0911         tp->process_data_packet  = tp->is_for_reading ?
0912             process_data_packet : process_unexpected_packet;
0913         tp->process_ack_packet   = tp->is_for_reading ?
0914             process_unexpected_packet : process_ack_packet;
0915         tp->process_oack_packet  = MUST_SEND_OPTIONS(tp->config.options) ?
0916             process_oack_packet : process_unexpected_packet;
0917         tp->process_error_packet = MUST_SEND_OPTIONS(tp->config.options) ?
0918             process_error_packet_option_negotiation : process_error_packet;
0919     }
0920 
0921     /*
0922      * getPacket() will change these values when the first packet is
0923      * received.  Yet, this first packet may be an unexpected one
0924      * (e.g. an ERROR or having a wrong block number).
0925      * If a second, third, forth, ... RRQ/WRQ is to be sent, it should
0926      * be directed to the server port again and not to the port the
0927      * first unexpected packet came from.
0928      */
0929     tp->farAddress.sin_port = htons (tp->config.server_port);
0930     tp->firstReply          = 1;
0931 
0932     return len;
0933 }
0934 
0935 /*
0936  * Conduct one communication step with the server. For windowsize == 1,
0937  * one step is:
0938  *   a) Send a packet to the server
0939  *   b) Receive a reply packet from the server
0940  *   c) Handle errors (if any)
0941  *   d) If no packet has been received from the server and the maximum
0942  *      retransmission count has not yet been reached, start over with a)
0943  * The flow of packets (i.e. which packet to send and which packet(s) to
0944  * expect from the server) is controlled by function pointers found in
0945  * struct tftpStream.
0946  *
0947  * Besides of handling errors and retransmissions, the essential data exchange
0948  * follows these patterns:
0949  *
0950  * Connection establishment and option negotiation:
0951  *   * Send RRQ/WRQ (read or write request packet)
0952  *   * Receive OACK (read and write) or ACK (write only) or DATA (read only)
0953  *
0954  * Read step with windowsize == 1:
0955  *   * Send ACK packet
0956  *   * Receive DATA packet
0957  * Sending the very last ACK packet for a "read" session is treated as a
0958  * special case.
0959  *
0960  * Write step with windowsize == 1:
0961  *   * Send DATA packet
0962  *   * Receive ACK packet
0963  *
0964  * A windowsize lager than one makes thinks more complicated.
0965  * In this case, a step normally only receives (read) or only sends (write)
0966  * a packet.  The sending or receiving of the ACK packets is skipped normally
0967  * and happens only at the last step of the window (in which case this last
0968  * step is similar to the windowsize == 1 case):
0969  *
0970  * Normal read step with windowsize > 1:
0971  *   * Receive DATA packet
0972  * Last read step of a window with windowsize > 1:
0973  *   * Send ACK packet
0974  *   * Receive DATA packet
0975  *
0976  * Normal write step with windowsize > 1:
0977  *   * Send DATA packet
0978  *   * Check for an ACK packet but do not wait for it
0979  * Last write step of a window with windowsize > 1:
0980  *   * Send DATA packet
0981  *   * Receive ACK packet
0982  *
0983  * The "normal write step for windowsize > 1" checks whether an ACK packet
0984  * has been received after each sending of a DATA packet.  Package lost and
0985  * exchanges in the network can give rise to situations in which the server
0986  * sends more than a single ACK packet during a window.  If these packets
0987  * are not reacted on immediately, the network would be flooded with
0988  * surplus packets.  (An example where two ACK packets appear in a window
0989  * appears in test case "read_file_windowsize_trouble" where the client/server
0990  * roles are exchanged.)
0991  */
0992 static int communicate_with_server (
0993     struct tftpStream    *tp,
0994     const void *create_packet_data
0995 )
0996 {
0997     ssize_t len;
0998     uint16_t opcode;
0999     union tftpPacket *send_buf;
1000     bool received_duplicated_or_old_package = false;
1001     bool force_retransmission = false;
1002     bool wait_for_packet_reception;
1003     int retryCount = 0;
1004     while (tp->error == 0) {
1005 
1006         if (!received_duplicated_or_old_package) {
1007             wait_for_packet_reception = true;
1008             len = tp->prepare_packet_for_sending (
1009                 tp,
1010                 force_retransmission,
1011                 &send_buf,
1012                 &wait_for_packet_reception,
1013                 create_packet_data
1014                 );
1015             if (len < 0) {
1016                 if (tp->error == 0) {
1017                     tp->error = EIO;
1018                 }
1019                 break;
1020             }
1021 
1022             if (len != DO_NOT_SEND_PACKET) {
1023                 /*
1024                  * Send the packet
1025                  */
1026                 if (sendto (tp->socket, send_buf, len, 0,
1027                             (struct sockaddr *)&tp->farAddress,
1028                             sizeof tp->farAddress) < 0) {
1029                     tp->error = EIO;
1030                     break;
1031                 }
1032             }
1033         }
1034         received_duplicated_or_old_package = false;
1035         force_retransmission = false;
1036 
1037         /*
1038          * Get reply
1039          */
1040         len = getPacket (
1041             tp,
1042             wait_for_packet_reception ? retryCount : GET_PACKET_DONT_WAIT
1043         );
1044         if (len >= (int) sizeof (tp->receive_buf->tftpDATA.opcode)) {
1045             opcode = ntohs (tp->receive_buf->tftpDATA.opcode);
1046             switch (opcode) {
1047             case TFTP_OPCODE_DATA:
1048                 tp->error = tp->process_data_packet (tp, len);
1049                 break;
1050             case TFTP_OPCODE_ACK:
1051                 tp->error = tp->process_ack_packet (tp, len);
1052                 break;
1053             case TFTP_OPCODE_OACK:
1054                 tp->error = tp->process_oack_packet (tp, len);
1055                 break;
1056             case TFTP_OPCODE_ERROR:
1057                 tp->error = tp->process_error_packet (tp, len);
1058                 break;
1059             default:
1060                 tp->error = process_unexpected_packet (tp, len);
1061                 break;
1062             }
1063             if (tp->error == GOT_EXPECTED_PACKET) {
1064                 break;
1065             } else if (tp->error == GOT_DUPLICATE_OF_CURRENT_PACKET) {
1066                 tp->error = 0;
1067             } else if (tp->error == GOT_OLD_PACKET) {
1068                 received_duplicated_or_old_package = true;
1069                 tp->error = 0;
1070             } else if (tp->error <= GOT_FIRST_OUT_OF_ORDER_PACKET) {
1071                 force_retransmission = true;
1072                 tp->error = 0;
1073             } /* else ... tp->error > 0 means "exit this function with error" */
1074         } else if (len >= 0) {
1075             tp->error = process_malformed_packet (tp, len);
1076         } else if (len < 0 && !wait_for_packet_reception) {
1077             tp->error = 0;
1078             break;
1079         } else {
1080             /*
1081              * Timeout or other problems to receive packets
1082              * Attempt a retransmission
1083              */
1084             if (++retryCount >= (int) tp->config.retransmissions) {
1085                 tp->error = tp->retransmission_error_code;
1086                 break;
1087             }
1088             force_retransmission = true;
1089         }
1090     }
1091 
1092     return tp->error;
1093 }
1094 
1095 /*
1096  * Allocate and initialize an struct tftpStream object.
1097  *
1098  * This function does not check whether the config values are in valid ranges.
1099  */
1100 static struct tftpStream *create_stream(
1101     const tftp_net_config *config,
1102     const struct in_addr *farAddress,
1103     bool is_for_reading
1104 )
1105 {
1106     struct tftpStream *tp = NULL;
1107     tp = malloc (sizeof (struct tftpStream));
1108     if (tp == NULL) {
1109         return NULL;
1110     }
1111 
1112     /*
1113      * Initialize fields accessed by _Tftp_Destroy().
1114      */
1115     tp->receive_buf = NULL;
1116     tp->send_buf    = NULL;
1117     tp->socket      = 0;
1118 
1119     /*
1120      * Allocate send and receive buffer for exchange of RRQ/WRQ and ACK/OACK.
1121      */
1122     tp->block_size  = TFTP_RFC1350_BLOCK_SIZE;
1123     tp->packet_size = PKT_SIZE_FROM_BLK_SIZE (tp->block_size);
1124     tp->receive_buf = malloc (tp->packet_size);
1125     if (tp->receive_buf == NULL) {
1126       _Tftp_Destroy (tp);
1127       return NULL;
1128     }
1129     tp->send_buf = tp->receive_buf;
1130     tp->send_buf_size_in_pkts = 1;
1131 
1132     /*
1133      * Create the socket
1134      */
1135     if ((tp->socket = socket (AF_INET, SOCK_DGRAM, 0)) < 0) {
1136         _Tftp_Destroy (tp);
1137         return NULL;
1138     }
1139 
1140     /*
1141      * Setup configuration and options
1142      */
1143     if ( config == NULL ) {
1144       tftp_initialize_net_config (&tp->config);
1145     } else {
1146       tp->config = *config;
1147     }
1148 
1149     /*
1150      * If the server does not confirm our option values later on,
1151      * use numbers from the original RFC 1350 for the actual transfer.
1152      */
1153     tp->server_options.block_size  = TFTP_RFC1350_BLOCK_SIZE;
1154     tp->server_options.window_size = TFTP_RFC1350_WINDOW_SIZE;
1155 
1156     /*
1157      * Set the UDP destination to the TFTP server
1158      * port on the remote machine.
1159      */
1160     tp->farAddress.sin_family              = AF_INET;
1161     tp->farAddress.sin_addr                = *farAddress;
1162     tp->farAddress.sin_port                = htons (tp->config.server_port);
1163 
1164     tp->nleft                              = 0;
1165     tp->nused                              = 0;
1166     tp->blocknum                           = 0;
1167     tp->blocknum_last_filled               = 0;
1168     tp->blocknum_eof_block                 = UINT16_MAX;
1169     tp->firstReply                         = 1;
1170     tp->at_eof                             = false;
1171     tp->is_for_reading                     = is_for_reading;
1172 
1173     tp->prepare_packet_for_sending         = prepare_request_packet_for_sending;
1174     tp->process_data_packet                = process_unexpected_packet;
1175     tp->process_ack_packet                 = process_unexpected_packet;
1176     tp->process_oack_packet                = process_unexpected_packet;
1177     tp->process_error_packet               = process_error_packet;
1178     tp->retransmission_error_code          = EIO;
1179     tp->ignore_out_of_order_packets        = false;
1180     tp->blocknum_of_first_packet_of_window = INT32_MIN;
1181     tp->error                              = 0;
1182 
1183     return tp;
1184 }
1185 
1186 /*
1187  * Change the size of the receive and send buffer to match the options
1188  * values acknowledged by the server.
1189  */
1190 static struct tftpStream *reallocate_stream_buffer(struct tftpStream *tp)
1191 {
1192     tp->block_size = tp->server_options.block_size;
1193     tp->packet_size = PKT_SIZE_FROM_BLK_SIZE (tp->block_size);
1194     /*
1195      * Defensive programming
1196      */
1197     if (tp->receive_buf == tp->send_buf) {
1198         tp->send_buf = NULL;
1199     } else {
1200        free (tp->send_buf);
1201     }
1202 
1203     tp->receive_buf = realloc (tp->receive_buf, tp->packet_size);
1204     if (tp->is_for_reading) {
1205         tp->send_buf = tp->receive_buf;
1206     } else {
1207         tp->send_buf_size_in_pkts = tp->server_options.window_size;
1208         tp->send_buf = malloc (
1209             tp->send_buf_size_in_pkts * tp->packet_size
1210         );
1211     }
1212 
1213     if (tp->receive_buf == NULL || tp->send_buf == NULL) {
1214       sendStifle (tp,  &tp->farAddress);
1215       _Tftp_Destroy (tp);
1216       return NULL;
1217     }
1218     return tp;
1219 }
1220 
1221 /*
1222  * Convert hostname to an Internet address
1223  */
1224 static struct in_addr *get_ip_address(
1225     const char     *hostname,
1226     struct in_addr *farAddress
1227 )
1228 {
1229         struct hostent *he = gethostbyname(hostname);
1230         if (he == NULL) {
1231             return NULL;
1232         }
1233         memcpy (farAddress, he->h_addr, sizeof (*farAddress));
1234   return farAddress;
1235 }
1236 
1237 void tftp_initialize_net_config (tftp_net_config *config)
1238 {
1239   static const tftp_net_config default_config = {
1240     .retransmissions = TFTP_RFC7440_DATA_RETRANSMISSIONS,
1241     .server_port     = TFTP_DEFAULT_SERVER_PORT,
1242     .timeout         = TFTP_RFC7440_TIMEOUT_MILLISECONDS,
1243     .first_timeout   = PACKET_FIRST_TIMEOUT_MILLISECONDS,
1244     .options = {
1245       .block_size    = TFTP_DEFAULT_BLOCK_SIZE,
1246       .window_size   = TFTP_DEFAULT_WINDOW_SIZE
1247     }
1248   };
1249 
1250   if (config != NULL) {
1251     memcpy (config, &default_config, sizeof (default_config));
1252   }
1253 }
1254 
1255 int tftp_open(
1256     const char               *hostname,
1257     const char               *path,
1258     bool                      is_for_reading,
1259     const tftp_net_config    *config,
1260     void                    **tftp_handle
1261 )
1262 {
1263     struct tftpStream    *tp;
1264     struct in_addr       farAddress;
1265     int                  err;
1266 
1267     /*
1268      * Check parameters
1269      */
1270     if (tftp_handle == NULL) {
1271       return EINVAL;
1272     }
1273     *tftp_handle = NULL;
1274     if (hostname == NULL || path == NULL) {
1275         return EINVAL;
1276     }
1277     if (config != NULL && (
1278         config->options.window_size < TFTP_WINDOW_SIZE_MIN ||
1279         config->options.block_size  < TFTP_BLOCK_SIZE_MIN  ||
1280         config->options.block_size  > TFTP_BLOCK_SIZE_MAX  ) ) {
1281         return EINVAL;
1282     }
1283 
1284     /*
1285      * Create tftpStream structure
1286      */
1287     if (get_ip_address( hostname, &farAddress ) == NULL) {
1288         return ENOENT;
1289     }
1290     tp = create_stream( config, &farAddress, is_for_reading );
1291     if (tp == NULL) {
1292         return ENOMEM;
1293     }
1294 
1295     /*
1296      * Send RRQ or WRQ and wait for reply
1297      */
1298     tp->prepare_packet_for_sending = prepare_request_packet_for_sending;
1299     err = communicate_with_server (tp, path);
1300     if ( err != 0 ) {
1301         _Tftp_Destroy (tp);
1302         return err;
1303     }
1304 
1305     *tftp_handle = reallocate_stream_buffer ( tp );
1306     if( *tftp_handle == NULL ) {
1307         return ENOMEM;
1308     }
1309 
1310     return 0;
1311 }
1312 
1313 /*
1314  * Read from a TFTP stream
1315  */
1316 ssize_t tftp_read(
1317     void          *tftp_handle,
1318     void          *buffer,
1319     size_t         count
1320 )
1321 {
1322     char              *bp;
1323     struct tftpStream *tp = tftp_handle;
1324     int               nwant;
1325     int               err;
1326 
1327     if (tp == NULL || !tp->is_for_reading || buffer == NULL)
1328         return -EIO;
1329 
1330     /*
1331      * Read till user request is satisfied or EOF is reached
1332      */
1333     bp = buffer;
1334     nwant = count;
1335     while (nwant) {
1336         if (tp->nleft) {
1337             int ncopy;
1338             if (nwant < tp->nleft)
1339                 ncopy = nwant;
1340             else
1341                 ncopy = tp->nleft;
1342             memcpy (bp, &tp->receive_buf->tftpDATA.data[tp->nused], ncopy);
1343             tp->nused += ncopy;
1344             tp->nleft -= ncopy;
1345             bp += ncopy;
1346             nwant -= ncopy;
1347             if (nwant == 0)
1348                 break;
1349         }
1350         if (tp->at_eof) {
1351             break;
1352         }
1353 
1354         /*
1355          * Wait for the next packet
1356          */
1357         tp->retransmission_error_code = -EIO;
1358         err = communicate_with_server(tp, NULL);
1359         if (err == tp->retransmission_error_code) {
1360           return -EIO;
1361         }
1362         /*
1363          * If communicate_with_server() returns an error, either
1364          *    * an error message from the server was received or
1365          *    * an error message was already sent to the server
1366          * Setting tp->at_eof true, prevents all further calls to
1367          * communicate_with_server() and suppresses the sending of
1368          * an error message to the server by tftp_close().
1369          */
1370         if (err != 0) {
1371             tp->at_eof = true;
1372             return -err;
1373         }
1374     }
1375     return count - nwant;
1376 }
1377 
1378 /*
1379  * Flush a write buffer and wait for acknowledgement
1380  *
1381  * This function returns only if there is at least one packet buffer free
1382  * in the tp->send_buf.  This ensures that tftp_write() can store
1383  * further data for sending in this free packet buffer.
1384  *
1385  * When the end of file has been reached (i.e. tftp_close() called this
1386  * function), this function returns only after all packets
1387  * in the write buffer have been send and acknowledged (or if an error
1388  * occurred).
1389  */
1390 static int rtems_tftp_flush (struct tftpStream *tp)
1391 {
1392     int err;
1393 
1394     if (tp->at_eof) {
1395         return 0;
1396     }
1397 
1398     do {
1399         err = communicate_with_server(tp, NULL);
1400         /*
1401          * If communicate_with_server() returns an error, either
1402          *    * an error message from the server was received or
1403          *    * an error message was already sent to the server
1404          * Setting tp->at_eof true, prevents all further calls to
1405          * communicate_with_server() and suppresses the sending of
1406          * an error message to the server by tftp_close().
1407          */
1408         if (err != 0) {
1409             tp->at_eof = true;
1410             return err;
1411         }
1412     } while(
1413          (int32_t) tp->blocknum_last_filled + 1 >=
1414          tp->blocknum_of_first_packet_of_window + tp->send_buf_size_in_pkts ||
1415          /*
1416           * tp->blocknum_eof_block == tp->blocknum_last_filled
1417           * holds only true when the user invoked tftp_close().
1418           */
1419          (tp->blocknum_eof_block == tp->blocknum_last_filled &&
1420          tp->blocknum_of_first_packet_of_window <=
1421          (int32_t) tp->blocknum_eof_block)
1422     );
1423 
1424     return 0;
1425 }
1426 
1427 /*
1428  * Close a TFTP stream
1429  */
1430 int tftp_close(
1431     void *tftp_handle
1432 )
1433 {
1434     struct tftpStream *tp = tftp_handle;
1435     int                e = 0;
1436 
1437     if (tp == NULL) {
1438         return 0;
1439     }
1440 
1441     if (!tp->is_for_reading) {
1442         tp->blocknum_last_filled++;
1443         tp->blocknum_eof_block = tp->blocknum_last_filled;
1444         e = rtems_tftp_flush (tp);
1445         tp->at_eof = true;
1446     }
1447     if (!tp->at_eof && !tp->firstReply) {
1448         /*
1449          * Tell the other end to stop
1450          */
1451         rtems_interval ticksPerSecond;
1452         send_error (
1453             tp,
1454             &tp->farAddress,
1455             TFTP_ERROR_CODE_NO_USER,
1456             "User (client) stopped reading or "
1457             "server stopped sending packets (timeout)"
1458         );
1459         ticksPerSecond = rtems_clock_get_ticks_per_second();
1460         rtems_task_wake_after (1 + ticksPerSecond / 10);
1461     }
1462     _Tftp_Destroy (tp);
1463     return e;
1464 }
1465 
1466 ssize_t tftp_write(
1467     void            *tftp_handle,
1468     const void      *buffer,
1469     size_t           count
1470 )
1471 {
1472     const char        *bp;
1473     struct tftpStream *tp = tftp_handle;
1474     int               nleft, nfree, ncopy;
1475     int               err;
1476     union tftpPacket *send_buf;
1477 
1478     /*
1479      * Bail out if an error has occurred
1480      */
1481     if (tp == NULL || tp->is_for_reading || tp->at_eof || buffer == NULL) {
1482         return -EIO;
1483     }
1484 
1485     /*
1486      * Write till user request is satisfied
1487      * Notice that the buffer is flushed as soon as it is filled rather
1488      * than waiting for the next write or a close.  This ensures that
1489      * the flush in close writes a less than full buffer so the far
1490      * end can detect the end-of-file condition.
1491      */
1492     bp = buffer;
1493     nleft = count;
1494     while (nleft) {
1495         nfree = tp->block_size - tp->nused;
1496         if (nleft < nfree)
1497             ncopy = nleft;
1498         else
1499             ncopy = nfree;
1500         send_buf = get_send_buffer_packet (tp, tp->blocknum_last_filled + 1);
1501         memcpy (&send_buf->tftpDATA.data[tp->nused], bp, ncopy);
1502         tp->nused += ncopy;
1503         nleft -= ncopy;
1504         bp += ncopy;
1505         if (tp->nused == tp->block_size) {
1506             tp->blocknum_last_filled++;
1507             err = rtems_tftp_flush (tp);
1508             if (err) {
1509                 return -err;
1510             }
1511             tp->nused = 0;
1512         }
1513     }
1514     return count;
1515 }
1516 
1517 void _Tftp_Destroy(
1518     void *tftp_handle
1519 )
1520 {
1521     struct tftpStream *tp = tftp_handle;
1522     if (tp == NULL) {
1523         return;
1524     }
1525 
1526     if (tp->socket >= 0) {
1527         close (tp->socket);
1528     }
1529 
1530     if (tp->receive_buf == tp->send_buf) {
1531         tp->send_buf = NULL;
1532     }
1533     free (tp->receive_buf);
1534     free (tp->send_buf);
1535     free (tp);
1536 }