source: rtems/cpukit/libfs/src/ftpfs/tftpDriver.c @ 679e7f10

Last change on this file since 679e7f10 was 679e7f10, checked in by Frank Kühndel <frank.kuehndel@…>, on 06/01/22 at 14:31:06

TFTPFS: Implement block and window size options

The original file cpukit/libfs/src/ftpfs/tftpDriver.c
is split into two:

tftpfs.c - This file contains the code from tftpDriver.c

related to file system operations such as mount(),
open(), read(), and so on.

tftpDriver.c - In the original file remains only the code related

to networking. This code implements the Trivial
File Transfer Protocol (TFTP).

Moreover, the code is extended to support

  • RFC 2347 TFTP Option Extension
  • RFC 2348 TFTP Blocksize Option
  • RFC 7440 TFTP Windowsize Option

Update #4666.

  • Property mode set to 100644
File size: 43.6 KB
Line 
1/* SPDX-License-Identifier: BSD-2-Clause */
2
3/**
4 * @file
5 *
6 * @ingroup RTEMSImplTFTPFS
7 *
8 * @brief This source file contains the implementation of
9 *   a Trivial File Transfer Protocol (TFTP) client library.
10 *
11 * The code in this file provides the ability to read files from and
12 * to write files to remote servers using the Trivial File Transfer
13 * Protocol (TFTP). It is used by the @ref tftpfs.c "TFTP file system" and
14 * tested through its test suite. The
15 * following RFCs are implemented:
16 *
17 *   + RFC 1350 "The TFTP Protocol (Revision 2)"
18 *   + RFC 2347 "TFTP Option Extension"
19 *   + RFC 2348 "TFTP Blocksize Option"
20 *   + RFC 7440 "TFTP Windowsize Option"
21 */
22
23/*
24 * Copyright (C) 1998 W. Eric Norum <eric@norum.ca>
25 * Copyright (C) 2012, 2022 embedded brains GmbH (http://www.embedded-brains.de)
26 *
27 * Redistribution and use in source and binary forms, with or without
28 * modification, are permitted provided that the following conditions
29 * are met:
30 * 1. Redistributions of source code must retain the above copyright
31 *    notice, this list of conditions and the following disclaimer.
32 * 2. Redistributions in binary form must reproduce the above copyright
33 *    notice, this list of conditions and the following disclaimer in the
34 *    documentation and/or other materials provided with the distribution.
35 *
36 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
37 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
38 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
39 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
40 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
41 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
42 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
43 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
44 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
45 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
46 * POSSIBILITY OF SUCH DAMAGE.
47 */
48
49#ifdef HAVE_CONFIG_H
50#include "config.h"
51#endif
52
53#include <stdio.h>
54#include <stdlib.h>
55#include <inttypes.h>
56#include <errno.h>
57#include <malloc.h>
58#include <string.h>
59#include <unistd.h>
60#include <fcntl.h>
61#include <rtems.h>
62#include <rtems/tftp.h>
63#include <sys/types.h>
64#include <sys/socket.h>
65#include <netinet/in.h>
66#include <arpa/inet.h>
67#include <netdb.h>
68
69#include "tftp_driver.h"
70
71/*
72 * Range of UDP ports to try
73 */
74#define UDP_PORT_BASE        3180
75
76/*
77 * Default limits
78 */
79#define PACKET_FIRST_TIMEOUT_MILLISECONDS  400L
80#define TFTP_WINDOW_SIZE_MIN               1
81#define TFTP_BLOCK_SIZE_MIN                8
82#define TFTP_BLOCK_SIZE_MAX                65464
83
84#define TFTP_BLOCK_SIZE_OPTION             "blksize"
85#define TFTP_WINDOW_SIZE_OPTION            "windowsize"
86#define TFTP_DECIMAL_BASE                  10
87
88#define TFTP_DEFAULT_SERVER_PORT           69
89
90/*
91 * These values are suggested by RFC 7440.
92 */
93#define TFTP_RFC7440_DATA_RETRANSMISSIONS  6
94#define TFTP_RFC7440_TIMEOUT_MILLISECONDS  1000
95
96/*
97 * TFTP opcodes
98 */
99#define TFTP_OPCODE_RRQ     1
100#define TFTP_OPCODE_WRQ     2
101#define TFTP_OPCODE_DATA    3
102#define TFTP_OPCODE_ACK     4
103#define TFTP_OPCODE_ERROR   5
104#define TFTP_OPCODE_OACK    6
105
106/*
107 * TFTP error codes
108 */
109#define TFTP_ERROR_CODE_NOT_DEFINED 0
110#define TFTP_ERROR_CODE_NOT_FOUND   1
111#define TFTP_ERROR_CODE_NO_ACCESS   2
112#define TFTP_ERROR_CODE_DISK_FULL   3
113#define TFTP_ERROR_CODE_ILLEGAL     4
114#define TFTP_ERROR_CODE_UNKNOWN_ID  5
115#define TFTP_ERROR_CODE_FILE_EXISTS 6
116#define TFTP_ERROR_CODE_NO_USER     7
117#define TFTP_ERROR_CODE_OPTION_NEGO 8
118
119/*
120 * Special return values for process_*_packet() functions
121 * (other return values are POSIX errors)
122 */
123#define GOT_EXPECTED_PACKET 0
124#define GOT_DUPLICATE_OF_CURRENT_PACKET -1
125#define GOT_OLD_PACKET -2
126#define GOT_FIRST_OUT_OF_ORDER_PACKET -3
127
128/*
129 * Special argument value for getPacket()
130 */
131#define GET_PACKET_DONT_WAIT -1
132
133/*
134 * Special return value for prepare_*_packet_for_sending() functions
135 * (other return values are the length of the packet to be send)
136 */
137#define DO_NOT_SEND_PACKET 0
138
139#define PKT_SIZE_FROM_BLK_SIZE(_blksize) ((_blksize) + 2 * sizeof (uint16_t))
140#define BLK_SIZE_FROM_PKT_SIZE(_pktsize) ((_pktsize) - 2 * sizeof (uint16_t))
141#define MUST_SEND_OPTIONS(_options) (\
142    (_options).block_size  != TFTP_RFC1350_BLOCK_SIZE || \
143    (_options).window_size != TFTP_RFC1350_WINDOW_SIZE )
144
145/*
146 * Packets transferred between machines
147 */
148union tftpPacket {
149    /*
150     * RRQ/WRQ packet
151     */
152    struct tftpRWRQ {
153        uint16_t      opcode;
154        char          filename_mode[];
155    } tftpRWRQ;
156
157    /*
158     * DATA packet
159     */
160    struct tftpDATA {
161        uint16_t      opcode;
162        uint16_t      blocknum;
163        uint8_t       data[];
164    } tftpDATA;
165
166    /*
167     * ACK packet
168     */
169    struct tftpACK {
170        uint16_t      opcode;
171        uint16_t      blocknum;
172    } tftpACK;
173
174    /*
175     * OACK packet
176     */
177    struct tftpOACK {
178        uint16_t      opcode;
179        char          options[];
180    } tftpOACK;
181
182    /*
183     * ERROR packet
184     */
185    struct tftpERROR {
186        uint16_t      opcode;
187        uint16_t      errorCode;
188        char          errorMessage[];
189    } tftpERROR;
190};
191
192/*
193 * State of each TFTP stream
194 */
195struct tftpStream {
196    /*
197     * Buffer for storing packets for sending and receiving.  Can point
198     * to the same address when only one buffer is needed for reading.
199     */
200    union tftpPacket *receive_buf;
201    union tftpPacket *send_buf;
202
203    /*
204     * Current block number - i.e. the block currently send or received
205     */
206    uint16_t      blocknum;
207
208    /*
209     * Size of the data area in a DATA single packet.
210     */
211    size_t block_size;
212
213    /*
214     * The maximum size of a packet.  It depends linearly on the block_size.
215     * The receive_buf and (the packets in) the send_buf are of this size.
216     */
217    size_t packet_size;
218
219    /*
220     * The number of packets which can be stored in the send buffer.
221     * During option negotiation and for reading a file from the server
222     * only a buffer for a single packet is needed.  In those cases, this
223     * value is always one.  When a file is written to the server,
224     * the value equals the window size:
225     *     send_buf_size_in_pkts == server_options.window_size
226     *
227     * Packet N is stored in
228     *     send_buf + packet_size * (N % send_buf_size_in_pkts)
229     */
230    uint16_t send_buf_size_in_pkts;
231
232    /*
233     * When writing files with windowsize > 1, the number of the completely
234     * filled packet with the highest block number in the send buffer.
235     * When the user calls write(), the data will be written into
236     * the block after this one.
237     */
238    uint16_t blocknum_last_filled;
239
240    /*
241     * When writing files with windowsize > 1, the number of the packet
242     * which is the last one in the whole file (i.e. the user
243     * called close()).  This block is never full (but maybe empty).
244     */
245    uint16_t blocknum_eof_block;
246
247    /*
248     * Data transfer socket
249     */
250    int                 socket;
251    struct sockaddr_in  myAddress;
252    struct sockaddr_in  farAddress;
253
254    /*
255     * Indices into buffer
256     * In case of sending a file with windowsize > 1, these values apply
257     * only to the packet with the highest number in the send buffer
258     * (blocknum_last_filled + 1).
259     */
260    int     nleft;
261    int     nused;
262
263    /*
264     * Flags
265     */
266    int     firstReply;
267    bool    at_eof;
268    bool    is_for_reading;
269
270    /*
271     * Function pointers and members for use by communicate_with_server().
272     */
273    ssize_t (*prepare_packet_for_sending) (
274        struct tftpStream *tp,
275        bool force_retransmission,
276        union tftpPacket **send_buf,
277        bool *wait_for_packet_reception,
278        const void *create_packet_data
279    );
280    int (*process_data_packet) (struct tftpStream *tp, ssize_t len);
281    int (*process_ack_packet) (struct tftpStream *tp, ssize_t len);
282    int (*process_oack_packet) (struct tftpStream *tp, ssize_t len);
283    int (*process_error_packet) (struct tftpStream *tp, ssize_t len);
284    int retransmission_error_code;
285    bool ignore_out_of_order_packets;
286    int32_t blocknum_of_first_packet_of_window;
287    int error;
288
289    /*
290     * Configuration and TFTP options
291     *
292     *     * config.options are options desired by the user (i.e. the values
293     *       send to the server).
294     *     * server_options are the options agreed by the server
295     *       (the option values actually used for the transfer of data).
296     */
297    tftp_net_config config;
298    tftp_options server_options;
299};
300
301/*
302 * Forward declaration cannot be avoided.
303 */
304static ssize_t prepare_data_packet_for_sending (
305    struct tftpStream *tp,
306    bool force_retransmission,
307    union tftpPacket **send_buf,
308    bool *wait_for_packet_reception,
309    const void *path_name
310);
311static ssize_t prepare_ack_packet_for_sending (
312    struct tftpStream *tp,
313    bool force_retransmission,
314    union tftpPacket **send_buf,
315    bool *wait_for_packet_reception,
316    const void *path_name
317);
318
319/*
320 * Calculate the address of packet N in the send buffer
321 */
322static union tftpPacket *get_send_buffer_packet (
323    struct tftpStream *tp,
324    uint16_t packet_num
325)
326{
327    return (union tftpPacket *) ( ( (char *) tp->send_buf) + tp->packet_size *
328        (packet_num % tp->send_buf_size_in_pkts) );
329}
330
331/*
332 * Create read or write request
333 */
334static size_t create_request (
335    union tftpPacket *send_buf,
336    size_t data_size,
337    bool is_for_reading,
338    const char *path,
339    const tftp_options *options
340)
341{
342  size_t res_size;
343  char *cur = send_buf->tftpRWRQ.filename_mode;
344
345  send_buf->tftpRWRQ.opcode = htons (
346      is_for_reading ? TFTP_OPCODE_RRQ : TFTP_OPCODE_WRQ
347  );
348
349  res_size = snprintf (cur, data_size, "%s%c%s", path, 0, "octet");
350  if (res_size >= data_size) {
351     return -1;
352  }
353  res_size++;
354  data_size -= res_size;
355  cur += res_size;
356
357  if (options->block_size != TFTP_RFC1350_BLOCK_SIZE) {
358      res_size = snprintf (
359          cur,
360          data_size,
361          "%s%c%"PRIu16,
362          TFTP_BLOCK_SIZE_OPTION,
363          0,
364          options->block_size
365      );
366      if (res_size >= data_size) {
367          return -1;
368      }
369      res_size++;
370      data_size -= res_size;
371      cur += res_size;
372  }
373
374  if (options->window_size != TFTP_RFC1350_WINDOW_SIZE) {
375      res_size = snprintf (
376          cur,
377          data_size,
378          "%s%c%"PRIu16,
379          TFTP_WINDOW_SIZE_OPTION,
380          0,
381          options->window_size
382      );
383      if (res_size >= data_size) {
384          return -1;
385      }
386      res_size++;
387      data_size -= res_size;
388      cur += res_size;
389  }
390
391  return cur - (char *)send_buf;
392}
393
394static bool parse_decimal_number (
395    char **pos,
396    size_t *remain,
397    long min,
398    long max,
399    uint16_t *variable
400)
401{
402    long value;
403    const char *start = *pos;
404    if (*remain < 2) {
405        return false;
406    }
407    value = strtoul(start, pos, TFTP_DECIMAL_BASE);
408    if (value < min || value > max || **pos != 0) {
409        return false;
410    }
411    *variable = (uint16_t) value;
412    (*pos)++;
413    *remain -= *pos - start;
414
415    return true;
416}
417
418/*
419 * Map error message
420 */
421static int tftpErrno (uint16_t error_code)
422{
423    unsigned int tftpError;
424    static const int errorMap[] = {
425        EINVAL,
426        ENOENT,
427        EPERM,
428        ENOSPC,
429        EINVAL,
430        ENXIO,
431        EEXIST,
432        ESRCH,
433        ENOTSUP, /* Error: Option negotiation failed (RFC 2347) */
434    };
435
436    tftpError = ntohs (error_code);
437    if (tftpError < (sizeof errorMap / sizeof errorMap[0]))
438        return errorMap[tftpError];
439    else
440        return 1000 + tftpError;
441}
442
443/*
444 * Parse options from an OACK packet
445 */
446static bool parse_options (
447    union tftpPacket *receive_buf,
448    size_t packet_size,
449    tftp_options *options_in,
450    tftp_options *options_out
451)
452{
453    char *pos = receive_buf->tftpOACK.options;
454    size_t remain   = packet_size - sizeof (receive_buf->tftpOACK.opcode);
455
456    /*
457     * Make sure there is a 0 byte in the end before comparing strings
458     */
459    if (remain > 0 && pos[remain - 1] != 0) {
460        return false;
461    }
462
463    while (remain > 0) {
464      if (strcasecmp(pos, TFTP_BLOCK_SIZE_OPTION) == 0 &&
465          options_in->block_size != TFTP_RFC1350_BLOCK_SIZE) {
466          remain -= sizeof (TFTP_BLOCK_SIZE_OPTION);
467          pos    += sizeof (TFTP_BLOCK_SIZE_OPTION);
468          if (!parse_decimal_number (
469              &pos,
470              &remain,
471              TFTP_BLOCK_SIZE_MIN,
472              options_in->block_size,
473              &options_out->block_size)) {
474              return false;
475          };
476
477      } else if (strcasecmp(pos, TFTP_WINDOW_SIZE_OPTION) == 0 &&
478          options_in->window_size != TFTP_RFC1350_WINDOW_SIZE) {
479          remain -= sizeof (TFTP_WINDOW_SIZE_OPTION);
480          pos    += sizeof (TFTP_WINDOW_SIZE_OPTION);
481          if (!parse_decimal_number (
482              &pos,
483              &remain,
484              TFTP_WINDOW_SIZE_MIN,
485              options_in->window_size,
486              &options_out->window_size)) {
487              return false;
488          };
489
490      } else {
491         return false; /* Unknown option */
492      }
493    }
494
495    return true;
496}
497
498/*
499 * Send an error message
500 */
501static void send_error (
502    struct tftpStream *tp,
503    struct sockaddr_in *to,
504    uint8_t error_code,
505    const char *error_message
506)
507{
508    int len;
509    struct {
510        uint16_t      opcode;
511        uint16_t      errorCode;
512        char          errorMessage[80];
513    } msg;
514
515    /*
516     * Create the error packet (Unknown transfer ID).
517     */
518    msg.opcode = htons (TFTP_OPCODE_ERROR);
519    msg.errorCode = htons (error_code);
520    len = snprintf (msg.errorMessage, sizeof (msg.errorMessage), error_message);
521    if (len >= sizeof (msg.errorMessage)) {
522      len = sizeof (msg.errorMessage) - 1;
523    }
524    len += sizeof (msg.opcode) + sizeof (msg.errorCode) + 1;
525
526    /*
527     * Send it
528     */
529    sendto (tp->socket, (char *)&msg, len, 0, (struct sockaddr *)to, sizeof *to);
530}
531
532/*
533 * Send a message to make the other end shut up
534 */
535static void sendStifle (struct tftpStream *tp, struct sockaddr_in *to)
536{
537    send_error (tp, to, TFTP_ERROR_CODE_UNKNOWN_ID, "GO AWAY");
538}
539
540/*
541 * Wait for a packet
542 */
543static ssize_t
544getPacket (struct tftpStream *tp, int retryCount)
545{
546    ssize_t len;
547    struct timeval tv;
548    int flags = 0;
549
550    if (retryCount == GET_PACKET_DONT_WAIT) {
551        flags = MSG_DONTWAIT;
552    } else if (retryCount == 0) {
553        tv.tv_sec = tp->config.first_timeout / 1000L;
554        tv.tv_usec = (tp->config.first_timeout % 1000L) * 1000L;
555        setsockopt (tp->socket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof tv);
556    } else {
557        tv.tv_sec = tp->config.timeout / 1000L;
558        tv.tv_usec = (tp->config.timeout % 1000L) * 1000L;
559        setsockopt (tp->socket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof tv);
560    }
561    for (;;) {
562        union {
563            struct sockaddr s;
564            struct sockaddr_in i;
565        } from;
566        socklen_t fromlen = sizeof from;
567        len = recvfrom (tp->socket,
568            tp->receive_buf,
569            tp->packet_size,
570            flags,
571            &from.s,
572            &fromlen
573        );
574        if (len < 0)
575            break;
576        if (from.i.sin_addr.s_addr == tp->farAddress.sin_addr.s_addr) {
577            if (tp->firstReply) {
578                tp->firstReply = 0;
579                tp->farAddress.sin_port = from.i.sin_port;
580            }
581            if (tp->farAddress.sin_port == from.i.sin_port)
582                break;
583        }
584
585        /*
586         * Packet is from someone with whom we are
587         * not interested.  Tell them to go away.
588         */
589        sendStifle (tp, &from.i);
590    }
591    if (retryCount != GET_PACKET_DONT_WAIT) {
592        tv.tv_sec = 0;
593        tv.tv_usec = 0;
594        setsockopt (tp->socket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof tv);
595    }
596    return len;
597}
598
599static int process_unexpected_packet (struct tftpStream *tp, ssize_t len)
600{
601    (void) len;
602    send_error (
603        tp,
604        &tp->farAddress,
605        TFTP_ERROR_CODE_ILLEGAL,
606        "Got packet with unexpected opcode from server"
607    );
608    return EPROTO;
609}
610
611static int process_malformed_packet (struct tftpStream *tp, ssize_t len)
612{
613    (void) len;
614    send_error (
615        tp,
616        &tp->farAddress,
617        TFTP_ERROR_CODE_ILLEGAL,
618        "Got malformed packet from server"
619    );
620    return EPROTO;
621}
622
623static int process_error_packet (struct tftpStream *tp, ssize_t len)
624{
625    (void) len;
626    return tftpErrno (tp->receive_buf->tftpERROR.errorCode);
627}
628
629/*
630 * When an RRQ or a WRQ with options is sent and the server responds with
631 * an error, this function will trigger a re-sent of an RRQ or WRQ
632 * without options (falling back to old RFC1350).
633 *
634 * If someone wants to change the implementation to force using options
635 * (i.e. prevent fallback to RFC1350), at least these points must be
636 * considered:
637 *
638 *     * Use `process_error_packet()` instead of
639 *       `process_error_packet_option_negotiation()`
640 *     * React to DATA and ACK packets, which are an immediate response to
641 *       an RRQ or a WRQ with options, with an error packet.
642 *     * Check the option values in the OACK whether they are in the
643 *       desired range.
644 */
645static int process_error_packet_option_negotiation (
646    struct tftpStream *tp, ssize_t len
647)
648{
649    (void) len;
650    /*
651     * Setting tp->config.options causes an RRQ or a WRQ to be created without
652     * options.
653     * Setting tp->server_option is defensive programming as these fields
654     * should already have these values.
655     */
656    tp->config.options.block_size  = TFTP_RFC1350_BLOCK_SIZE;
657    tp->config.options.window_size = TFTP_RFC1350_WINDOW_SIZE;
658    tp->server_options.block_size  = TFTP_RFC1350_BLOCK_SIZE;
659    tp->server_options.window_size = TFTP_RFC1350_WINDOW_SIZE;
660
661    tp->process_error_packet = process_error_packet;
662    /*
663     * GOT_FIRST_OUT_OF_ORDER_PACKET will trigger a re-send of the RRQ or WRQ.
664     */
665    return GOT_FIRST_OUT_OF_ORDER_PACKET;
666}
667
668static int process_data_packet (struct tftpStream *tp, ssize_t len)
669{
670    ssize_t plen;
671    int32_t pkt_blocknum;
672    union tftpPacket *send_buf;
673
674    if (len < sizeof (tp->receive_buf->tftpACK)) {
675        return process_malformed_packet (tp, len);
676    }
677    pkt_blocknum = (int32_t) ntohs (tp->receive_buf->tftpACK.blocknum);
678    if (pkt_blocknum == 0) {
679        return process_malformed_packet (tp, len);
680    }
681
682    /*
683     * In case of reading a file from the server:
684     * If the latest ACK packet(s) did not reach the server, the server
685     * starts the window from the last ACK it received.  This if-clause
686     * ensures, the client sends an ACK after having seen `windowsize`
687     * packets.
688     */
689    if (pkt_blocknum < tp->blocknum_of_first_packet_of_window &&
690        pkt_blocknum >= (int32_t) tp->blocknum + 1 -
691            (int32_t) tp->server_options.window_size) {
692        tp->blocknum_of_first_packet_of_window = pkt_blocknum;
693    }
694    if (!tp->ignore_out_of_order_packets &&
695       pkt_blocknum > (int32_t) tp->blocknum + 1) {
696        tp->ignore_out_of_order_packets = true;
697        return GOT_FIRST_OUT_OF_ORDER_PACKET;
698    } else if (pkt_blocknum == (int32_t) tp->blocknum) {
699      /*
700       * In case of reading a file from the server:
701       * If the last ACK packet send by the client did not reach the
702       * server, the server re-sends all packets of the window.  In this
703       * case, the client must re-send the ACK packet after having
704       * received the last packet of the window (even through it has
705       * already received that packet before).
706       * GOT_OLD_PACKET would wrongly suppress this.
707       */
708      return GOT_DUPLICATE_OF_CURRENT_PACKET;
709    } else if (pkt_blocknum != (int32_t) tp->blocknum + 1) {
710        return GOT_OLD_PACKET;
711    }
712    tp->ignore_out_of_order_packets = false;
713
714    tp->blocknum++;
715    tp->nused = 0; /* Only for 2nd, 3rd, 4th DATA packet received */
716    tp->nleft = BLK_SIZE_FROM_PKT_SIZE (len);
717    tp->at_eof = (tp->nleft < tp->server_options.block_size);
718    /*
719     * After the last DATA packet, the client must send a final ACK
720     */
721    if (tp->at_eof) {
722        plen = prepare_ack_packet_for_sending (tp, true, &send_buf, NULL, NULL);
723
724        /*
725         * Send it. Errors during send will not matter for this last ACK.
726         */
727        sendto (
728            tp->socket,
729            send_buf,
730            plen,
731            0,
732            (struct sockaddr *) &tp->farAddress,
733            sizeof (tp->farAddress)
734        );
735    }
736    tp->prepare_packet_for_sending = prepare_ack_packet_for_sending;
737    return GOT_EXPECTED_PACKET;
738}
739
740static int process_ack_packet (struct tftpStream *tp, ssize_t len)
741{
742    uint16_t blocknum_ack;
743    if (len < sizeof (tp->receive_buf->tftpACK)) {
744        return process_malformed_packet (tp, len);
745    }
746    blocknum_ack = ntohs (tp->receive_buf->tftpACK.blocknum);
747    if ((int32_t) blocknum_ack == tp->blocknum_of_first_packet_of_window - 1 &&
748        blocknum_ack != 0
749    ) {
750        tp->blocknum = tp->blocknum_of_first_packet_of_window;
751        return GOT_DUPLICATE_OF_CURRENT_PACKET;
752    }
753    if ((int32_t) blocknum_ack < tp->blocknum_of_first_packet_of_window ||
754        blocknum_ack > tp->blocknum_last_filled) {
755        return GOT_OLD_PACKET;
756    }
757    tp->blocknum = blocknum_ack + 1;
758    tp->blocknum_of_first_packet_of_window = (int32_t) tp->blocknum;
759    tp->prepare_packet_for_sending = prepare_data_packet_for_sending;
760    return GOT_EXPECTED_PACKET;
761}
762
763static ssize_t prepare_data_packet_for_sending (
764    struct tftpStream *tp,
765    bool force_retransmission,
766    union tftpPacket **send_buf,
767    bool *wait_for_packet_reception,
768    const void *not_used
769)
770{
771    (void) not_used;
772    ssize_t len;
773    *send_buf = get_send_buffer_packet (tp, tp->blocknum);
774
775    len = PKT_SIZE_FROM_BLK_SIZE (
776        (tp->blocknum == tp->blocknum_eof_block) ? tp->nused : tp->block_size
777    );
778    (*send_buf)->tftpDATA.opcode   = htons (TFTP_OPCODE_DATA);
779    (*send_buf)->tftpDATA.blocknum = htons (tp->blocknum);
780
781    /*
782     * If the client sends the last packet of a window,
783     * it must wait for an ACK and - in case no ACK is received - begin
784     * a retransmission with the first packet of the window.
785     * Note that the last DATA block for the whole transfer is also
786     * a "last packet of a window".
787     */
788    if ((int32_t) tp->blocknum + 1 >=
789        tp->blocknum_of_first_packet_of_window + tp->send_buf_size_in_pkts ||
790        tp->blocknum == tp->blocknum_eof_block) {
791        tp->blocknum = (uint16_t) tp->blocknum_of_first_packet_of_window;
792    } else {
793        tp->blocknum++;
794        *wait_for_packet_reception = false;
795    }
796
797    tp->process_data_packet  = process_unexpected_packet;
798    tp->process_ack_packet   = process_ack_packet;
799    tp->process_oack_packet  = process_unexpected_packet;
800    tp->process_error_packet = process_error_packet;
801
802    /*
803     * Our last packet won't necessarily be acknowledged!
804     */
805    if (tp->blocknum == tp->blocknum_eof_block) {
806        tp->retransmission_error_code = 0;
807    }
808
809    return len;
810}
811
812static ssize_t prepare_ack_packet_for_sending (
813    struct tftpStream *tp,
814    bool force_retransmission,
815    union tftpPacket **send_buf,
816    bool *wait_for_packet_reception,
817    const void *path_name
818)
819{
820    (void) wait_for_packet_reception;
821    if (!force_retransmission &&
822        tp->blocknum_of_first_packet_of_window - 1 +
823        (int32_t) tp->server_options.window_size > (int32_t) tp->blocknum) {
824      return DO_NOT_SEND_PACKET;
825    }
826    tp->blocknum_of_first_packet_of_window = (int32_t) tp->blocknum + 1;
827
828    /*
829     * Create the acknowledgement
830     */
831    *send_buf = tp->send_buf;
832    (*send_buf)->tftpACK.opcode   = htons (TFTP_OPCODE_ACK);
833    (*send_buf)->tftpACK.blocknum = htons (tp->blocknum);
834
835    tp->process_data_packet  = process_data_packet;
836    tp->process_ack_packet   = process_unexpected_packet;
837    tp->process_oack_packet  = process_unexpected_packet;
838    tp->process_error_packet = process_error_packet;
839
840    return sizeof (tp->send_buf->tftpACK);
841}
842
843static int process_oack_packet (struct tftpStream *tp, ssize_t len)
844{
845    if (!parse_options(tp->receive_buf,
846        len,
847        &tp->config.options,
848        &tp->server_options)) {
849        send_error (
850            tp,
851            &tp->farAddress,
852            TFTP_ERROR_CODE_OPTION_NEGO,
853            "Bad options, option values or malformed OACK packet"
854        );
855        return EPROTO;
856    }
857    if (tp->is_for_reading) {
858        /*
859         * Since no DATA packet has been received yet, tell
860         * tftp_read() there is no data left.
861         */
862        tp->nleft = 0;
863        tp->prepare_packet_for_sending = prepare_ack_packet_for_sending;
864    } else {
865        tp->blocknum_of_first_packet_of_window = 1;
866        tp->blocknum = (uint16_t) tp->blocknum_of_first_packet_of_window;
867        tp->prepare_packet_for_sending = prepare_data_packet_for_sending;
868    }
869    return GOT_EXPECTED_PACKET;
870}
871
872static ssize_t prepare_request_packet_for_sending (
873    struct tftpStream *tp,
874    bool force_retransmission,
875    union tftpPacket **send_buf,
876    bool *wait_for_packet_reception,
877    const void *path_name
878)
879{
880    (void) wait_for_packet_reception;
881    ssize_t len;
882    *send_buf = tp->send_buf;
883    len = create_request (
884        *send_buf,
885        tp->block_size,
886        tp->is_for_reading,
887        path_name,
888        &tp->config.options
889    );
890
891    if (len < 0) {
892        tp->error = ENAMETOOLONG;
893    } else {
894        tp->process_data_packet  = tp->is_for_reading ?
895            process_data_packet : process_unexpected_packet;
896        tp->process_ack_packet   = tp->is_for_reading ?
897            process_unexpected_packet : process_ack_packet;
898        tp->process_oack_packet  = MUST_SEND_OPTIONS(tp->config.options) ?
899            process_oack_packet : process_unexpected_packet;
900        tp->process_error_packet = MUST_SEND_OPTIONS(tp->config.options) ?
901            process_error_packet_option_negotiation : process_error_packet;
902    }
903
904    /*
905     * getPacket() will change these values when the first packet is
906     * received.  Yet, this first packet may be an unexpected one
907     * (e.g. an ERROR or having a wrong block number).
908     * If a second, third, forth, ... RRQ/WRQ is to be sent, it should
909     * be directed to the server port again and not to the port the
910     * first unexpected packet came from.
911     */
912    tp->farAddress.sin_port = htons (tp->config.server_port);
913    tp->firstReply          = 1;
914
915    return len;
916}
917
918/*
919 * Conduct one communication step with the server. For windowsize == 1,
920 * one step is:
921 *   a) Send a packet to the server
922 *   b) Receive a reply packet from the server
923 *   c) Handle errors (if any)
924 *   d) If no packet has been received from the server and the maximum
925 *      retransmission count has not yet been reached, start over with a)
926 * The flow of packets (i.e. which packet to send and which packet(s) to
927 * expect from the server) is controlled by function pointers found in
928 * struct tftpStream.
929 *
930 * Besides of handling errors and retransmissions, the essential data exchange
931 * follows these patterns:
932 *
933 * Connection establishment and option negotiation:
934 *   * Send RRQ/WRQ (read or write request packet)
935 *   * Receive OACK (read and write) or ACK (write only) or DATA (read only)
936 *
937 * Read step with windowsize == 1:
938 *   * Send ACK packet
939 *   * Receive DATA packet
940 * Sending the very last ACK packet for a "read" session is treated as a
941 * special case.
942 *
943 * Write step with windowsize == 1:
944 *   * Send DATA packet
945 *   * Receive ACK packet
946 *
947 * A windowsize lager than one makes thinks more complicated.
948 * In this case, a step normally only receives (read) or only sends (write)
949 * a packet.  The sending or receiving of the ACK packets is skipped normally
950 * and happens only at the last step of the window (in which case this last
951 * step is similar to the windowsize == 1 case):
952 *
953 * Normal read step with windowsize > 1:
954 *   * Receive DATA packet
955 * Last read step of a window with windowsize > 1:
956 *   * Send ACK packet
957 *   * Receive DATA packet
958 *
959 * Normal write step with windowsize > 1:
960 *   * Send DATA packet
961 *   * Check for an ACK packet but do not wait for it
962 * Last write step of a window with windowsize > 1:
963 *   * Send DATA packet
964 *   * Receive ACK packet
965 *
966 * The "normal write step for windowsize > 1" checks whether an ACK packet
967 * has been received after each sending of a DATA packet.  Package lost and
968 * exchanges in the network can give rise to situations in which the server
969 * sends more than a single ACK packet during a window.  If these packets
970 * are not reacted on immediately, the network would be flooded with
971 * surplus packets.  (An example where two ACK packets appear in a window
972 * appears in test case "read_file_windowsize_trouble" where the client/server
973 * roles are exchanged.)
974 */
975static int communicate_with_server (
976    struct tftpStream    *tp,
977    const void *create_packet_data
978)
979{
980    ssize_t len;
981    uint16_t opcode;
982    union tftpPacket *send_buf;
983    bool received_duplicated_or_old_package = false;
984    bool force_retransmission = false;
985    bool wait_for_packet_reception;
986    int retryCount = 0;
987    while (tp->error == 0) {
988
989        if (!received_duplicated_or_old_package) {
990            wait_for_packet_reception = true;
991            len = tp->prepare_packet_for_sending (
992                tp,
993                force_retransmission,
994                &send_buf,
995                &wait_for_packet_reception,
996                create_packet_data
997                );
998            if (len < 0) {
999                if (tp->error == 0) {
1000                    tp->error = EIO;
1001                }
1002                break;
1003            }
1004
1005            if (len != DO_NOT_SEND_PACKET) {
1006                /*
1007                 * Send the packet
1008                 */
1009                if (sendto (tp->socket, send_buf, len, 0,
1010                            (struct sockaddr *)&tp->farAddress,
1011                            sizeof tp->farAddress) < 0) {
1012                    tp->error = EIO;
1013                    break;
1014                }
1015            }
1016        }
1017        received_duplicated_or_old_package = false;
1018        force_retransmission = false;
1019
1020        /*
1021         * Get reply
1022         */
1023        len = getPacket (
1024            tp,
1025            wait_for_packet_reception ? retryCount : GET_PACKET_DONT_WAIT
1026        );
1027        if (len >= (int) sizeof (tp->receive_buf->tftpDATA.opcode)) {
1028            opcode = ntohs (tp->receive_buf->tftpDATA.opcode);
1029            switch (opcode) {
1030            case TFTP_OPCODE_DATA:
1031                tp->error = tp->process_data_packet (tp, len);
1032                break;
1033            case TFTP_OPCODE_ACK:
1034                tp->error = tp->process_ack_packet (tp, len);
1035                break;
1036            case TFTP_OPCODE_OACK:
1037                tp->error = tp->process_oack_packet (tp, len);
1038                break;
1039            case TFTP_OPCODE_ERROR:
1040                tp->error = tp->process_error_packet (tp, len);
1041                break;
1042            default:
1043                tp->error = process_unexpected_packet (tp, len);
1044                break;
1045            }
1046            if (tp->error == GOT_EXPECTED_PACKET) {
1047                break;
1048            } else if (tp->error == GOT_DUPLICATE_OF_CURRENT_PACKET) {
1049                tp->error = 0;
1050            } else if (tp->error == GOT_OLD_PACKET) {
1051                received_duplicated_or_old_package = true;
1052                tp->error = 0;
1053            } else if (tp->error <= GOT_FIRST_OUT_OF_ORDER_PACKET) {
1054                force_retransmission = true;
1055                tp->error = 0;
1056            } /* else ... tp->error > 0 means "exit this function with error" */
1057        } else if (len >= 0) {
1058            tp->error = process_malformed_packet (tp, len);
1059        } else if (len < 0 && !wait_for_packet_reception) {
1060            tp->error = 0;
1061            break;
1062        } else {
1063            /*
1064             * Timeout or other problems to receive packets
1065             * Attempt a retransmission
1066             */
1067            if (++retryCount >= (int) tp->config.retransmissions) {
1068                tp->error = tp->retransmission_error_code;
1069                break;
1070            }
1071            force_retransmission = true;
1072        }
1073    }
1074
1075    return tp->error;
1076}
1077
1078/*
1079 * Allocate and initialize an struct tftpStream object.
1080 *
1081 * This function does not check whether the config values are in valid ranges.
1082 */
1083static struct tftpStream *create_stream(
1084    const tftp_net_config *config,
1085    const struct in_addr *farAddress,
1086    bool is_for_reading
1087)
1088{
1089    struct tftpStream *tp = NULL;
1090    tp = malloc (sizeof (struct tftpStream));
1091    if (tp == NULL) {
1092        return NULL;
1093    }
1094
1095    /*
1096     * Initialize fields accessed by _Tftp_Destroy().
1097     */
1098    tp->receive_buf = NULL;
1099    tp->send_buf    = NULL;
1100    tp->socket      = 0;
1101
1102    /*
1103     * Allocate send and receive buffer for exchange of RRQ/WRQ and ACK/OACK.
1104     */
1105    tp->block_size  = TFTP_RFC1350_BLOCK_SIZE;
1106    tp->packet_size = PKT_SIZE_FROM_BLK_SIZE (tp->block_size);
1107    tp->receive_buf = malloc (tp->packet_size);
1108    if (tp->receive_buf == NULL) {
1109      _Tftp_Destroy (tp);
1110      return NULL;
1111    }
1112    tp->send_buf = tp->receive_buf;
1113    tp->send_buf_size_in_pkts = 1;
1114
1115    /*
1116     * Create the socket
1117     */
1118    if ((tp->socket = socket (AF_INET, SOCK_DGRAM, 0)) < 0) {
1119        _Tftp_Destroy (tp);
1120        return NULL;
1121    }
1122
1123    /*
1124     * Setup configuration and options
1125     */
1126    if ( config == NULL ) {
1127      tftp_initialize_net_config (&tp->config);
1128    } else {
1129      tp->config = *config;
1130    }
1131
1132    /*
1133     * If the server does not confirm our option values later on,
1134     * use numbers from the original RFC 1350 for the actual transfer.
1135     */
1136    tp->server_options.block_size  = TFTP_RFC1350_BLOCK_SIZE;
1137    tp->server_options.window_size = TFTP_RFC1350_WINDOW_SIZE;
1138
1139    /*
1140     * Set the UDP destination to the TFTP server
1141     * port on the remote machine.
1142     */
1143    tp->farAddress.sin_family              = AF_INET;
1144    tp->farAddress.sin_addr                = *farAddress;
1145    tp->farAddress.sin_port                = htons (tp->config.server_port);
1146
1147    tp->nleft                              = 0;
1148    tp->nused                              = 0;
1149    tp->blocknum                           = 0;
1150    tp->blocknum_last_filled               = 0;
1151    tp->blocknum_eof_block                 = UINT16_MAX;
1152    tp->firstReply                         = 1;
1153    tp->at_eof                             = false;
1154    tp->is_for_reading                     = is_for_reading;
1155
1156    tp->prepare_packet_for_sending         = prepare_request_packet_for_sending;
1157    tp->process_data_packet                = process_unexpected_packet;
1158    tp->process_ack_packet                 = process_unexpected_packet;
1159    tp->process_oack_packet                = process_unexpected_packet;
1160    tp->process_error_packet               = process_error_packet;
1161    tp->retransmission_error_code          = EIO;
1162    tp->ignore_out_of_order_packets        = false;
1163    tp->blocknum_of_first_packet_of_window = INT32_MIN;
1164    tp->error                              = 0;
1165
1166    return tp;
1167}
1168
1169/*
1170 * Change the size of the receive and send buffer to match the options
1171 * values acknowledged by the server.
1172 */
1173static struct tftpStream *reallocate_stream_buffer(struct tftpStream *tp)
1174{
1175    tp->block_size = tp->server_options.block_size;
1176    tp->packet_size = PKT_SIZE_FROM_BLK_SIZE (tp->block_size);
1177    /*
1178     * Defensive programming
1179     */
1180    if (tp->receive_buf == tp->send_buf) {
1181        tp->send_buf = NULL;
1182    } else {
1183       free (tp->send_buf);
1184    }
1185
1186    tp->receive_buf = realloc (tp->receive_buf, tp->packet_size);
1187    if (tp->is_for_reading) {
1188        tp->send_buf = tp->receive_buf;
1189    } else {
1190        tp->send_buf_size_in_pkts = tp->server_options.window_size;
1191        tp->send_buf = malloc (
1192            tp->send_buf_size_in_pkts * tp->packet_size
1193        );
1194    }
1195
1196    if (tp->receive_buf == NULL || tp->send_buf == NULL) {
1197      sendStifle (tp,  &tp->farAddress);
1198      _Tftp_Destroy (tp);
1199      return NULL;
1200    }
1201    return tp;
1202}
1203
1204/*
1205 * Convert hostname to an Internet address
1206 */
1207static struct in_addr *get_ip_address(
1208    const char     *hostname,
1209    struct in_addr *farAddress
1210)
1211{
1212        struct hostent *he = gethostbyname(hostname);
1213        if (he == NULL) {
1214            return NULL;
1215        }
1216        memcpy (farAddress, he->h_addr, sizeof (*farAddress));
1217  return farAddress;
1218}
1219
1220void tftp_initialize_net_config (tftp_net_config *config)
1221{
1222  static const tftp_net_config default_config = {
1223    .retransmissions = TFTP_RFC7440_DATA_RETRANSMISSIONS,
1224    .server_port     = TFTP_DEFAULT_SERVER_PORT,
1225    .timeout         = TFTP_RFC7440_TIMEOUT_MILLISECONDS,
1226    .first_timeout   = PACKET_FIRST_TIMEOUT_MILLISECONDS,
1227    .options = {
1228      .block_size    = TFTP_DEFAULT_BLOCK_SIZE,
1229      .window_size   = TFTP_DEFAULT_WINDOW_SIZE
1230    }
1231  };
1232
1233  if (config != NULL) {
1234    memcpy (config, &default_config, sizeof (default_config));
1235  }
1236}
1237
1238int tftp_open(
1239    const char               *hostname,
1240    const char               *path,
1241    bool                      is_for_reading,
1242    const tftp_net_config    *config,
1243    void                    **tftp_handle
1244)
1245{
1246    struct tftpStream    *tp;
1247    struct in_addr       farAddress;
1248    int                  err;
1249
1250    /*
1251     * Check parameters
1252     */
1253    if (tftp_handle == NULL) {
1254      return EINVAL;
1255    }
1256    *tftp_handle = NULL;
1257    if (hostname == NULL || path == NULL) {
1258        return EINVAL;
1259    }
1260    if (config != NULL && (
1261        config->options.window_size < TFTP_WINDOW_SIZE_MIN ||
1262        config->options.block_size  < TFTP_BLOCK_SIZE_MIN  ||
1263        config->options.block_size  > TFTP_BLOCK_SIZE_MAX  ) ) {
1264        return EINVAL;
1265    }
1266
1267    /*
1268     * Create tftpStream structure
1269     */
1270    if (get_ip_address( hostname, &farAddress ) == NULL) {
1271        return ENOENT;
1272    }
1273    tp = create_stream( config, &farAddress, is_for_reading );
1274    if (tp == NULL) {
1275        return ENOMEM;
1276    }
1277
1278    /*
1279     * Send RRQ or WRQ and wait for reply
1280     */
1281    tp->prepare_packet_for_sending = prepare_request_packet_for_sending;
1282    err = communicate_with_server (tp, path);
1283    if ( err != 0 ) {
1284        _Tftp_Destroy (tp);
1285        return err;
1286    }
1287
1288    *tftp_handle = reallocate_stream_buffer ( tp );
1289    if( *tftp_handle == NULL ) {
1290        return ENOMEM;
1291    }
1292
1293    return 0;
1294}
1295
1296/*
1297 * Read from a TFTP stream
1298 */
1299ssize_t tftp_read(
1300    void          *tftp_handle,
1301    void          *buffer,
1302    size_t         count
1303)
1304{
1305    char              *bp;
1306    struct tftpStream *tp = tftp_handle;
1307    int               nwant;
1308    int               err;
1309
1310    if (tp == NULL || !tp->is_for_reading || buffer == NULL)
1311        return -EIO;
1312
1313    /*
1314     * Read till user request is satisfied or EOF is reached
1315     */
1316    bp = buffer;
1317    nwant = count;
1318    while (nwant) {
1319        if (tp->nleft) {
1320            int ncopy;
1321            if (nwant < tp->nleft)
1322                ncopy = nwant;
1323            else
1324                ncopy = tp->nleft;
1325            memcpy (bp, &tp->receive_buf->tftpDATA.data[tp->nused], ncopy);
1326            tp->nused += ncopy;
1327            tp->nleft -= ncopy;
1328            bp += ncopy;
1329            nwant -= ncopy;
1330            if (nwant == 0)
1331                break;
1332        }
1333        if (tp->at_eof) {
1334            break;
1335        }
1336
1337        /*
1338         * Wait for the next packet
1339         */
1340        tp->retransmission_error_code = -EIO;
1341        err = communicate_with_server(tp, NULL);
1342        if (err == tp->retransmission_error_code) {
1343          return -EIO;
1344        }
1345        /*
1346         * If communicate_with_server() returns an error, either
1347         *    * an error message from the server was received or
1348         *    * an error message was already sent to the server
1349         * Setting tp->at_eof true, prevents all further calls to
1350         * communicate_with_server() and suppresses the sending of
1351         * an error message to the server by tftp_close().
1352         */
1353        if (err != 0) {
1354            tp->at_eof = true;
1355            return -err;
1356        }
1357    }
1358    return count - nwant;
1359}
1360
1361/*
1362 * Flush a write buffer and wait for acknowledgement
1363 *
1364 * This function returns only if there is at least one packet buffer free
1365 * in the tp->send_buf.  This ensures that tftp_write() can store
1366 * further data for sending in this free packet buffer.
1367 *
1368 * When the end of file has been reached (i.e. tftp_close() called this
1369 * function), this function returns only after all packets
1370 * in the write buffer have been send and acknowledged (or if an error
1371 * occurred).
1372 */
1373static int rtems_tftp_flush (struct tftpStream *tp)
1374{
1375    int err;
1376
1377    if (tp->at_eof) {
1378        return 0;
1379    }
1380
1381    do {
1382        err = communicate_with_server(tp, NULL);
1383        /*
1384         * If communicate_with_server() returns an error, either
1385         *    * an error message from the server was received or
1386         *    * an error message was already sent to the server
1387         * Setting tp->at_eof true, prevents all further calls to
1388         * communicate_with_server() and suppresses the sending of
1389         * an error message to the server by tftp_close().
1390         */
1391        if (err != 0) {
1392            tp->at_eof = true;
1393            return err;
1394        }
1395    } while(
1396         (int32_t) tp->blocknum_last_filled + 1 >=
1397         tp->blocknum_of_first_packet_of_window + tp->send_buf_size_in_pkts ||
1398         /*
1399          * tp->blocknum_eof_block == tp->blocknum_last_filled
1400          * holds only true when the user invoked tftp_close().
1401          */
1402         (tp->blocknum_eof_block == tp->blocknum_last_filled &&
1403         tp->blocknum_of_first_packet_of_window <=
1404         (int32_t) tp->blocknum_eof_block)
1405    );
1406
1407    return 0;
1408}
1409
1410/*
1411 * Close a TFTP stream
1412 */
1413int tftp_close(
1414    void *tftp_handle
1415)
1416{
1417    struct tftpStream *tp = tftp_handle;
1418    int                e = 0;
1419
1420    if (tp == NULL) {
1421        return 0;
1422    }
1423
1424    if (!tp->is_for_reading) {
1425        tp->blocknum_last_filled++;
1426        tp->blocknum_eof_block = tp->blocknum_last_filled;
1427        e = rtems_tftp_flush (tp);
1428        tp->at_eof = true;
1429    }
1430    if (!tp->at_eof && !tp->firstReply) {
1431        /*
1432         * Tell the other end to stop
1433         */
1434        rtems_interval ticksPerSecond;
1435        send_error (
1436            tp,
1437            &tp->farAddress,
1438            TFTP_ERROR_CODE_NO_USER,
1439            "User (client) stopped reading or "
1440            "server stopped sending packets (timeout)"
1441        );
1442        ticksPerSecond = rtems_clock_get_ticks_per_second();
1443        rtems_task_wake_after (1 + ticksPerSecond / 10);
1444    }
1445    _Tftp_Destroy (tp);
1446    return e;
1447}
1448
1449ssize_t tftp_write(
1450    void            *tftp_handle,
1451    const void      *buffer,
1452    size_t           count
1453)
1454{
1455    const char        *bp;
1456    struct tftpStream *tp = tftp_handle;
1457    int               nleft, nfree, ncopy;
1458    int               err;
1459    union tftpPacket *send_buf;
1460
1461    /*
1462     * Bail out if an error has occurred
1463     */
1464    if (tp == NULL || tp->is_for_reading || tp->at_eof || buffer == NULL) {
1465        return -EIO;
1466    }
1467
1468    /*
1469     * Write till user request is satisfied
1470     * Notice that the buffer is flushed as soon as it is filled rather
1471     * than waiting for the next write or a close.  This ensures that
1472     * the flush in close writes a less than full buffer so the far
1473     * end can detect the end-of-file condition.
1474     */
1475    bp = buffer;
1476    nleft = count;
1477    while (nleft) {
1478        nfree = tp->block_size - tp->nused;
1479        if (nleft < nfree)
1480            ncopy = nleft;
1481        else
1482            ncopy = nfree;
1483        send_buf = get_send_buffer_packet (tp, tp->blocknum_last_filled + 1);
1484        memcpy (&send_buf->tftpDATA.data[tp->nused], bp, ncopy);
1485        tp->nused += ncopy;
1486        nleft -= ncopy;
1487        bp += ncopy;
1488        if (tp->nused == tp->block_size) {
1489            tp->blocknum_last_filled++;
1490            err = rtems_tftp_flush (tp);
1491            if (err) {
1492                return -err;
1493            }
1494            tp->nused = 0;
1495        }
1496    }
1497    return count;
1498}
1499
1500void _Tftp_Destroy(
1501    void *tftp_handle
1502)
1503{
1504    struct tftpStream *tp = tftp_handle;
1505    if (tp == NULL) {
1506        return;
1507    }
1508
1509    if (tp->socket >= 0) {
1510        close (tp->socket);
1511    }
1512
1513    if (tp->receive_buf == tp->send_buf) {
1514        tp->send_buf = NULL;
1515    }
1516    free (tp->receive_buf);
1517    free (tp->send_buf);
1518    free (tp);
1519}
Note: See TracBrowser for help on using the repository browser.