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 | */ |
---|
148 | union 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 | */ |
---|
195 | struct 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 | */ |
---|
304 | static 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 | ); |
---|
311 | static 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 | */ |
---|
322 | static 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 | */ |
---|
334 | static 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 | |
---|
394 | static 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 | */ |
---|
421 | static 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 | */ |
---|
446 | static 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 | */ |
---|
501 | static 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 | */ |
---|
535 | static 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 | */ |
---|
543 | static ssize_t |
---|
544 | getPacket (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 | |
---|
599 | static 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 | |
---|
611 | static 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 | |
---|
623 | static 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 | */ |
---|
645 | static 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 | |
---|
668 | static 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 | |
---|
740 | static 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 | |
---|
763 | static 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 | |
---|
812 | static 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 | |
---|
843 | static 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 | |
---|
872 | static 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 | */ |
---|
975 | static 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 | */ |
---|
1083 | static 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 | */ |
---|
1173 | static 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 | */ |
---|
1207 | static 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 | |
---|
1220 | void 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 | |
---|
1238 | int 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 | */ |
---|
1299 | ssize_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 | */ |
---|
1373 | static 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 | */ |
---|
1413 | int 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 | |
---|
1449 | ssize_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 | |
---|
1500 | void _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 | } |
---|