Back to home page

LXR

 
 

    


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

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup RTEMSTestSuiteTestsTFTPFS
0007  *
0008  * @brief This source file contains the implementation of tests for libtftpfs.
0009  *
0010  * The tested source files are:
0011  *   + @ref tftpfs.c "tftpfs.c: TFTP file system"
0012  *   + @ref tftpDriver.c "tftpDriver.c: TFTP client library"
0013  * These tests focus on testing the UDP network interaction of libtftpfs.
0014  */
0015 
0016 /*
0017  * Copyright (C) 2022 embedded brains GmbH & Co. KG
0018  *
0019  * Redistribution and use in source and binary forms, with or without
0020  * modification, are permitted provided that the following conditions
0021  * are met:
0022  * 1. Redistributions of source code must retain the above copyright
0023  *    notice, this list of conditions and the following disclaimer.
0024  * 2. Redistributions in binary form must reproduce the above copyright
0025  *    notice, this list of conditions and the following disclaimer in the
0026  *    documentation and/or other materials provided with the distribution.
0027  *
0028  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0029  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0030  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0031  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0032  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0033  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0034  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0035  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0036  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0037  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0038  * POSSIBILITY OF SUCH DAMAGE.
0039  */
0040 
0041 #ifdef HAVE_CONFIG_H
0042 #include "config.h"
0043 #endif
0044 
0045 #include <stdio.h>
0046 #include <stdlib.h> /* malloc(), free() */
0047 #include <ctype.h> /* isprint() */
0048 #include <errno.h>
0049 #include <sys/stat.h> /* mkdir(), open() */
0050 #include <sys/types.h> /* mkdir(), open() */
0051 #include <sys/socket.h> /* AF_INET, SOCK_DGRAM */
0052 #include <fcntl.h> /* open() */
0053 #include <unistd.h> /* read(), close(), rmdir() */
0054 
0055 #include <rtems/tftp.h>
0056 #include <rtems/libio.h> /* mount(), RTEMS_FILESYSTEM_TYPE_TFTPFS */
0057 #include <rtems/test.h>
0058 #include <rtems/test-info.h>
0059 #include <rtems/testopts.h> /* RTEMS_TEST_VERBOSITY */
0060 #include <rtems.h>
0061 
0062 #include "tftpfs_udp_network_fake.h"
0063 #include "tftpfs_interactions.h"
0064 #include "tftp_driver.h"
0065 
0066 #define SERV_PORT 12345
0067 #define FIRST_TIMEOUT_MILLISECONDS  400
0068 #define TIMEOUT_MILLISECONDS        1000
0069 #define LARGE_BLOCK_SIZE            TFTP_BLOCK_SIZE_MAX
0070 #define SMALL_BLOCK_SIZE            12
0071 #define SMALL_WINDOW_SIZE           4
0072 #define T_no_more_interactions() T_assert_true( \
0073   _Tftp_Has_no_more_interactions(), \
0074   "The TFTP client skiped some final network interactions." \
0075 )
0076 
0077 /*
0078  * Test fixture and text context
0079  */
0080 
0081 typedef struct tftp_test_context {
0082   int fd0; /* File descriptor of a file read from or written to the tftpsfs */
0083   void *tftp_handle; /* TFTP client handle for this file transfer */
0084 } tftp_test_context;
0085 
0086 static const char *tftpfs_mount_point   = "/tftp";
0087 static const char *tftpfs_ipv4_loopback = TFTP_KNOWN_IPV4_ADDR0_STR;
0088 static const char *tftpfs_server0_name  = TFTP_KNOWN_SERVER0_NAME;
0089 static const char *tftpfs_server0_ipv4  = TFTP_KNOWN_SERVER0_IPV4;
0090 static const char *tftpfs_file          = "file.txt";
0091 static tftp_test_context tftp_context;
0092 
0093 static void mount_tftp_fs( const char *mount_point, const char *options )
0094 {
0095   int result;
0096 
0097   result = mkdir( mount_point, S_IRWXU | S_IRWXG | S_IRWXO );
0098   T_assert_eq_int( result, 0 );
0099 
0100   result = mount(
0101     "",
0102     mount_point,
0103     RTEMS_FILESYSTEM_TYPE_TFTPFS,
0104     RTEMS_FILESYSTEM_READ_WRITE,
0105     options
0106   );
0107   T_assert_eq_int( result, 0 );
0108 }
0109 
0110 static void umount_tftp_fs( const char *mount_point )
0111 {
0112   int result;
0113 
0114   result = unmount( mount_point );
0115   T_assert_eq_int( result, 0 );
0116 
0117   result = rmdir( mount_point );
0118   T_assert_eq_int( result, 0 );
0119 }
0120 
0121 static void setup_rfc1350( void *context )
0122 {
0123   tftp_test_context *ctx = context;
0124   _Tftp_Reset();
0125   ctx->fd0 = -1;
0126   ctx->tftp_handle = NULL;
0127   mount_tftp_fs( tftpfs_mount_point, "verbose,rfc1350" );
0128 }
0129 
0130 static void teardown( void *context )
0131 {
0132   tftp_test_context *ctx = context;
0133   if ( ctx->fd0 >= 0 ) {
0134     close( ctx->fd0 );
0135   }
0136   tftp_close( ctx->tftp_handle ); /* is a no-op if NULL */
0137   umount_tftp_fs( tftpfs_mount_point );
0138   _Tftp_Reset();
0139 }
0140 
0141 static const T_fixture fixture_rfc1350 = {
0142   .setup = setup_rfc1350,
0143   .stop = NULL,
0144   .teardown = teardown,
0145   .scope = NULL,
0146   .initial_context = &tftp_context
0147 };
0148 
0149 static void setup_default_options( void *context )
0150 {
0151   tftp_test_context *ctx = context;
0152   _Tftp_Reset();
0153   ctx->fd0 = -1;
0154   ctx->tftp_handle = NULL;
0155   mount_tftp_fs( tftpfs_mount_point, NULL );
0156 }
0157 
0158 static const T_fixture fixture_default_options = {
0159   .setup = setup_default_options,
0160   .stop = NULL,
0161   .teardown = teardown,
0162   .scope = NULL,
0163   .initial_context = &tftp_context
0164 };
0165 
0166 static void setup_large_blocksize( void *context )
0167 {
0168   tftp_test_context *ctx = context;
0169   _Tftp_Reset();
0170   ctx->fd0 = -1;
0171   ctx->tftp_handle = NULL;
0172   mount_tftp_fs(
0173     tftpfs_mount_point,
0174     "verbose,blocksize=" RTEMS_XSTRING(LARGE_BLOCK_SIZE) ",windowsize=1"
0175   );
0176 }
0177 
0178 static const T_fixture fixture_large_blocksize = {
0179   .setup = setup_large_blocksize,
0180   .stop = NULL,
0181   .teardown = teardown,
0182   .scope = NULL,
0183   .initial_context = &tftp_context
0184 };
0185 
0186 static void setup_small_opt_size( void *context )
0187 {
0188   tftp_test_context *ctx = context;
0189   _Tftp_Reset();
0190   ctx->fd0 = -1;
0191   ctx->tftp_handle = NULL;
0192   mount_tftp_fs(
0193     tftpfs_mount_point,
0194     "blocksize=" RTEMS_XSTRING(SMALL_BLOCK_SIZE)
0195     ",windowsize=" RTEMS_XSTRING(SMALL_WINDOW_SIZE)
0196   );
0197 }
0198 
0199 static const T_fixture fixture_small_opt_size = {
0200   .setup = setup_small_opt_size,
0201   .stop = NULL,
0202   .teardown = teardown,
0203   .scope = NULL,
0204   .initial_context = &tftp_context
0205 };
0206 
0207 static void setup_mount_point( void *context )
0208 {
0209   int result;
0210 
0211   _Tftp_Reset();
0212   result = mkdir( tftpfs_mount_point, S_IRWXU | S_IRWXG | S_IRWXO );
0213   T_assert_eq_int( result, 0 );
0214 }
0215 
0216 static void teardown_mount_point( void *context )
0217 {
0218   int result;
0219 
0220   result = rmdir( tftpfs_mount_point );
0221   T_assert_eq_int( result, 0 );
0222   _Tftp_Reset();
0223 }
0224 
0225 static const T_fixture fixture_mount_point = {
0226   .setup = setup_mount_point,
0227   .stop = NULL,
0228   .teardown = teardown_mount_point,
0229   .scope = NULL,
0230   .initial_context = &tftp_context
0231 };
0232 
0233 /*
0234  * Test helper functions
0235  */
0236 
0237 /*
0238  * Produce an artificial file content to be able to compare the
0239  * sent and the received file later on.
0240  */
0241 static uint8_t get_file_content( size_t pos )
0242 {
0243   static const size_t frame_size = 100;
0244   static const size_t num_size = 11;
0245   static const size_t alpha_size = 53;
0246   char buf[10];
0247   size_t remainder = pos % frame_size;
0248 
0249   switch ( remainder ) {
0250     case 0:
0251     case 1:
0252     case 2:
0253       sprintf( buf, "%9zu", pos - remainder );
0254       return buf[remainder];
0255     case 3:
0256     case 7:
0257       return '\'';
0258     case 4:
0259     case 5:
0260     case 6:
0261       sprintf( buf, "%9zu", pos - remainder );
0262       return buf[remainder-1];
0263     case 8:
0264     case 9:
0265     case 10:
0266       sprintf( buf, "%9zu", pos - remainder );
0267       return buf[remainder-2];
0268     default:
0269       pos -= ( pos / frame_size + 1 ) * num_size;
0270       remainder = pos % alpha_size;
0271       return ( remainder <= 'Z' - '@' ) ?
0272         remainder + '@' : remainder - ( 'Z' - '@' + 1) + 'a';
0273   }
0274 }
0275 
0276 /*
0277  * Produce bad file content.
0278  */
0279 static uint8_t get_bad_file_content( size_t pos )
0280 {
0281   static const char buf[] = "BAD!";
0282   return (uint8_t) buf[ pos % strlen( buf ) ];
0283 }
0284 
0285 static const char *create_tftpfs_path(
0286   const char *sever_addr,
0287   const char *file_name
0288 )
0289 {
0290   static char buffer[100];
0291   int len;
0292 
0293   len = snprintf(
0294     buffer,
0295     sizeof( buffer ),
0296     "%s/%s:%s",
0297     tftpfs_mount_point,
0298     sever_addr,
0299     file_name
0300   );
0301 
0302   T_quiet_gt_int( len, 0 );
0303   T_quiet_lt_int( len, (int) sizeof( buffer ) );
0304   return buffer;
0305 }
0306 
0307 static int read_tftp_file(
0308   const char *path,
0309   size_t buffer_size,
0310   size_t max_bytes,
0311   int *fd
0312 )
0313 {
0314   char *data_buffer;
0315   int result = 0;
0316   int res;
0317   ssize_t i;
0318   ssize_t bytes = 1;
0319   ssize_t bytes_total = 0;
0320   int errno_store;
0321 
0322   T_log( T_VERBOSE, "File system: open( %s, O_RDONLY )", path );
0323   errno = 0;
0324   *fd = open( path, O_RDONLY );
0325   errno_store = errno;
0326   T_log(
0327     T_VERBOSE,
0328     "File system: [open( %s, O_RDONLY )] = fd:%d (errno = %d)",
0329     path,
0330     *fd,
0331     errno
0332   );
0333 
0334   if ( *fd < 0 ) {
0335     /* open() may intentionally fail (e.g. test for invalid server address) */
0336     T_log( T_VERBOSE, "File system: cannot open \"%s\" for reading", path );
0337     errno = errno_store;
0338     result = -1;
0339   }
0340 
0341   if ( *fd >= 0 ) {
0342     data_buffer = malloc( buffer_size );
0343 
0344     while ( bytes > 0 && max_bytes >= bytes ) {
0345       errno = 0;
0346       bytes = read(
0347         *fd,
0348         data_buffer,
0349         ( max_bytes > buffer_size ) ? buffer_size : max_bytes
0350       );
0351       errno_store = errno;
0352       T_log(
0353         T_VERBOSE,
0354         "File system: [read( fd:%d, size=%zu )] = %zd (errno = %d)",
0355         *fd,
0356         ( max_bytes > buffer_size ) ? buffer_size : max_bytes,
0357         bytes,
0358         errno
0359       );
0360 
0361       if ( bytes > 0 ) {
0362         max_bytes -= bytes;
0363         for ( i = 0; i < bytes; ++i ) {
0364           if ( data_buffer[i] != get_file_content( bytes_total + i ) ) {
0365             T_true(
0366               false,
0367               "File system: wrong file content '%c' (expected '%c') "
0368                 "at position %zd",
0369               (int) ( isprint( (int) data_buffer[i] ) ? data_buffer[i] : '?' ),
0370               (int) get_file_content( bytes_total + i ),
0371               bytes_total + i
0372             );
0373             bytes = 0;
0374             break;
0375           }
0376         } /* for */
0377         bytes_total += bytes;
0378       }
0379       if ( bytes == 0 ) {
0380         result = (int) bytes_total;
0381       }
0382       if ( bytes < 0 ) {
0383         /* read() may intentionally fail (e.g. test lost network connection) */
0384         T_log(
0385           T_VERBOSE,
0386           "File system: error reading from \"%s\" after %zd bytes",
0387           path,
0388           bytes_total
0389         );
0390         result = (int) bytes_total;
0391       }
0392     } /* while */
0393 
0394     free( data_buffer );
0395   } /* if */
0396 
0397   if ( bytes > 0 ) {
0398     T_log(
0399       T_VERBOSE,
0400       "File system: reader closes \"%s\" after %zd bytes",
0401       path,
0402       bytes_total
0403     );
0404     result = (int) bytes_total;
0405   }
0406 
0407   if ( *fd >= 0 ) {
0408     res = close( *fd );
0409     T_log(
0410       T_VERBOSE,
0411       "File system: [close( %s (fd:%d) )] = %d",
0412       path,
0413       *fd,
0414       res
0415     );
0416     *fd = -1;
0417     T_eq_int( res, 0 );
0418   }
0419 
0420   errno = errno_store;
0421   return result;
0422 }
0423 
0424 static int write_tftp_file(
0425   const char *path,
0426   size_t file_size,
0427   size_t buffer_size,
0428   int *fd )
0429 {
0430   char *data_buffer;
0431   int result = 0;
0432   int res;
0433   ssize_t i;
0434   ssize_t bytes;
0435   ssize_t bytes_total = 0;
0436   int errno_store;
0437 
0438   errno = 0;
0439   T_log( T_VERBOSE, "File system: open( %s, O_WRONLY )", path );
0440   *fd = open( path, O_WRONLY );
0441   errno_store = errno;
0442   T_log(
0443     T_VERBOSE,
0444     "File system: [open( %s, O_WRONLY )] = fd:%d (errno = %d)",
0445     path,
0446     *fd,
0447     errno
0448   );
0449   if ( *fd < 0 ) {
0450     /* open() may intentionally fail (e.g. test for invalid server address) */
0451     T_log( T_VERBOSE, "File system: cannot open \"%s\" for writing", path );
0452     errno = errno_store;
0453     result = -1;
0454   }
0455 
0456   if ( *fd >= 0 ) {
0457     data_buffer = malloc( buffer_size );
0458 
0459     do { /* Try also to write files with 0 bytes size */
0460       bytes = ( file_size - bytes_total >= buffer_size ) ?
0461         buffer_size : file_size - bytes_total;
0462       for ( i = 0; i < bytes; ++i ) {
0463         data_buffer[i] = get_file_content( bytes_total + i );
0464       }
0465       errno = 0;
0466       bytes = write( *fd, data_buffer, i );
0467       errno_store = errno;
0468       T_log(
0469         T_VERBOSE,
0470         "File system: [write( fd:%d, size=%zd )] = %zd (errno = %d)",
0471         *fd,
0472         i,
0473         bytes,
0474         errno
0475       );
0476       if ( bytes > 0 ) {
0477         bytes_total += bytes;
0478         result = (int) bytes_total;
0479       }
0480       if ( bytes != i ) {
0481         /* write() may intentionally fail (e.g. test lost network connection) */
0482         T_log(
0483           T_VERBOSE,
0484           "File system: error writing to \"%s\" after %zd bytes",
0485           path,
0486           bytes_total
0487         );
0488         break;
0489       }
0490     } while( bytes_total < file_size );
0491 
0492     free( data_buffer );
0493   } /* if */
0494 
0495   if ( *fd >= 0 ) {
0496     res = close( *fd );
0497     if (res != 0) {
0498       errno_store = errno;
0499       result = res;
0500     }
0501     T_log(
0502       T_VERBOSE,
0503       "File system: [close( %s (fd:%d) )] = %d",
0504       path,
0505       *fd,
0506       res
0507     );
0508     *fd = -1;
0509   }
0510 
0511   errno = errno_store;
0512   return result;
0513 }
0514 
0515 static int rdwt_tftp_client_file(
0516   const char *hostname,
0517   const char *filename,
0518   bool is_for_reading,
0519   ssize_t file_size, /* Only used when `is_for_reading == false` */
0520   const tftp_net_config *config,
0521   void **tftp_handle
0522 )
0523 {
0524   const static size_t buffer_size = 4001;
0525   char *data_buffer;
0526   int res = 0;
0527   ssize_t i;
0528   ssize_t bytes = 1;
0529   ssize_t bytes_total = 0;
0530   int errno_store = 0;
0531 
0532   if ( *tftp_handle == NULL ) {
0533     T_log(
0534       T_VERBOSE,
0535       "TFTP Client: tftp_open( \"%s\", \"%s\", %s, ... )",
0536       hostname,
0537       filename,
0538       is_for_reading ? "read" : "write"
0539     );
0540     res = tftp_open(
0541       hostname,
0542       filename,
0543       is_for_reading,
0544       config,
0545       tftp_handle
0546     );
0547     T_log(
0548       T_VERBOSE,
0549       "TFTP Client: [tftp_open( \"%s\", \"%s\", %s, ... )] = %d (handle:%p)",
0550       hostname,
0551       filename,
0552       is_for_reading ? "read" : "write",
0553       res,
0554       *tftp_handle
0555     );
0556   } else {
0557     T_log(
0558       T_VERBOSE,
0559       "TFTP Client: \"%s\":\"%s\" already open for %s, handle: %p ",
0560       hostname,
0561       filename,
0562       is_for_reading ? "read" : "write",
0563       *tftp_handle
0564     );
0565   }
0566 
0567   if ( res != 0 ) {
0568     /* open() may intentionally fail (e.g. test for invalid server address) */
0569     T_log(
0570       T_VERBOSE,
0571       "TFTP client: cannot open \"%s\":\"%s\" for %s",
0572       hostname,
0573       filename,
0574       is_for_reading ? "reading" : "writing"
0575     );
0576     errno_store = res;
0577   } else {
0578     T_assert_not_null( *tftp_handle );
0579   }
0580 
0581   if ( *tftp_handle != NULL ) {
0582     data_buffer = malloc( buffer_size );
0583 
0584     if ( is_for_reading ) {
0585 
0586       /* Read file */
0587       while ( bytes > 0 ) {
0588         errno = 0;
0589         bytes = tftp_read(
0590           *tftp_handle,
0591           data_buffer,
0592           buffer_size
0593         );
0594         T_log(
0595           T_VERBOSE,
0596           "TFTP Client: [tftp_read( %p, size=%zu )] = %zd",
0597           *tftp_handle,
0598           buffer_size,
0599           bytes
0600         );
0601 
0602         if ( bytes > 0 ) {
0603           for ( i = 0; i < bytes; ++i ) {
0604             if ( data_buffer[i] != get_file_content( bytes_total + i ) ) {
0605               T_true(
0606                 false,
0607                 "FTP Client: wrong file content '%c' (expected '%c') at positon %zd",
0608                 (int) ( isprint( (int) data_buffer[i] ) ? data_buffer[i] : '?' ),
0609                 (int) get_file_content( bytes_total + i ),
0610                 bytes_total + i
0611               );
0612               bytes = 0;
0613               break;
0614             }
0615           } /* for */
0616           bytes_total += bytes;
0617         }
0618         if ( bytes < 0 ) {
0619           /* read() may intentionally fail (e.g. test lost network connection) */
0620           T_log(
0621             T_VERBOSE,
0622             "TFTP Client: error reading from \"%s\":\"%s\" after %zd bytes",
0623             hostname,
0624             filename,
0625             bytes_total
0626           );
0627           errno_store = -bytes;
0628         }
0629       } /* while */
0630     } else {
0631 
0632       /* Write file */
0633       do { /* Try also to write files with 0 bytes size */
0634         bytes = ( file_size - bytes_total >= buffer_size ) ?
0635           buffer_size : file_size - bytes_total;
0636         for ( i = 0; i < bytes; ++i ) {
0637           data_buffer[i] = get_file_content( bytes_total + i );
0638         }
0639         errno = 0;
0640         bytes = tftp_write( *tftp_handle, data_buffer, i );
0641         T_log(
0642           T_VERBOSE,
0643           "TFTP Client: [tftp_write( %p, size=%zd )] = %zd",
0644           *tftp_handle,
0645           i,
0646           bytes
0647         );
0648         if ( bytes > 0 ) {
0649           bytes_total += bytes;
0650         } else {
0651           errno_store = -bytes;
0652         }
0653         if ( bytes != i ) {
0654           /* write() may intentionally fail (e.g. test lost network connection) */
0655           T_log(
0656             T_VERBOSE,
0657             "TFTP Client: error writing to \"%s\":\"%s\" after %zd bytes",
0658             hostname,
0659             filename,
0660             bytes_total
0661           );
0662           break;
0663         }
0664       } while( bytes_total < file_size );
0665     } /* if ( is_for_reading ) */
0666 
0667     free( data_buffer );
0668   } /* if ( *tftp_handle != NULL ) */
0669 
0670   if ( *tftp_handle != NULL ) {
0671     res = tftp_close( *tftp_handle );
0672     T_log(
0673       T_VERBOSE,
0674       "TFTP Client: [tftp_close( \"%s\":\"%s\" (handle:%p) )] = %d",
0675       hostname,
0676       filename,
0677       *tftp_handle,
0678       res
0679     );
0680     *tftp_handle = NULL; /* Avoid that the fixture closes it again */
0681     T_eq_int( res, 0 );
0682   } /* if ( *tftp_handle != NULL ) */
0683 
0684   errno = errno_store;
0685   return (int) bytes_total;
0686 }
0687 
0688 /*
0689  * Unit test cases
0690  */
0691 
0692 /*
0693  * This is a classical unit test for the function tftp_initialize_net_config().
0694  * Tests:
0695  *   * tftp_initialize_net_config() sets correct default values as defined
0696  *     in the documentation of the data structures tftp_net_config
0697  *     and tftp_options.
0698  */
0699 T_TEST_CASE( tftp_initialize_net_config )
0700 {
0701   tftp_net_config config;
0702   memset( &config, 0, sizeof( config ) );
0703   tftp_initialize_net_config( &config );
0704   T_eq_u16( config.retransmissions, 6 );
0705   T_eq_u16( config.server_port, 69 );
0706   T_eq_u32( config.timeout, 1000 );
0707   T_eq_u32( config.first_timeout, 400 );
0708   T_eq_u16( config.options.block_size, 1456 );
0709   T_eq_u16( config.options.window_size, 8 );
0710 }
0711 
0712 /*
0713  * This is a classical unit test for the function tftp_initialize_net_config().
0714  * Tests:
0715  *   * tftp_initialize_net_config() does not crash when called with a
0716  *     NULL pointer.
0717  */
0718 T_TEST_CASE( tftp_initialize_net_config_null )
0719 {
0720   tftp_initialize_net_config( NULL );
0721 }
0722 
0723 /*
0724  * This is a classical unit test for the function tftp_open().
0725  * Tests:
0726  *   * tftp_open() returns an error when called with a NULL pointer
0727  *     for hostname.
0728  */
0729 T_TEST_CASE_FIXTURE( tftp_open_null_hostname, &fixture_rfc1350 )
0730 {
0731   tftp_test_context *ctx = T_fixture_context();
0732   int res;
0733 
0734   res = tftp_open(
0735     NULL, /* hostname */
0736     tftpfs_file,
0737     true, /* is_for_reading */
0738     NULL, /* config */
0739     &ctx->tftp_handle
0740   );
0741   T_eq_int( res, EINVAL );
0742   T_null( ctx->tftp_handle );
0743 }
0744 
0745 /*
0746  * This is a classical unit test for the function tftp_open().
0747  * Tests:
0748  *   * tftp_open() returns an error when called with a NULL pointer
0749  *     for filename.
0750  */
0751 T_TEST_CASE_FIXTURE( tftp_open_null_filename, &fixture_rfc1350 )
0752 {
0753   tftp_test_context *ctx = T_fixture_context();
0754   int res;
0755 
0756   res = tftp_open(
0757     tftpfs_ipv4_loopback,
0758     NULL, /* filename */
0759     true, /* is_for_reading */
0760     NULL, /* config */
0761     &ctx->tftp_handle
0762   );
0763   T_eq_int( res, EINVAL );
0764   T_null( ctx->tftp_handle );
0765 }
0766 
0767 /*
0768  * This is a classical unit test for the function tftp_open().
0769  * Tests:
0770  *   * tftp_open() returns an error when called with a NULL pointer
0771  *     for tftp_handle.
0772  */
0773 T_TEST_CASE( tftp_open_null_tftp_handle )
0774 {
0775   int res;
0776 
0777   res = tftp_open(
0778     tftpfs_ipv4_loopback,
0779     tftpfs_file,
0780     true, /* is_for_reading */
0781     NULL, /* config */
0782     NULL /* tftp_handle */
0783   );
0784   T_eq_int( res, EINVAL );
0785 }
0786 
0787 /*
0788  * This is a classical unit test for the function tftp_open().
0789  * Tests:
0790  *   * tftp_open() returns an error when called with value 0 for
0791  *     option window_size.
0792  */
0793 T_TEST_CASE_FIXTURE( tftp_open_illegal_window_size, &fixture_rfc1350 )
0794 {
0795   tftp_test_context *ctx = T_fixture_context();
0796   tftp_net_config config;
0797   int res;
0798 
0799   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
0800   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
0801 
0802   tftp_initialize_net_config( &config );
0803   config.options.window_size = 1 - 1;
0804 
0805   res = tftp_open(
0806     tftpfs_ipv4_loopback,
0807     tftpfs_file,
0808     true, /* is_for_reading */
0809     &config,
0810     &ctx->tftp_handle
0811   );
0812   T_eq_int( res, EINVAL );
0813   T_null( ctx->tftp_handle );
0814   T_no_more_interactions();
0815 }
0816 
0817 /*
0818  * This is a classical unit test for the function tftp_open().
0819  * Tests:
0820  *   * tftp_open() returns an error when called with a too small
0821  *     value for option block_size.
0822  */
0823 T_TEST_CASE_FIXTURE( tftp_open_block_size_too_small, &fixture_rfc1350 )
0824 {
0825   tftp_test_context *ctx = T_fixture_context();
0826   tftp_net_config config;
0827   int res;
0828 
0829   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
0830   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
0831 
0832   tftp_initialize_net_config( &config );
0833   config.options.block_size = 8 - 1;
0834 
0835   res = tftp_open(
0836     tftpfs_ipv4_loopback,
0837     tftpfs_file,
0838     true, /* is_for_reading */
0839     &config,
0840     &ctx->tftp_handle
0841   );
0842   T_eq_int( res, EINVAL );
0843   T_null( ctx->tftp_handle );
0844   T_no_more_interactions();
0845 }
0846 
0847 /*
0848  * This is a classical unit test for the function tftp_open().
0849  * Tests:
0850  *   * tftp_open() returns an error when called with a too large
0851  *     value for option block_size.
0852  */
0853 T_TEST_CASE_FIXTURE( tftp_open_block_size_too_large, &fixture_rfc1350 )
0854 {
0855   tftp_test_context *ctx = T_fixture_context();
0856   tftp_net_config config;
0857   int res;
0858 
0859   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
0860   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
0861 
0862   tftp_initialize_net_config( &config );
0863   config.options.block_size = 65464 + 1;
0864 
0865   res = tftp_open(
0866     tftpfs_ipv4_loopback,
0867     tftpfs_file,
0868     false, /* is_for_reading */
0869     &config,
0870     &ctx->tftp_handle
0871   );
0872   T_eq_int( res, EINVAL );
0873   T_null( ctx->tftp_handle );
0874   T_no_more_interactions();
0875 }
0876 
0877 /*
0878  * This is a classical unit test for the function tftp_read().
0879  * Tests:
0880  *   * tftp_read() returns an error when called with a NULL pointer
0881  *     for tftp_handle.
0882  */
0883 T_TEST_CASE( tftp_read_null_tftp_handle )
0884 {
0885   char data_buffer[10];
0886   ssize_t res;
0887 
0888   res = tftp_read(
0889     NULL, /* tftp_handle */
0890     data_buffer,
0891     sizeof( data_buffer)
0892   );
0893   T_eq_int( res, -EIO );
0894 }
0895 
0896 /*
0897  * This is a classical unit test for the function tftp_read().
0898  * Tests:
0899  *   * tftp_read() returns an error when called with a NULL pointer
0900  *     for buffer.
0901  */
0902 T_TEST_CASE( tftp_read_null_buffer )
0903 {
0904   int tftp_handle;
0905   ssize_t res;
0906 
0907   res = tftp_read(
0908     &tftp_handle,
0909     NULL, /* buffer */
0910     8
0911   );
0912   T_eq_int( res, -EIO );
0913 }
0914 
0915 /*
0916  * This is a classical unit test for the function tftp_write().
0917  * Tests:
0918  *   * tftp_write() returns an error when called with a NULL pointer
0919  *     for tftp_handle.
0920  */
0921 T_TEST_CASE( tftp_write_null_tftp_handle )
0922 {
0923   char data_buffer[10] = { 0 };
0924   ssize_t res;
0925 
0926   res = tftp_write(
0927     NULL, /* tftp_handle */
0928     data_buffer,
0929     sizeof( data_buffer)
0930   );
0931   T_eq_int( res, -EIO );
0932 }
0933 
0934 /*
0935  * This is a classical unit test for the function tftp_write().
0936  * Tests:
0937  *   * tftp_write() returns an error when called with a NULL pointer
0938  *     for buffer.
0939  */
0940 T_TEST_CASE( tftp_write_null_buffer )
0941 {
0942   int tftp_handle;
0943   ssize_t res;
0944 
0945   res = tftp_write(
0946     &tftp_handle,
0947     NULL, /* buffer */
0948     8
0949   );
0950   T_eq_int( res, -EIO );
0951 }
0952 
0953 /*
0954  * This is a classical unit test for the function tftp_close().
0955  * Tests:
0956  *   * tftp_close() returns 0 when called with a NULL pointer.
0957  */
0958 T_TEST_CASE( tftp_close_null )
0959 {
0960   T_eq_int( tftp_close( NULL ), 0 );
0961 }
0962 
0963 /*
0964  * This is a classical unit test for the function _Tftpfs_Parse_options().
0965  * Tests:
0966  *   * Parsing an empty string has no effects.
0967  */
0968 T_TEST_CASE( _Tftpfs_Parse_options_empty )
0969 {
0970   size_t err_pos;
0971   uint32_t flags = 0;
0972   tftp_net_config config;
0973 
0974   tftp_initialize_net_config( &config );
0975   err_pos = _Tftpfs_Parse_options( "", &config, &flags );
0976   T_eq_sz( err_pos, 0 );
0977   T_eq_u16( config.options.block_size, TFTP_DEFAULT_BLOCK_SIZE );
0978   T_eq_u16( config.options.window_size, TFTP_DEFAULT_WINDOW_SIZE );
0979   T_eq_u32( flags, 0 );
0980 }
0981 
0982 /*
0983  * This is a classical unit test for the function _Tftpfs_Parse_options().
0984  * Tests:
0985  *   * Providing an NULL pointer instead of a string has no effect.
0986  */
0987 T_TEST_CASE( _Tftpfs_Parse_options_null )
0988 {
0989   size_t err_pos;
0990   uint32_t flags = 0;
0991   tftp_net_config config;
0992 
0993   tftp_initialize_net_config( &config );
0994   err_pos = _Tftpfs_Parse_options( NULL, &config, &flags );
0995   T_eq_sz( err_pos, 0 );
0996   T_eq_u16( config.options.block_size, TFTP_DEFAULT_BLOCK_SIZE );
0997   T_eq_u16( config.options.window_size, TFTP_DEFAULT_WINDOW_SIZE );
0998   T_eq_u32( flags, 0 );
0999 }
1000 
1001 /*
1002  * This is a classical unit test for the function _Tftpfs_Parse_options().
1003  * Tests:
1004  *   * Option "verbose" has the desired effect.
1005  */
1006 T_TEST_CASE( _Tftpfs_Parse_options_verbose )
1007 {
1008   size_t err_pos;
1009   uint32_t flags = 0;
1010   tftp_net_config config;
1011 
1012   tftp_initialize_net_config( &config );
1013   err_pos = _Tftpfs_Parse_options( "verbose", &config, &flags );
1014   T_eq_sz( err_pos, 0 );
1015   T_eq_u16( config.options.block_size, TFTP_DEFAULT_BLOCK_SIZE );
1016   T_eq_u16( config.options.window_size, TFTP_DEFAULT_WINDOW_SIZE );
1017   T_gt_u32( flags, 0 );
1018 }
1019 
1020 /*
1021  * This is a classical unit test for the function _Tftpfs_Parse_options().
1022  * Tests:
1023  *   * Option "rfc1350" has the desired effect.
1024  */
1025 T_TEST_CASE( _Tftpfs_Parse_options_rfc1350 )
1026 {
1027   size_t err_pos;
1028   uint32_t flags = 0;
1029   tftp_net_config config;
1030 
1031   tftp_initialize_net_config( &config );
1032   err_pos = _Tftpfs_Parse_options( "rfc1350", &config, &flags );
1033   T_eq_sz( err_pos, 0 );
1034   T_eq_u16( config.options.block_size, TFTP_RFC1350_BLOCK_SIZE );
1035   T_eq_u16( config.options.window_size, TFTP_RFC1350_WINDOW_SIZE );
1036   T_eq_u32( flags, 0 );
1037 }
1038 
1039 /*
1040  * This is a classical unit test for the function _Tftpfs_Parse_options().
1041  * Tests:
1042  *   * Option "blocksize" has the desired effect.
1043  */
1044 T_TEST_CASE( _Tftpfs_Parse_options_blocksize )
1045 {
1046   size_t err_pos;
1047   uint32_t flags = 0;
1048   tftp_net_config config;
1049 
1050   tftp_initialize_net_config( &config );
1051   err_pos = _Tftpfs_Parse_options( "blocksize=21", &config, &flags );
1052   T_eq_sz( err_pos, 0 );
1053   T_eq_u16( config.options.block_size, 21 );
1054   T_eq_u16( config.options.window_size, TFTP_DEFAULT_WINDOW_SIZE );
1055   T_eq_u32( flags, 0 );
1056 }
1057 
1058 /*
1059  * This is a classical unit test for the function _Tftpfs_Parse_options().
1060  * Tests:
1061  *   * Option "windowsize" has the desired effect.
1062  */
1063 T_TEST_CASE( _Tftpfs_Parse_options_windowsize )
1064 {
1065   size_t err_pos;
1066   uint32_t flags = 0;
1067   tftp_net_config config;
1068 
1069   tftp_initialize_net_config( &config );
1070   err_pos = _Tftpfs_Parse_options( "windowsize=13", &config, &flags );
1071   T_eq_sz( err_pos, 0 );
1072   T_eq_u16( config.options.block_size, TFTP_DEFAULT_BLOCK_SIZE );
1073   T_eq_u16( config.options.window_size, 13 );
1074   T_eq_u32( flags, 0 );
1075 }
1076 
1077 /*
1078  * This is a classical unit test for the function _Tftpfs_Parse_options().
1079  * Tests:
1080  *   * Processing of all options in one string works as expected.
1081  */
1082 T_TEST_CASE( _Tftpfs_Parse_options_all )
1083 {
1084   size_t err_pos;
1085   uint32_t flags = 0;
1086   tftp_net_config config;
1087 
1088   tftp_initialize_net_config( &config );
1089   err_pos = _Tftpfs_Parse_options( "rfc1350,blocksize=1234,windowsize=4567,verbose", &config, &flags );
1090   T_eq_sz( err_pos, 0 );
1091   T_eq_u16( config.options.block_size, 1234 );
1092   T_eq_u16( config.options.window_size, 4567 );
1093   T_gt_u32( flags, 0 );
1094 }
1095 
1096 /*
1097  * This is a classical unit test for the function _Tftpfs_Parse_options().
1098  * Tests:
1099  *   * Parser ignores unnecessary commas.
1100  */
1101 T_TEST_CASE( _Tftpfs_Parse_options_surplus_comma )
1102 {
1103   size_t err_pos;
1104   uint32_t flags = 0;
1105   tftp_net_config config;
1106 
1107   tftp_initialize_net_config( &config );
1108   err_pos = _Tftpfs_Parse_options( ",blocksize=1234,,,,windowsize=4567,,", &config, &flags );
1109   T_eq_sz( err_pos, 0 );
1110   T_eq_u16( config.options.block_size, 1234 );
1111   T_eq_u16( config.options.window_size, 4567 );
1112   T_eq_u32( flags, 0 );
1113 }
1114 
1115 /*
1116  * This is a classical unit test for the function _Tftpfs_Parse_options().
1117  * Tests:
1118  *   * Parser detects a bad value.
1119  */
1120 T_TEST_CASE( _Tftpfs_Parse_options_bad_value )
1121 {
1122   size_t err_pos;
1123   uint32_t flags = 0;
1124   tftp_net_config config;
1125 
1126   tftp_initialize_net_config( &config );
1127   err_pos = _Tftpfs_Parse_options( "blocksize=123.4,windowsize=4567", &config, &flags );
1128   T_eq_sz( err_pos, 14 );
1129 }
1130 
1131 /*
1132  * This is a classical unit test for the function _Tftpfs_Parse_options().
1133  * Tests:
1134  *   * Parser detects an illegal option.
1135  */
1136 T_TEST_CASE( _Tftpfs_Parse_options_illegal_option )
1137 {
1138   size_t err_pos;
1139   uint32_t flags = 0;
1140   tftp_net_config config;
1141 
1142   tftp_initialize_net_config( &config );
1143   err_pos = _Tftpfs_Parse_options( "blocksize=123,illegal", &config, &flags );
1144   T_eq_sz( err_pos, 15 );
1145 }
1146 
1147 /*
1148  * This is a classical unit test for the function _Tftpfs_Parse_options().
1149  * Tests:
1150  *   * Parser detects a truncated option.
1151  */
1152 T_TEST_CASE( _Tftpfs_Parse_options_truncated_option )
1153 {
1154   size_t err_pos;
1155   uint32_t flags = 0;
1156   tftp_net_config config;
1157 
1158   tftp_initialize_net_config( &config );
1159   err_pos = _Tftpfs_Parse_options( "blocksize", &config, &flags );
1160   T_eq_sz( err_pos, 1 );
1161 }
1162 
1163 /*
1164  * This is a classical unit test for the function rtems_tftpfs_initialize().
1165  * Tests:
1166  *   * Correct error handling in case mount options cannot be parsed.
1167  */
1168 T_TEST_CASE_FIXTURE( mount_with_bad_options, &fixture_mount_point )
1169 {
1170   int result;
1171 
1172   result = mount(
1173     "",
1174     tftpfs_mount_point,
1175     RTEMS_FILESYSTEM_TYPE_TFTPFS,
1176     RTEMS_FILESYSTEM_READ_WRITE,
1177     "windowsize=4567,blocksize=123bad"
1178   );
1179   T_assert_le_int( result, -1 );
1180   T_assert_eq_int( errno, EINVAL );
1181 }
1182 
1183 /*
1184  * Test cases for the TFTP client interface
1185  *
1186  * Since the TFTP file system uses the TFTP client interface for all
1187  * file transfers, the function of the TFTP client is almost
1188  * completely tested by the tests for the file system interface.
1189  * The test cases here - for the TFTP client interface - test only
1190  * those aspects not (easily) testable through the file system interface.
1191  */
1192 
1193 /*
1194  * Read a file from the server using the TFTP client interface.
1195  * The file is one byte long.  No timeouts, packet loss, ...
1196  * Tests:
1197  *   * tftp_open() called with NULL for config uses
1198  *     default configuration values.
1199  *   * Read a file using only the TFTP client (i.e. not using the
1200  *     file system)
1201  */
1202 T_TEST_CASE_FIXTURE( client_open_with_NULL_config, &fixture_rfc1350 )
1203 {
1204   tftp_test_context *ctx = T_fixture_context();
1205   int bytes_read;
1206   uint16_t block_num = 1;
1207   size_t pos_in_file = 0;
1208 
1209   /* T_set_verbosity( T_VERBOSE ); */
1210   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
1211   _Tftp_Add_interaction_send_rrq(
1212     TFTP_FIRST_FD,
1213     tftpfs_file,
1214     TFTP_STD_PORT,
1215     tftpfs_ipv4_loopback,
1216     TFTP_DEFAULT_BLOCK_SIZE,
1217     TFTP_DEFAULT_WINDOW_SIZE,
1218     true
1219   );
1220   _Tftp_Add_interaction_recv_data(
1221     TFTP_FIRST_FD,
1222     FIRST_TIMEOUT_MILLISECONDS,
1223     SERV_PORT,
1224     tftpfs_ipv4_loopback,
1225     block_num,
1226     pos_in_file,
1227     1, /* Number of bytes transferred */
1228     get_file_content,
1229     true
1230   );
1231   pos_in_file += 1;
1232   _Tftp_Add_interaction_send_ack(
1233     TFTP_FIRST_FD,
1234     block_num++,
1235     SERV_PORT,
1236     tftpfs_ipv4_loopback,
1237     true
1238   );
1239   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
1240 
1241   bytes_read = rdwt_tftp_client_file(
1242     tftpfs_ipv4_loopback,
1243     tftpfs_file,
1244     true, /* is_for_reading */
1245     -1, /* file_size for writing files only */
1246     NULL, /* config */
1247     &ctx->tftp_handle
1248   );
1249   T_eq_sz( bytes_read, pos_in_file );
1250   T_eq_int( errno, 0 );
1251   T_no_more_interactions();
1252 }
1253 
1254 /*
1255  * Read a very short file from the server using the TFTP client interface.
1256  * The file is one data packet long.  Use none-default configuration values.
1257  * The second and the third DATA packets are lost.  This causes
1258  * a termination of the connection because only two retransmissions are
1259  * configured.
1260  * Tests:
1261  *   * tftp_open() called with all configuration values having
1262  *     none default values.
1263  *   * The test writes a file using only the TFTP client (i.e. not using the
1264  *     file system API).
1265  *   * The client uses the none default configuration values:
1266  *     retransmissions, server_port, timeout, first_timeout,
1267  *     block_size, window_size.
1268  *   * The server sends the options in a different order than the client.
1269  *   * The option names in the OACK can be upper or lower case.
1270  *   * If windowsize > 1, the client sends ACK only each windowsize packet.
1271  *   * If windowsize > 1 and no packet is received in the timeout period,
1272  *     the client retransmits the last ACK.
1273  *   * The client makes a limited number of retransmissions attempts
1274  *     and then terminates the connections with an error.
1275  */
1276 T_TEST_CASE_FIXTURE( client_open_with_none_default_config, &fixture_rfc1350 )
1277 {
1278   tftp_test_context *ctx = T_fixture_context();
1279   tftp_net_config config;
1280   int bytes_read;
1281   uint16_t block_num = 0;
1282   size_t pos_in_file = 0;
1283   uint16_t retransmissions = 2;
1284   uint16_t server_port = 3456;
1285   uint32_t timeout = 300;
1286   uint32_t first_timeout = 200;
1287   uint16_t block_size = 8;
1288   uint16_t window_size = 2;
1289   const char options[] =
1290     "WINDOWSIZE" "\0" "2\0"
1291     TFTP_OPTION_BLKSIZE "\0" "8";
1292 
1293   /* T_set_verbosity( T_VERBOSE ); */
1294   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
1295   _Tftp_Add_interaction_send_rrq(
1296     TFTP_FIRST_FD,
1297     tftpfs_file,
1298     server_port,
1299     tftpfs_ipv4_loopback,
1300     block_size,
1301     window_size,
1302     true
1303   );
1304   _Tftp_Add_interaction_recv_oack(
1305     TFTP_FIRST_FD,
1306     first_timeout,
1307     SERV_PORT,
1308     tftpfs_ipv4_loopback,
1309     options,
1310     sizeof( options ),
1311     true
1312   );
1313   _Tftp_Add_interaction_send_ack(
1314     TFTP_FIRST_FD,
1315     block_num++,
1316     SERV_PORT,
1317     tftpfs_ipv4_loopback,
1318     true
1319   );
1320   _Tftp_Add_interaction_recv_data(
1321     TFTP_FIRST_FD,
1322     first_timeout,
1323     SERV_PORT,
1324     tftpfs_ipv4_loopback,
1325     block_num++,
1326     pos_in_file,
1327     block_size, /* Number of bytes transferred */
1328     get_file_content,
1329     true
1330   );
1331   pos_in_file += TFTP_RFC1350_BLOCK_SIZE;
1332   _Tftp_Add_interaction_recv_data(
1333     TFTP_FIRST_FD,
1334     first_timeout,
1335     SERV_PORT,
1336     tftpfs_ipv4_loopback,
1337     block_num,
1338     pos_in_file,
1339     block_size, /* Number of bytes transferred */
1340     get_file_content,
1341     true
1342   );
1343   pos_in_file += TFTP_RFC1350_BLOCK_SIZE;
1344   _Tftp_Add_interaction_send_ack(
1345     TFTP_FIRST_FD,
1346     block_num++,
1347     SERV_PORT,
1348     tftpfs_ipv4_loopback,
1349     true
1350   );
1351   _Tftp_Add_interaction_recv_nothing(
1352     TFTP_FIRST_FD,
1353     first_timeout /* Timeout: No packet received within timeout period */
1354   );
1355   _Tftp_Add_interaction_send_ack(
1356     TFTP_FIRST_FD,
1357     block_num - 1, /* Block number OK: Last block successfully received */
1358     SERV_PORT,
1359     tftpfs_ipv4_loopback,
1360     true
1361   );
1362   _Tftp_Add_interaction_recv_nothing(
1363     TFTP_FIRST_FD,
1364     timeout /* Timeout: No packet received within timeout period */
1365   );
1366   _Tftp_Add_interaction_send_error(
1367     TFTP_FIRST_FD,
1368     TFTP_ERROR_CODE_NO_USER,
1369     SERV_PORT,
1370     tftpfs_ipv4_loopback,
1371     true
1372   );
1373   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
1374 
1375   tftp_initialize_net_config( &config );
1376   config.retransmissions = retransmissions;
1377   config.server_port = server_port;
1378   config.timeout = timeout;
1379   config.first_timeout = first_timeout;
1380   config.options.block_size = block_size;
1381   config.options.window_size = window_size;
1382 
1383   bytes_read = rdwt_tftp_client_file(
1384     tftpfs_ipv4_loopback,
1385     tftpfs_file,
1386     true, /* is_for_reading */
1387     -1, /* file_size for writing files only */
1388     &config,
1389     &ctx->tftp_handle
1390   );
1391 
1392   /*
1393    * Not a bug but not nice: The client has received data before the connection
1394    * breaks down due to timeout and this data is not provided to the user.
1395    */
1396 
1397   T_eq_sz( bytes_read, 0 );
1398   T_eq_int( errno, EIO );
1399   T_no_more_interactions();
1400 }
1401 
1402 /*
1403  * Attempt to write to a file open for reading using the TFTP client interface.
1404  * Tests:
1405  *   * tftp_open() called with NULL for config uses
1406  *     default configuration values.
1407  *   * Read a file using only the TFTP client (i.e. not using the
1408  *     file system)
1409  *   * The attempt to write to a file open for reading is rejected
1410  *     with an error.
1411  *   * The server receives an error message to indicate that the client
1412  *     closes the connection without having transferred data.
1413  */
1414 T_TEST_CASE_FIXTURE( client_write_to_file_opened_for_reading, &fixture_rfc1350 )
1415 {
1416   tftp_test_context *ctx = T_fixture_context();
1417   int res = 0;
1418   const char options[] =
1419     TFTP_OPTION_BLKSIZE "\0"
1420     RTEMS_XSTRING( TFTP_DEFAULT_BLOCK_SIZE ) "\0"
1421     TFTP_OPTION_WINDOWSIZE"\0"
1422     RTEMS_XSTRING( TFTP_DEFAULT_WINDOW_SIZE );
1423 
1424   /* T_set_verbosity( T_VERBOSE ); */
1425   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
1426   _Tftp_Add_interaction_send_rrq(
1427     TFTP_FIRST_FD,
1428     tftpfs_file,
1429     TFTP_STD_PORT,
1430     tftpfs_ipv4_loopback,
1431     TFTP_DEFAULT_BLOCK_SIZE,
1432     TFTP_DEFAULT_WINDOW_SIZE,
1433     true
1434   );
1435   _Tftp_Add_interaction_recv_oack(
1436     TFTP_FIRST_FD,
1437     FIRST_TIMEOUT_MILLISECONDS,
1438     SERV_PORT,
1439     tftpfs_ipv4_loopback,
1440     options,
1441     sizeof( options ),
1442     true
1443   );
1444   /* Sending an ACK at this place before the ERROR would be OK, too. */
1445   _Tftp_Add_interaction_send_error(
1446     TFTP_FIRST_FD,
1447     TFTP_ERROR_CODE_NO_USER,
1448     SERV_PORT,
1449     tftpfs_ipv4_loopback,
1450     true
1451   );
1452   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
1453 
1454   res = tftp_open(
1455     tftpfs_ipv4_loopback,
1456     tftpfs_file,
1457     true, /* is_for_reading */
1458     NULL, /* Config */
1459     &ctx->tftp_handle
1460   );
1461   T_eq_int( res, 0 );
1462   T_assert_not_null( ctx->tftp_handle );
1463 
1464   res = (int) tftp_write( ctx->tftp_handle, &res, 1 );
1465   T_eq_int( res, -EIO );
1466 
1467   res = tftp_close( ctx->tftp_handle );
1468   ctx->tftp_handle = NULL; /* Avoid that the fixture closes it again */
1469   T_eq_int( res, 0 );
1470   T_no_more_interactions();
1471 }
1472 
1473 /*
1474  * Attempt to read from a file open for writing using the TFTP client
1475  * interface.
1476  * Tests:
1477  *   * tftp_open() called with NULL for config uses
1478  *     default configuration values.
1479  *   * Read a file using only the TFTP client (i.e. not using the
1480  *     file system)
1481  *   * Attempt to read from a file open for writing is rejected with an error.
1482  */
1483 T_TEST_CASE_FIXTURE( client_read_to_file_opened_for_writing, &fixture_rfc1350 )
1484 {
1485   tftp_test_context *ctx = T_fixture_context();
1486   int res = 0;
1487   uint16_t block_num = 1;
1488   size_t pos_in_file = 0;
1489   const char options[] =
1490     TFTP_OPTION_BLKSIZE "\0"
1491     RTEMS_XSTRING( TFTP_DEFAULT_BLOCK_SIZE ) "\0"
1492     TFTP_OPTION_WINDOWSIZE"\0"
1493     RTEMS_XSTRING( TFTP_DEFAULT_WINDOW_SIZE );
1494 
1495   /* T_set_verbosity( T_VERBOSE ); */
1496   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
1497   _Tftp_Add_interaction_send_wrq(
1498     TFTP_FIRST_FD,
1499     tftpfs_file,
1500     TFTP_STD_PORT,
1501     tftpfs_ipv4_loopback,
1502     TFTP_DEFAULT_BLOCK_SIZE,
1503     TFTP_DEFAULT_WINDOW_SIZE,
1504     true
1505   );
1506   _Tftp_Add_interaction_recv_oack(
1507     TFTP_FIRST_FD,
1508     FIRST_TIMEOUT_MILLISECONDS,
1509     SERV_PORT,
1510     tftpfs_ipv4_loopback,
1511     options,
1512     sizeof( options ),
1513     true
1514   );
1515   _Tftp_Add_interaction_send_data(
1516     TFTP_FIRST_FD,
1517     block_num,
1518     pos_in_file,
1519     0, /* Data size */
1520     get_file_content,
1521     SERV_PORT,
1522     tftpfs_ipv4_loopback,
1523     true
1524   );
1525   pos_in_file += 0;
1526   _Tftp_Add_interaction_recv_ack(
1527      TFTP_FIRST_FD,
1528      FIRST_TIMEOUT_MILLISECONDS,
1529      SERV_PORT,
1530      tftpfs_ipv4_loopback,
1531      block_num++,
1532      true
1533    );
1534   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
1535 
1536   res = tftp_open(
1537     tftpfs_ipv4_loopback,
1538     tftpfs_file,
1539     false, /* is_for_reading */
1540     NULL, /* config */
1541     &ctx->tftp_handle
1542   );
1543   T_eq_int( res, 0 );
1544   T_assert_not_null( ctx->tftp_handle );
1545 
1546   res = (int) tftp_read( ctx->tftp_handle, &res, 1 );
1547   T_eq_int( res, -EIO );
1548 
1549   res = tftp_close( ctx->tftp_handle );
1550   ctx->tftp_handle = NULL; /* Avoid that the fixture closes it again */
1551   T_eq_int( res, 0 );
1552   T_no_more_interactions();
1553 }
1554 
1555 /*
1556  * Write a file to the server using the TFTP client interface.
1557  * The test uses the default options.
1558  * The file is 2 and a half data packet long.  No timeouts, packet loss, ...
1559  * Tests:
1560  *   * The default options (windowsize = 8 and blocksize = 1456) are used.
1561  *   * tftp_open() is called with default configuration values.
1562  *   * The test writes a file using only the TFTP client (i.e. not using the
1563  *     file system)
1564  *   * The code supports the use of a server name instead of an IP address.
1565  *   * The first window is also the last window.
1566  *   * The only ACK packet is the one at the end of window.
1567  *   * Between sending data packets, the client checks whether any packets
1568  *     are received.
1569  *   * The client handles files correctly which end in the middle of a window.
1570  */
1571 T_TEST_CASE_FIXTURE( client_write_simple_file, &fixture_default_options )
1572 {
1573   tftp_test_context *ctx = T_fixture_context();
1574   tftp_net_config config;
1575   int bytes_written;
1576   uint16_t block_num = 1;
1577   size_t pos_in_file = 0;
1578   const char options[] =
1579     TFTP_OPTION_BLKSIZE "\0"
1580     RTEMS_XSTRING( TFTP_DEFAULT_BLOCK_SIZE ) "\0"
1581     TFTP_OPTION_WINDOWSIZE "\0"
1582     RTEMS_XSTRING( TFTP_DEFAULT_WINDOW_SIZE );
1583 
1584   /* T_set_verbosity( T_VERBOSE ); */
1585   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
1586   _Tftp_Add_interaction_send_wrq(
1587     TFTP_FIRST_FD,
1588     tftpfs_file,
1589     TFTP_STD_PORT,
1590     tftpfs_server0_ipv4,
1591     TFTP_DEFAULT_BLOCK_SIZE,
1592     TFTP_DEFAULT_WINDOW_SIZE,
1593     true
1594   );
1595   _Tftp_Add_interaction_recv_oack(
1596     TFTP_FIRST_FD,
1597     FIRST_TIMEOUT_MILLISECONDS,
1598     SERV_PORT,
1599     tftpfs_server0_ipv4,
1600     options,
1601     sizeof( options ),
1602     true
1603   );
1604   _Tftp_Add_interaction_send_data(
1605     TFTP_FIRST_FD,
1606     block_num++,
1607     pos_in_file,
1608     TFTP_DEFAULT_BLOCK_SIZE,
1609     get_file_content,
1610     SERV_PORT,
1611     tftpfs_server0_ipv4,
1612     true
1613   );
1614   pos_in_file += TFTP_DEFAULT_BLOCK_SIZE;
1615   _Tftp_Add_interaction_recv_nothing(
1616     TFTP_FIRST_FD,
1617     DO_NOT_WAIT_FOR_ANY_TIMEOUT
1618   );
1619   _Tftp_Add_interaction_send_data(
1620     TFTP_FIRST_FD,
1621     block_num++,
1622     pos_in_file,
1623     TFTP_DEFAULT_BLOCK_SIZE,
1624     get_file_content,
1625     SERV_PORT,
1626     tftpfs_server0_ipv4,
1627     true
1628   );
1629   pos_in_file += TFTP_DEFAULT_BLOCK_SIZE;
1630   _Tftp_Add_interaction_recv_nothing(
1631     TFTP_FIRST_FD,
1632     DO_NOT_WAIT_FOR_ANY_TIMEOUT
1633   );
1634   _Tftp_Add_interaction_send_data(
1635     TFTP_FIRST_FD,
1636     block_num,
1637     pos_in_file,
1638     TFTP_DEFAULT_BLOCK_SIZE / 2, /* Data bytes in this block */
1639     get_file_content,
1640     SERV_PORT,
1641     tftpfs_server0_ipv4,
1642     true
1643   );
1644   pos_in_file += TFTP_DEFAULT_BLOCK_SIZE / 2;
1645   _Tftp_Add_interaction_recv_ack(
1646     TFTP_FIRST_FD,
1647     FIRST_TIMEOUT_MILLISECONDS,
1648     SERV_PORT,
1649     tftpfs_server0_ipv4,
1650     block_num++,
1651     true
1652   );
1653   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
1654 
1655   tftp_initialize_net_config( &config );
1656   bytes_written = rdwt_tftp_client_file(
1657     tftpfs_server0_name,
1658     tftpfs_file,
1659     false, /* is_for_reading */
1660     pos_in_file, /* file_size for writing files only */
1661     &config,
1662     &ctx->tftp_handle
1663   );
1664   T_eq_sz( bytes_written, pos_in_file );
1665   T_eq_int( errno, 0 );
1666   T_no_more_interactions();
1667 }
1668 
1669 /*
1670  * Test cases for the file system interface
1671  */
1672 
1673 /*
1674  * Read a file from the server using only RFC1350.
1675  * The file is two and a half data packet long.  No timeouts, packet loss, ...
1676  * Tests:
1677  *   * The code supports requests without options (RFC1350 only).
1678  *   * The code supports the use of an IPv4 address instead of a server name.
1679  *   * The first packet is sent to standard port 69 of server.
1680  *   * All other packets are sent to the port used for this connection.
1681  *   * The first and second data packet are full.
1682  *   * The third data packet signals the end of transfer.
1683  *   * Read the file from file system in one big chunk of exactly
1684  *     the size of the file.
1685  */
1686 T_TEST_CASE_FIXTURE( read_simple_file, &fixture_rfc1350 )
1687 {
1688   tftp_test_context *ctx = T_fixture_context();
1689   int bytes_read;
1690   uint16_t block_num = 1;
1691   size_t pos_in_file = 0;
1692 
1693   /* T_set_verbosity( T_VERBOSE ); */
1694   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
1695   _Tftp_Add_interaction_send_rrq(
1696     TFTP_FIRST_FD,
1697     tftpfs_file,
1698     TFTP_STD_PORT,
1699     tftpfs_ipv4_loopback,
1700     NO_BLOCK_SIZE_OPTION,
1701     NO_WINDOW_SIZE_OPTION,
1702     true
1703   );
1704   _Tftp_Add_interaction_recv_data(
1705     TFTP_FIRST_FD,
1706     FIRST_TIMEOUT_MILLISECONDS,
1707     SERV_PORT,
1708     tftpfs_ipv4_loopback,
1709     block_num,
1710     pos_in_file,
1711     TFTP_RFC1350_BLOCK_SIZE, /* Number of bytes transferred */
1712     get_file_content,
1713     true
1714   );
1715   pos_in_file += TFTP_RFC1350_BLOCK_SIZE;
1716   _Tftp_Add_interaction_send_ack(
1717     TFTP_FIRST_FD,
1718     block_num++,
1719     SERV_PORT,
1720     tftpfs_ipv4_loopback,
1721     true
1722   );
1723   _Tftp_Add_interaction_recv_data(
1724     TFTP_FIRST_FD,
1725     FIRST_TIMEOUT_MILLISECONDS,
1726     SERV_PORT,
1727     tftpfs_ipv4_loopback,
1728     block_num,
1729     pos_in_file,
1730     TFTP_RFC1350_BLOCK_SIZE, /* Number of bytes transferred */
1731     get_file_content,
1732     true
1733   );
1734   pos_in_file += TFTP_RFC1350_BLOCK_SIZE;
1735   _Tftp_Add_interaction_send_ack(
1736     TFTP_FIRST_FD,
1737     block_num++,
1738     SERV_PORT,
1739     tftpfs_ipv4_loopback,
1740     true
1741   );
1742   _Tftp_Add_interaction_recv_data(
1743     TFTP_FIRST_FD,
1744     FIRST_TIMEOUT_MILLISECONDS,
1745     SERV_PORT,
1746     tftpfs_ipv4_loopback,
1747     block_num,
1748     pos_in_file,
1749     TFTP_RFC1350_BLOCK_SIZE / 2, /* Number of bytes transferred */
1750     get_file_content,
1751     true
1752   );
1753   pos_in_file += TFTP_RFC1350_BLOCK_SIZE / 2;
1754   _Tftp_Add_interaction_send_ack(
1755     TFTP_FIRST_FD,
1756     block_num++,
1757     SERV_PORT,
1758     tftpfs_ipv4_loopback,
1759     true
1760   );
1761   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
1762 
1763   bytes_read = read_tftp_file(
1764     create_tftpfs_path( tftpfs_ipv4_loopback, tftpfs_file ),
1765     /* Bytes read per call to read() */
1766     2 * TFTP_RFC1350_BLOCK_SIZE + TFTP_RFC1350_BLOCK_SIZE / 2,
1767     SIZE_MAX,
1768     &ctx->fd0
1769   );
1770   T_eq_int( bytes_read, pos_in_file );
1771   T_no_more_interactions();
1772 }
1773 
1774 /*
1775  * Read a file from the server using only RFC1350.
1776  * The file is one byte long.  No timeouts, packet loss, ...
1777  * Tests:
1778  *   * The code supports requests without options (RFC1350 only).
1779  *   * The code supports the use of an IPv4 address instead of a server name.
1780  *   * The first packet is sent to standard port 69 of server.
1781  *   * All other packets are sent to the port used for this connection.
1782  *   * The first data packet is not full and signals the end of the transfer.
1783  *   * The test reads a file from the file system in one-byte chunks.
1784  */
1785 T_TEST_CASE_FIXTURE( read_tiny_file, &fixture_rfc1350 )
1786 {
1787   tftp_test_context *ctx = T_fixture_context();
1788   int bytes_read;
1789   uint16_t block_num = 1;
1790   size_t pos_in_file = 0;
1791 
1792   /* T_set_verbosity( T_VERBOSE ); */
1793   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
1794   _Tftp_Add_interaction_send_rrq(
1795     TFTP_FIRST_FD,
1796     tftpfs_file,
1797     TFTP_STD_PORT,
1798     tftpfs_ipv4_loopback,
1799     NO_BLOCK_SIZE_OPTION,
1800     NO_WINDOW_SIZE_OPTION,
1801     true
1802   );
1803   _Tftp_Add_interaction_recv_data(
1804     TFTP_FIRST_FD,
1805     FIRST_TIMEOUT_MILLISECONDS,
1806     SERV_PORT,
1807     tftpfs_ipv4_loopback,
1808     block_num,
1809     pos_in_file,
1810     1, /* Number of bytes transferred */
1811     get_file_content,
1812     true
1813   );
1814   pos_in_file += 1;
1815   _Tftp_Add_interaction_send_ack(
1816     TFTP_FIRST_FD,
1817     block_num++,
1818     SERV_PORT,
1819     tftpfs_ipv4_loopback,
1820     true
1821   );
1822   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
1823 
1824   bytes_read = read_tftp_file(
1825     create_tftpfs_path( tftpfs_ipv4_loopback, tftpfs_file ),
1826     1, /* Bytes read per call to read() */
1827     SIZE_MAX,
1828     &ctx->fd0
1829   );
1830   T_eq_int( bytes_read, pos_in_file );
1831   T_no_more_interactions();
1832 }
1833 
1834 /*
1835  * Read a file from the server using only RFC1350.
1836  * The file is one data packet long.  No timeouts, packet loss, ...
1837  * Tests:
1838  *   * The code supports requests without options (RFC1350 only).
1839  *   * The code supports the use of an IPv4 address instead of a server name.
1840  *   * The first packet is sent to standard port 69 of server.
1841  *   * All other packets are sent to the port used for this connection.
1842  *   * The first data packet is full.
1843  *   * The second data packet is empty and signals the end of the transfer.
1844  *   * The client handles an empty data packet correctly as end
1845  *     of file indicator.
1846  *   * The test reads a file from the file system in chunks of three quarters
1847  *     of the block size.
1848  */
1849 T_TEST_CASE_FIXTURE( read_one_block_file, &fixture_rfc1350 )
1850 {
1851   tftp_test_context *ctx = T_fixture_context();
1852   int bytes_read;
1853   uint16_t block_num = 1;
1854   size_t pos_in_file = 0;
1855 
1856   /* T_set_verbosity( T_VERBOSE ); */
1857   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
1858   _Tftp_Add_interaction_send_rrq(
1859     TFTP_FIRST_FD,
1860     tftpfs_file,
1861     TFTP_STD_PORT,
1862     tftpfs_ipv4_loopback,
1863     NO_BLOCK_SIZE_OPTION,
1864     NO_WINDOW_SIZE_OPTION,
1865     true
1866   );
1867   _Tftp_Add_interaction_recv_data(
1868     TFTP_FIRST_FD,
1869     FIRST_TIMEOUT_MILLISECONDS,
1870     SERV_PORT,
1871     tftpfs_ipv4_loopback,
1872     block_num,
1873     pos_in_file,
1874     TFTP_RFC1350_BLOCK_SIZE, /* Number of bytes transferred */
1875     get_file_content,
1876     true
1877   );
1878   pos_in_file += TFTP_RFC1350_BLOCK_SIZE;
1879   _Tftp_Add_interaction_send_ack(
1880     TFTP_FIRST_FD,
1881     block_num++,
1882     SERV_PORT,
1883     tftpfs_ipv4_loopback,
1884     true
1885   );
1886   _Tftp_Add_interaction_recv_data(
1887     TFTP_FIRST_FD,
1888     FIRST_TIMEOUT_MILLISECONDS,
1889     SERV_PORT,
1890     tftpfs_ipv4_loopback,
1891     block_num,
1892     pos_in_file,
1893     0, /* Number of bytes transferred */
1894     get_file_content,
1895     true
1896   );
1897   _Tftp_Add_interaction_send_ack(
1898     TFTP_FIRST_FD,
1899     block_num++,
1900     SERV_PORT,
1901     tftpfs_ipv4_loopback,
1902     true
1903   );
1904   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
1905 
1906   bytes_read = read_tftp_file(
1907     create_tftpfs_path( tftpfs_ipv4_loopback, tftpfs_file ),
1908     /* Bytes read per call to read() */
1909     TFTP_RFC1350_BLOCK_SIZE / 4 * 3,
1910     SIZE_MAX,
1911     &ctx->fd0
1912   );
1913   T_eq_int( bytes_read, pos_in_file );
1914   T_no_more_interactions();
1915 }
1916 
1917 /*
1918  * Read a file from the server using only RFC1350.
1919  * The file is one data packet long.
1920  * The client receives stray packets:
1921  *   * A packet from an unknown server (wrong TID)
1922  *   * An ACK packet instead of a DATA packet
1923  * Tests:
1924  *   * The code supports requests without options (RFC1350 only).
1925  *   * The code supports the use of an IPv4 address instead of a server name.
1926  *   * The first packet is sent to standard port 69 of server.
1927  *   * All other packets are sent to the port used for this connection.
1928  *   * The first data packet is full.
1929  *   * The next received packet originates from a wrong TID
1930  *     (i.e. wrong connection).
1931  *   * Upon reception of a packet with a wrong TID, the client sends
1932  *     an ERROR message with code 5 and does not terminate the current
1933  *     transfer.
1934  *   * The final received packet is an ACK packet instead or the expected
1935  *     DATA packet.
1936  *   * Upon the reception of an unexpected packet, the client terminates
1937  *     the connection by sending an error packet to the server.
1938  */
1939 T_TEST_CASE_FIXTURE( read_file_stray_packets, &fixture_rfc1350 )
1940 {
1941   tftp_test_context *ctx = T_fixture_context();
1942   int bytes_read;
1943   uint16_t block_num = 1;
1944   size_t pos_in_file = 0;
1945 
1946   /* T_set_verbosity( T_VERBOSE ); */
1947   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
1948   _Tftp_Add_interaction_send_rrq(
1949     TFTP_FIRST_FD,
1950     tftpfs_file,
1951     TFTP_STD_PORT,
1952     tftpfs_ipv4_loopback,
1953     NO_BLOCK_SIZE_OPTION,
1954     NO_WINDOW_SIZE_OPTION,
1955     true
1956   );
1957   _Tftp_Add_interaction_recv_data(
1958     TFTP_FIRST_FD,
1959     FIRST_TIMEOUT_MILLISECONDS,
1960     SERV_PORT,
1961     tftpfs_ipv4_loopback,
1962     block_num,
1963     pos_in_file,
1964     TFTP_RFC1350_BLOCK_SIZE, /* Number of bytes transferred */
1965     get_file_content,
1966     true
1967   );
1968   pos_in_file += TFTP_RFC1350_BLOCK_SIZE;
1969   _Tftp_Add_interaction_send_ack(
1970     TFTP_FIRST_FD,
1971     block_num++,
1972     SERV_PORT,
1973     tftpfs_ipv4_loopback,
1974     true
1975   );
1976   _Tftp_Add_interaction_recv_data(
1977     TFTP_FIRST_FD,
1978     FIRST_TIMEOUT_MILLISECONDS,
1979     SERV_PORT + 1, /* Stray packet with wrong server TID */
1980     tftpfs_ipv4_loopback,
1981     block_num,
1982     pos_in_file,
1983     TFTP_RFC1350_BLOCK_SIZE, /* Number of bytes transferred */
1984     get_file_content,
1985     true
1986   );
1987   _Tftp_Add_interaction_send_error(
1988     TFTP_FIRST_FD,
1989     TFTP_ERROR_CODE_UNKNOWN_ID,
1990     SERV_PORT + 1,
1991     tftpfs_ipv4_loopback,
1992     true
1993   );
1994   _Tftp_Add_interaction_recv_ack( /* Stray ACK packet */
1995     TFTP_FIRST_FD,
1996     FIRST_TIMEOUT_MILLISECONDS,
1997     SERV_PORT,
1998     tftpfs_ipv4_loopback,
1999     block_num - 1,
2000     true
2001   );
2002   _Tftp_Add_interaction_send_error(
2003     TFTP_FIRST_FD,
2004     TFTP_ERROR_CODE_ILLEGAL,
2005     SERV_PORT,
2006     tftpfs_ipv4_loopback,
2007     true
2008   );
2009   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
2010 
2011   bytes_read = read_tftp_file(
2012     create_tftpfs_path( tftpfs_ipv4_loopback, tftpfs_file ),
2013     /* Bytes read per call to read() */
2014     TFTP_RFC1350_BLOCK_SIZE / 4 * 3,
2015     SIZE_MAX,
2016     &ctx->fd0
2017   );
2018   T_eq_int( errno, EPROTO );
2019   /*
2020    * The client received one packet with TFTP_RFC1350_BLOCK_SIZE
2021    * before the error occurred.  The test reads in chunks of
2022    * TFTP_RFC1350_BLOCK_SIZE /4 * 3.  Thus, after the first chunk
2023    * the client signals the error to the test.
2024    *
2025    * It would be a little improvement if the client would return all
2026    * bytes received before signaling the error.
2027    */
2028   T_eq_int( bytes_read, TFTP_RFC1350_BLOCK_SIZE / 4 * 3 );
2029   T_no_more_interactions();
2030 }
2031 
2032 /*
2033  * Read a file from the server using only RFC1350.
2034  * The file is one data packet long.
2035  * The server sends an error message after the first DATA packet.
2036  * Tests:
2037  *   * The code supports requests without options (RFC1350 only).
2038  *   * The code supports the use of an IPv4 address instead of a server name.
2039  *   * The first packet is sent to standard port 69 of server.
2040  *   * All other packets are sent to the port used for this connection.
2041  *   * The client uses a short time out for all packets.
2042  *   * The client handles error packets from the server and stops the
2043  *     connection by signaling an error to the user on the file system side.
2044  *   * The test reads a file from the file system in chunks of three quarters
2045  *     of the block size.
2046  */
2047 T_TEST_CASE_FIXTURE( read_one_block_file_server_error, &fixture_rfc1350 )
2048 {
2049   tftp_test_context *ctx = T_fixture_context();
2050   int bytes_read;
2051   uint16_t block_num = 1;
2052   size_t pos_in_file = 0;
2053 
2054   /* T_set_verbosity( T_VERBOSE ); */
2055   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
2056   _Tftp_Add_interaction_send_rrq(
2057     TFTP_FIRST_FD,
2058     tftpfs_file,
2059     TFTP_STD_PORT,
2060     tftpfs_ipv4_loopback,
2061     NO_BLOCK_SIZE_OPTION,
2062     NO_WINDOW_SIZE_OPTION,
2063     true
2064   );
2065   _Tftp_Add_interaction_recv_data(
2066     TFTP_FIRST_FD,
2067     FIRST_TIMEOUT_MILLISECONDS,
2068     SERV_PORT,
2069     tftpfs_ipv4_loopback,
2070     block_num,
2071     pos_in_file,
2072     TFTP_RFC1350_BLOCK_SIZE, /* Number of bytes transferred */
2073     get_file_content,
2074     true
2075   );
2076   pos_in_file += TFTP_RFC1350_BLOCK_SIZE;
2077   _Tftp_Add_interaction_send_ack(
2078     TFTP_FIRST_FD,
2079     block_num++,
2080     SERV_PORT,
2081     tftpfs_ipv4_loopback,
2082     true
2083   );
2084   _Tftp_Add_interaction_recv_error(
2085     TFTP_FIRST_FD,
2086     FIRST_TIMEOUT_MILLISECONDS,
2087     SERV_PORT,
2088     tftpfs_ipv4_loopback,
2089     TFTP_ERROR_CODE_NO_ACCESS,
2090     "Cannot read more",
2091     true
2092   );
2093   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
2094 
2095   bytes_read = read_tftp_file(
2096     create_tftpfs_path( tftpfs_ipv4_loopback, tftpfs_file ),
2097     /* Bytes read per call to read() */
2098     TFTP_RFC1350_BLOCK_SIZE / 4 * 3,
2099     SIZE_MAX,
2100     &ctx->fd0
2101   );
2102   T_eq_int( bytes_read, TFTP_RFC1350_BLOCK_SIZE / 4 * 3 );
2103   T_eq_int( errno, EPERM );
2104   T_no_more_interactions();
2105 }
2106 
2107 /*
2108  * Read a file from the server using only RFC1350.
2109  * The file is one data packet long.
2110  * The server sends a malformed error packet after the first DATA packet.
2111  * The error message in the packet is not a 0 terminated string
2112  * Tests:
2113  *   * The code supports requests without options (RFC1350 only).
2114  *   * The code supports the use of an IPv4 address instead of a server name.
2115  *   * The first packet is sent to standard port 69 of server.
2116  *   * All other packets are sent to the port used for this connection.
2117  *   * The client handles malformed errors from the server and does not crash.
2118  *   * The test reads a file from the file system in chunks of three quarters
2119  *     of the block size.
2120  */
2121 T_TEST_CASE_FIXTURE( read_one_block_file_malformed_server_error, &fixture_rfc1350 )
2122 {
2123   tftp_test_context *ctx = T_fixture_context();
2124   int bytes_read;
2125   uint16_t block_num = 1;
2126   size_t pos_in_file = 0;
2127   static const uint8_t packet_malformed_error[] = {
2128   0x00, 0x05, /* Opcode = TFTP_OPCODE_ERROR */
2129   0x00, 0x02, /* Error code = TFTP_ERROR_CODE_NO_ACCESS */
2130   'n', 'o', ' ', 'a', 'c', 'c', 'e', 's', 's' /* missing '\0' at the end */
2131   };
2132 
2133   /* T_set_verbosity( T_VERBOSE ); */
2134   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
2135   _Tftp_Add_interaction_send_rrq(
2136     TFTP_FIRST_FD,
2137     tftpfs_file,
2138     TFTP_STD_PORT,
2139     tftpfs_ipv4_loopback,
2140     NO_BLOCK_SIZE_OPTION,
2141     NO_WINDOW_SIZE_OPTION,
2142     true
2143   );
2144   _Tftp_Add_interaction_recv_data(
2145     TFTP_FIRST_FD,
2146     FIRST_TIMEOUT_MILLISECONDS,
2147     SERV_PORT,
2148     tftpfs_ipv4_loopback,
2149     block_num,
2150     pos_in_file,
2151     TFTP_RFC1350_BLOCK_SIZE, /* Number of bytes transferred */
2152     get_file_content,
2153     true
2154   );
2155   pos_in_file += TFTP_RFC1350_BLOCK_SIZE;
2156   _Tftp_Add_interaction_send_ack(
2157     TFTP_FIRST_FD,
2158     block_num++,
2159     SERV_PORT,
2160     tftpfs_ipv4_loopback,
2161     true
2162   );
2163   _Tftp_Add_interaction_recv_raw(
2164     TFTP_FIRST_FD,
2165     FIRST_TIMEOUT_MILLISECONDS,
2166     SERV_PORT,
2167     tftpfs_ipv4_loopback,
2168     sizeof( packet_malformed_error ), /* Malformed ERROR packet */
2169     packet_malformed_error,
2170     true
2171   );
2172   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
2173 
2174   bytes_read = read_tftp_file(
2175     create_tftpfs_path( tftpfs_ipv4_loopback, tftpfs_file ),
2176     /* Bytes read per call to read() */
2177     TFTP_RFC1350_BLOCK_SIZE / 4 * 3,
2178     SIZE_MAX,
2179     &ctx->fd0
2180   );
2181   T_eq_int( bytes_read, TFTP_RFC1350_BLOCK_SIZE / 4 * 3 );
2182   T_eq_int( errno, EPERM );
2183   T_no_more_interactions();
2184 }
2185 
2186 /*
2187  * Read a file from the server using only RFC1350.
2188  * The reader on the file system side stops after having read half a
2189  * data packet and before having received the whole file and closes the file.
2190  * Tests:
2191  *   * The code supports requests without options (RFC1350 only).
2192  *   * The code supports the use of an IPv4 address instead of a server name.
2193  *   * The first packet is sent to standard port 69 of server.
2194  *   * All other packets are sent to the port used for this connection.
2195  *   * The first data packet is full.
2196  *   * The client handles the closing of the file by the user correctly.
2197  *   * The client sends an error to the server after the user stops reading
2198  *     the file.
2199  *   * The test reads a file from the file system in chunks of block size.
2200  */
2201 T_TEST_CASE_FIXTURE( read_one_block_close_file, &fixture_rfc1350 )
2202 {
2203   tftp_test_context *ctx = T_fixture_context();
2204   int bytes_read;
2205   uint16_t block_num = 1;
2206   size_t pos_in_file = 0;
2207 
2208   /* T_set_verbosity( T_VERBOSE ); */
2209   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
2210   _Tftp_Add_interaction_send_rrq(
2211     TFTP_FIRST_FD,
2212     tftpfs_file,
2213     TFTP_STD_PORT,
2214     tftpfs_ipv4_loopback,
2215     NO_BLOCK_SIZE_OPTION,
2216     NO_WINDOW_SIZE_OPTION,
2217     true
2218   );
2219   _Tftp_Add_interaction_recv_data(
2220     TFTP_FIRST_FD,
2221     FIRST_TIMEOUT_MILLISECONDS,
2222     SERV_PORT,
2223     tftpfs_ipv4_loopback,
2224     block_num,
2225     pos_in_file,
2226     TFTP_RFC1350_BLOCK_SIZE, /* Number of bytes transferred */
2227     get_file_content,
2228     true
2229   );
2230   /* Sending an ACK at this place before the ERROR would be OK, too. */
2231   _Tftp_Add_interaction_send_error(
2232     TFTP_FIRST_FD,
2233     TFTP_ERROR_CODE_NO_USER,
2234     SERV_PORT,
2235     tftpfs_ipv4_loopback,
2236     true
2237   );
2238   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
2239 
2240   bytes_read = read_tftp_file(
2241     create_tftpfs_path( tftpfs_ipv4_loopback, tftpfs_file ),
2242     TFTP_RFC1350_BLOCK_SIZE / 4, /* Bytes read per call to read() */
2243     TFTP_RFC1350_BLOCK_SIZE / 2, /* Max bytes read from this file */
2244     &ctx->fd0
2245   );
2246   T_eq_int( bytes_read, TFTP_RFC1350_BLOCK_SIZE / 2 );
2247   T_no_more_interactions();
2248 }
2249 
2250 /*
2251  * Read a file from the server using only RFC1350.
2252  * The reader on the file system side just open()s and then immediately closes
2253  * the file without ever reading a single byte.
2254  * Tests:
2255  *   * The code supports requests without options (RFC1350 only).
2256  *   * The code supports the use of an IPv4 address instead of a server name.
2257  *   * The first packet is sent to standard port 69 of server.
2258  *   * All other packets are sent to the port used for this connection.
2259  *   * The first data packet is full.
2260  *   * The client handles the closing of the file by the user correctly.
2261  *   * The client sends an error to the server when the user closes the file.
2262  */
2263 T_TEST_CASE_FIXTURE( read_close_file_immediately, &fixture_rfc1350 )
2264 {
2265   tftp_test_context *ctx = T_fixture_context();
2266   int bytes_read;
2267   uint16_t block_num = 1;
2268   size_t pos_in_file = 0;
2269 
2270   /* T_set_verbosity( T_VERBOSE ); */
2271   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
2272   _Tftp_Add_interaction_send_rrq(
2273     TFTP_FIRST_FD,
2274     tftpfs_file,
2275     TFTP_STD_PORT,
2276     tftpfs_ipv4_loopback,
2277     NO_BLOCK_SIZE_OPTION,
2278     NO_WINDOW_SIZE_OPTION,
2279     true
2280   );
2281   _Tftp_Add_interaction_recv_data(
2282     TFTP_FIRST_FD,
2283     FIRST_TIMEOUT_MILLISECONDS,
2284     SERV_PORT,
2285     tftpfs_ipv4_loopback,
2286     block_num,
2287     pos_in_file,
2288     TFTP_RFC1350_BLOCK_SIZE, /* Number of bytes transferred */
2289     get_file_content,
2290     true
2291   );
2292   /* Sending an ACK at this place before the ERROR would be OK, too. */
2293   _Tftp_Add_interaction_send_error(
2294     TFTP_FIRST_FD,
2295     TFTP_ERROR_CODE_NO_USER,
2296     SERV_PORT,
2297     tftpfs_ipv4_loopback,
2298     true
2299   );
2300   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
2301 
2302   bytes_read = read_tftp_file(
2303     create_tftpfs_path( tftpfs_ipv4_loopback, tftpfs_file ),
2304     TFTP_RFC1350_BLOCK_SIZE / 4, /* Bytes read per call to read() */
2305     0, /* Max bytes read from this file */
2306     &ctx->fd0
2307   );
2308   T_eq_int( bytes_read, 0 );
2309   T_no_more_interactions();
2310 }
2311 
2312 /*
2313  * Read an empty file from the server using only RFC1350.
2314  * No timeouts, packet loss, ...
2315  * Tests:
2316  *   * The code supports requests without options (RFC1350 only).
2317  *   * The code supports the use of a server name instead of an IP address.
2318  *   * The first packet is sent to standard port 69 of server.
2319  *   * All other packets are sent to the port used for this connection.
2320  *   * The client uses a short time out for all packets.
2321  *   * The first data packet has length 0.
2322  *   * The client can read empty files from the server.
2323  *   * The test reads a file from the file system in one big chunk which
2324  *     is larger than the file.
2325  */
2326 T_TEST_CASE_FIXTURE( read_empty_file, &fixture_rfc1350 )
2327 {
2328   tftp_test_context *ctx = T_fixture_context();
2329   int bytes_read;
2330   uint16_t block_num = 1;
2331   size_t pos_in_file = 0;
2332 
2333   /* T_set_verbosity( T_VERBOSE ); */
2334   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
2335   _Tftp_Add_interaction_send_rrq(
2336     TFTP_FIRST_FD,
2337     tftpfs_file,
2338     TFTP_STD_PORT,
2339     tftpfs_server0_ipv4,
2340     NO_BLOCK_SIZE_OPTION,
2341     NO_WINDOW_SIZE_OPTION,
2342     true
2343   );
2344   _Tftp_Add_interaction_recv_data(
2345     TFTP_FIRST_FD,
2346     FIRST_TIMEOUT_MILLISECONDS,
2347     SERV_PORT,
2348     tftpfs_server0_ipv4,
2349     block_num,
2350     pos_in_file,
2351     0, /* Number of bytes transferred */
2352     get_file_content,
2353     true
2354   );
2355   _Tftp_Add_interaction_send_ack(
2356     TFTP_FIRST_FD,
2357     block_num++,
2358     SERV_PORT,
2359     tftpfs_server0_ipv4,
2360     true
2361   );
2362   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
2363 
2364   bytes_read = read_tftp_file(
2365     create_tftpfs_path( tftpfs_server0_name, tftpfs_file ),
2366     /* Bytes read per call to read() */
2367     TFTP_RFC1350_BLOCK_SIZE,
2368     SIZE_MAX,
2369     &ctx->fd0
2370   );
2371   T_assert_eq_int( bytes_read, pos_in_file );
2372   T_no_more_interactions();
2373 }
2374 
2375 /*
2376  * Read an empty file from the server using only RFC1350.
2377  * The first two RRQ packets are lost.
2378  * Tests:
2379  *   * The code supports requests without options (RFC1350 only).
2380  *   * The code supports the use of a server name instead of an IP address.
2381  *   * The first packet is sent to standard port 69 of server.
2382  *   * The client uses a short time out for first packets.
2383  *   * The client uses a longer time out for repeated packets.
2384  *   * The client repeats lost RRQs packets.
2385  *   * The client does not repeat the ACK packet for the last DATA packet
2386  *     which signals the end of transfer.
2387  *   * The first data packet is empty and signals the end of the transfer.
2388  *   * It is possible to read a file with 0 bytes content from
2389  *     the file system.
2390  */
2391 T_TEST_CASE_FIXTURE( read_empty_file_looing_rrq, &fixture_rfc1350 )
2392 {
2393   tftp_test_context *ctx = T_fixture_context();
2394   int bytes_read;
2395   uint16_t block_num = 1;
2396   size_t pos_in_file = 0;
2397 
2398   /* T_set_verbosity( T_VERBOSE ); */
2399   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
2400   _Tftp_Add_interaction_send_rrq(
2401     TFTP_FIRST_FD,
2402     tftpfs_file,
2403     TFTP_STD_PORT,
2404     tftpfs_server0_ipv4,
2405     NO_BLOCK_SIZE_OPTION,
2406     NO_WINDOW_SIZE_OPTION,
2407     true
2408   );
2409   _Tftp_Add_interaction_recv_nothing(
2410     TFTP_FIRST_FD, /* Timeout: No packet received within timeout period */
2411     FIRST_TIMEOUT_MILLISECONDS
2412   );
2413   _Tftp_Add_interaction_send_rrq(
2414     TFTP_FIRST_FD,
2415     tftpfs_file,
2416     TFTP_STD_PORT,
2417     tftpfs_server0_ipv4,
2418     NO_BLOCK_SIZE_OPTION,
2419     NO_WINDOW_SIZE_OPTION,
2420     true
2421   );
2422   _Tftp_Add_interaction_recv_nothing(
2423     TFTP_FIRST_FD, /* Timeout: No packet received within timeout period */
2424     TIMEOUT_MILLISECONDS
2425   );
2426   _Tftp_Add_interaction_send_rrq(
2427     TFTP_FIRST_FD,
2428     tftpfs_file,
2429     TFTP_STD_PORT,
2430     tftpfs_server0_ipv4,
2431     NO_BLOCK_SIZE_OPTION,
2432     NO_WINDOW_SIZE_OPTION,
2433     true
2434   );
2435   _Tftp_Add_interaction_recv_data(
2436     TFTP_FIRST_FD,
2437     TIMEOUT_MILLISECONDS,
2438     SERV_PORT,
2439     tftpfs_server0_ipv4,
2440     block_num,
2441     pos_in_file,
2442     0, /* Number of bytes transferred */
2443     get_file_content,
2444     true
2445   );
2446   _Tftp_Add_interaction_send_ack(
2447     TFTP_FIRST_FD,
2448     block_num++,
2449     SERV_PORT,
2450     tftpfs_server0_ipv4,
2451     true
2452   );
2453   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
2454 
2455   bytes_read = read_tftp_file(
2456     create_tftpfs_path( tftpfs_server0_name, tftpfs_file ),
2457     /* Bytes read per call to read() */
2458     TFTP_RFC1350_BLOCK_SIZE,
2459     SIZE_MAX,
2460     &ctx->fd0
2461   );
2462   T_assert_eq_int( bytes_read, pos_in_file );
2463   T_no_more_interactions();
2464 }
2465 
2466 /*
2467  * Read a file from the server using only RFC1350.
2468  * The file is one and a half data packet long.
2469  * Two data packet are lost (timeout) and the client must repeat the ACK.
2470  * Tests:
2471  *   * The code supports requests without options (RFC1350 only).
2472  *   * The code supports the use of an IPv4 address instead of a server name.
2473  *   * The first packet is sent to standard port 69 of server.
2474  *   * The client uses a short time out for first packets.
2475  *   * The client uses a longer time out for repeated packets.
2476  *   * The client repeats the ACK packets which are supposed
2477  *     to be lost.
2478  *   * The client does not repeat the ACK packet for the last DATA packet
2479  *     which signals the end of transfer.
2480  *   * The test reads a file in chunks of 17 bytes from file system.
2481  */
2482 T_TEST_CASE_FIXTURE( read_small_file_lost_packets, &fixture_rfc1350 )
2483 {
2484   tftp_test_context *ctx = T_fixture_context();
2485   int bytes_read;
2486   uint16_t block_num = 1;
2487   size_t pos_in_file = 0;
2488 
2489   /* T_set_verbosity( T_VERBOSE ); */
2490   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
2491   _Tftp_Add_interaction_send_rrq(
2492     TFTP_FIRST_FD,
2493     tftpfs_file,
2494     TFTP_STD_PORT,
2495     tftpfs_ipv4_loopback,
2496     NO_BLOCK_SIZE_OPTION,
2497     NO_WINDOW_SIZE_OPTION,
2498     true
2499   );
2500   _Tftp_Add_interaction_recv_data(
2501     TFTP_FIRST_FD,
2502     FIRST_TIMEOUT_MILLISECONDS,
2503     SERV_PORT,
2504     tftpfs_ipv4_loopback,
2505     block_num,
2506     pos_in_file,
2507     TFTP_RFC1350_BLOCK_SIZE, /* Number of bytes transferred */
2508     get_file_content,
2509     true
2510   );
2511   pos_in_file += TFTP_RFC1350_BLOCK_SIZE;
2512   _Tftp_Add_interaction_send_ack(
2513     TFTP_FIRST_FD,
2514     block_num,
2515     SERV_PORT,
2516     tftpfs_ipv4_loopback,
2517     true
2518   );
2519   _Tftp_Add_interaction_recv_nothing(
2520     TFTP_FIRST_FD, /* Timeout: No packet received within timeout period */
2521     FIRST_TIMEOUT_MILLISECONDS
2522   );
2523   _Tftp_Add_interaction_send_ack(
2524     TFTP_FIRST_FD,
2525     block_num,
2526     SERV_PORT,
2527     tftpfs_ipv4_loopback,
2528     true
2529   );
2530   _Tftp_Add_interaction_recv_nothing(
2531     TFTP_FIRST_FD, /* Timeout: No packet received within timeout period */
2532     TIMEOUT_MILLISECONDS
2533   );
2534   _Tftp_Add_interaction_send_ack(
2535     TFTP_FIRST_FD,
2536     block_num++,
2537     SERV_PORT,
2538     tftpfs_ipv4_loopback,
2539     true
2540   );
2541   _Tftp_Add_interaction_recv_data(
2542     TFTP_FIRST_FD,
2543     TIMEOUT_MILLISECONDS,
2544     SERV_PORT,
2545     tftpfs_ipv4_loopback,
2546     block_num,
2547     pos_in_file,
2548     TFTP_RFC1350_BLOCK_SIZE / 2, /* Number of bytes transferred */
2549     get_file_content,
2550     true
2551   );
2552   pos_in_file += TFTP_RFC1350_BLOCK_SIZE / 2;
2553   _Tftp_Add_interaction_send_ack(
2554     TFTP_FIRST_FD,
2555     block_num++,
2556     SERV_PORT,
2557     tftpfs_ipv4_loopback,
2558     true
2559   );
2560   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
2561 
2562   bytes_read = read_tftp_file(
2563     create_tftpfs_path( tftpfs_ipv4_loopback, tftpfs_file ),
2564     17, /* Bytes read per call to read() */
2565     SIZE_MAX,
2566     &ctx->fd0
2567   );
2568   T_eq_int( bytes_read, pos_in_file );
2569   T_no_more_interactions();
2570 }
2571 
2572 /*
2573  * Read a file from the server using only RFC1350.
2574  * The file is exactly one data packet long.
2575  * The client receives a malformed DATA packet (wrong op code).
2576  * Tests:
2577  *   * The code supports requests without options (RFC1350 only).
2578  *   * The code supports the use of an IPv4 address instead of a server name.
2579  *   * The first packet is sent to standard port 69 of server.
2580  *   * All other packets are sent to the port used for this connection.
2581  *   * The client uses a short time out for all packets.
2582  *   * The first data packet is full.
2583  *   * The client terminates the connection with an error message upon
2584  *     reception of a malformed packet.
2585  */
2586 T_TEST_CASE_FIXTURE( read_small_file_malformed_packet_1, &fixture_rfc1350 )
2587 {
2588   tftp_test_context *ctx = T_fixture_context();
2589   int bytes_read;
2590   uint16_t block_num = 1;
2591   size_t pos_in_file = 0;
2592   static const uint8_t packet_illegal_opcode_1[] = { 0x00, 0xFF, 0x00, 0x00 };
2593 
2594   /* T_set_verbosity( T_VERBOSE ); */
2595   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
2596   _Tftp_Add_interaction_send_rrq(
2597     TFTP_FIRST_FD,
2598     tftpfs_file,
2599     TFTP_STD_PORT,
2600     tftpfs_ipv4_loopback,
2601     NO_BLOCK_SIZE_OPTION,
2602     NO_WINDOW_SIZE_OPTION,
2603     true
2604   );
2605   _Tftp_Add_interaction_recv_data(
2606     TFTP_FIRST_FD,
2607     FIRST_TIMEOUT_MILLISECONDS,
2608     SERV_PORT,
2609     tftpfs_ipv4_loopback,
2610     block_num,
2611     pos_in_file,
2612     TFTP_RFC1350_BLOCK_SIZE, /* Number of bytes transferred */
2613     get_file_content,
2614     true
2615   );
2616   pos_in_file += TFTP_RFC1350_BLOCK_SIZE;
2617   _Tftp_Add_interaction_send_ack(
2618     TFTP_FIRST_FD,
2619     block_num,
2620     SERV_PORT,
2621     tftpfs_ipv4_loopback,
2622     true
2623   );
2624   _Tftp_Add_interaction_recv_raw(
2625     TFTP_FIRST_FD,
2626     FIRST_TIMEOUT_MILLISECONDS,
2627     SERV_PORT,
2628     tftpfs_ipv4_loopback,
2629     sizeof( packet_illegal_opcode_1 ), /* Malformed DATA packet */
2630     packet_illegal_opcode_1,
2631     true
2632   );
2633   _Tftp_Add_interaction_send_error(
2634     TFTP_FIRST_FD,
2635     TFTP_ERROR_CODE_ILLEGAL,
2636     SERV_PORT,
2637     tftpfs_ipv4_loopback,
2638     true
2639   );
2640   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
2641 
2642   bytes_read = read_tftp_file(
2643     create_tftpfs_path( tftpfs_ipv4_loopback, tftpfs_file ),
2644     TFTP_RFC1350_BLOCK_SIZE / 4, /* Bytes read per call to read() */
2645     SIZE_MAX,
2646     &ctx->fd0
2647   );
2648   T_eq_int( bytes_read, pos_in_file );
2649   T_eq_int( errno, EPROTO );
2650   T_no_more_interactions();
2651 }
2652 
2653 /*
2654  * Read a file from the server using only RFC1350.
2655  * The file is exactly one data packet long.
2656  * The client receives a malformed DATA packet (wrong op code).
2657  * Tests:
2658  *   * The code supports requests without options (RFC1350 only).
2659  *   * The code supports the use of an IPv4 address instead of a server name.
2660  *   * The first packet is sent to standard port 69 of server.
2661  *   * All other packets are sent to the port used for this connection.
2662  *   * The first data packet is full.
2663  *   * The second data packet is malformed.
2664  *   * The client terminates the connection with an error message upon
2665  *     reception of a malformed packet.
2666  */
2667 T_TEST_CASE_FIXTURE( read_small_file_malformed_packet_2, &fixture_rfc1350 )
2668 {
2669   tftp_test_context *ctx = T_fixture_context();
2670   int bytes_read;
2671   uint16_t block_num = 1;
2672   size_t pos_in_file = 0;
2673   static const uint8_t packet_illegal_opcode_2[] = { 0x03, 0x00, 0x00, 0x01 };
2674 
2675   /* T_set_verbosity( T_VERBOSE ); */
2676   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
2677   _Tftp_Add_interaction_send_rrq(
2678     TFTP_FIRST_FD,
2679     tftpfs_file,
2680     TFTP_STD_PORT,
2681     tftpfs_ipv4_loopback,
2682     NO_BLOCK_SIZE_OPTION,
2683     NO_WINDOW_SIZE_OPTION,
2684     true
2685   );
2686   _Tftp_Add_interaction_recv_data(
2687     TFTP_FIRST_FD,
2688     FIRST_TIMEOUT_MILLISECONDS,
2689     SERV_PORT,
2690     tftpfs_ipv4_loopback,
2691     block_num,
2692     pos_in_file,
2693     TFTP_RFC1350_BLOCK_SIZE, /* Number of bytes transferred */
2694     get_file_content,
2695     true
2696   );
2697   pos_in_file += TFTP_RFC1350_BLOCK_SIZE;
2698   _Tftp_Add_interaction_send_ack(
2699     TFTP_FIRST_FD,
2700     block_num,
2701     SERV_PORT,
2702     tftpfs_ipv4_loopback,
2703     true
2704   );
2705   _Tftp_Add_interaction_recv_raw(
2706     TFTP_FIRST_FD,
2707     FIRST_TIMEOUT_MILLISECONDS,
2708     SERV_PORT,
2709     tftpfs_ipv4_loopback,
2710     sizeof( packet_illegal_opcode_2 ), /* Malformed DATA packet */
2711     packet_illegal_opcode_2,
2712     true
2713   );
2714   _Tftp_Add_interaction_send_error(
2715     TFTP_FIRST_FD,
2716     TFTP_ERROR_CODE_ILLEGAL,
2717     SERV_PORT,
2718     tftpfs_ipv4_loopback,
2719     true
2720   );
2721   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
2722 
2723   bytes_read = read_tftp_file(
2724     create_tftpfs_path( tftpfs_ipv4_loopback, tftpfs_file ),
2725     TFTP_RFC1350_BLOCK_SIZE / 4, /* Bytes read per call to read() */
2726     SIZE_MAX,
2727     &ctx->fd0
2728   );
2729   T_eq_int( bytes_read, pos_in_file );
2730   T_eq_int( errno, EPROTO );
2731   T_no_more_interactions();
2732 }
2733 
2734 /*
2735  * Read a file from the server using only RFC1350.
2736  * The file is exactly one data packet long.
2737  * The client receives a malformed packet.
2738  * Tests:
2739  *   * The code supports requests without options (RFC1350 only).
2740  *   * The code supports the use of an IPv4 address instead of a server name.
2741  *   * The first packet is sent to standard port 69 of server.
2742  *   * All other packets are sent to the port used for this connection.
2743  *   * The first DATA packet received after the RRQ packet is malformed.
2744  *     It is too short with only one byte length.
2745  *   * The client sends an error and terminates the file transfer upon
2746  *     reception of a malformed packet.
2747  */
2748 T_TEST_CASE_FIXTURE( read_file_malformed_ack_1, &fixture_rfc1350 )
2749 {
2750   tftp_test_context *ctx = T_fixture_context();
2751   int bytes_read;
2752   size_t pos_in_file = 0;
2753   static const uint8_t packet_too_short_1[] = { 0x03 };
2754 
2755   /* T_set_verbosity( T_VERBOSE ); */
2756   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
2757   _Tftp_Add_interaction_send_rrq(
2758     TFTP_FIRST_FD,
2759     tftpfs_file,
2760     TFTP_STD_PORT,
2761     tftpfs_ipv4_loopback,
2762     NO_BLOCK_SIZE_OPTION,
2763     NO_WINDOW_SIZE_OPTION,
2764     true
2765   );
2766   _Tftp_Add_interaction_recv_raw(
2767     TFTP_FIRST_FD,
2768     FIRST_TIMEOUT_MILLISECONDS,
2769     SERV_PORT,
2770     tftpfs_ipv4_loopback,
2771     sizeof( packet_too_short_1 ), /* Malformed DATA packet */
2772     packet_too_short_1,
2773     true
2774   );
2775   _Tftp_Add_interaction_send_error(
2776     TFTP_FIRST_FD,
2777     TFTP_ERROR_CODE_ILLEGAL,
2778     SERV_PORT,
2779     tftpfs_ipv4_loopback,
2780     true
2781   );
2782   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
2783 
2784   bytes_read = read_tftp_file(
2785     create_tftpfs_path( tftpfs_ipv4_loopback, tftpfs_file ),
2786     TFTP_RFC1350_BLOCK_SIZE / 4, /* Bytes read per call to read() */
2787     SIZE_MAX,
2788     &ctx->fd0
2789   );
2790   T_eq_int( bytes_read, pos_in_file );
2791   T_eq_int( errno, EPROTO );
2792   T_no_more_interactions();
2793 }
2794 
2795 /*
2796  * Read a file from the server using only RFC1350.
2797  * The file is exactly one data packet long.
2798  * The client receives a malformed packet.
2799  * Tests:
2800  *   * The code supports requests without options (RFC1350 only).
2801  *   * The code supports the use of an IPv4 address instead of a server name.
2802  *   * The first packet is sent to standard port 69 of server.
2803  *   * All other packets are sent to the port used for this connection.
2804  *   * The first DATA packet received after the RRQ packet is malformed.
2805  *     It is too short with only two bytes length.
2806  *   * The client sends an error and terminates the file transfer upon
2807  *     reception of a malformed packet.
2808  */
2809 T_TEST_CASE_FIXTURE( read_file_malformed_ack_2, &fixture_rfc1350 )
2810 {
2811   tftp_test_context *ctx = T_fixture_context();
2812   int bytes_read;
2813   size_t pos_in_file = 0;
2814   static const uint8_t packet_too_short_2[] = { 0x00, 0x03 };
2815 
2816   /* T_set_verbosity( T_VERBOSE ); */
2817   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
2818   _Tftp_Add_interaction_send_rrq(
2819     TFTP_FIRST_FD,
2820     tftpfs_file,
2821     TFTP_STD_PORT,
2822     tftpfs_ipv4_loopback,
2823     NO_BLOCK_SIZE_OPTION,
2824     NO_WINDOW_SIZE_OPTION,
2825     true
2826   );
2827   _Tftp_Add_interaction_recv_raw(
2828     TFTP_FIRST_FD,
2829     FIRST_TIMEOUT_MILLISECONDS,
2830     SERV_PORT,
2831     tftpfs_ipv4_loopback,
2832     sizeof( packet_too_short_2 ), /* Malformed DATA packet */
2833     packet_too_short_2,
2834     true
2835   );
2836   _Tftp_Add_interaction_send_error(
2837     TFTP_FIRST_FD,
2838     TFTP_ERROR_CODE_ILLEGAL,
2839     SERV_PORT,
2840     tftpfs_ipv4_loopback,
2841     true
2842   );
2843   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
2844 
2845   bytes_read = read_tftp_file(
2846     create_tftpfs_path( tftpfs_ipv4_loopback, tftpfs_file ),
2847     TFTP_RFC1350_BLOCK_SIZE / 4, /* Bytes read per call to read() */
2848     SIZE_MAX,
2849     &ctx->fd0
2850   );
2851   T_eq_int( bytes_read, pos_in_file );
2852   T_eq_int( errno, EPROTO );
2853   T_no_more_interactions();
2854 }
2855 
2856 /*
2857  * Read a file from the server using only RFC1350.
2858  * The file is exactly one data packet long.
2859  * The client receives a malformed packet.
2860  * Tests:
2861  *   * The code supports requests without options (RFC1350 only).
2862  *   * The code supports the use of an IPv4 address instead of a server name.
2863  *   * The first packet is sent to standard port 69 of server.
2864  *   * All other packets are sent to the port used for this connection.
2865  *   * The first DATA packet received after the RRQ packet is malformed.
2866  *     It is too short with only three bytes length.
2867  *   * The client sends an error and terminates the file transfer upon
2868  *     reception of a malformed packet.
2869  */
2870 T_TEST_CASE_FIXTURE( read_file_malformed_ack_3, &fixture_rfc1350 )
2871 {
2872   tftp_test_context *ctx = T_fixture_context();
2873   int bytes_read;
2874   size_t pos_in_file = 0;
2875   static const uint8_t packet_too_short_3[] = { 0x00, 0x03, 0x00 };
2876 
2877   /* T_set_verbosity( T_VERBOSE ); */
2878   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
2879   _Tftp_Add_interaction_send_rrq(
2880     TFTP_FIRST_FD,
2881     tftpfs_file,
2882     TFTP_STD_PORT,
2883     tftpfs_ipv4_loopback,
2884     NO_BLOCK_SIZE_OPTION,
2885     NO_WINDOW_SIZE_OPTION,
2886     true
2887   );
2888   _Tftp_Add_interaction_recv_raw(
2889     TFTP_FIRST_FD,
2890     FIRST_TIMEOUT_MILLISECONDS,
2891     SERV_PORT,
2892     tftpfs_ipv4_loopback,
2893     sizeof( packet_too_short_3 ), /* Malformed DATA packet */
2894     packet_too_short_3,
2895     true
2896   );
2897   _Tftp_Add_interaction_send_error(
2898     TFTP_FIRST_FD,
2899     TFTP_ERROR_CODE_ILLEGAL,
2900     SERV_PORT,
2901     tftpfs_ipv4_loopback,
2902     true
2903   );
2904   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
2905 
2906   bytes_read = read_tftp_file(
2907     create_tftpfs_path( tftpfs_ipv4_loopback, tftpfs_file ),
2908     TFTP_RFC1350_BLOCK_SIZE / 4, /* Bytes read per call to read() */
2909     SIZE_MAX,
2910     &ctx->fd0
2911   );
2912   T_eq_int( bytes_read, pos_in_file );
2913   T_eq_int( errno, EPROTO );
2914   T_no_more_interactions();
2915 }
2916 
2917 /*
2918  * Read a file from the server using only RFC1350.
2919  * The file is exactly one data packet long.
2920  * The client receives a data packet with block number 0.
2921  * Tests:
2922  *   * The code supports requests without options (RFC1350 only).
2923  *   * The code supports the use of an IPv4 address instead of a server name.
2924  *   * The first packet is sent to standard port 69 of server.
2925  *   * All other packets are sent to the port used for this connection.
2926  *   * The first DATA packet received after the RRQ packet is malformed.
2927  *     It has block number 0.
2928  *   * The client sends an error and terminates the file transfer upon
2929  *     reception of a malformed packet.
2930  */
2931 T_TEST_CASE_FIXTURE( read_file_block_number_0, &fixture_rfc1350 )
2932 {
2933   tftp_test_context *ctx = T_fixture_context();
2934   int bytes_read;
2935   size_t pos_in_file = 0;
2936 
2937   /* T_set_verbosity( T_VERBOSE ); */
2938   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
2939   _Tftp_Add_interaction_send_rrq(
2940     TFTP_FIRST_FD,
2941     tftpfs_file,
2942     TFTP_STD_PORT,
2943     tftpfs_ipv4_loopback,
2944     NO_BLOCK_SIZE_OPTION,
2945     NO_WINDOW_SIZE_OPTION,
2946     true
2947   );
2948   _Tftp_Add_interaction_recv_data(
2949     TFTP_FIRST_FD,
2950     FIRST_TIMEOUT_MILLISECONDS,
2951     SERV_PORT,
2952     tftpfs_ipv4_loopback,
2953     0, /* Wrong block number 0 */
2954     pos_in_file,
2955     TFTP_RFC1350_BLOCK_SIZE, /* Number of bytes transferred */
2956     get_file_content,
2957     true
2958   );
2959   _Tftp_Add_interaction_send_error(
2960     TFTP_FIRST_FD,
2961     TFTP_ERROR_CODE_ILLEGAL,
2962     SERV_PORT,
2963     tftpfs_ipv4_loopback,
2964     true
2965   );
2966   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
2967 
2968   bytes_read = read_tftp_file(
2969     create_tftpfs_path( tftpfs_ipv4_loopback, tftpfs_file ),
2970     TFTP_RFC1350_BLOCK_SIZE / 4, /* Bytes read per call to read() */
2971     SIZE_MAX,
2972     &ctx->fd0
2973   );
2974   T_eq_int( bytes_read, pos_in_file );
2975   T_eq_int( errno, EPROTO );
2976   T_no_more_interactions();
2977 }
2978 
2979 /*
2980  * Read a file from the server using only RFC1350.
2981  * The file is exactly one data packet long.
2982  * The client receives a malformed packet.
2983  * Tests:
2984  *   * The code supports requests without options (RFC1350 only).
2985  *   * The code supports the use of an IPv4 address instead of a server name.
2986  *   * The first packet is sent to standard port 69 of server.
2987  *   * All other packets are sent to the port used for this connection.
2988  *   * The first DATA packet received after the RRQ packet is malformed.
2989  *     The packet contains an illegal op code.
2990  *   * The client sends an error and terminates the file transfer upon
2991  *     reception of a malformed packet.
2992  */
2993 T_TEST_CASE_FIXTURE( read_file_illegal_opcode_1, &fixture_rfc1350 )
2994 {
2995   tftp_test_context *ctx = T_fixture_context();
2996   int bytes_read;
2997   size_t pos_in_file = 0;
2998   static const uint8_t packet_illegal_opcode_1[] = { 0x00, 0xFF, 0x00, 0x00 };
2999 
3000   /* T_set_verbosity( T_VERBOSE ); */
3001   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
3002   _Tftp_Add_interaction_send_rrq(
3003     TFTP_FIRST_FD,
3004     tftpfs_file,
3005     TFTP_STD_PORT,
3006     tftpfs_ipv4_loopback,
3007     NO_BLOCK_SIZE_OPTION,
3008     NO_WINDOW_SIZE_OPTION,
3009     true
3010   );
3011   _Tftp_Add_interaction_recv_raw(
3012     TFTP_FIRST_FD,
3013     FIRST_TIMEOUT_MILLISECONDS,
3014     SERV_PORT,
3015     tftpfs_ipv4_loopback,
3016     sizeof( packet_illegal_opcode_1 ), /* Malformed DATA packet */
3017     packet_illegal_opcode_1,
3018     true
3019   );
3020   _Tftp_Add_interaction_send_error(
3021     TFTP_FIRST_FD,
3022     TFTP_ERROR_CODE_ILLEGAL,
3023     SERV_PORT,
3024     tftpfs_ipv4_loopback,
3025     true
3026   );
3027   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
3028 
3029   bytes_read = read_tftp_file(
3030     create_tftpfs_path( tftpfs_ipv4_loopback, tftpfs_file ),
3031     TFTP_RFC1350_BLOCK_SIZE / 4, /* Bytes read per call to read() */
3032     SIZE_MAX,
3033     &ctx->fd0
3034   );
3035   T_eq_int( bytes_read, pos_in_file );
3036   T_eq_int( errno, EPROTO );
3037   T_no_more_interactions();
3038 }
3039 
3040 /*
3041  * Read a file from the server using only RFC1350.
3042  * The file is exactly two data packet long.
3043  * The client receives DATA packets with wrong block numbers.
3044  * Tests:
3045  *   * The code supports requests without options (RFC1350 only).
3046  *   * The code supports the use of an IPv4 address instead of a server name.
3047  *   * The first packet is sent to standard port 69 of server.
3048  *   * The second RRQ is sent to the TFTP server port 69 and not to the
3049  *     port from which the first packet with the wrong block number came from.
3050  *   * The client uses a short time out for all packets.
3051  *   * The client uses a longer time out for repeated packets.
3052  *   * The client handles DATA packets with the wrong block numbers
3053  *     appropriately.
3054  *   * The third data packet is empty and signals the end of the transfer.
3055  *   * Old data packets are ignored (i.e. do not cause a retransmission).
3056  *   * Duplicates of the last data packet cause a retransmission of the
3057  *     last ACK.
3058  *   * The first data packet with a block number larger than the expected one,
3059  *     cause a retransmission of ACK or RRQ.  (They can appear together
3060  *     with the windowsize option.)
3061  *   * The test reads a file from the file system in one big chunk with is larger
3062  *     than the files size.
3063  */
3064 T_TEST_CASE_FIXTURE( read_two_block_file_wrong_block_numbers, &fixture_rfc1350 )
3065 {
3066   tftp_test_context *ctx = T_fixture_context();
3067   int bytes_read;
3068   uint16_t block_num = 1;
3069   size_t pos_in_file = 0;
3070 
3071   /* T_set_verbosity( T_VERBOSE ); */
3072   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
3073   _Tftp_Add_interaction_send_rrq(
3074     TFTP_FIRST_FD,
3075     tftpfs_file,
3076     TFTP_STD_PORT,
3077     tftpfs_ipv4_loopback,
3078     NO_BLOCK_SIZE_OPTION,
3079     NO_WINDOW_SIZE_OPTION,
3080     true
3081   );
3082   _Tftp_Add_interaction_recv_data(
3083     TFTP_FIRST_FD,
3084     FIRST_TIMEOUT_MILLISECONDS,
3085     SERV_PORT,
3086     tftpfs_ipv4_loopback,
3087     block_num + 1, /* Wrong block number */
3088     pos_in_file,
3089     TFTP_RFC1350_BLOCK_SIZE, /* Number of bytes transferred */
3090     get_file_content,
3091     true
3092   );
3093   _Tftp_Add_interaction_send_rrq(
3094     TFTP_FIRST_FD,
3095     tftpfs_file,
3096     TFTP_STD_PORT,
3097     tftpfs_ipv4_loopback,
3098     NO_BLOCK_SIZE_OPTION,
3099     NO_WINDOW_SIZE_OPTION,
3100     true
3101   );
3102   _Tftp_Add_interaction_recv_data(
3103     TFTP_FIRST_FD,
3104     FIRST_TIMEOUT_MILLISECONDS,
3105     SERV_PORT,
3106     tftpfs_ipv4_loopback,
3107     block_num + 1, /* Wrong block number */
3108     pos_in_file,
3109     TFTP_RFC1350_BLOCK_SIZE, /* Number of bytes transferred */
3110     get_file_content,
3111     true
3112   );
3113   _Tftp_Add_interaction_recv_data(
3114     TFTP_FIRST_FD,
3115     FIRST_TIMEOUT_MILLISECONDS,
3116     SERV_PORT,
3117     tftpfs_ipv4_loopback,
3118     block_num,
3119     pos_in_file,
3120     TFTP_RFC1350_BLOCK_SIZE, /* Number of bytes transferred */
3121     get_file_content,
3122     true
3123   );
3124   pos_in_file += TFTP_RFC1350_BLOCK_SIZE;
3125   _Tftp_Add_interaction_send_ack(
3126     TFTP_FIRST_FD,
3127     block_num++,
3128     SERV_PORT,
3129     tftpfs_ipv4_loopback,
3130     true
3131   );
3132   _Tftp_Add_interaction_recv_data(
3133     TFTP_FIRST_FD,
3134     FIRST_TIMEOUT_MILLISECONDS,
3135     SERV_PORT,
3136     tftpfs_ipv4_loopback,
3137     block_num - 1, /*  Wrong block number / duplicates last packet */
3138     pos_in_file,
3139     TFTP_RFC1350_BLOCK_SIZE, /* Number of bytes transferred */
3140     get_file_content,
3141     true
3142   );
3143   _Tftp_Add_interaction_send_ack(
3144     TFTP_FIRST_FD,
3145     block_num - 1, /* Client assumes last ACK got lost and retransmits it. */
3146     SERV_PORT,
3147     tftpfs_ipv4_loopback,
3148     true
3149   );
3150   _Tftp_Add_interaction_recv_data(
3151     TFTP_FIRST_FD,
3152     FIRST_TIMEOUT_MILLISECONDS,
3153     SERV_PORT,
3154     tftpfs_ipv4_loopback,
3155     block_num + 1, /*  Wrong block number */
3156     pos_in_file,
3157     TFTP_RFC1350_BLOCK_SIZE, /* Number of bytes transferred */
3158     get_file_content,
3159     true
3160   );
3161   _Tftp_Add_interaction_send_ack(
3162     TFTP_FIRST_FD,
3163     block_num - 1, /* Client assumes last ACK got lost and retransmits it. */
3164     SERV_PORT,
3165     tftpfs_ipv4_loopback,
3166     true
3167   );
3168   _Tftp_Add_interaction_recv_data(
3169     TFTP_FIRST_FD,
3170     FIRST_TIMEOUT_MILLISECONDS,
3171     SERV_PORT,
3172     tftpfs_ipv4_loopback,
3173     block_num + 1, /*  Wrong block number */
3174     pos_in_file,
3175     TFTP_RFC1350_BLOCK_SIZE, /* Number of bytes transferred */
3176     get_file_content,
3177     true
3178   );
3179   _Tftp_Add_interaction_recv_data(
3180     TFTP_FIRST_FD,
3181     FIRST_TIMEOUT_MILLISECONDS,
3182     SERV_PORT,
3183     tftpfs_ipv4_loopback,
3184     block_num,
3185     pos_in_file,
3186     TFTP_RFC1350_BLOCK_SIZE, /* Number of bytes transferred */
3187     get_file_content,
3188     true
3189   );
3190   pos_in_file += TFTP_RFC1350_BLOCK_SIZE;
3191   _Tftp_Add_interaction_send_ack(
3192     TFTP_FIRST_FD,
3193     block_num++,
3194     SERV_PORT,
3195     tftpfs_ipv4_loopback,
3196     true
3197   );
3198   _Tftp_Add_interaction_recv_data(
3199     TFTP_FIRST_FD,
3200     FIRST_TIMEOUT_MILLISECONDS,
3201     SERV_PORT,
3202     tftpfs_ipv4_loopback,
3203     block_num - 2, /*  Wrong block number */
3204     pos_in_file,
3205     TFTP_RFC1350_BLOCK_SIZE, /* Number of bytes transferred */
3206     get_file_content,
3207     true
3208   );
3209   _Tftp_Add_interaction_recv_data(
3210     TFTP_FIRST_FD,
3211     FIRST_TIMEOUT_MILLISECONDS,
3212     SERV_PORT,
3213     tftpfs_ipv4_loopback,
3214     block_num + 1, /*  Wrong block number */
3215     pos_in_file,
3216     TFTP_RFC1350_BLOCK_SIZE, /* Number of bytes transferred */
3217     get_file_content,
3218     true
3219   );
3220   _Tftp_Add_interaction_send_ack(
3221     TFTP_FIRST_FD,
3222     block_num - 1, /* Client assumes last ACK got lost and retransmits it. */
3223     SERV_PORT,
3224     tftpfs_ipv4_loopback,
3225     true
3226   );
3227   _Tftp_Add_interaction_recv_data(
3228     TFTP_FIRST_FD,
3229     FIRST_TIMEOUT_MILLISECONDS,
3230     SERV_PORT,
3231     tftpfs_ipv4_loopback,
3232     block_num,
3233     pos_in_file,
3234     0, /* Number of bytes transferred */
3235     get_file_content,
3236     true
3237   );
3238   _Tftp_Add_interaction_send_ack(
3239     TFTP_FIRST_FD,
3240     block_num++,
3241     SERV_PORT,
3242     tftpfs_ipv4_loopback,
3243     true
3244   );
3245   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
3246 
3247   bytes_read = read_tftp_file(
3248     create_tftpfs_path( tftpfs_ipv4_loopback, tftpfs_file ),
3249     /* Bytes read per call to read() */
3250     3 * TFTP_RFC1350_BLOCK_SIZE,
3251     SIZE_MAX,
3252     &ctx->fd0
3253   );
3254   T_eq_int( bytes_read, pos_in_file );
3255   T_no_more_interactions();
3256 }
3257 
3258 /*
3259  * Attempt to read a file from the server using filename without ':'.
3260  * Tests:
3261  *   * The TFTP FS rejects malformed file names (i.e. it does not crash).
3262  */
3263 T_TEST_CASE_FIXTURE( read_malformed_filename, &fixture_rfc1350 )
3264 {
3265   tftp_test_context *ctx = T_fixture_context();
3266   int bytes_read;
3267   char buffer[100];
3268   int len;
3269 
3270   len = snprintf(
3271     buffer,
3272     sizeof( buffer ),
3273     "%s/%s",
3274     tftpfs_mount_point,
3275     tftpfs_server0_name
3276   );
3277 
3278   T_quiet_gt_int( len, 0 );
3279   T_quiet_lt_int( len, (int) sizeof( buffer ) );
3280 
3281   bytes_read = read_tftp_file(
3282     buffer,
3283     /* Bytes read per call to read() */
3284     TFTP_RFC1350_BLOCK_SIZE,
3285     SIZE_MAX,
3286     &ctx->fd0
3287   );
3288   T_assert_eq_int( bytes_read, 0 );
3289   T_assert_eq_int( errno, EINVAL );
3290 }
3291 
3292 /*
3293  * Attempt to read a file from a none exiting server address.
3294  * Tests:
3295  *   * TFTP FS returns an error if the server name cannot be resolved.
3296  */
3297 T_TEST_CASE_FIXTURE( read_from_unknown_ip_address, &fixture_rfc1350 )
3298 {
3299   tftp_test_context *ctx = T_fixture_context();
3300   int bytes_read;
3301 
3302   bytes_read = read_tftp_file(
3303     create_tftpfs_path( "not-existing-server-address", tftpfs_file ),
3304     /* Bytes read per call to read() */
3305     TFTP_RFC1350_BLOCK_SIZE,
3306     SIZE_MAX,
3307     &ctx->fd0
3308   );
3309   T_assert_eq_int( bytes_read, 0 );
3310   T_assert_eq_int( errno, ENOENT );
3311 }
3312 
3313 /*
3314  * Attempt to read a file which the server does not know
3315  * No timeouts, packet loss, ...
3316  * Tests:
3317  *   * The code supports requests without options (RFC1350 only).
3318  *   * The code supports the use of a server name instead of an IP address.
3319  *   * The client handles an ERROR packet received upon sending an RRQ
3320  *     correctly.
3321  *   * TFTP FS returns an error upon the reception of the ERROR packet.
3322  */
3323 T_TEST_CASE_FIXTURE( read_not_existing_file, &fixture_rfc1350 )
3324 {
3325   tftp_test_context *ctx = T_fixture_context();
3326   int bytes_read;
3327 
3328   /* T_set_verbosity( T_VERBOSE ); */
3329   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
3330   _Tftp_Add_interaction_send_rrq(
3331     TFTP_FIRST_FD,
3332     tftpfs_file,
3333     TFTP_STD_PORT,
3334     tftpfs_server0_ipv4,
3335     NO_BLOCK_SIZE_OPTION,
3336     NO_WINDOW_SIZE_OPTION,
3337     true
3338   );
3339   _Tftp_Add_interaction_recv_error(
3340     TFTP_FIRST_FD,
3341     FIRST_TIMEOUT_MILLISECONDS,
3342     SERV_PORT,
3343     tftpfs_server0_ipv4,
3344     TFTP_ERROR_CODE_NOT_FOUND,
3345     "No such file",
3346     true
3347   );
3348   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
3349 
3350   bytes_read = read_tftp_file(
3351     create_tftpfs_path( tftpfs_server0_name, tftpfs_file ),
3352     /* Bytes read per call to read() */
3353     TFTP_RFC1350_BLOCK_SIZE,
3354     SIZE_MAX,
3355     &ctx->fd0
3356   );
3357   T_assert_eq_int( bytes_read, 0 );
3358   T_assert_eq_int( errno, ENOENT );
3359   T_no_more_interactions();
3360 }
3361 
3362 /*
3363  * Write an empty file to the server using only RFC1350.
3364  * The first two WRQ as well as the first two DATA packets are lost.
3365  * Tests:
3366  *   * The code supports requests without options (RFC1350 only).
3367  *   * The code supports the use of a server name instead of an IP address.
3368  *   * The all WRQ are sent to standard port 69 of server.
3369  *   * All other packets are sent to the port used for this connection.
3370  *   * The client uses a short time out for first packets.
3371  *   * The client uses a longer time out for repeated packets.
3372  *   * The client repeats the WRQs and DATA packets which are supposed
3373  *     to be lost.
3374  *   * When a timeout occurs, the client repeats the last and empty packet.
3375  *   * The first data packet is empty and signals the end of the transfer.
3376  *   * The test writes a file with 0 bytes content to the file system.
3377  */
3378 T_TEST_CASE_FIXTURE( write_empty_file_packet_losts, &fixture_rfc1350 )
3379 {
3380   tftp_test_context *ctx = T_fixture_context();
3381   int bytes_written;
3382   uint16_t block_num = 0;
3383   size_t pos_in_file = 0;
3384 
3385   /* T_set_verbosity( T_VERBOSE ); */
3386   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
3387   _Tftp_Add_interaction_send_wrq(
3388     TFTP_FIRST_FD,
3389     tftpfs_file,
3390     TFTP_STD_PORT,
3391     tftpfs_server0_ipv4,
3392     NO_BLOCK_SIZE_OPTION,
3393     NO_WINDOW_SIZE_OPTION,
3394     true
3395   );
3396   _Tftp_Add_interaction_recv_nothing(
3397     TFTP_FIRST_FD, /* Timeout: No packet received within timeout period */
3398     FIRST_TIMEOUT_MILLISECONDS
3399   );
3400   _Tftp_Add_interaction_send_wrq(
3401     TFTP_FIRST_FD,
3402     tftpfs_file,
3403     TFTP_STD_PORT,
3404     tftpfs_server0_ipv4,
3405     NO_BLOCK_SIZE_OPTION,
3406     NO_WINDOW_SIZE_OPTION,
3407     true
3408   );
3409   _Tftp_Add_interaction_recv_nothing(
3410     TFTP_FIRST_FD, /* Timeout: No packet received within timeout period */
3411     TIMEOUT_MILLISECONDS
3412   );
3413   _Tftp_Add_interaction_send_wrq(
3414     TFTP_FIRST_FD,
3415     tftpfs_file,
3416     TFTP_STD_PORT,
3417     tftpfs_server0_ipv4,
3418     NO_BLOCK_SIZE_OPTION,
3419     NO_WINDOW_SIZE_OPTION,
3420     true
3421   );
3422   _Tftp_Add_interaction_recv_ack(
3423     TFTP_FIRST_FD,
3424     TIMEOUT_MILLISECONDS,
3425     SERV_PORT,
3426     tftpfs_server0_ipv4,
3427     block_num++,
3428     true
3429   );
3430   _Tftp_Add_interaction_send_data(
3431     TFTP_FIRST_FD,
3432     block_num,
3433     pos_in_file,
3434     0, /* Number of bytes transferred */
3435     get_file_content,
3436     SERV_PORT,
3437     tftpfs_server0_ipv4,
3438     true
3439   );
3440   _Tftp_Add_interaction_recv_nothing(
3441     TFTP_FIRST_FD, /* Timeout: No packet received within timeout period */
3442     FIRST_TIMEOUT_MILLISECONDS
3443   );
3444   _Tftp_Add_interaction_send_data(
3445     TFTP_FIRST_FD,
3446     block_num,
3447     pos_in_file,
3448     0, /* Number of bytes transferred */
3449     get_file_content,
3450     SERV_PORT,
3451     tftpfs_server0_ipv4,
3452     true
3453   );
3454   _Tftp_Add_interaction_recv_nothing(
3455     TFTP_FIRST_FD, /* Timeout: No packet received within timeout period */
3456     TIMEOUT_MILLISECONDS
3457   );
3458   _Tftp_Add_interaction_send_data(
3459     TFTP_FIRST_FD,
3460     block_num,
3461     pos_in_file,
3462     0, /* Number of bytes transferred */
3463     get_file_content,
3464     SERV_PORT,
3465     tftpfs_server0_ipv4,
3466     true
3467   );
3468   _Tftp_Add_interaction_recv_ack(
3469     TFTP_FIRST_FD,
3470     TIMEOUT_MILLISECONDS,
3471     SERV_PORT,
3472     tftpfs_server0_ipv4,
3473     block_num++,
3474     true
3475   );
3476   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
3477 
3478   bytes_written = write_tftp_file(
3479     create_tftpfs_path( tftpfs_server0_name, tftpfs_file ),
3480     0, /* Size of file */
3481     4, /* Bytes written per call to write() */
3482     &ctx->fd0
3483   );
3484   T_eq_int( bytes_written, pos_in_file );
3485   T_no_more_interactions();
3486 }
3487 
3488 /*
3489  * Write a very short file to the server using only RFC1350.
3490  * The file is one and half data packets long.
3491  * The first two DATA packets and one ACK packet are lost.
3492  * Tests:
3493  *   * The code supports requests without options (RFC1350 only).
3494  *   * The code supports the use of a server name instead of an IP address.
3495  *   * The first packet is sent to standard port 69 of server.
3496  *   * All other packets are sent to the port used for this connection.
3497  *   * The client uses a short time out for first packets.
3498  *   * The client uses a longer time out for repeated packets.
3499  *   * The client repeats sending DATA packets which are supposed
3500  *     to be lost.
3501  *   * The client also repeats the last DATA packet when it is supposed
3502  *     to be lost.
3503  *   * The client repeats sending DATA packets when an ACK packet is repeated
3504  *     (presumably the DATA packet has been lost).
3505  *   * The test writes a file to the file system in chunks of a quarter of the block size.
3506  */
3507 T_TEST_CASE_FIXTURE( write_tiny_file_packet_losts, &fixture_rfc1350 )
3508 {
3509   tftp_test_context *ctx = T_fixture_context();
3510   int bytes_written;
3511   uint16_t block_num = 0;
3512   size_t pos_in_file = 0;
3513 
3514   /* T_set_verbosity( T_VERBOSE ); */
3515   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
3516   _Tftp_Add_interaction_send_wrq(
3517     TFTP_FIRST_FD,
3518     tftpfs_file,
3519     TFTP_STD_PORT,
3520     tftpfs_server0_ipv4,
3521     NO_BLOCK_SIZE_OPTION,
3522     NO_WINDOW_SIZE_OPTION,
3523     true
3524   );
3525   _Tftp_Add_interaction_recv_ack(
3526     TFTP_FIRST_FD,
3527     FIRST_TIMEOUT_MILLISECONDS,
3528     SERV_PORT,
3529     tftpfs_server0_ipv4,
3530     block_num++,
3531     true
3532   );
3533   _Tftp_Add_interaction_send_data(
3534     TFTP_FIRST_FD,
3535     block_num,
3536     pos_in_file,
3537     TFTP_RFC1350_BLOCK_SIZE,
3538     get_file_content,
3539     SERV_PORT,
3540     tftpfs_server0_ipv4,
3541     true
3542   );
3543   _Tftp_Add_interaction_recv_nothing(
3544     TFTP_FIRST_FD, /* Timeout: No packet received within timeout period */
3545     FIRST_TIMEOUT_MILLISECONDS
3546   );
3547   _Tftp_Add_interaction_send_data(
3548     TFTP_FIRST_FD,
3549     block_num,
3550     pos_in_file,
3551     TFTP_RFC1350_BLOCK_SIZE,
3552     get_file_content,
3553     SERV_PORT,
3554     tftpfs_server0_ipv4,
3555     true
3556   );
3557   _Tftp_Add_interaction_recv_nothing(
3558     TFTP_FIRST_FD, /* Timeout: No packet received within timeout period */
3559     TIMEOUT_MILLISECONDS
3560   );
3561   _Tftp_Add_interaction_send_data(
3562     TFTP_FIRST_FD,
3563     block_num,
3564     pos_in_file,
3565     TFTP_RFC1350_BLOCK_SIZE,
3566     get_file_content,
3567     SERV_PORT,
3568     tftpfs_server0_ipv4,
3569     true
3570   );
3571   _Tftp_Add_interaction_recv_ack(
3572     TFTP_FIRST_FD,
3573     TIMEOUT_MILLISECONDS,
3574     SERV_PORT,
3575     tftpfs_server0_ipv4,
3576     block_num++,
3577     true
3578   );
3579   pos_in_file += TFTP_RFC1350_BLOCK_SIZE;
3580   _Tftp_Add_interaction_send_data(
3581     TFTP_FIRST_FD,
3582     block_num,
3583     pos_in_file,
3584     TFTP_RFC1350_BLOCK_SIZE / 2,
3585     get_file_content,
3586     SERV_PORT,
3587     tftpfs_server0_ipv4,
3588     true
3589   );
3590   _Tftp_Add_interaction_recv_ack(
3591     TFTP_FIRST_FD,
3592     FIRST_TIMEOUT_MILLISECONDS,
3593     SERV_PORT,
3594     tftpfs_server0_ipv4,
3595     block_num - 1, /* Repeated ACK packet received */
3596     true
3597   );
3598   _Tftp_Add_interaction_send_data(
3599     TFTP_FIRST_FD,
3600     block_num,
3601     pos_in_file,
3602     TFTP_RFC1350_BLOCK_SIZE / 2,
3603     get_file_content,
3604     SERV_PORT,
3605     tftpfs_server0_ipv4,
3606     true
3607   );
3608   pos_in_file += TFTP_RFC1350_BLOCK_SIZE / 2;
3609   _Tftp_Add_interaction_recv_ack(
3610     TFTP_FIRST_FD,
3611     FIRST_TIMEOUT_MILLISECONDS,
3612     SERV_PORT,
3613     tftpfs_server0_ipv4,
3614     block_num++,
3615     true
3616   );
3617   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
3618 
3619   bytes_written = write_tftp_file(
3620     create_tftpfs_path( tftpfs_server0_name, tftpfs_file ),
3621     TFTP_RFC1350_BLOCK_SIZE / 2 * 3, /* Size of file */
3622     TFTP_RFC1350_BLOCK_SIZE / 4, /* Bytes written per call to write() */
3623     &ctx->fd0
3624   );
3625   T_eq_int( bytes_written, pos_in_file );
3626   T_no_more_interactions();
3627 }
3628 
3629 /*
3630  * Write a file to the server using only RFC1350.
3631  * The file is 2 data packet and 1 byte long.  No timeouts, packet loss, ...
3632  * Tests:
3633  *   * The code supports requests without options (RFC1350 only).
3634  *   * The code supports the use of an IPv4 address instead of a server name.
3635  *   * The first packet is sent to standard port 69 of server.
3636  *   * All other packets are sent to the port used for this connection.
3637  *   * First and second data packet is full.
3638  *   * Third data packet signals the end of transfer.
3639  *   * The test writes a file to the file system in one big chunk
3640  *     of exactly the files size.
3641  */
3642 T_TEST_CASE_FIXTURE( write_simple_file, &fixture_rfc1350 )
3643 {
3644   tftp_test_context *ctx = T_fixture_context();
3645   int bytes_written;
3646   uint16_t block_num = 0;
3647   size_t pos_in_file = 0;
3648 
3649   /* T_set_verbosity( T_VERBOSE ); */
3650   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
3651   _Tftp_Add_interaction_send_wrq(
3652     TFTP_FIRST_FD,
3653     tftpfs_file,
3654     TFTP_STD_PORT,
3655     tftpfs_ipv4_loopback,
3656     NO_BLOCK_SIZE_OPTION,
3657     NO_WINDOW_SIZE_OPTION,
3658     true
3659   );
3660   _Tftp_Add_interaction_recv_ack(
3661     TFTP_FIRST_FD,
3662     FIRST_TIMEOUT_MILLISECONDS,
3663     SERV_PORT,
3664     tftpfs_ipv4_loopback,
3665     block_num++,
3666     true
3667   );
3668   _Tftp_Add_interaction_send_data(
3669     TFTP_FIRST_FD,
3670     block_num,
3671     pos_in_file,
3672     TFTP_RFC1350_BLOCK_SIZE,
3673     get_file_content,
3674     SERV_PORT,
3675     tftpfs_ipv4_loopback,
3676     true
3677   );
3678   pos_in_file += TFTP_RFC1350_BLOCK_SIZE;
3679   _Tftp_Add_interaction_recv_ack(
3680     TFTP_FIRST_FD,
3681     FIRST_TIMEOUT_MILLISECONDS,
3682     SERV_PORT,
3683     tftpfs_ipv4_loopback,
3684     block_num++,
3685     true
3686   );
3687   _Tftp_Add_interaction_send_data(
3688     TFTP_FIRST_FD,
3689     block_num,
3690     pos_in_file,
3691     TFTP_RFC1350_BLOCK_SIZE,
3692     get_file_content,
3693     SERV_PORT,
3694     tftpfs_ipv4_loopback,
3695     true
3696   );
3697   pos_in_file += TFTP_RFC1350_BLOCK_SIZE;
3698   _Tftp_Add_interaction_recv_ack(
3699     TFTP_FIRST_FD,
3700     FIRST_TIMEOUT_MILLISECONDS,
3701     SERV_PORT,
3702     tftpfs_ipv4_loopback,
3703     block_num++,
3704     true
3705   );
3706   _Tftp_Add_interaction_send_data(
3707     TFTP_FIRST_FD,
3708     block_num,
3709     pos_in_file,
3710     1, /* Data bytes in this block */
3711     get_file_content,
3712     SERV_PORT,
3713     tftpfs_ipv4_loopback,
3714     true
3715   );
3716   pos_in_file += 1;
3717   _Tftp_Add_interaction_recv_ack(
3718     TFTP_FIRST_FD,
3719     FIRST_TIMEOUT_MILLISECONDS,
3720     SERV_PORT,
3721     tftpfs_ipv4_loopback,
3722     block_num++,
3723     true
3724   );
3725   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
3726 
3727   bytes_written = write_tftp_file(
3728     create_tftpfs_path( tftpfs_ipv4_loopback, tftpfs_file ),
3729     pos_in_file, /* Size of file */
3730     pos_in_file, /* Bytes written per call to write() */
3731     &ctx->fd0
3732   );
3733   T_eq_int( bytes_written, pos_in_file );
3734   T_no_more_interactions();
3735 }
3736 
3737 /*
3738  * Write a file to the server using only RFC1350.
3739  * As response to the first DATA packet, the server sends an error packet.
3740  * Tests:
3741  *   * The code supports requests without options (RFC1350 only).
3742  *   * The code supports the use of an IPv4 address instead of a server name.
3743  *   * The first packet is sent to standard port 69 of server.
3744  *   * All other packets are sent to the port used for this connection.
3745  *   * The first data packet is full.
3746  *   * The second packet from the server is an error packet.
3747  *   * The TFTP client ends the connection after receiving an error packet.
3748  *   * The test writes a file to the file system with a call to write()
3749  *     for each byte.
3750  */
3751 T_TEST_CASE_FIXTURE( write_simple_file_disk_full, &fixture_rfc1350 )
3752 {
3753   tftp_test_context *ctx = T_fixture_context();
3754   int bytes_written;
3755   uint16_t block_num = 0;
3756   size_t pos_in_file = 0;
3757 
3758   /* T_set_verbosity( T_VERBOSE ); */
3759   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
3760   _Tftp_Add_interaction_send_wrq(
3761     TFTP_FIRST_FD,
3762     tftpfs_file,
3763     TFTP_STD_PORT,
3764     tftpfs_ipv4_loopback,
3765     NO_BLOCK_SIZE_OPTION,
3766     NO_WINDOW_SIZE_OPTION,
3767     true
3768   );
3769   _Tftp_Add_interaction_recv_ack(
3770     TFTP_FIRST_FD,
3771     FIRST_TIMEOUT_MILLISECONDS,
3772     SERV_PORT,
3773     tftpfs_ipv4_loopback,
3774     block_num++,
3775     true
3776   );
3777   _Tftp_Add_interaction_send_data(
3778     TFTP_FIRST_FD,
3779     block_num,
3780     pos_in_file,
3781     TFTP_RFC1350_BLOCK_SIZE,
3782     get_file_content,
3783     SERV_PORT,
3784     tftpfs_ipv4_loopback,
3785     true
3786   );
3787   pos_in_file += TFTP_RFC1350_BLOCK_SIZE;
3788   _Tftp_Add_interaction_recv_error(
3789     TFTP_FIRST_FD,
3790     FIRST_TIMEOUT_MILLISECONDS,
3791     SERV_PORT,
3792     tftpfs_ipv4_loopback,
3793     TFTP_ERROR_CODE_DISK_FULL,
3794     "disk full",
3795     true
3796   );
3797   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
3798 
3799   bytes_written = write_tftp_file(
3800     create_tftpfs_path( tftpfs_ipv4_loopback, tftpfs_file ),
3801     pos_in_file, /* Size of file */
3802     1, /* Bytes written per call to write() */
3803     &ctx->fd0
3804   );
3805   T_eq_int( errno, ENOSPC );
3806   T_eq_int( bytes_written, pos_in_file - 1 );
3807   T_no_more_interactions();
3808 }
3809 
3810 /*
3811  * Write a file to the server using only RFC1350.
3812  * The file is one and a half data packet long.
3813  * The server sends a malformed packet.
3814  * Tests:
3815  *   * The code supports requests without options (RFC1350 only).
3816  *   * The code supports the use of an IPv4 address instead of a server name.
3817  *   * The first packet is sent to standard port 69 of server.
3818  *   * All other packets are sent to the port used for this connection.
3819  *   * The first ACK to the WRQ packet is malformed.
3820  *     It is only one byte long.
3821  *   * The client sends an error upon the reception of a malformed packet
3822  *     and terminates the file transfer.
3823  */
3824 T_TEST_CASE_FIXTURE( write_file_malformed_ack_1, &fixture_rfc1350 )
3825 {
3826   tftp_test_context *ctx = T_fixture_context();
3827   int bytes_written;
3828   size_t pos_in_file = 0;
3829   static const uint8_t packet_too_short_1[] = { 0x04 };
3830 
3831   /* T_set_verbosity( T_VERBOSE ); */
3832   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
3833   _Tftp_Add_interaction_send_wrq(
3834     TFTP_FIRST_FD,
3835     tftpfs_file,
3836     TFTP_STD_PORT,
3837     tftpfs_ipv4_loopback,
3838     NO_BLOCK_SIZE_OPTION,
3839     NO_WINDOW_SIZE_OPTION,
3840     true
3841   );
3842   _Tftp_Add_interaction_recv_raw(
3843     TFTP_FIRST_FD,
3844     FIRST_TIMEOUT_MILLISECONDS,
3845     SERV_PORT,
3846     tftpfs_ipv4_loopback,
3847     sizeof( packet_too_short_1 ), /* Malformed ACK packet */
3848     packet_too_short_1,
3849     true
3850   );
3851   _Tftp_Add_interaction_send_error(
3852     TFTP_FIRST_FD,
3853     TFTP_ERROR_CODE_ILLEGAL,
3854     SERV_PORT,
3855     tftpfs_ipv4_loopback,
3856     true
3857   );
3858   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
3859 
3860   bytes_written = write_tftp_file(
3861     create_tftpfs_path( tftpfs_ipv4_loopback, tftpfs_file ),
3862     pos_in_file, /* Size of file */
3863     17, /* Bytes written per call to write() */
3864     &ctx->fd0
3865   );
3866   T_eq_int( bytes_written, -1 );
3867   T_eq_int( errno, EPROTO );
3868   T_no_more_interactions();
3869 }
3870 
3871 /*
3872  * Write a file to the server using only RFC1350.
3873  * The file is one and a half data packet long.
3874  * The server sends a malformed packet.
3875  * Tests:
3876  *   * The code supports requests without options (RFC1350 only).
3877  *   * The code supports the use of an IPv4 address instead of a server name.
3878  *   * The first packet is sent to standard port 69 of server.
3879  *   * All other packets are sent to the port used for this connection.
3880  *   * The first ACK to the WRQ packet is malformed.
3881  *     It is only two bytes long.
3882  *   * The client sends an error upon the reception of a malformed packet
3883  *     and terminates the file transfer.
3884  */
3885 T_TEST_CASE_FIXTURE( write_file_malformed_ack_2, &fixture_rfc1350 )
3886 {
3887   tftp_test_context *ctx = T_fixture_context();
3888   int bytes_written;
3889   size_t pos_in_file = 0;
3890   static const uint8_t packet_too_short_2[] = { 0x00, 0x04 };
3891 
3892   /* T_set_verbosity( T_VERBOSE ); */
3893   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
3894   _Tftp_Add_interaction_send_wrq(
3895     TFTP_FIRST_FD,
3896     tftpfs_file,
3897     TFTP_STD_PORT,
3898     tftpfs_ipv4_loopback,
3899     NO_BLOCK_SIZE_OPTION,
3900     NO_WINDOW_SIZE_OPTION,
3901     true
3902   );
3903   _Tftp_Add_interaction_recv_raw(
3904     TFTP_FIRST_FD,
3905     FIRST_TIMEOUT_MILLISECONDS,
3906     SERV_PORT,
3907     tftpfs_ipv4_loopback,
3908     sizeof( packet_too_short_2 ), /* Malformed ACK packet */
3909     packet_too_short_2,
3910     true
3911   );
3912   _Tftp_Add_interaction_send_error(
3913     TFTP_FIRST_FD,
3914     TFTP_ERROR_CODE_ILLEGAL,
3915     SERV_PORT,
3916     tftpfs_ipv4_loopback,
3917     true
3918   );
3919   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
3920 
3921   bytes_written = write_tftp_file(
3922     create_tftpfs_path( tftpfs_ipv4_loopback, tftpfs_file ),
3923     pos_in_file, /* Size of file */
3924     17, /* Bytes written per call to write() */
3925     &ctx->fd0
3926   );
3927   T_eq_int( bytes_written, -1 );
3928   T_eq_int( errno, EPROTO );
3929   T_no_more_interactions();
3930 }
3931 
3932 /*
3933  * Write a file to the server using only RFC1350.
3934  * The file is one and a half data packet long.
3935  * The server sends a malformed packet.
3936  * Tests:
3937  *   * The code supports requests without options (RFC1350 only).
3938  *   * The code supports the use of an IPv4 address instead of a server name.
3939  *   * The first packet is sent to standard port 69 of server.
3940  *   * All other packets are sent to the port used for this connection.
3941  *   * The first ACK to the WRQ packet is malformed.
3942  *     It is only three bytes long.
3943  *   * The client sends an error upon the reception of a malformed packet
3944  *     and terminates the file transfer.
3945  */
3946 T_TEST_CASE_FIXTURE( write_file_malformed_ack_3, &fixture_rfc1350 )
3947 {
3948   tftp_test_context *ctx = T_fixture_context();
3949   int bytes_written;
3950   size_t pos_in_file = 0;
3951   static const uint8_t packet_too_short_3[] = { 0x00, 0x04, 0x00 };
3952 
3953   /* T_set_verbosity( T_VERBOSE ); */
3954   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
3955   _Tftp_Add_interaction_send_wrq(
3956     TFTP_FIRST_FD,
3957     tftpfs_file,
3958     TFTP_STD_PORT,
3959     tftpfs_ipv4_loopback,
3960     NO_BLOCK_SIZE_OPTION,
3961     NO_WINDOW_SIZE_OPTION,
3962     true
3963   );
3964   _Tftp_Add_interaction_recv_raw(
3965     TFTP_FIRST_FD,
3966     FIRST_TIMEOUT_MILLISECONDS,
3967     SERV_PORT,
3968     tftpfs_ipv4_loopback,
3969     sizeof( packet_too_short_3 ), /* Malformed ACK packet */
3970     packet_too_short_3,
3971     true
3972   );
3973   _Tftp_Add_interaction_send_error(
3974     TFTP_FIRST_FD,
3975     TFTP_ERROR_CODE_ILLEGAL,
3976     SERV_PORT,
3977     tftpfs_ipv4_loopback,
3978     true
3979   );
3980   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
3981 
3982   bytes_written = write_tftp_file(
3983     create_tftpfs_path( tftpfs_ipv4_loopback, tftpfs_file ),
3984     pos_in_file, /* Size of file */
3985     17, /* Bytes written per call to write() */
3986     &ctx->fd0
3987   );
3988   T_eq_int( bytes_written, -1 );
3989   T_eq_int( errno, EPROTO );
3990   T_no_more_interactions();
3991 }
3992 
3993 /*
3994  * Write a file to the server using only RFC1350.
3995  * The file is one and a half data packet long.
3996  * The server sends a malformed packet.
3997  * Tests:
3998  *   * The code supports requests without options (RFC1350 only).
3999  *   * The code supports the use of an IPv4 address instead of a server name.
4000  *   * The first packet is sent to standard port 69 of server.
4001  *   * All other packets are sent to the port used for this connection.
4002  *   * The first ACK to the WRQ packet is malformed.
4003  *     The packet contains an illegal op code.
4004  *   * The client sends an error upon the reception of a malformed packet
4005  *     and terminates the file transfer.
4006  */
4007 T_TEST_CASE_FIXTURE( write_file_illegal_opcode_1, &fixture_rfc1350 )
4008 {
4009   tftp_test_context *ctx = T_fixture_context();
4010   int bytes_written;
4011   size_t pos_in_file = 0;
4012   static const uint8_t packet_illegal_opcode_1[] = { 0x00, 0xFF, 0x00, 0x00 };
4013 
4014   /* T_set_verbosity( T_VERBOSE ); */
4015   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
4016   _Tftp_Add_interaction_send_wrq(
4017     TFTP_FIRST_FD,
4018     tftpfs_file,
4019     TFTP_STD_PORT,
4020     tftpfs_ipv4_loopback,
4021     NO_BLOCK_SIZE_OPTION,
4022     NO_WINDOW_SIZE_OPTION,
4023     true
4024   );
4025   _Tftp_Add_interaction_recv_raw(
4026     TFTP_FIRST_FD,
4027     FIRST_TIMEOUT_MILLISECONDS,
4028     SERV_PORT,
4029     tftpfs_ipv4_loopback,
4030     sizeof( packet_illegal_opcode_1 ), /* Malformed ACK packet */
4031     packet_illegal_opcode_1,
4032     true
4033   );
4034   _Tftp_Add_interaction_send_error(
4035     TFTP_FIRST_FD,
4036     TFTP_ERROR_CODE_ILLEGAL,
4037     SERV_PORT,
4038     tftpfs_ipv4_loopback,
4039     true
4040   );
4041   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
4042 
4043   bytes_written = write_tftp_file(
4044     create_tftpfs_path( tftpfs_ipv4_loopback, tftpfs_file ),
4045     pos_in_file, /* Size of file */
4046     17, /* Bytes written per call to write() */
4047     &ctx->fd0
4048   );
4049   T_eq_int( bytes_written, -1 );
4050   T_eq_int( errno, EPROTO );
4051   T_no_more_interactions();
4052 }
4053 
4054 /*
4055  * Write a file to the server using only RFC1350.
4056  * The server sends a malformed packet.
4057  * Tests:
4058  *   * The code supports requests without options (RFC1350 only).
4059  *   * The code supports the use of an IPv4 address instead of a server name.
4060  *   * The first packet is sent to standard port 69 of server.
4061  *   * All other packets are sent to the port used for this connection.
4062  *   * A malformed ACK packet is received by the TFTP client.
4063  *     The packet is only three bytes long.
4064  *   * The client sends an error upon the reception of a malformed packet
4065  *     and terminates the file transfer.
4066  */
4067 T_TEST_CASE_FIXTURE( write_short_file_malformed_ACK_1, &fixture_rfc1350 )
4068 {
4069   tftp_test_context *ctx = T_fixture_context();
4070   int bytes_written;
4071   uint16_t block_num = 0;
4072   size_t pos_in_file = 0;
4073   static const uint8_t packet_too_short_3[] = { 0x00, 0x04, 0x00 };
4074 
4075   /* T_set_verbosity( T_VERBOSE ); */
4076   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
4077   _Tftp_Add_interaction_send_wrq(
4078     TFTP_FIRST_FD,
4079     tftpfs_file,
4080     TFTP_STD_PORT,
4081     tftpfs_ipv4_loopback,
4082     NO_BLOCK_SIZE_OPTION,
4083     NO_WINDOW_SIZE_OPTION,
4084     true
4085   );
4086   _Tftp_Add_interaction_recv_ack(
4087     TFTP_FIRST_FD,
4088     FIRST_TIMEOUT_MILLISECONDS,
4089     SERV_PORT,
4090     tftpfs_ipv4_loopback,
4091     block_num++,
4092     true
4093   );
4094   _Tftp_Add_interaction_send_data(
4095     TFTP_FIRST_FD,
4096     block_num,
4097     pos_in_file,
4098     TFTP_RFC1350_BLOCK_SIZE,
4099     get_file_content,
4100     SERV_PORT,
4101     tftpfs_ipv4_loopback,
4102     true
4103   );
4104   _Tftp_Add_interaction_recv_raw(
4105     TFTP_FIRST_FD,
4106     FIRST_TIMEOUT_MILLISECONDS,
4107     SERV_PORT,
4108     tftpfs_ipv4_loopback,
4109     sizeof( packet_too_short_3 ), /* Malformed ACK packet */
4110     packet_too_short_3,
4111     true
4112   );
4113   _Tftp_Add_interaction_send_error(
4114     TFTP_FIRST_FD,
4115     TFTP_ERROR_CODE_ILLEGAL,
4116     SERV_PORT,
4117     tftpfs_ipv4_loopback,
4118     true
4119   );
4120   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
4121 
4122   bytes_written = write_tftp_file(
4123     create_tftpfs_path( tftpfs_ipv4_loopback, tftpfs_file ),
4124     2 * TFTP_RFC1350_BLOCK_SIZE, /* Size of file */
4125     17, /* Bytes written per call to write() */
4126     &ctx->fd0
4127   );
4128   T_eq_int( errno, EPROTO );
4129   T_eq_int( bytes_written, 510 );
4130   T_no_more_interactions();
4131 }
4132 
4133 /*
4134  * Write a file to the server using only RFC1350.
4135  * The server sends a malformed packet.
4136  * Tests:
4137  *   * The code supports requests without options (RFC1350 only).
4138  *   * The code supports the use of an IPv4 address instead of a server name.
4139  *   * The first packet is sent to standard port 69 of server.
4140  *   * All other packets are sent to the port used for this connection.
4141  *   * A malformed ACK packet is received by the TFTP client after the first
4142  *     DATA packet has been exchanged successfully.
4143  *     The packet is only one byte long.
4144  *   * The client sends an error upon the reception of a malformed packet
4145  *     and terminates the file transfer.
4146  */
4147 T_TEST_CASE_FIXTURE( write_short_file_malformed_ACK_2, &fixture_rfc1350 )
4148 {
4149   tftp_test_context *ctx = T_fixture_context();
4150   int bytes_written;
4151   uint16_t block_num = 0;
4152   size_t pos_in_file = 0;
4153   static const uint8_t packet_too_short_1[] = { 0x04 };
4154 
4155   /* T_set_verbosity( T_VERBOSE ); */
4156   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
4157   _Tftp_Add_interaction_send_wrq(
4158     TFTP_FIRST_FD,
4159     tftpfs_file,
4160     TFTP_STD_PORT,
4161     tftpfs_ipv4_loopback,
4162     NO_BLOCK_SIZE_OPTION,
4163     NO_WINDOW_SIZE_OPTION,
4164     true
4165   );
4166   _Tftp_Add_interaction_recv_ack(
4167     TFTP_FIRST_FD,
4168     FIRST_TIMEOUT_MILLISECONDS,
4169     SERV_PORT,
4170     tftpfs_ipv4_loopback,
4171     block_num++,
4172     true
4173   );
4174   _Tftp_Add_interaction_send_data(
4175     TFTP_FIRST_FD,
4176     block_num,
4177     pos_in_file,
4178     TFTP_RFC1350_BLOCK_SIZE,
4179     get_file_content,
4180     SERV_PORT,
4181     tftpfs_ipv4_loopback,
4182     true
4183   );
4184   pos_in_file += TFTP_RFC1350_BLOCK_SIZE;
4185   _Tftp_Add_interaction_recv_ack(
4186     TFTP_FIRST_FD,
4187     FIRST_TIMEOUT_MILLISECONDS,
4188     SERV_PORT,
4189     tftpfs_ipv4_loopback,
4190     block_num++,
4191     true
4192   );
4193   _Tftp_Add_interaction_send_data(
4194     TFTP_FIRST_FD,
4195     block_num,
4196     pos_in_file,
4197     TFTP_RFC1350_BLOCK_SIZE / 4,
4198     get_file_content,
4199     SERV_PORT,
4200     tftpfs_ipv4_loopback,
4201     true
4202   );
4203   pos_in_file += TFTP_RFC1350_BLOCK_SIZE / 4;
4204   _Tftp_Add_interaction_recv_raw(
4205     TFTP_FIRST_FD,
4206     FIRST_TIMEOUT_MILLISECONDS,
4207     SERV_PORT,
4208     tftpfs_ipv4_loopback,
4209     sizeof( packet_too_short_1 ), /* Malformed ACK packet */
4210     packet_too_short_1,
4211     true
4212   );
4213   _Tftp_Add_interaction_send_error(
4214     TFTP_FIRST_FD,
4215     TFTP_ERROR_CODE_ILLEGAL,
4216     SERV_PORT,
4217     tftpfs_ipv4_loopback,
4218     true
4219   );
4220   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
4221 
4222   bytes_written = write_tftp_file(
4223     create_tftpfs_path( tftpfs_ipv4_loopback, tftpfs_file ),
4224     pos_in_file, /* Size of file */
4225     17, /* Bytes written per call to write() */
4226     &ctx->fd0
4227   );
4228   T_eq_int( errno, EPROTO );
4229   T_eq_int( bytes_written, -1 );
4230   T_no_more_interactions();
4231 }
4232 
4233 /*
4234  * Write a file to the server using only RFC1350.
4235  * The server sends a malformed packet.
4236  * Tests:
4237  *   * The code supports requests without options (RFC1350 only).
4238  *   * The code supports the use of an IPv4 address instead of a server name.
4239  *   * The first packet is sent to standard port 69 of server.
4240  *   * All other packets are sent to the port used for this connection.
4241  *   * A malformed ACK packet is received by the TFTP client after the first
4242  *     DATA packet has been exchanged successfully.
4243  *     The packet contains an illegal op code.
4244  *   * The client sends an error upon the reception of a malformed packet
4245  *     and terminates the file transfer.
4246  */
4247 T_TEST_CASE_FIXTURE( write_short_file_malformed_opcode, &fixture_rfc1350 )
4248 {
4249   tftp_test_context *ctx = T_fixture_context();
4250   int bytes_written;
4251   uint16_t block_num = 0;
4252   size_t pos_in_file = 0;
4253   static const uint8_t packet_illegal_opcode_2[] = { 0x04, 0x00, 0x00, 0x01 };
4254 
4255   /* T_set_verbosity( T_VERBOSE ); */
4256   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
4257   _Tftp_Add_interaction_send_wrq(
4258     TFTP_FIRST_FD,
4259     tftpfs_file,
4260     TFTP_STD_PORT,
4261     tftpfs_ipv4_loopback,
4262     NO_BLOCK_SIZE_OPTION,
4263     NO_WINDOW_SIZE_OPTION,
4264     true
4265   );
4266   _Tftp_Add_interaction_recv_ack(
4267     TFTP_FIRST_FD,
4268     FIRST_TIMEOUT_MILLISECONDS,
4269     SERV_PORT,
4270     tftpfs_ipv4_loopback,
4271     block_num++,
4272     true
4273   );
4274   _Tftp_Add_interaction_send_data(
4275     TFTP_FIRST_FD,
4276     block_num,
4277     pos_in_file,
4278     TFTP_RFC1350_BLOCK_SIZE,
4279     get_file_content,
4280     SERV_PORT,
4281     tftpfs_ipv4_loopback,
4282     true
4283   );
4284   _Tftp_Add_interaction_recv_raw(
4285     TFTP_FIRST_FD,
4286     FIRST_TIMEOUT_MILLISECONDS,
4287     SERV_PORT,
4288     tftpfs_ipv4_loopback,
4289     sizeof( packet_illegal_opcode_2 ), /* Malformed ACK packet */
4290     packet_illegal_opcode_2,
4291     true
4292   );
4293   _Tftp_Add_interaction_send_error(
4294     TFTP_FIRST_FD,
4295     TFTP_ERROR_CODE_ILLEGAL,
4296     SERV_PORT,
4297     tftpfs_ipv4_loopback,
4298     true
4299   );
4300   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
4301 
4302   bytes_written = write_tftp_file(
4303     create_tftpfs_path( tftpfs_ipv4_loopback, tftpfs_file ),
4304     2 * TFTP_RFC1350_BLOCK_SIZE, /* Size of file */
4305     17, /* Bytes written per call to write() */
4306     &ctx->fd0
4307   );
4308   T_eq_int( errno, EPROTO );
4309   T_eq_int( bytes_written, 510 );
4310   T_no_more_interactions();
4311 }
4312 
4313 /*
4314  * Write a file to the server using only RFC1350.
4315  * The file is two and a half data packet long.
4316  * The server sends packets with wrong block numbers.
4317  * Tests:
4318  *   * The code supports requests without options (RFC1350 only).
4319  *   * The code supports the use of an IPv4 address instead of a server name.
4320  *   * The first packet is sent to standard port 69 of server.
4321  *   * All other packets are sent to the port used for this connection.
4322  *   * The first ACK packet contains a wrong block number.
4323  *   * The client repeats the WRQ upon reception of an ACK with
4324  *     an too high block number.
4325  *   * The client uses a short time out for waiting on the answer of the
4326  *     first WRQ or DATA packets.
4327  *   * The client uses a long time out for waiting on the answer of
4328  *     repeated WRQ or DATA packets.
4329  *   * The first DATA packet is full.
4330  *   * The second DATA packet signals the end of transfer.
4331  *   * The client handles DATA packets with wrong block numbers
4332  *     appropriately.
4333  *   * The test writes a file to the file system with calls to write() of
4334  *     exactly block size.
4335  */
4336 T_TEST_CASE_FIXTURE( write_short_file_bad_block_numbers, &fixture_rfc1350 )
4337 {
4338   tftp_test_context *ctx = T_fixture_context();
4339   int bytes_written;
4340   uint16_t block_num = 0;
4341   size_t pos_in_file = 0;
4342 
4343   /* T_set_verbosity( T_VERBOSE ); */
4344   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
4345   _Tftp_Add_interaction_send_wrq(
4346     TFTP_FIRST_FD,
4347     tftpfs_file,
4348     TFTP_STD_PORT,
4349     tftpfs_ipv4_loopback,
4350     NO_BLOCK_SIZE_OPTION,
4351     NO_WINDOW_SIZE_OPTION,
4352     true
4353   );
4354   _Tftp_Add_interaction_recv_ack(
4355     TFTP_FIRST_FD,
4356     FIRST_TIMEOUT_MILLISECONDS,
4357     SERV_PORT,
4358     tftpfs_ipv4_loopback,
4359     block_num + 1, /* Wrong block number */
4360     true
4361   );
4362   _Tftp_Add_interaction_recv_ack(
4363     TFTP_FIRST_FD,
4364     FIRST_TIMEOUT_MILLISECONDS,
4365     SERV_PORT,
4366     tftpfs_ipv4_loopback,
4367     block_num++,
4368     true
4369   );
4370   _Tftp_Add_interaction_send_data(
4371     TFTP_FIRST_FD,
4372     block_num,
4373     pos_in_file,
4374     TFTP_RFC1350_BLOCK_SIZE,
4375     get_file_content,
4376     SERV_PORT,
4377     tftpfs_ipv4_loopback,
4378     true
4379   );
4380   _Tftp_Add_interaction_recv_ack(
4381     TFTP_FIRST_FD,
4382     FIRST_TIMEOUT_MILLISECONDS,
4383     SERV_PORT,
4384     tftpfs_ipv4_loopback,
4385     block_num - 1, /* Wrong block number */
4386     true
4387   );
4388   pos_in_file += TFTP_RFC1350_BLOCK_SIZE;
4389   _Tftp_Add_interaction_recv_ack(
4390     TFTP_FIRST_FD,
4391     FIRST_TIMEOUT_MILLISECONDS,
4392     SERV_PORT,
4393     tftpfs_ipv4_loopback,
4394     block_num++,
4395     true
4396   );
4397   _Tftp_Add_interaction_send_data(
4398     TFTP_FIRST_FD,
4399     block_num,
4400     pos_in_file,
4401     TFTP_RFC1350_BLOCK_SIZE,
4402     get_file_content,
4403     SERV_PORT,
4404     tftpfs_ipv4_loopback,
4405     true
4406   );
4407   _Tftp_Add_interaction_recv_ack(
4408     TFTP_FIRST_FD,
4409     FIRST_TIMEOUT_MILLISECONDS,
4410     SERV_PORT,
4411     tftpfs_ipv4_loopback,
4412     block_num - 2, /* Wrong block number */
4413     true
4414   );
4415   pos_in_file += TFTP_RFC1350_BLOCK_SIZE;
4416   _Tftp_Add_interaction_recv_ack(
4417     TFTP_FIRST_FD,
4418     FIRST_TIMEOUT_MILLISECONDS,
4419     SERV_PORT,
4420     tftpfs_ipv4_loopback,
4421     block_num++,
4422     true
4423   );
4424   _Tftp_Add_interaction_send_data(
4425     TFTP_FIRST_FD,
4426     block_num,
4427     pos_in_file,
4428     TFTP_RFC1350_BLOCK_SIZE / 4,
4429     get_file_content,
4430     SERV_PORT,
4431     tftpfs_ipv4_loopback,
4432     true
4433   );
4434   _Tftp_Add_interaction_recv_ack(
4435     TFTP_FIRST_FD,
4436     FIRST_TIMEOUT_MILLISECONDS,
4437     SERV_PORT,
4438     tftpfs_ipv4_loopback,
4439     block_num - 2, /* Wrong block number */
4440     true
4441   );
4442   _Tftp_Add_interaction_recv_ack(
4443     TFTP_FIRST_FD,
4444     FIRST_TIMEOUT_MILLISECONDS,
4445     SERV_PORT,
4446     tftpfs_ipv4_loopback,
4447     block_num + 1, /* Wrong block number */
4448     true
4449   );
4450   pos_in_file += TFTP_RFC1350_BLOCK_SIZE / 4;
4451   _Tftp_Add_interaction_recv_ack(
4452     TFTP_FIRST_FD,
4453     FIRST_TIMEOUT_MILLISECONDS,
4454     SERV_PORT,
4455     tftpfs_ipv4_loopback,
4456     block_num++,
4457     true
4458   );
4459   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
4460 
4461   bytes_written = write_tftp_file(
4462     create_tftpfs_path( tftpfs_ipv4_loopback, tftpfs_file ),
4463     pos_in_file, /* Size of file */
4464     TFTP_RFC1350_BLOCK_SIZE, /* Bytes written per call to write() */
4465     &ctx->fd0
4466   );
4467   T_eq_int( bytes_written, pos_in_file );
4468   T_no_more_interactions();
4469 }
4470 
4471 /*
4472  * Write a file to the server using only RFC1350.
4473  * The file is one data packet long.
4474  * The client receives a stray packet from an unknown server (wrong TID).
4475  * Directly afterwards the expected ACK packet is lost and
4476  * the client must retransmit the original DATA packet.
4477  * Tests:
4478  *   * The code supports requests without options (RFC1350 only).
4479  *   * The code supports the use of an IPv4 address instead of a server name.
4480  *   * The first packet is sent to standard port 69 of server.
4481  *   * All other packets are sent to the port used for this connection.
4482  *   * The client uses a short time out for waiting on the answer of the
4483  *     first DATA packet.
4484  *   * The client uses a long time out for waiting on the answer of
4485  *     the repeated DATA.
4486  *   * Upon reception of a packet with a wrong TID, the client sends
4487  *     an ERROR message with code 5 but does not terminate the current
4488  *     transfer.
4489  *   * When re-transmitting the an packet, the data is intact (i.e.
4490  *     not corrupted by the reception of any packet in-between).
4491  */
4492 T_TEST_CASE_FIXTURE( write_one_block_file_stray_packets, &fixture_rfc1350 )
4493 {
4494   tftp_test_context *ctx = T_fixture_context();
4495   int bytes_written;
4496   uint16_t block_num = 0;
4497   size_t pos_in_file = 0;
4498 
4499   /* T_set_verbosity( T_VERBOSE ); */
4500   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
4501   _Tftp_Add_interaction_send_wrq(
4502     TFTP_FIRST_FD,
4503     tftpfs_file,
4504     TFTP_STD_PORT,
4505     tftpfs_ipv4_loopback,
4506     NO_BLOCK_SIZE_OPTION,
4507     NO_WINDOW_SIZE_OPTION,
4508     true
4509   );
4510   _Tftp_Add_interaction_recv_ack(
4511     TFTP_FIRST_FD,
4512     FIRST_TIMEOUT_MILLISECONDS,
4513     SERV_PORT,
4514     tftpfs_ipv4_loopback,
4515     block_num++,
4516     true
4517   );
4518   _Tftp_Add_interaction_send_data(
4519     TFTP_FIRST_FD,
4520     block_num,
4521     pos_in_file,
4522     TFTP_RFC1350_BLOCK_SIZE,
4523     get_file_content,
4524     SERV_PORT,
4525     tftpfs_ipv4_loopback,
4526     true
4527   );
4528   _Tftp_Add_interaction_recv_data(
4529     TFTP_FIRST_FD,
4530     FIRST_TIMEOUT_MILLISECONDS,
4531     SERV_PORT + 1, /* Stray packet with wrong server TID */
4532     tftpfs_ipv4_loopback,
4533     block_num,
4534     0,
4535     TFTP_RFC1350_BLOCK_SIZE / 2, /* Number of bytes transferred */
4536     get_bad_file_content,
4537     true
4538   );
4539   _Tftp_Add_interaction_send_error(
4540     TFTP_FIRST_FD,
4541     TFTP_ERROR_CODE_UNKNOWN_ID,
4542     SERV_PORT + 1,
4543     tftpfs_ipv4_loopback,
4544     true
4545   );
4546   _Tftp_Add_interaction_recv_nothing(
4547     TFTP_FIRST_FD, /* Timeout: No packet received within timeout period */
4548     FIRST_TIMEOUT_MILLISECONDS
4549   );
4550   _Tftp_Add_interaction_send_data( /* Retransmission of the DATA packet */
4551     TFTP_FIRST_FD,
4552     block_num,
4553     pos_in_file,
4554     TFTP_RFC1350_BLOCK_SIZE,
4555     get_file_content,
4556     SERV_PORT,
4557     tftpfs_ipv4_loopback,
4558     true
4559   );
4560   pos_in_file += TFTP_RFC1350_BLOCK_SIZE;
4561   _Tftp_Add_interaction_recv_ack(
4562     TFTP_FIRST_FD,
4563     TIMEOUT_MILLISECONDS,
4564     SERV_PORT,
4565     tftpfs_ipv4_loopback,
4566     block_num++,
4567     true
4568   );
4569   _Tftp_Add_interaction_send_data(
4570     TFTP_FIRST_FD,
4571     block_num,
4572     pos_in_file,
4573     0, /* Number of bytes */
4574     get_file_content,
4575     SERV_PORT,
4576     tftpfs_ipv4_loopback,
4577     true
4578   );
4579   pos_in_file += 0;
4580   _Tftp_Add_interaction_recv_ack(
4581     TFTP_FIRST_FD,
4582     FIRST_TIMEOUT_MILLISECONDS,
4583     SERV_PORT,
4584     tftpfs_ipv4_loopback,
4585     block_num++,
4586     true
4587   );
4588   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
4589 
4590   bytes_written = write_tftp_file(
4591     create_tftpfs_path( tftpfs_ipv4_loopback, tftpfs_file ),
4592     pos_in_file, /* Size of file */
4593     TFTP_RFC1350_BLOCK_SIZE, /* Bytes written per call to write() */
4594     &ctx->fd0
4595   );
4596   T_eq_int( bytes_written, pos_in_file );
4597   T_no_more_interactions();
4598 }
4599 
4600 /*
4601  * Read a file from the server using option to increase the block size.
4602  * The file is one data packet long.  No timeouts, packet loss, ...
4603  * Tests:
4604  *   * Only the blksize option appears in RRQ and OACK.
4605  *   * The client uses a block size which is larger than the default size.
4606  *   * The first data packet is full.
4607  *   * The second data packet is empty and signals the end of the transfer.
4608  *   * Client handles the empty data packet correctly as
4609  *     end of file indicator.
4610  *   * The test reads a file from the file system in chunks of block size.
4611  */
4612 T_TEST_CASE_FIXTURE( read_file_one_large_block, &fixture_large_blocksize )
4613 {
4614   tftp_test_context *ctx = T_fixture_context();
4615   int bytes_read;
4616   uint16_t block_num = 0;
4617   size_t pos_in_file = 0;
4618   const char options[] =
4619     TFTP_OPTION_BLKSIZE "\0"
4620     RTEMS_XSTRING( LARGE_BLOCK_SIZE );
4621 
4622   /* T_set_verbosity( T_VERBOSE ); */
4623   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
4624   _Tftp_Add_interaction_send_rrq(
4625     TFTP_FIRST_FD,
4626     tftpfs_file,
4627     TFTP_STD_PORT,
4628     tftpfs_ipv4_loopback,
4629     LARGE_BLOCK_SIZE,
4630     NO_WINDOW_SIZE_OPTION,
4631     true
4632   );
4633   _Tftp_Add_interaction_recv_oack(
4634     TFTP_FIRST_FD,
4635     FIRST_TIMEOUT_MILLISECONDS,
4636     SERV_PORT,
4637     tftpfs_ipv4_loopback,
4638     options,
4639     sizeof( options ),
4640     true
4641   );
4642   _Tftp_Add_interaction_send_ack(
4643     TFTP_FIRST_FD,
4644     block_num++,
4645     SERV_PORT,
4646     tftpfs_ipv4_loopback,
4647     true
4648   );
4649   _Tftp_Add_interaction_recv_data(
4650     TFTP_FIRST_FD,
4651     FIRST_TIMEOUT_MILLISECONDS,
4652     SERV_PORT,
4653     tftpfs_ipv4_loopback,
4654     block_num,
4655     pos_in_file,
4656     LARGE_BLOCK_SIZE, /* Number of bytes transferred */
4657     get_file_content,
4658     true
4659   );
4660   pos_in_file += LARGE_BLOCK_SIZE;
4661   _Tftp_Add_interaction_send_ack(
4662     TFTP_FIRST_FD,
4663     block_num++,
4664     SERV_PORT,
4665     tftpfs_ipv4_loopback,
4666     true
4667   );
4668   _Tftp_Add_interaction_recv_data(
4669     TFTP_FIRST_FD,
4670     FIRST_TIMEOUT_MILLISECONDS,
4671     SERV_PORT,
4672     tftpfs_ipv4_loopback,
4673     block_num,
4674     pos_in_file,
4675     0, /* Number of bytes transferred */
4676     get_file_content,
4677     true
4678   );
4679   _Tftp_Add_interaction_send_ack(
4680     TFTP_FIRST_FD,
4681     block_num++,
4682     SERV_PORT,
4683     tftpfs_ipv4_loopback,
4684     true
4685   );
4686   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
4687 
4688   bytes_read = read_tftp_file(
4689     create_tftpfs_path( tftpfs_ipv4_loopback, tftpfs_file ),
4690     LARGE_BLOCK_SIZE, /* Bytes read per call to read() */
4691     SIZE_MAX,
4692     &ctx->fd0
4693   );
4694   T_eq_int( bytes_read, pos_in_file );
4695   T_no_more_interactions();
4696 }
4697 
4698 /*
4699  * Try to read a file from the server using a file name too large for a RRQ.
4700  * Tests:
4701  *   * The client rejects an attempt to open a file with a too long
4702  *     file name is with an error.
4703  */
4704 T_TEST_CASE_FIXTURE( read_too_long_file_name, &fixture_default_options )
4705 {
4706   tftp_test_context *ctx = T_fixture_context();
4707   int bytes_read;
4708   char buffer[TFTP_RFC1350_BLOCK_SIZE -
4709               strlen( TFTP_MODE_OCTET ) - 1 - 5];
4710   int len;
4711 
4712   /* T_set_verbosity( T_VERBOSE ); */
4713   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
4714   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
4715 
4716   len = sizeof( buffer ) - strlen( tftpfs_mount_point ) -
4717         strlen( tftpfs_ipv4_loopback ) - 2 - 4;
4718   len = snprintf(
4719     buffer,
4720     sizeof( buffer ),
4721     "%s/%s:%0*d",
4722     tftpfs_mount_point,
4723     tftpfs_ipv4_loopback,
4724     len,
4725     123
4726   );
4727   T_quiet_gt_int( len, 0 );
4728   T_quiet_lt_int( len, (int) sizeof( buffer ) );
4729 
4730   bytes_read = read_tftp_file(
4731     buffer,
4732     TFTP_DEFAULT_BLOCK_SIZE, /* Bytes read per call to read() */
4733     SIZE_MAX,
4734     &ctx->fd0
4735   );
4736   T_eq_int( bytes_read, 0 );
4737   T_eq_int( errno, ENAMETOOLONG );
4738   T_no_more_interactions();
4739 }
4740 
4741 /*
4742  * Read a file using options but the server sends a DATA packet.
4743  * The file is one byte long.  No timeouts, packet loss, ...
4744  * Tests:
4745  *   * The client uses windowsize and blksize option in the RRQ.
4746  *   * For the data transfer the client uses the RFC1350 option values
4747  *     because the server responded with a DATA packet.
4748  *   * The whole package sequence behaves as if only RFC1350 was used.
4749  *   * The first data packet contains a single byte and signals the end of the transfer.
4750  *   * The test reads a file from the file system in chunks of half block size.
4751  */
4752 T_TEST_CASE_FIXTURE( read_file_DATA_instead_of_OACK, &fixture_default_options )
4753 {
4754   tftp_test_context *ctx = T_fixture_context();
4755   int bytes_read;
4756   uint16_t block_num = 1;
4757   size_t pos_in_file = 0;
4758 
4759   /* T_set_verbosity( T_VERBOSE ); */
4760   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
4761   _Tftp_Add_interaction_send_rrq(
4762     TFTP_FIRST_FD,
4763     tftpfs_file,
4764     TFTP_STD_PORT,
4765     tftpfs_ipv4_loopback,
4766     TFTP_DEFAULT_BLOCK_SIZE,
4767     TFTP_DEFAULT_WINDOW_SIZE,
4768     true
4769   );
4770   _Tftp_Add_interaction_recv_data(
4771     TFTP_FIRST_FD,
4772     FIRST_TIMEOUT_MILLISECONDS,
4773     SERV_PORT,
4774     tftpfs_ipv4_loopback,
4775     block_num,
4776     pos_in_file,
4777     1, /* Number of bytes transferred */
4778     get_file_content,
4779     true
4780   );
4781   pos_in_file += 1;
4782   _Tftp_Add_interaction_send_ack(
4783     TFTP_FIRST_FD,
4784     block_num++,
4785     SERV_PORT,
4786     tftpfs_ipv4_loopback,
4787     true
4788   );
4789   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
4790 
4791   bytes_read = read_tftp_file(
4792     create_tftpfs_path( tftpfs_ipv4_loopback, tftpfs_file ),
4793     TFTP_DEFAULT_BLOCK_SIZE / 2, /* Bytes read per call to read() */
4794     SIZE_MAX,
4795     &ctx->fd0
4796   );
4797   T_eq_int( bytes_read, pos_in_file );
4798   T_no_more_interactions();
4799 }
4800 
4801 /*
4802  * Read a file using RFC1350 but the server sends an OACK packet.
4803  * Tests:
4804  *   * The code supports requests without options (RFC1350 only).
4805  *   * The server wrongly responds with an OACK which contains no options.
4806  *   * The client sends an error upon reception of an unexpected packet.
4807  */
4808 T_TEST_CASE_FIXTURE( read_tiny_file_OACK_instead_of_DATA, &fixture_rfc1350 )
4809 {
4810   tftp_test_context *ctx = T_fixture_context();
4811   int bytes_read;
4812   const char options[] = {};
4813 
4814   /* T_set_verbosity( T_VERBOSE ); */
4815   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
4816   _Tftp_Add_interaction_send_rrq(
4817     TFTP_FIRST_FD,
4818     tftpfs_file,
4819     TFTP_STD_PORT,
4820     tftpfs_ipv4_loopback,
4821     NO_BLOCK_SIZE_OPTION,
4822     NO_WINDOW_SIZE_OPTION,
4823     true
4824   );
4825   _Tftp_Add_interaction_recv_oack(
4826     TFTP_FIRST_FD,
4827     FIRST_TIMEOUT_MILLISECONDS,
4828     SERV_PORT,
4829     tftpfs_ipv4_loopback,
4830     options,
4831     sizeof( options ),
4832     true
4833   );
4834   _Tftp_Add_interaction_send_error(
4835     TFTP_FIRST_FD,
4836     TFTP_ERROR_CODE_ILLEGAL,
4837     SERV_PORT,
4838     tftpfs_ipv4_loopback,
4839     true
4840   );
4841   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
4842 
4843   bytes_read = read_tftp_file(
4844     create_tftpfs_path( tftpfs_ipv4_loopback, tftpfs_file ),
4845     1, /* Bytes read per call to read() */
4846     SIZE_MAX,
4847     &ctx->fd0
4848   );
4849   T_eq_int( bytes_read, 0 );
4850   T_eq_int( errno, EPROTO );
4851   T_no_more_interactions();
4852 }
4853 
4854 /*
4855  * Read a file from the server using the default options.
4856  * The file is 18 and a half data packet long.  No timeouts, packet loss, ...
4857  * Tests:
4858  *   * The client uses the default options
4859  *     (windowsize = 8 and blocksize = 1456).
4860  *   * The server send the options in the same order as the client did
4861  *     send them.
4862  *   * The ninetenth data packet signals the end of transfer.
4863  *   * The test reads a file from the file system in chunks of 2000 bytes.
4864  */
4865 T_TEST_CASE_FIXTURE( read_file_with_default_options, &fixture_default_options )
4866 {
4867   tftp_test_context *ctx = T_fixture_context();
4868   int i;
4869   int bytes_read;
4870   uint16_t block_num = 0;
4871   size_t pos_in_file = 0;
4872   const char options[] =
4873     TFTP_OPTION_BLKSIZE "\0"
4874     RTEMS_XSTRING( TFTP_DEFAULT_BLOCK_SIZE ) "\0"
4875     TFTP_OPTION_WINDOWSIZE"\0"
4876     RTEMS_XSTRING( TFTP_DEFAULT_WINDOW_SIZE );
4877 
4878   /* T_set_verbosity( T_VERBOSE ); */
4879   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
4880   _Tftp_Add_interaction_send_rrq(
4881     TFTP_FIRST_FD,
4882     tftpfs_file,
4883     TFTP_STD_PORT,
4884     tftpfs_ipv4_loopback,
4885     TFTP_DEFAULT_BLOCK_SIZE,
4886     TFTP_DEFAULT_WINDOW_SIZE,
4887     true
4888   );
4889   _Tftp_Add_interaction_recv_oack(
4890     TFTP_FIRST_FD,
4891     FIRST_TIMEOUT_MILLISECONDS,
4892     SERV_PORT,
4893     tftpfs_ipv4_loopback,
4894     options,
4895     sizeof( options ),
4896     true
4897   );
4898   _Tftp_Add_interaction_send_ack(
4899     TFTP_FIRST_FD,
4900     block_num,
4901     SERV_PORT,
4902     tftpfs_ipv4_loopback,
4903     true
4904   );
4905   while ( block_num < 16 ) {
4906     for ( i = 0; i < TFTP_DEFAULT_WINDOW_SIZE; ++i ) {
4907       _Tftp_Add_interaction_recv_data(
4908         TFTP_FIRST_FD,
4909         FIRST_TIMEOUT_MILLISECONDS,
4910         SERV_PORT,
4911         tftpfs_ipv4_loopback,
4912         ++block_num,
4913         pos_in_file,
4914         TFTP_DEFAULT_BLOCK_SIZE, /* Number of bytes transferred */
4915         get_file_content,
4916         true
4917       );
4918       pos_in_file += TFTP_DEFAULT_BLOCK_SIZE;
4919     }
4920     _Tftp_Add_interaction_send_ack(
4921       TFTP_FIRST_FD,
4922       block_num,
4923       SERV_PORT,
4924       tftpfs_ipv4_loopback,
4925       true
4926     );
4927   }
4928   _Tftp_Add_interaction_recv_data(
4929     TFTP_FIRST_FD,
4930     FIRST_TIMEOUT_MILLISECONDS,
4931     SERV_PORT,
4932     tftpfs_ipv4_loopback,
4933     ++block_num,
4934     pos_in_file,
4935     TFTP_DEFAULT_BLOCK_SIZE, /* Number of bytes transferred */
4936     get_file_content,
4937     true
4938   );
4939   pos_in_file += TFTP_DEFAULT_BLOCK_SIZE;
4940   _Tftp_Add_interaction_recv_data(
4941     TFTP_FIRST_FD,
4942     FIRST_TIMEOUT_MILLISECONDS,
4943     SERV_PORT,
4944     tftpfs_ipv4_loopback,
4945     ++block_num,
4946     pos_in_file,
4947     TFTP_DEFAULT_BLOCK_SIZE, /* Number of bytes transferred */
4948     get_file_content,
4949     true
4950   );
4951   pos_in_file += TFTP_DEFAULT_BLOCK_SIZE;
4952   _Tftp_Add_interaction_recv_data(
4953     TFTP_FIRST_FD,
4954     FIRST_TIMEOUT_MILLISECONDS,
4955     SERV_PORT,
4956     tftpfs_ipv4_loopback,
4957     ++block_num,
4958     pos_in_file,
4959     TFTP_DEFAULT_BLOCK_SIZE / 2, /* Number of bytes transferred */
4960     get_file_content,
4961     true
4962   );
4963   pos_in_file += TFTP_DEFAULT_BLOCK_SIZE / 2;
4964   _Tftp_Add_interaction_send_ack(
4965     TFTP_FIRST_FD,
4966     block_num,
4967     SERV_PORT,
4968     tftpfs_ipv4_loopback,
4969     true
4970   );
4971   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
4972 
4973   bytes_read = read_tftp_file(
4974     create_tftpfs_path( tftpfs_ipv4_loopback, tftpfs_file ),
4975     2000, /* Bytes read per call to read() */
4976     SIZE_MAX,
4977     &ctx->fd0
4978   );
4979   T_eq_int( bytes_read, pos_in_file );
4980   T_no_more_interactions();
4981 }
4982 
4983 /*
4984  * Read a file following exactly the scenario in RFC 7440.
4985  * This test uses window size and block size options.  There are lost packets.
4986  * Tests:
4987  *   * The client uses of non-default options
4988  *     (windowsize = 4 and blocksize = 12).
4989  *   * Test the scenario included in RFC 7440.
4990  *   * When a packet from the server is lost (client receives DATA packet with
4991  *     a too high block number), the client sends an ACK for the last package
4992  *     received in the correct sequence.
4993  *   * The client ignores duplicated packets (with block numbers it has
4994  *     already processed).
4995  *   * The data of the file ends exactly at a window size border (i.e.
4996  *     after the window a single empty DATA packet is sent by the server).
4997  *   * The test reads a file from the file system in chunks of 10 bytes.
4998  */
4999 T_TEST_CASE_FIXTURE( read_file_rfc7440_scenario, &fixture_small_opt_size )
5000 {
5001   tftp_test_context *ctx = T_fixture_context();
5002   int i;
5003   int bytes_read;
5004   uint16_t block_num = 0;
5005   size_t pos_in_file = 0;
5006   const char options[] =
5007     TFTP_OPTION_WINDOWSIZE"\0"
5008     RTEMS_XSTRING( SMALL_WINDOW_SIZE ) "\0"
5009     TFTP_OPTION_BLKSIZE "\0"
5010     RTEMS_XSTRING( SMALL_BLOCK_SIZE );
5011 
5012   /* T_set_verbosity( T_VERBOSE ); */
5013   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
5014   _Tftp_Add_interaction_send_rrq(
5015     TFTP_FIRST_FD,
5016     tftpfs_file,
5017     TFTP_STD_PORT,
5018     tftpfs_ipv4_loopback,
5019     SMALL_BLOCK_SIZE,
5020     SMALL_WINDOW_SIZE,
5021     true
5022   );
5023   _Tftp_Add_interaction_recv_oack(
5024     TFTP_FIRST_FD,
5025     FIRST_TIMEOUT_MILLISECONDS,
5026     SERV_PORT,
5027     tftpfs_ipv4_loopback,
5028     options,
5029     sizeof( options ),
5030     true
5031   );
5032   _Tftp_Add_interaction_send_ack(
5033     TFTP_FIRST_FD,
5034     block_num,
5035     SERV_PORT,
5036     tftpfs_ipv4_loopback,
5037     true
5038   );
5039   for ( i = 0; i < SMALL_WINDOW_SIZE; ++i ) {
5040     _Tftp_Add_interaction_recv_data(
5041       TFTP_FIRST_FD,
5042       FIRST_TIMEOUT_MILLISECONDS,
5043       SERV_PORT,
5044       tftpfs_ipv4_loopback,
5045       ++block_num,
5046       pos_in_file,
5047       SMALL_BLOCK_SIZE, /* Number of bytes transferred */
5048       get_file_content,
5049       true
5050     );
5051     pos_in_file += SMALL_BLOCK_SIZE;
5052   }
5053   _Tftp_Add_interaction_send_ack(
5054     TFTP_FIRST_FD,
5055     block_num,
5056     SERV_PORT,
5057     tftpfs_ipv4_loopback,
5058     true
5059   );
5060   _Tftp_Add_interaction_recv_data(
5061     TFTP_FIRST_FD,
5062     FIRST_TIMEOUT_MILLISECONDS,
5063     SERV_PORT,
5064     tftpfs_ipv4_loopback,
5065     ++block_num,
5066     pos_in_file,
5067     SMALL_BLOCK_SIZE, /* Number of bytes transferred */
5068     get_file_content,
5069     true
5070   );
5071   pos_in_file += SMALL_BLOCK_SIZE;
5072   _Tftp_Add_interaction_recv_data(
5073     TFTP_FIRST_FD,
5074     FIRST_TIMEOUT_MILLISECONDS,
5075     SERV_PORT,
5076     tftpfs_ipv4_loopback,
5077     block_num + 2, /* Error: One packet from the server has been lost */
5078     pos_in_file,
5079     SMALL_BLOCK_SIZE, /* Number of bytes transferred */
5080     get_file_content,
5081     true
5082   );
5083   _Tftp_Add_interaction_send_ack(
5084     TFTP_FIRST_FD,
5085     block_num,
5086     SERV_PORT,
5087     tftpfs_ipv4_loopback,
5088     true
5089   );
5090   for ( i = 0; i < SMALL_WINDOW_SIZE; ++i ) {
5091     _Tftp_Add_interaction_recv_data(
5092       TFTP_FIRST_FD,
5093       FIRST_TIMEOUT_MILLISECONDS,
5094       SERV_PORT,
5095       tftpfs_ipv4_loopback,
5096       ++block_num,
5097       pos_in_file,
5098       SMALL_BLOCK_SIZE, /* Number of bytes transferred */
5099       get_file_content,
5100       true
5101     );
5102     pos_in_file += SMALL_BLOCK_SIZE;
5103   }
5104   _Tftp_Add_interaction_send_ack(
5105     TFTP_FIRST_FD,
5106     block_num,
5107     SERV_PORT,
5108     tftpfs_ipv4_loopback,
5109     true
5110   );
5111   _Tftp_Add_interaction_recv_data(
5112     TFTP_FIRST_FD,
5113     FIRST_TIMEOUT_MILLISECONDS,
5114     SERV_PORT,
5115     tftpfs_ipv4_loopback,
5116     ++block_num,
5117     pos_in_file,
5118     SMALL_BLOCK_SIZE, /* Number of bytes transferred */
5119     get_file_content,
5120     true
5121   );
5122   pos_in_file += SMALL_BLOCK_SIZE;
5123   _Tftp_Add_interaction_recv_data(
5124     TFTP_FIRST_FD,
5125     FIRST_TIMEOUT_MILLISECONDS,
5126     SERV_PORT,
5127     tftpfs_ipv4_loopback,
5128     block_num + 2, /* Error: One packet from the server has been lost */
5129     pos_in_file,
5130     SMALL_BLOCK_SIZE, /* Number of bytes transferred */
5131     get_file_content,
5132     true
5133   );
5134   _Tftp_Add_interaction_send_ack(
5135     TFTP_FIRST_FD,
5136     block_num, /* The packet is assumed to be lost/does not reach the server */
5137     SERV_PORT,
5138     tftpfs_ipv4_loopback,
5139     true
5140   );
5141   _Tftp_Add_interaction_recv_data(
5142     TFTP_FIRST_FD,
5143     FIRST_TIMEOUT_MILLISECONDS,
5144     SERV_PORT,
5145     tftpfs_ipv4_loopback,
5146     block_num + 3, /* Error: One packet from the server has been lost */
5147     pos_in_file,
5148     SMALL_BLOCK_SIZE, /* Number of bytes transferred */
5149     get_file_content,
5150     true
5151   );
5152   block_num = 9; /* The ACK for DATA packet 10 did not reach the server */
5153   pos_in_file = block_num * SMALL_BLOCK_SIZE;
5154   for ( i = 0; i < SMALL_WINDOW_SIZE; ++i ) {
5155     _Tftp_Add_interaction_recv_data(
5156       TFTP_FIRST_FD,
5157       FIRST_TIMEOUT_MILLISECONDS,
5158       SERV_PORT,
5159       tftpfs_ipv4_loopback,
5160       ++block_num,
5161       pos_in_file,
5162       SMALL_BLOCK_SIZE, /* Number of bytes transferred */
5163       get_file_content,
5164       true
5165     );
5166     pos_in_file += SMALL_BLOCK_SIZE;
5167   }
5168   _Tftp_Add_interaction_send_ack(
5169     TFTP_FIRST_FD,
5170     block_num,
5171     SERV_PORT,
5172     tftpfs_ipv4_loopback,
5173     true
5174   );
5175   _Tftp_Add_interaction_recv_data(
5176     TFTP_FIRST_FD,
5177     FIRST_TIMEOUT_MILLISECONDS,
5178     SERV_PORT,
5179     tftpfs_ipv4_loopback,
5180     ++block_num,
5181     pos_in_file,
5182     0, /* Number of bytes transferred */
5183     get_file_content,
5184     true
5185   );
5186   _Tftp_Add_interaction_send_ack(
5187     TFTP_FIRST_FD,
5188     block_num,
5189     SERV_PORT,
5190     tftpfs_ipv4_loopback,
5191     true
5192   );
5193   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
5194 
5195   bytes_read = read_tftp_file(
5196     create_tftpfs_path( tftpfs_ipv4_loopback, tftpfs_file ),
5197     10, /* Bytes read per call to read() */
5198     SIZE_MAX,
5199     &ctx->fd0
5200   );
5201   T_eq_int( bytes_read, pos_in_file );
5202   T_no_more_interactions();
5203 }
5204 
5205 /*
5206  * Read a file using windowsize = 4.  All kinds of packet loss, out of order
5207  * packets and duplicated packets occur.
5208  * This test uses window size and block size options.  It is a stress test
5209  * for all kind of network problems which can appear during a transfer
5210  * of a file with window size larger than 1.
5211  * Tests:
5212  *   * The client uses non-default options (windowsize = 4 and blocksize = 12).
5213  *   * The first DATA packet of a window is lost.
5214  *   * The last DATA packet of a window is lost.
5215  *   * The middle DATA packets of a window is lost.
5216  *   * The first two DATA packets of a window are received in reverse order.
5217  *   * The middle two DATA packets of a window are received in reverse order.
5218  *   * The last two DATA packets of a window are received in reverse order.
5219  *   * The a DATA packet is received duplicated.
5220  *   * The an old DATA packet is received duplicated.
5221  *   * The a very old DATA packet is received duplicated.
5222  *   * The normal ACK of a window is not received by the server.
5223  *   * The server repeats a whole window (ensure the client sends an ACK
5224  *     packet despite of the repetition).
5225  *   * An ACK for an out-of-order packet is not received by the server.
5226  *   * Windows with errors appear consecutively without
5227  *     error free windows in between.
5228  *   * After the reception of the first two DATA packets of a window,
5229  *     a timeout occurs and the client must send an ACK.
5230  *   * File transfer ends exactly with the last packet of a window
5231  *     (the second last packet is full and the last one is empty).
5232  *   * The test reads a file from the file system in chunks 100 bytes.
5233  */
5234 T_TEST_CASE_FIXTURE( read_file_windowsize_trouble, &fixture_small_opt_size )
5235 {
5236   tftp_test_context *ctx = T_fixture_context();
5237   int i;
5238   int bytes_read;
5239   uint16_t block_num = 0;
5240   size_t pos_in_file = 0;
5241   int timeout = FIRST_TIMEOUT_MILLISECONDS;
5242   const char options[] =
5243     TFTP_OPTION_WINDOWSIZE"\0"
5244     RTEMS_XSTRING( SMALL_WINDOW_SIZE ) "\0"
5245     TFTP_OPTION_BLKSIZE "\0"
5246     RTEMS_XSTRING( SMALL_BLOCK_SIZE );
5247   /*
5248    * A positive number is the number of a DATA packet received.
5249    * A negative number is the number of an ACK packet send.
5250    * A zero indicates a timeout when waiting for a DATA packet.
5251    * Each line corresponds to a window.
5252    */
5253   int16_t pkg_sequence[] = {
5254     1, 1, 2, 3, 2, 1, 3, 4, -4, /* Duplicated DATA packets */
5255     6, -4, 7, 8, /* DATA packet 5 lost */
5256     6, 5, 7, -5, 4, 8, /* DATA packet 5 and 6 received in revers order;
5257                           reception of an very old packet: 4 */
5258     7, 6, 8, -6, /* DATA packet 6 and 7 received in revers order;
5259                     DATA packet 9 not send or lost */
5260     6, 7, 8, 9, -9, /* ACK packet 6 was not received by server */
5261     10, 11, 12, 0, -12, /* DATA packet 13 lost */
5262     13, 16, -13, /* DATA packets 14, 15 lost */
5263     12, 13, 14, 15, -15, 16, 17, /* Reception of duplicated old packets 12 and
5264                                     13 */
5265     16, 17, 18, 19, -19, /* Normal sequence; ACK 19 not receive by server */
5266     16, 17, 18, 19, -19, /* Normal sequence repeated;
5267                             ACK 19 not receive by server */
5268     16, 19, -19, 18, 17, /* Sequence repeated but DATA packet 17 and 18
5269                             received after 19 and in revers order */
5270     20, -20, 21, 22, 23, /* ACK 20 because the client assumes the server
5271                             did not get ACK 19 and restarted with 17 */
5272     21, 22, 23, 24, -24, /* Normal sequence */
5273     25, 27, -25, 26, 28, -26, /* The middle data packets 26, 27 are exchanged;
5274                                  the client assumes DATA 26 being the start
5275                                  of the next window and sends an ACK 26
5276                                  upon reception of out-of-sequence DATA 28;
5277                                  assume ACK 26 not received by server */
5278     26, 27, 29, -27, 28, /* The last data packets are exchanged;
5279                             ACK 27 not received by server */
5280     26, 27, 28, 29, -29, /* Normal sequence repeated from ACK 25 */
5281     30, 31, 0, -31, /* The last two data packets are lost (timeout) */
5282     32, 33, 34, /* Normal sequence; the last DATA packet (here missing) will
5283                    contain no data and ends the transfer at a window
5284                    boundary; a final ACK (here missing too) follows */
5285   };
5286 
5287   /* T_set_verbosity( T_VERBOSE ); */
5288   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
5289   _Tftp_Add_interaction_send_rrq(
5290     TFTP_FIRST_FD,
5291     tftpfs_file,
5292     TFTP_STD_PORT,
5293     tftpfs_ipv4_loopback,
5294     SMALL_BLOCK_SIZE,
5295     SMALL_WINDOW_SIZE,
5296     true
5297   );
5298   _Tftp_Add_interaction_recv_oack(
5299     TFTP_FIRST_FD,
5300     FIRST_TIMEOUT_MILLISECONDS,
5301     SERV_PORT,
5302     tftpfs_ipv4_loopback,
5303     options,
5304     sizeof( options ),
5305     true
5306   );
5307   _Tftp_Add_interaction_send_ack(
5308     TFTP_FIRST_FD,
5309     block_num,
5310     SERV_PORT,
5311     tftpfs_ipv4_loopback,
5312     true
5313   );
5314   for ( i = 0; i < RTEMS_ARRAY_SIZE( pkg_sequence ); ++i ) {
5315     if ( pkg_sequence[i] == 0 ) {
5316       block_num = pkg_sequence[i];
5317       _Tftp_Add_interaction_recv_nothing(
5318         TFTP_FIRST_FD, /* Timeout: No packet received within timeout period */
5319         timeout
5320       );
5321       timeout = TIMEOUT_MILLISECONDS;
5322     } else if ( pkg_sequence[i] > 0 ) {
5323       block_num = pkg_sequence[i];
5324       _Tftp_Add_interaction_recv_data(
5325         TFTP_FIRST_FD,
5326         timeout,
5327         SERV_PORT,
5328         tftpfs_ipv4_loopback,
5329         block_num,
5330         ( block_num - 1 ) * SMALL_BLOCK_SIZE,
5331         SMALL_BLOCK_SIZE, /* Number of bytes transferred */
5332         get_file_content,
5333         pkg_sequence[i] > 0 /* pkg_sequence[i] == 0 means timeout */
5334       );
5335       timeout = FIRST_TIMEOUT_MILLISECONDS;
5336       pos_in_file = block_num * SMALL_BLOCK_SIZE;
5337     } else {
5338       block_num = -pkg_sequence[i];
5339       _Tftp_Add_interaction_send_ack(
5340         TFTP_FIRST_FD,
5341         block_num,
5342         SERV_PORT,
5343         tftpfs_ipv4_loopback,
5344         true
5345       );
5346     }
5347   }
5348   _Tftp_Add_interaction_recv_data(
5349     TFTP_FIRST_FD,
5350     timeout,
5351     SERV_PORT,
5352     tftpfs_ipv4_loopback,
5353     ++block_num,
5354     pos_in_file,
5355     0, /* Number of bytes transferred */
5356     get_file_content,
5357     true
5358   );
5359   _Tftp_Add_interaction_send_ack(
5360     TFTP_FIRST_FD,
5361     block_num,
5362     SERV_PORT,
5363     tftpfs_ipv4_loopback,
5364     true
5365   );
5366   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
5367 
5368   bytes_read = read_tftp_file(
5369     create_tftpfs_path( tftpfs_ipv4_loopback, tftpfs_file ),
5370     100, /* Bytes read per call to read() */
5371     SIZE_MAX,
5372     &ctx->fd0
5373   );
5374   T_eq_int( bytes_read, pos_in_file );
5375   T_no_more_interactions();
5376 }
5377 
5378 /*
5379  * Write a file to the server using an option to increase block size.
5380  * The file is 2 DATA packet and 1 byte long.  No timeouts, packet loss, ...
5381  * Tests:
5382  *   * The client uses only the blksize option in WRQ and OACK.
5383  *   * The client uses a block size which is larger than the default size.
5384  *   * The server can change the block size value in the OACK.
5385  *   * The option name in the OACK can be upper or lower case.
5386  *   * First and second DATA packets are full.
5387  *   * The second DATA packet is not full and signals the end of the transfer.
5388  *   * The client handles an empty DATA packet correctly as
5389  *     end of file indicator.
5390  *   * The test writes the file to the file system in chunks of 333 bytes.
5391  */
5392 T_TEST_CASE_FIXTURE( write_simple_file_large_blocks, &fixture_large_blocksize )
5393 {
5394   tftp_test_context *ctx = T_fixture_context();
5395   int bytes_written;
5396   size_t pos_in_file = 0;
5397   uint16_t block_num = 1;
5398   uint16_t block_size = 211;
5399   const char options[] = "BLKsiZe" "\0" "211";
5400 
5401   /* T_set_verbosity( T_VERBOSE ); */
5402   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
5403   _Tftp_Add_interaction_send_wrq(
5404     TFTP_FIRST_FD,
5405     tftpfs_file,
5406     TFTP_STD_PORT,
5407     tftpfs_ipv4_loopback,
5408     LARGE_BLOCK_SIZE,
5409     NO_WINDOW_SIZE_OPTION,
5410     true
5411   );
5412   _Tftp_Add_interaction_recv_oack(
5413     TFTP_FIRST_FD,
5414     FIRST_TIMEOUT_MILLISECONDS,
5415     SERV_PORT,
5416     tftpfs_ipv4_loopback,
5417     options,
5418     sizeof( options ),
5419     true
5420   );
5421   _Tftp_Add_interaction_send_data(
5422     TFTP_FIRST_FD,
5423     block_num,
5424     pos_in_file,
5425     block_size,
5426     get_file_content,
5427     SERV_PORT,
5428     tftpfs_ipv4_loopback,
5429     true
5430   );
5431   pos_in_file += block_size;
5432   _Tftp_Add_interaction_recv_ack(
5433     TFTP_FIRST_FD,
5434     FIRST_TIMEOUT_MILLISECONDS,
5435     SERV_PORT,
5436     tftpfs_ipv4_loopback,
5437     block_num++,
5438     true
5439   );
5440   _Tftp_Add_interaction_send_data(
5441     TFTP_FIRST_FD,
5442     block_num,
5443     pos_in_file,
5444     block_size,
5445     get_file_content,
5446     SERV_PORT,
5447     tftpfs_ipv4_loopback,
5448     true
5449   );
5450   pos_in_file += block_size;
5451   _Tftp_Add_interaction_recv_ack(
5452     TFTP_FIRST_FD,
5453     FIRST_TIMEOUT_MILLISECONDS,
5454     SERV_PORT,
5455     tftpfs_ipv4_loopback,
5456     block_num++,
5457     true
5458   );
5459   _Tftp_Add_interaction_send_data(
5460     TFTP_FIRST_FD,
5461     block_num,
5462     pos_in_file,
5463     1, /* Data bytes in this block */
5464     get_file_content,
5465     SERV_PORT,
5466     tftpfs_ipv4_loopback,
5467     true
5468   );
5469   pos_in_file += 1;
5470   _Tftp_Add_interaction_recv_ack(
5471     TFTP_FIRST_FD,
5472     FIRST_TIMEOUT_MILLISECONDS,
5473     SERV_PORT,
5474     tftpfs_ipv4_loopback,
5475     block_num++,
5476     true
5477   );
5478   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
5479 
5480   bytes_written = write_tftp_file(
5481     create_tftpfs_path( tftpfs_ipv4_loopback, tftpfs_file ),
5482     pos_in_file, /* Size of file */
5483     333, /* Bytes written per call to write() */
5484     &ctx->fd0
5485   );
5486   T_eq_int( bytes_written, pos_in_file );
5487   T_no_more_interactions();
5488 }
5489 
5490 /*
5491  * Write a file to the server using default options.
5492  * The file is 23 data packet long.  No timeouts, packet loss, ...
5493  * Tests:
5494  *   * The client uses the default options
5495  *     (windowsize = 8 and blocksize = 1456).
5496  *   * The server sends the options in the same order the client
5497  *     did send them.
5498  *   * The 24th data packet signals the end of file transfer.
5499  *   * Client sends an empty data packet as end of file indicator.
5500  *   * The client handles files correctly which end exactly at
5501  *     a window border.
5502  */
5503 T_TEST_CASE_FIXTURE(
5504   write_simple_file_default_options,
5505   &fixture_default_options
5506 )
5507 {
5508   tftp_test_context *ctx = T_fixture_context();
5509   int i;
5510   int bytes_written;
5511   size_t pos_in_file = 0;
5512   uint16_t block_num = 1;
5513   const char options[] =
5514     TFTP_OPTION_BLKSIZE "\0"
5515     RTEMS_XSTRING( TFTP_DEFAULT_BLOCK_SIZE ) "\0"
5516     TFTP_OPTION_WINDOWSIZE "\0"
5517     RTEMS_XSTRING( TFTP_DEFAULT_WINDOW_SIZE );
5518 
5519   /* T_set_verbosity( T_VERBOSE ); */
5520   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
5521   _Tftp_Add_interaction_send_wrq(
5522     TFTP_FIRST_FD,
5523     tftpfs_file,
5524     TFTP_STD_PORT,
5525     tftpfs_ipv4_loopback,
5526     TFTP_DEFAULT_BLOCK_SIZE,
5527     TFTP_DEFAULT_WINDOW_SIZE,
5528     true
5529   );
5530   _Tftp_Add_interaction_recv_oack(
5531     TFTP_FIRST_FD,
5532     FIRST_TIMEOUT_MILLISECONDS,
5533     SERV_PORT,
5534     tftpfs_ipv4_loopback,
5535     options,
5536     sizeof( options ),
5537     true
5538   );
5539   for ( i = 0; i < 23; ++i ) {
5540     _Tftp_Add_interaction_send_data(
5541       TFTP_FIRST_FD,
5542       block_num++,
5543       pos_in_file,
5544       TFTP_DEFAULT_BLOCK_SIZE,
5545       get_file_content,
5546       SERV_PORT,
5547       tftpfs_ipv4_loopback,
5548       true
5549     );
5550     pos_in_file += TFTP_DEFAULT_BLOCK_SIZE;
5551     if ( i % 8 == 7 ) {
5552       _Tftp_Add_interaction_recv_ack(
5553         TFTP_FIRST_FD,
5554         FIRST_TIMEOUT_MILLISECONDS,
5555         SERV_PORT,
5556         tftpfs_ipv4_loopback,
5557         block_num - 1,
5558         true
5559       );
5560     } else {
5561       _Tftp_Add_interaction_recv_nothing(
5562         TFTP_FIRST_FD,
5563         DO_NOT_WAIT_FOR_ANY_TIMEOUT
5564       );
5565     }
5566   }
5567   _Tftp_Add_interaction_send_data(
5568     TFTP_FIRST_FD,
5569     block_num,
5570     pos_in_file,
5571     0,
5572     get_file_content,
5573     SERV_PORT,
5574     tftpfs_ipv4_loopback,
5575     true
5576   );
5577   _Tftp_Add_interaction_recv_ack(
5578     TFTP_FIRST_FD,
5579     FIRST_TIMEOUT_MILLISECONDS,
5580     SERV_PORT,
5581     tftpfs_ipv4_loopback,
5582     block_num++,
5583     true
5584   );
5585   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
5586 
5587   bytes_written = write_tftp_file(
5588     create_tftpfs_path( tftpfs_ipv4_loopback, tftpfs_file ),
5589     pos_in_file, /* Size of file */
5590     333, /* Bytes written per call to write() */
5591     &ctx->fd0
5592   );
5593   T_eq_int( bytes_written, pos_in_file );
5594   T_no_more_interactions();
5595 }
5596 
5597 /*
5598  * Write a file following exactly the scenario from RFC 7440.
5599  * This test uses window size and block size options.  There are lost packets.
5600  * Tests:
5601  *   * The client uses non-default options
5602  *     (windowsize = 4 and blocksize = 12).
5603  *   * Test the scenario included in RFC 7440.
5604  *   * The server sends the options in the inverse order the client
5605  *     did send them.
5606  *   * The data of the file ends exactly at a window size border (i.e.
5607  *     after the last window the server sends a single empty DATA packet).
5608  *   * The test writes a file to the file system in chunks of 10 bytes.
5609  */
5610 T_TEST_CASE_FIXTURE( write_file_rfc7440_scenario, &fixture_small_opt_size )
5611 {
5612   tftp_test_context *ctx = T_fixture_context();
5613   int i;
5614   int bytes_written;
5615   size_t pos_in_file = 0;
5616   uint16_t block_num = 1;
5617   const char options[] =
5618     TFTP_OPTION_WINDOWSIZE"\0"
5619     RTEMS_XSTRING( SMALL_WINDOW_SIZE ) "\0"
5620     TFTP_OPTION_BLKSIZE "\0"
5621     RTEMS_XSTRING( SMALL_BLOCK_SIZE );
5622 
5623   /* T_set_verbosity( T_VERBOSE ); */
5624   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
5625   _Tftp_Add_interaction_send_wrq(
5626     TFTP_FIRST_FD,
5627     tftpfs_file,
5628     TFTP_STD_PORT,
5629     tftpfs_ipv4_loopback,
5630     SMALL_BLOCK_SIZE,
5631     SMALL_WINDOW_SIZE,
5632     true
5633   );
5634   _Tftp_Add_interaction_recv_oack(
5635     TFTP_FIRST_FD,
5636     FIRST_TIMEOUT_MILLISECONDS,
5637     SERV_PORT,
5638     tftpfs_ipv4_loopback,
5639     options,
5640     sizeof( options ),
5641     true
5642   );
5643   for ( i = 0; i < 6; ++i ) {
5644     _Tftp_Add_interaction_send_data(
5645       TFTP_FIRST_FD,
5646       block_num++,
5647       pos_in_file,
5648       SMALL_BLOCK_SIZE,
5649       get_file_content,
5650       SERV_PORT,
5651       tftpfs_ipv4_loopback,
5652       true
5653     );
5654     pos_in_file += SMALL_BLOCK_SIZE;
5655     if ( i % 4 == 3 ) {
5656       _Tftp_Add_interaction_recv_ack(
5657         TFTP_FIRST_FD,
5658         FIRST_TIMEOUT_MILLISECONDS,
5659         SERV_PORT,
5660         tftpfs_ipv4_loopback,
5661         block_num - 1,
5662         true
5663       );
5664     } else {
5665       _Tftp_Add_interaction_recv_nothing(
5666         TFTP_FIRST_FD,
5667         DO_NOT_WAIT_FOR_ANY_TIMEOUT
5668       );
5669     }
5670   }
5671   _Tftp_Add_interaction_send_data(
5672     TFTP_FIRST_FD,
5673     block_num,
5674     pos_in_file,
5675     SMALL_BLOCK_SIZE,
5676     get_file_content,
5677     SERV_PORT,
5678     tftpfs_ipv4_loopback,
5679     true
5680   );
5681   _Tftp_Add_interaction_recv_ack(
5682     TFTP_FIRST_FD,
5683     DO_NOT_WAIT_FOR_ANY_TIMEOUT,
5684     SERV_PORT,
5685     tftpfs_ipv4_loopback,
5686     5,
5687     true
5688   );
5689   block_num = 6;
5690   pos_in_file = (block_num - 1) * SMALL_BLOCK_SIZE;
5691   for ( i = 0; i < 7; ++i ) {
5692     _Tftp_Add_interaction_send_data(
5693       TFTP_FIRST_FD,
5694       block_num++,
5695       pos_in_file,
5696       SMALL_BLOCK_SIZE,
5697       get_file_content,
5698       SERV_PORT,
5699       tftpfs_ipv4_loopback,
5700       true
5701     );
5702     pos_in_file += SMALL_BLOCK_SIZE;
5703     if ( i % 4 == 3 ) {
5704       _Tftp_Add_interaction_recv_ack(
5705         TFTP_FIRST_FD,
5706         FIRST_TIMEOUT_MILLISECONDS,
5707         SERV_PORT,
5708         tftpfs_ipv4_loopback,
5709         block_num - 1,
5710         true
5711       );
5712     } else {
5713       _Tftp_Add_interaction_recv_nothing(
5714         TFTP_FIRST_FD,
5715         DO_NOT_WAIT_FOR_ANY_TIMEOUT
5716       );
5717     }
5718   }
5719   _Tftp_Add_interaction_send_data(
5720     TFTP_FIRST_FD,
5721     block_num,
5722     pos_in_file,
5723     SMALL_BLOCK_SIZE,
5724     get_file_content,
5725     SERV_PORT,
5726     tftpfs_ipv4_loopback,
5727     true
5728   );
5729   _Tftp_Add_interaction_recv_nothing(
5730     TFTP_FIRST_FD,
5731     FIRST_TIMEOUT_MILLISECONDS
5732   );
5733   block_num = 10;
5734   pos_in_file = (block_num - 1) * SMALL_BLOCK_SIZE;
5735   for ( i = 0; i < 4; ++i ) {
5736     _Tftp_Add_interaction_send_data(
5737       TFTP_FIRST_FD,
5738       block_num++,
5739       pos_in_file,
5740       SMALL_BLOCK_SIZE,
5741       get_file_content,
5742       SERV_PORT,
5743       tftpfs_ipv4_loopback,
5744       true
5745     );
5746     pos_in_file += SMALL_BLOCK_SIZE;
5747     if ( i % 4 == 3 ) {
5748       _Tftp_Add_interaction_recv_ack(
5749         TFTP_FIRST_FD,
5750         FIRST_TIMEOUT_MILLISECONDS,
5751         SERV_PORT,
5752         tftpfs_ipv4_loopback,
5753         block_num - 1,
5754         true
5755       );
5756     } else {
5757       _Tftp_Add_interaction_recv_nothing(
5758         TFTP_FIRST_FD,
5759         DO_NOT_WAIT_FOR_ANY_TIMEOUT
5760       );
5761     }
5762   }
5763   _Tftp_Add_interaction_send_data(
5764     TFTP_FIRST_FD,
5765     block_num,
5766     pos_in_file,
5767     0,
5768     get_file_content,
5769     SERV_PORT,
5770     tftpfs_ipv4_loopback,
5771     true
5772   );
5773   _Tftp_Add_interaction_recv_ack(
5774     TFTP_FIRST_FD,
5775     FIRST_TIMEOUT_MILLISECONDS,
5776     SERV_PORT,
5777     tftpfs_ipv4_loopback,
5778     block_num++,
5779     true
5780   );
5781   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
5782 
5783   bytes_written = write_tftp_file(
5784     create_tftpfs_path( tftpfs_ipv4_loopback, tftpfs_file ),
5785     pos_in_file, /* Size of file */
5786     10, /* Bytes written per call to write() */
5787     &ctx->fd0
5788   );
5789   T_eq_int( bytes_written, pos_in_file );
5790   T_no_more_interactions();
5791 }
5792 
5793 /*
5794  * Write a file using windowsize = 4.  All kinds of packet loss, out of
5795  * order packets and duplicated ACK packets appear.
5796  * This test uses window size and block size options.  It is a stress test
5797  * for all kind of network problems which can appear during a transfer
5798  * of a file with window size larger than 1.
5799  * Tests:
5800  *   * The server repeats a whole window (timeout).
5801  *   * The client receives a duplicated ACK packet (directly in sequence).
5802  *   * The client receives a duplicated ACK (after sending a window).
5803  *   * The client receives an ACK with a block number which is not
5804  *     the end of the current window.
5805  *   * The client receives an very old ACK in the middle of a window.
5806  *   * The client receives an very old ACK at the end of a window.
5807  *   * The client receives an ACK for a not yet send DATA packet in the
5808  *     middle of a window (should be ignored or cause a error).
5809  *   * The client receives an ACK for a not yet send DATA packet at the
5810  *     end of a window (should be ignored or cause a error).
5811  *   * The client receives an ACK after sending a full window.
5812  *   * The client receives an ACK before all DATA packets of a
5813  *     window have been sent.
5814  *   * The client must repeat the first window completely (timeout).
5815  *   * The client must repeat the first window partially.
5816  *   * The client must repeat the last window completely (timeout).
5817  *   * The client must repeat the last window partially.
5818  *   * Windows with errors in between appear consecutively, without
5819  *     error free windows in between.
5820  *   * The test writes a file to the file system in chunks of block size.
5821  */
5822 T_TEST_CASE_FIXTURE( write_file_windowsize_trouble, &fixture_small_opt_size )
5823 {
5824   tftp_test_context *ctx = T_fixture_context();
5825   int i;
5826   int bytes_written;
5827   size_t pos_in_file = 0;
5828   uint16_t block_num = 1;
5829   int timeout = FIRST_TIMEOUT_MILLISECONDS;
5830   const char options[] =
5831     TFTP_OPTION_BLKSIZE "\0"
5832     RTEMS_XSTRING( SMALL_BLOCK_SIZE ) "\0"
5833     TFTP_OPTION_WINDOWSIZE"\0"
5834     RTEMS_XSTRING( SMALL_WINDOW_SIZE );
5835   /*
5836    * A positive number is the number of an ACK packet received
5837    *   at the end of window.
5838    * A 9999 indicates a timeout when waiting for an ACK packet.
5839    * A zero indicates no ACK packet is received when checking for it.
5840    * A positive number >= 10000 is the number+10000 of an ACK packet received
5841    *   while only checking for a packet.
5842    * A negative number is the number of a DATA packet send
5843    *   at the end of a window.
5844    * A negative number <= -10000 is the number-10000 of an *empty* DATA
5845    *   packet send.
5846    * Each line corresponds to a window.
5847    */
5848   int16_t pkg_sequence[] = {
5849     -1, 0, -2, 0, -3, 0, -4, 9999, /* First window, trigger full repeat */
5850     -1, 0, -2, 0, -3, 0, -4, 2, /* ACK at end of window;
5851                                    first window must be partially repeated */
5852     -3, 0, -4, 0, -5, 0, -6, 6, /* Normal sequence */
5853     -7, 0, -8, 0, -9, 0, -10, 6, /* Duplicate ACK */
5854     -7, 10006, /* Duplicate ACK; ACK before sending all packets of a window */
5855     -7, 0, -8, 10008, /* ACK before sending all packets of a window;
5856                          ACK is not at the window end */
5857     -9, 10007, 0, -10, 10013, 0, -11, 0, -12, 12, /* Reception of very old ACK;
5858                                                     Reception of future ACK (The
5859                                                     wrong "future" ACK must be
5860                                                     beyond the block size)
5861                                                     in the middle of a window */
5862     -13, 0, -14, 0, -15, 0, -16, 11, 17, 16, /* Reception of very old ACK;
5863                                                 Reception of future ACK at the
5864                                                 end of a window */
5865     -17, 0, -18, 0, -10019, 9999, /* Last window timeout, trigger full repeat */
5866     -17, 0, -18, 0, -10019, 16, /* Last window, duplicated ACK */
5867     -17, 0, -18, 10017, /* Last window, ACK before sending all packets */
5868     -18, 0, -10019, 19 /* Last window partially repeated */
5869   };
5870 
5871   /* T_set_verbosity( T_VERBOSE ); */
5872   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
5873   _Tftp_Add_interaction_send_wrq(
5874     TFTP_FIRST_FD,
5875     tftpfs_file,
5876     TFTP_STD_PORT,
5877     tftpfs_ipv4_loopback,
5878     SMALL_BLOCK_SIZE,
5879     SMALL_WINDOW_SIZE,
5880     true
5881   );
5882   _Tftp_Add_interaction_recv_oack(
5883     TFTP_FIRST_FD,
5884     FIRST_TIMEOUT_MILLISECONDS,
5885     SERV_PORT,
5886     tftpfs_ipv4_loopback,
5887     options,
5888     sizeof( options ),
5889     true
5890   );
5891   for ( i = 0; i < RTEMS_ARRAY_SIZE( pkg_sequence ); ++i ) {
5892     if ( pkg_sequence[i] == 0 ) {
5893       _Tftp_Add_interaction_recv_nothing(
5894         TFTP_FIRST_FD,
5895         DO_NOT_WAIT_FOR_ANY_TIMEOUT
5896       );
5897       timeout = FIRST_TIMEOUT_MILLISECONDS;
5898     } else if ( pkg_sequence[i] == 9999 ) {
5899       _Tftp_Add_interaction_recv_nothing(
5900         TFTP_FIRST_FD,
5901         timeout
5902       );
5903       timeout = FIRST_TIMEOUT_MILLISECONDS;
5904     } else if ( pkg_sequence[i] >= 10000 ) {
5905       block_num = pkg_sequence[i] - 10000;
5906       _Tftp_Add_interaction_recv_ack(
5907         TFTP_FIRST_FD,
5908         DO_NOT_WAIT_FOR_ANY_TIMEOUT,
5909         SERV_PORT,
5910         tftpfs_ipv4_loopback,
5911         block_num++,
5912         true
5913       );
5914       timeout = FIRST_TIMEOUT_MILLISECONDS;
5915     } else if ( pkg_sequence[i] > 0 ) {
5916       block_num = pkg_sequence[i];
5917       _Tftp_Add_interaction_recv_ack(
5918         TFTP_FIRST_FD,
5919         timeout,
5920         SERV_PORT,
5921         tftpfs_ipv4_loopback,
5922         block_num++,
5923         true
5924       );
5925       timeout = FIRST_TIMEOUT_MILLISECONDS;
5926     } else if ( pkg_sequence[i] <= -10000 ) {
5927       block_num = -pkg_sequence[i] - 10000;
5928       pos_in_file = (block_num - 1) * SMALL_BLOCK_SIZE;
5929       _Tftp_Add_interaction_send_data(
5930         TFTP_FIRST_FD,
5931         block_num++,
5932         pos_in_file,
5933         0, /* Number of bytes transferred */
5934         get_file_content,
5935         SERV_PORT,
5936         tftpfs_ipv4_loopback,
5937         true
5938       );
5939       timeout = FIRST_TIMEOUT_MILLISECONDS;
5940     } else {
5941       block_num = -pkg_sequence[i];
5942       pos_in_file = (block_num - 1) * SMALL_BLOCK_SIZE;
5943       _Tftp_Add_interaction_send_data(
5944         TFTP_FIRST_FD,
5945         block_num++,
5946         pos_in_file,
5947         SMALL_BLOCK_SIZE,
5948         get_file_content,
5949         SERV_PORT,
5950         tftpfs_ipv4_loopback,
5951         true
5952       );
5953       timeout = FIRST_TIMEOUT_MILLISECONDS;
5954       pos_in_file += SMALL_BLOCK_SIZE;
5955     }
5956   }
5957   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
5958 
5959   bytes_written = write_tftp_file(
5960     create_tftpfs_path( tftpfs_ipv4_loopback, tftpfs_file ),
5961     pos_in_file, /* Size of file */
5962     SMALL_BLOCK_SIZE, /* Bytes written per call to write() */
5963     &ctx->fd0
5964   );
5965   T_eq_int( bytes_written, pos_in_file );
5966   T_no_more_interactions();
5967 }
5968 
5969 /*
5970  * Write a file to the server where the server sends an OACK without options.
5971  * The file is half a data packet long.  No timeouts, packet loss, ...
5972  * Tests:
5973  *   * The client processes an OACK without any options in it correctly.
5974  *   * The client uses the RFC1350 block size because the server does
5975  *     not agree to the options send.
5976  *   * The first data packet is half full and signals the end of the transfer.
5977  *   * The test reads a file from the file system in chunks of double block size.
5978  */
5979 T_TEST_CASE_FIXTURE( write_tiny_file_OACK_no_options, &fixture_large_blocksize )
5980 {
5981   tftp_test_context *ctx = T_fixture_context();
5982   int bytes_written;
5983   size_t pos_in_file = 0;
5984   uint16_t block_num = 1;
5985   const char options[] = {};
5986 
5987   /* T_set_verbosity( T_VERBOSE ); */
5988   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
5989   _Tftp_Add_interaction_send_wrq(
5990     TFTP_FIRST_FD,
5991     tftpfs_file,
5992     TFTP_STD_PORT,
5993     tftpfs_ipv4_loopback,
5994     LARGE_BLOCK_SIZE,
5995     NO_WINDOW_SIZE_OPTION,
5996     true
5997   );
5998   _Tftp_Add_interaction_recv_oack(
5999     TFTP_FIRST_FD,
6000     FIRST_TIMEOUT_MILLISECONDS,
6001     SERV_PORT,
6002     tftpfs_ipv4_loopback,
6003     options,
6004     sizeof( options ),
6005     true
6006   );
6007   _Tftp_Add_interaction_send_data(
6008     TFTP_FIRST_FD,
6009     block_num,
6010     pos_in_file,
6011     TFTP_RFC1350_BLOCK_SIZE / 2,
6012     get_file_content,
6013     SERV_PORT,
6014     tftpfs_ipv4_loopback,
6015     true
6016   );
6017   pos_in_file += TFTP_RFC1350_BLOCK_SIZE / 2;
6018   _Tftp_Add_interaction_recv_ack(
6019     TFTP_FIRST_FD,
6020     FIRST_TIMEOUT_MILLISECONDS,
6021     SERV_PORT,
6022     tftpfs_ipv4_loopback,
6023     block_num++,
6024     true
6025   );
6026   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
6027 
6028   bytes_written = write_tftp_file(
6029     create_tftpfs_path( tftpfs_ipv4_loopback, tftpfs_file ),
6030     pos_in_file, /* Size of file */
6031     2 * TFTP_RFC1350_BLOCK_SIZE, /* Bytes written per call to write() */
6032     &ctx->fd0
6033   );
6034   T_eq_int( bytes_written, pos_in_file );
6035   T_no_more_interactions();
6036 }
6037 
6038 /*
6039  * Read a file and when the server responses with an ERROR to options
6040  * fallback to no options.
6041  * The file is one byte long.  No timeouts, packet loss, ...
6042  * Tests:
6043  *   * The client uses windowsize and blksize option in the first RRQ.
6044  *   * Upon reception of an ERROR packet from the server, the client
6045  *     re-tries opening the session using an RRQ without options.
6046  *   * The server accepts the RRQ without options by sending a DATA packet.
6047  *   * The second RRQ is sent to the TFTP server port 69 and not to the
6048  *     port from which the first ERROR packet came from.
6049  *   * The first data packet contains a single byte and signals the
6050  *     end of the transfer.
6051  */
6052 T_TEST_CASE_FIXTURE( read_file_fallback_to_no_options,
6053   &fixture_default_options )
6054 {
6055   tftp_test_context *ctx = T_fixture_context();
6056   int bytes_read;
6057   uint16_t block_num = 1;
6058   size_t pos_in_file = 0;
6059 
6060   /* T_set_verbosity( T_VERBOSE ); */
6061   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
6062   _Tftp_Add_interaction_send_rrq(
6063     TFTP_FIRST_FD,
6064     tftpfs_file,
6065     TFTP_STD_PORT,
6066     tftpfs_ipv4_loopback,
6067     TFTP_DEFAULT_BLOCK_SIZE,
6068     TFTP_DEFAULT_WINDOW_SIZE,
6069     true
6070   );
6071   _Tftp_Add_interaction_recv_error(
6072     TFTP_FIRST_FD,
6073     FIRST_TIMEOUT_MILLISECONDS,
6074     SERV_PORT,
6075     tftpfs_ipv4_loopback,
6076     TFTP_ERROR_CODE_OPTION_NEGO,
6077     "Don't like options",
6078     true
6079   );
6080   _Tftp_Add_interaction_send_rrq(
6081     TFTP_FIRST_FD,
6082     tftpfs_file,
6083     TFTP_STD_PORT,
6084     tftpfs_ipv4_loopback,
6085     NO_BLOCK_SIZE_OPTION,
6086     NO_WINDOW_SIZE_OPTION,
6087     true
6088   );
6089   _Tftp_Add_interaction_recv_data(
6090     TFTP_FIRST_FD,
6091     FIRST_TIMEOUT_MILLISECONDS,
6092     SERV_PORT,
6093     tftpfs_ipv4_loopback,
6094     block_num,
6095     pos_in_file,
6096     1, /* Number of bytes transferred */
6097     get_file_content,
6098     true
6099   );
6100   pos_in_file += 1;
6101   _Tftp_Add_interaction_send_ack(
6102     TFTP_FIRST_FD,
6103     block_num++,
6104     SERV_PORT,
6105     tftpfs_ipv4_loopback,
6106     true
6107   );
6108   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
6109 
6110   bytes_read = read_tftp_file(
6111     create_tftpfs_path( tftpfs_ipv4_loopback, tftpfs_file ),
6112     TFTP_DEFAULT_BLOCK_SIZE / 2, /* Bytes read per call to read() */
6113     SIZE_MAX,
6114     &ctx->fd0
6115   );
6116   T_eq_int( bytes_read, pos_in_file );
6117   T_no_more_interactions();
6118 }
6119 
6120 /*
6121  * Read a file from the server but the server responds with
6122  * an ERROR to all RRQ with and without options.
6123  * The file is one byte long.  No timeouts, packet loss, ...
6124  * Tests:
6125  *   * The client uses windowsize and blksize option in the first RRQ.
6126  *   * Upon reception of an ERROR packet from the server, the client
6127  *     re-tries opening a session using an RRQ without options.
6128  *   * The second RRQ is sent to the TFTP server port 69 and not to the
6129  *     port from which the first ERROR packet came from.
6130  *   * The server does not accept the RRQ without options
6131  *     and responds again with an ERROR packet.
6132  *   * The client ends all attempts to create a connection after
6133  *     receiving an ERROR packet to an RRQ without options.
6134  *   * The client signals the error to the user.
6135  */
6136 T_TEST_CASE_FIXTURE( read_file_useless_fallback_to_no_options,
6137   &fixture_default_options )
6138 {
6139   tftp_test_context *ctx = T_fixture_context();
6140   int bytes_read;
6141 
6142   /* T_set_verbosity( T_VERBOSE ); */
6143   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
6144   _Tftp_Add_interaction_send_rrq(
6145     TFTP_FIRST_FD,
6146     tftpfs_file,
6147     TFTP_STD_PORT,
6148     tftpfs_ipv4_loopback,
6149     TFTP_DEFAULT_BLOCK_SIZE,
6150     TFTP_DEFAULT_WINDOW_SIZE,
6151     true
6152   );
6153   _Tftp_Add_interaction_recv_error(
6154     TFTP_FIRST_FD,
6155     FIRST_TIMEOUT_MILLISECONDS,
6156     SERV_PORT,
6157     tftpfs_ipv4_loopback,
6158     TFTP_ERROR_CODE_ILLEGAL,
6159     "Don't like options",
6160     true
6161   );
6162   _Tftp_Add_interaction_send_rrq(
6163     TFTP_FIRST_FD,
6164     tftpfs_file,
6165     TFTP_STD_PORT,
6166     tftpfs_ipv4_loopback,
6167     NO_BLOCK_SIZE_OPTION,
6168     NO_WINDOW_SIZE_OPTION,
6169     true
6170   );
6171   _Tftp_Add_interaction_recv_error(
6172     TFTP_FIRST_FD,
6173     FIRST_TIMEOUT_MILLISECONDS,
6174     SERV_PORT,
6175     tftpfs_ipv4_loopback,
6176     TFTP_ERROR_CODE_ILLEGAL,
6177     "Go away",
6178     true
6179   );
6180   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
6181 
6182   bytes_read = read_tftp_file(
6183     create_tftpfs_path( tftpfs_ipv4_loopback, tftpfs_file ),
6184     TFTP_DEFAULT_BLOCK_SIZE / 2, /* Bytes read per call to read() */
6185     SIZE_MAX,
6186     &ctx->fd0
6187   );
6188   T_eq_int( errno, EINVAL );
6189   T_eq_int( bytes_read, 0 );
6190   T_no_more_interactions();
6191 }
6192 
6193 /*
6194  * Write a file to the server and the server responses with an ACK packet.
6195  * The file is half a data packet long.  No timeouts, packet loss, ...
6196  * Tests:
6197  *   * The client uses windowsize and blksize option in the WRQ.
6198  *   * The client uses the RFC1350 option values for the data transfer
6199  *     because the server responded with an ACK packet.
6200  *   * The whole package sequence behaves as if only RFC1350 was used.
6201  *   * The first data packet is half filled and signals the end of the
6202  *     transfer.
6203  */
6204 T_TEST_CASE_FIXTURE( write_file_ACK_instead_of_OACK, &fixture_default_options )
6205 {
6206   tftp_test_context *ctx = T_fixture_context();
6207   int bytes_written;
6208   size_t pos_in_file = 0;
6209   uint16_t block_num = 0;
6210 
6211   /* T_set_verbosity( T_VERBOSE ); */
6212   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
6213   _Tftp_Add_interaction_send_wrq(
6214     TFTP_FIRST_FD,
6215     tftpfs_file,
6216     TFTP_STD_PORT,
6217     tftpfs_ipv4_loopback,
6218     TFTP_DEFAULT_BLOCK_SIZE,
6219     TFTP_DEFAULT_WINDOW_SIZE,
6220     true
6221   );
6222   _Tftp_Add_interaction_recv_ack(
6223     TFTP_FIRST_FD,
6224     FIRST_TIMEOUT_MILLISECONDS,
6225     SERV_PORT,
6226     tftpfs_ipv4_loopback,
6227     block_num++,
6228     true
6229   );
6230   _Tftp_Add_interaction_send_data(
6231     TFTP_FIRST_FD,
6232     block_num,
6233     pos_in_file,
6234     TFTP_RFC1350_BLOCK_SIZE / 2,
6235     get_file_content,
6236     SERV_PORT,
6237     tftpfs_ipv4_loopback,
6238     true
6239   );
6240   pos_in_file += TFTP_RFC1350_BLOCK_SIZE / 2;
6241   _Tftp_Add_interaction_recv_ack(
6242     TFTP_FIRST_FD,
6243     FIRST_TIMEOUT_MILLISECONDS,
6244     SERV_PORT,
6245     tftpfs_ipv4_loopback,
6246     block_num++,
6247     true
6248   );
6249   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
6250 
6251   bytes_written = write_tftp_file(
6252     create_tftpfs_path( tftpfs_ipv4_loopback, tftpfs_file ),
6253     pos_in_file, /* Size of file */
6254     2 * TFTP_RFC1350_BLOCK_SIZE, /* Bytes written per call to write() */
6255     &ctx->fd0
6256   );
6257   T_eq_int( bytes_written, pos_in_file );
6258   T_no_more_interactions();
6259 }
6260 
6261 /*
6262  * Write a file and when the server responses with an ERROR to options
6263  * fallback to no options.
6264  * The file is half a data packet long.  No timeouts, packet loss, ...
6265  * Tests:
6266  *   * The client uses windowsize and blksize options in the first WRQ.
6267  *   * Upon reception of an ERROR from the server, the client re-tries
6268  *     opening a session using a WRQ without options.
6269  *   * The second WRQ is sent to the TFTP server port 69 and not to the
6270  *     port from which the first ERROR packet came from.
6271  *   * The server accepts the WRQ without options by sending an ACK packet.
6272  *   * The first data packet is half filled and signals the end of the transfer.
6273  */
6274 T_TEST_CASE_FIXTURE( write_file_fallback_to_no_options,
6275   &fixture_default_options )
6276 {
6277   tftp_test_context *ctx = T_fixture_context();
6278   int bytes_written;
6279   size_t pos_in_file = 0;
6280   uint16_t block_num = 0;
6281 
6282   /* T_set_verbosity( T_VERBOSE ); */
6283   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
6284   _Tftp_Add_interaction_send_wrq(
6285     TFTP_FIRST_FD,
6286     tftpfs_file,
6287     TFTP_STD_PORT,
6288     tftpfs_ipv4_loopback,
6289     TFTP_DEFAULT_BLOCK_SIZE,
6290     TFTP_DEFAULT_WINDOW_SIZE,
6291     true
6292   );
6293   _Tftp_Add_interaction_recv_error(
6294     TFTP_FIRST_FD,
6295     FIRST_TIMEOUT_MILLISECONDS,
6296     SERV_PORT,
6297     tftpfs_ipv4_loopback,
6298     TFTP_ERROR_CODE_ILLEGAL,
6299     "Don't like options",
6300     true
6301   );
6302   _Tftp_Add_interaction_send_wrq(
6303     TFTP_FIRST_FD,
6304     tftpfs_file,
6305     TFTP_STD_PORT,
6306     tftpfs_ipv4_loopback,
6307     NO_BLOCK_SIZE_OPTION,
6308     NO_WINDOW_SIZE_OPTION,
6309     true
6310   );
6311   _Tftp_Add_interaction_recv_ack(
6312     TFTP_FIRST_FD,
6313     FIRST_TIMEOUT_MILLISECONDS,
6314     SERV_PORT,
6315     tftpfs_ipv4_loopback,
6316     block_num++,
6317     true
6318   );
6319   _Tftp_Add_interaction_send_data(
6320     TFTP_FIRST_FD,
6321     block_num,
6322     pos_in_file,
6323     TFTP_RFC1350_BLOCK_SIZE / 2,
6324     get_file_content,
6325     SERV_PORT,
6326     tftpfs_ipv4_loopback,
6327     true
6328   );
6329   pos_in_file += TFTP_RFC1350_BLOCK_SIZE / 2;
6330   _Tftp_Add_interaction_recv_ack(
6331     TFTP_FIRST_FD,
6332     FIRST_TIMEOUT_MILLISECONDS,
6333     SERV_PORT,
6334     tftpfs_ipv4_loopback,
6335     block_num++,
6336     true
6337   );
6338   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
6339 
6340   bytes_written = write_tftp_file(
6341     create_tftpfs_path( tftpfs_ipv4_loopback, tftpfs_file ),
6342     pos_in_file, /* Size of file */
6343     2 * TFTP_RFC1350_BLOCK_SIZE, /* Bytes written per call to write() */
6344     &ctx->fd0
6345   );
6346   T_eq_int( bytes_written, pos_in_file );
6347   T_no_more_interactions();
6348 }
6349 
6350 /*
6351  * The server sends a malformed OACK: The final 0 byte is missing.
6352  */
6353 T_TEST_CASE_FIXTURE( OACK_without_null, &fixture_default_options )
6354 {
6355   tftp_test_context *ctx = T_fixture_context();
6356   int bytes_read;
6357   const char options[] = { 'b', 'l', 'k', 's', 'i', 'z', 'e', '\0', '1', '2' };
6358 
6359   /* T_set_verbosity( T_VERBOSE ); */
6360   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
6361   _Tftp_Add_interaction_send_rrq(
6362     TFTP_FIRST_FD,
6363     tftpfs_file,
6364     TFTP_STD_PORT,
6365     tftpfs_ipv4_loopback,
6366     TFTP_DEFAULT_BLOCK_SIZE,
6367     TFTP_DEFAULT_WINDOW_SIZE,
6368     true
6369   );
6370   _Tftp_Add_interaction_recv_oack(
6371     TFTP_FIRST_FD,
6372     FIRST_TIMEOUT_MILLISECONDS,
6373     SERV_PORT,
6374     tftpfs_ipv4_loopback,
6375     options,
6376     sizeof( options ),
6377     true
6378   );
6379   _Tftp_Add_interaction_send_error(
6380     TFTP_FIRST_FD,
6381     TFTP_ERROR_CODE_OPTION_NEGO,
6382     SERV_PORT,
6383     tftpfs_ipv4_loopback,
6384     true
6385   );
6386   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
6387 
6388   bytes_read = read_tftp_file(
6389     create_tftpfs_path( tftpfs_ipv4_loopback, tftpfs_file ),
6390     LARGE_BLOCK_SIZE, /* Bytes read per call to read() */
6391     SIZE_MAX,
6392     &ctx->fd0
6393   );
6394   T_eq_int( errno, EPROTO );
6395   T_eq_int( bytes_read, 0 );
6396   T_no_more_interactions();
6397 }
6398 
6399 /*
6400  * Server sends a malformed OACK packet: The value of the option is missing.
6401  */
6402 T_TEST_CASE_FIXTURE( OACK_without_option_value, &fixture_default_options )
6403 {
6404   tftp_test_context *ctx = T_fixture_context();
6405   int bytes_read;
6406   const char options[] = TFTP_OPTION_BLKSIZE;
6407 
6408   /* T_set_verbosity( T_VERBOSE ); */
6409   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
6410   _Tftp_Add_interaction_send_rrq(
6411     TFTP_FIRST_FD,
6412     tftpfs_file,
6413     TFTP_STD_PORT,
6414     tftpfs_ipv4_loopback,
6415     TFTP_DEFAULT_BLOCK_SIZE,
6416     TFTP_DEFAULT_WINDOW_SIZE,
6417     true
6418   );
6419   _Tftp_Add_interaction_recv_oack(
6420     TFTP_FIRST_FD,
6421     FIRST_TIMEOUT_MILLISECONDS,
6422     SERV_PORT,
6423     tftpfs_ipv4_loopback,
6424     options,
6425     sizeof( options ),
6426     true
6427   );
6428   _Tftp_Add_interaction_send_error(
6429     TFTP_FIRST_FD,
6430     TFTP_ERROR_CODE_OPTION_NEGO,
6431     SERV_PORT,
6432     tftpfs_ipv4_loopback,
6433     true
6434   );
6435   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
6436 
6437   bytes_read = read_tftp_file(
6438     create_tftpfs_path( tftpfs_ipv4_loopback, tftpfs_file ),
6439     LARGE_BLOCK_SIZE, /* Bytes read per call to read() */
6440     SIZE_MAX,
6441     &ctx->fd0
6442   );
6443   T_eq_int( errno, EPROTO );
6444   T_eq_int( bytes_read, 0 );
6445   T_no_more_interactions();
6446 }
6447 
6448 /*
6449  * Server sends a malformed OACK packet: The option is unknown.
6450  */
6451 T_TEST_CASE_FIXTURE( OACK_with_unknown_option, &fixture_default_options )
6452 {
6453   tftp_test_context *ctx = T_fixture_context();
6454   int bytes_read;
6455   const char options[] =
6456     "shoesize" "\0"
6457     RTEMS_XSTRING( TFTP_DEFAULT_BLOCK_SIZE );
6458 
6459   /* T_set_verbosity( T_VERBOSE ); */
6460   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
6461   _Tftp_Add_interaction_send_rrq(
6462     TFTP_FIRST_FD,
6463     tftpfs_file,
6464     TFTP_STD_PORT,
6465     tftpfs_ipv4_loopback,
6466     TFTP_DEFAULT_BLOCK_SIZE,
6467     TFTP_DEFAULT_WINDOW_SIZE,
6468     true
6469   );
6470   _Tftp_Add_interaction_recv_oack(
6471     TFTP_FIRST_FD,
6472     FIRST_TIMEOUT_MILLISECONDS,
6473     SERV_PORT,
6474     tftpfs_ipv4_loopback,
6475     options,
6476     sizeof( options ),
6477     true
6478   );
6479   _Tftp_Add_interaction_send_error(
6480     TFTP_FIRST_FD,
6481     TFTP_ERROR_CODE_OPTION_NEGO,
6482     SERV_PORT,
6483     tftpfs_ipv4_loopback,
6484     true
6485   );
6486   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
6487 
6488   bytes_read = read_tftp_file(
6489     create_tftpfs_path( tftpfs_ipv4_loopback, tftpfs_file ),
6490     LARGE_BLOCK_SIZE, /* Bytes read per call to read() */
6491     SIZE_MAX,
6492     &ctx->fd0
6493   );
6494   T_eq_int( errno, EPROTO );
6495   T_eq_int( bytes_read, 0 );
6496   T_no_more_interactions();
6497 }
6498 
6499 /*
6500  * Server sends a malformed OACK packet: The value of the option is
6501  * not a number.
6502  */
6503 T_TEST_CASE_FIXTURE( OACK_malformed_option_value, &fixture_default_options )
6504 {
6505   tftp_test_context *ctx = T_fixture_context();
6506   int bytes_read;
6507   const char options[] = TFTP_OPTION_BLKSIZE "\0" "abc";
6508 
6509   /* T_set_verbosity( T_VERBOSE ); */
6510   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
6511   _Tftp_Add_interaction_send_rrq(
6512     TFTP_FIRST_FD,
6513     tftpfs_file,
6514     TFTP_STD_PORT,
6515     tftpfs_ipv4_loopback,
6516     TFTP_DEFAULT_BLOCK_SIZE,
6517     TFTP_DEFAULT_WINDOW_SIZE,
6518     true
6519   );
6520   _Tftp_Add_interaction_recv_oack(
6521     TFTP_FIRST_FD,
6522     FIRST_TIMEOUT_MILLISECONDS,
6523     SERV_PORT,
6524     tftpfs_ipv4_loopback,
6525     options,
6526     sizeof( options ),
6527     true
6528   );
6529   _Tftp_Add_interaction_send_error(
6530     TFTP_FIRST_FD,
6531     TFTP_ERROR_CODE_OPTION_NEGO,
6532     SERV_PORT,
6533     tftpfs_ipv4_loopback,
6534     true
6535   );
6536   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
6537 
6538   bytes_read = read_tftp_file(
6539     create_tftpfs_path( tftpfs_ipv4_loopback, tftpfs_file ),
6540     LARGE_BLOCK_SIZE, /* Bytes read per call to read() */
6541     SIZE_MAX,
6542     &ctx->fd0
6543   );
6544   T_eq_int( errno, EPROTO );
6545   T_eq_int( bytes_read, 0 );
6546   T_no_more_interactions();
6547 }
6548 
6549 /*
6550  * Server sends a malformed OACK packet: The value of the option is empty.
6551  */
6552 T_TEST_CASE_FIXTURE( OACK_with_empty_option_value, &fixture_default_options )
6553 {
6554   tftp_test_context *ctx = T_fixture_context();
6555   int bytes_read;
6556   const char options[] = TFTP_OPTION_BLKSIZE "\0";
6557 
6558   /* T_set_verbosity( T_VERBOSE ); */
6559   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
6560   _Tftp_Add_interaction_send_rrq(
6561     TFTP_FIRST_FD,
6562     tftpfs_file,
6563     TFTP_STD_PORT,
6564     tftpfs_ipv4_loopback,
6565     TFTP_DEFAULT_BLOCK_SIZE,
6566     TFTP_DEFAULT_WINDOW_SIZE,
6567     true
6568   );
6569   _Tftp_Add_interaction_recv_oack(
6570     TFTP_FIRST_FD,
6571     FIRST_TIMEOUT_MILLISECONDS,
6572     SERV_PORT,
6573     tftpfs_ipv4_loopback,
6574     options,
6575     sizeof( options ),
6576     true
6577   );
6578   _Tftp_Add_interaction_send_error(
6579     TFTP_FIRST_FD,
6580     TFTP_ERROR_CODE_OPTION_NEGO,
6581     SERV_PORT,
6582     tftpfs_ipv4_loopback,
6583     true
6584   );
6585   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
6586 
6587   bytes_read = read_tftp_file(
6588     create_tftpfs_path( tftpfs_ipv4_loopback, tftpfs_file ),
6589     LARGE_BLOCK_SIZE, /* Bytes read per call to read() */
6590     SIZE_MAX,
6591     &ctx->fd0
6592   );
6593   T_eq_int( errno, EPROTO );
6594   T_eq_int( bytes_read, 0 );
6595   T_no_more_interactions();
6596 }
6597 
6598 /*
6599  * Server sends a malformed OACK packet: The option name is empty.
6600  */
6601 T_TEST_CASE_FIXTURE( OACK_with_empty_option_name, &fixture_default_options )
6602 {
6603   tftp_test_context *ctx = T_fixture_context();
6604   int bytes_read;
6605   const char options[] = "\0" RTEMS_XSTRING( TFTP_DEFAULT_BLOCK_SIZE );
6606 
6607   /* T_set_verbosity( T_VERBOSE ); */
6608   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
6609   _Tftp_Add_interaction_send_rrq(
6610     TFTP_FIRST_FD,
6611     tftpfs_file,
6612     TFTP_STD_PORT,
6613     tftpfs_ipv4_loopback,
6614     TFTP_DEFAULT_BLOCK_SIZE,
6615     TFTP_DEFAULT_WINDOW_SIZE,
6616     true
6617   );
6618   _Tftp_Add_interaction_recv_oack(
6619     TFTP_FIRST_FD,
6620     FIRST_TIMEOUT_MILLISECONDS,
6621     SERV_PORT,
6622     tftpfs_ipv4_loopback,
6623     options,
6624     sizeof( options ),
6625     true
6626   );
6627   _Tftp_Add_interaction_send_error(
6628     TFTP_FIRST_FD,
6629     TFTP_ERROR_CODE_OPTION_NEGO,
6630     SERV_PORT,
6631     tftpfs_ipv4_loopback,
6632     true
6633   );
6634   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
6635 
6636   bytes_read = read_tftp_file(
6637     create_tftpfs_path( tftpfs_ipv4_loopback, tftpfs_file ),
6638     LARGE_BLOCK_SIZE, /* Bytes read per call to read() */
6639     SIZE_MAX,
6640     &ctx->fd0
6641   );
6642   T_eq_int( errno, EPROTO );
6643   T_eq_int( bytes_read, 0 );
6644   T_no_more_interactions();
6645 }
6646 
6647 /*
6648  * Server sends a malformed OACK packet: The block size option value
6649  * is too small.
6650  */
6651 T_TEST_CASE_FIXTURE( OACK_blocksize_too_small, &fixture_default_options )
6652 {
6653   tftp_test_context *ctx = T_fixture_context();
6654   int bytes_read;
6655   const char options[] = TFTP_OPTION_BLKSIZE "\0" "7";
6656 
6657   /* T_set_verbosity( T_VERBOSE ); */
6658   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
6659   _Tftp_Add_interaction_send_rrq(
6660     TFTP_FIRST_FD,
6661     tftpfs_file,
6662     TFTP_STD_PORT,
6663     tftpfs_ipv4_loopback,
6664     TFTP_DEFAULT_BLOCK_SIZE,
6665     TFTP_DEFAULT_WINDOW_SIZE,
6666     true
6667   );
6668   _Tftp_Add_interaction_recv_oack(
6669     TFTP_FIRST_FD,
6670     FIRST_TIMEOUT_MILLISECONDS,
6671     SERV_PORT,
6672     tftpfs_ipv4_loopback,
6673     options,
6674     sizeof( options ),
6675     true
6676   );
6677   _Tftp_Add_interaction_send_error(
6678     TFTP_FIRST_FD,
6679     TFTP_ERROR_CODE_OPTION_NEGO,
6680     SERV_PORT,
6681     tftpfs_ipv4_loopback,
6682     true
6683   );
6684   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
6685 
6686   bytes_read = read_tftp_file(
6687     create_tftpfs_path( tftpfs_ipv4_loopback, tftpfs_file ),
6688     LARGE_BLOCK_SIZE, /* Bytes read per call to read() */
6689     SIZE_MAX,
6690     &ctx->fd0
6691   );
6692   T_eq_int( errno, EPROTO );
6693   T_eq_int( bytes_read, 0 );
6694   T_no_more_interactions();
6695 }
6696 
6697 /*
6698  * Server sends a malformed OACK packet: The block size option value
6699  * is too large.
6700  */
6701 T_TEST_CASE_FIXTURE( OACK_blocksize_too_large, &fixture_default_options )
6702 {
6703   tftp_test_context *ctx = T_fixture_context();
6704   int bytes_read;
6705   const char options[] = TFTP_OPTION_BLKSIZE "\0" "1457";
6706 
6707   /* T_set_verbosity( T_VERBOSE ); */
6708   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
6709   _Tftp_Add_interaction_send_rrq(
6710     TFTP_FIRST_FD,
6711     tftpfs_file,
6712     TFTP_STD_PORT,
6713     tftpfs_ipv4_loopback,
6714     TFTP_DEFAULT_BLOCK_SIZE,
6715     TFTP_DEFAULT_WINDOW_SIZE,
6716     true
6717   );
6718   _Tftp_Add_interaction_recv_oack(
6719     TFTP_FIRST_FD,
6720     FIRST_TIMEOUT_MILLISECONDS,
6721     SERV_PORT,
6722     tftpfs_ipv4_loopback,
6723     options,
6724     sizeof( options ),
6725     true
6726   );
6727   _Tftp_Add_interaction_send_error(
6728     TFTP_FIRST_FD,
6729     TFTP_ERROR_CODE_OPTION_NEGO,
6730     SERV_PORT,
6731     tftpfs_ipv4_loopback,
6732     true
6733   );
6734   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
6735 
6736   bytes_read = read_tftp_file(
6737     create_tftpfs_path( tftpfs_ipv4_loopback, tftpfs_file ),
6738     LARGE_BLOCK_SIZE, /* Bytes read per call to read() */
6739     SIZE_MAX,
6740     &ctx->fd0
6741   );
6742   T_eq_int( errno, EPROTO );
6743   T_eq_int( bytes_read, 0 );
6744   T_no_more_interactions();
6745 }
6746 
6747 /*
6748  * Server sends a malformed OACK packet: The windowsize option value
6749  * is too small.
6750  */
6751 T_TEST_CASE_FIXTURE( OACK_windowsize_too_small, &fixture_default_options )
6752 {
6753   tftp_test_context *ctx = T_fixture_context();
6754   int bytes_read;
6755   const char options[] = TFTP_OPTION_WINDOWSIZE "\0" "0";
6756 
6757   /* T_set_verbosity( T_VERBOSE ); */
6758   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
6759   _Tftp_Add_interaction_send_rrq(
6760     TFTP_FIRST_FD,
6761     tftpfs_file,
6762     TFTP_STD_PORT,
6763     tftpfs_ipv4_loopback,
6764     TFTP_DEFAULT_BLOCK_SIZE,
6765     TFTP_DEFAULT_WINDOW_SIZE,
6766     true
6767   );
6768   _Tftp_Add_interaction_recv_oack(
6769     TFTP_FIRST_FD,
6770     FIRST_TIMEOUT_MILLISECONDS,
6771     SERV_PORT,
6772     tftpfs_ipv4_loopback,
6773     options,
6774     sizeof( options ),
6775     true
6776   );
6777   _Tftp_Add_interaction_send_error(
6778     TFTP_FIRST_FD,
6779     TFTP_ERROR_CODE_OPTION_NEGO,
6780     SERV_PORT,
6781     tftpfs_ipv4_loopback,
6782     true
6783   );
6784   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
6785 
6786   bytes_read = read_tftp_file(
6787     create_tftpfs_path( tftpfs_ipv4_loopback, tftpfs_file ),
6788     LARGE_BLOCK_SIZE, /* Bytes read per call to read() */
6789     SIZE_MAX,
6790     &ctx->fd0
6791   );
6792   T_eq_int( errno, EPROTO );
6793   T_eq_int( bytes_read, 0 );
6794   T_no_more_interactions();
6795 }
6796 
6797 /*
6798  * Server sends a malformed OACK packet: The windowsize option is too large.
6799  */
6800 T_TEST_CASE_FIXTURE( OACK_windowsize_too_large, &fixture_default_options )
6801 {
6802   tftp_test_context *ctx = T_fixture_context();
6803   int bytes_read;
6804   const char options[] = TFTP_OPTION_WINDOWSIZE "\0" "9";
6805 
6806   /* T_set_verbosity( T_VERBOSE ); */
6807   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
6808   _Tftp_Add_interaction_send_rrq(
6809     TFTP_FIRST_FD,
6810     tftpfs_file,
6811     TFTP_STD_PORT,
6812     tftpfs_ipv4_loopback,
6813     TFTP_DEFAULT_BLOCK_SIZE,
6814     TFTP_DEFAULT_WINDOW_SIZE,
6815     true
6816   );
6817   _Tftp_Add_interaction_recv_oack(
6818     TFTP_FIRST_FD,
6819     FIRST_TIMEOUT_MILLISECONDS,
6820     SERV_PORT,
6821     tftpfs_ipv4_loopback,
6822     options,
6823     sizeof( options ),
6824     true
6825   );
6826   _Tftp_Add_interaction_send_error(
6827     TFTP_FIRST_FD,
6828     TFTP_ERROR_CODE_OPTION_NEGO,
6829     SERV_PORT,
6830     tftpfs_ipv4_loopback,
6831     true
6832   );
6833   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
6834 
6835   bytes_read = read_tftp_file(
6836     create_tftpfs_path( tftpfs_ipv4_loopback, tftpfs_file ),
6837     LARGE_BLOCK_SIZE, /* Bytes read per call to read() */
6838     SIZE_MAX,
6839     &ctx->fd0
6840   );
6841   T_eq_int( errno, EPROTO );
6842   T_eq_int( bytes_read, 0 );
6843   T_no_more_interactions();
6844 }
6845 
6846 /*
6847  * Server sends a malformed OACK packet: There is a known but surplus option.
6848  */
6849 T_TEST_CASE_FIXTURE( OACK_with_surplus_option, &fixture_large_blocksize )
6850 {
6851   tftp_test_context *ctx = T_fixture_context();
6852   int bytes_read;
6853   const char options[] =
6854     TFTP_OPTION_BLKSIZE "\0"
6855     RTEMS_XSTRING( LARGE_BLOCK_SIZE ) "\0"
6856     TFTP_OPTION_WINDOWSIZE "\0"
6857     "1";
6858 
6859   /* T_set_verbosity( T_VERBOSE ); */
6860   _Tftp_Add_interaction_socket( AF_INET, SOCK_DGRAM, 0, TFTP_FIRST_FD );
6861   _Tftp_Add_interaction_send_rrq(
6862     TFTP_FIRST_FD,
6863     tftpfs_file,
6864     TFTP_STD_PORT,
6865     tftpfs_ipv4_loopback,
6866     LARGE_BLOCK_SIZE,
6867     NO_WINDOW_SIZE_OPTION,
6868     true
6869   );
6870   _Tftp_Add_interaction_recv_oack(
6871     TFTP_FIRST_FD,
6872     FIRST_TIMEOUT_MILLISECONDS,
6873     SERV_PORT,
6874     tftpfs_ipv4_loopback,
6875     options,
6876     sizeof( options ),
6877     true
6878   );
6879   _Tftp_Add_interaction_send_error(
6880     TFTP_FIRST_FD,
6881     TFTP_ERROR_CODE_OPTION_NEGO,
6882     SERV_PORT,
6883     tftpfs_ipv4_loopback,
6884     true
6885   );
6886   _Tftp_Add_interaction_close( TFTP_FIRST_FD, 0 );
6887 
6888   bytes_read = read_tftp_file(
6889     create_tftpfs_path( tftpfs_ipv4_loopback, tftpfs_file ),
6890     LARGE_BLOCK_SIZE, /* Bytes read per call to read() */
6891     SIZE_MAX,
6892     &ctx->fd0
6893   );
6894   T_eq_int( errno, EPROTO );
6895   T_eq_int( bytes_read, 0 );
6896   T_no_more_interactions();
6897 }
6898 
6899 const char rtems_test_name[] = "TFTPFS";
6900 
6901 static void Init( rtems_task_argument argument )
6902 {
6903   rtems_test_run( argument, TEST_STATE );
6904 }
6905 
6906 /*
6907  * RTEMS configuration for tftp
6908  */
6909 
6910 #define CONFIGURE_FILESYSTEM_TFTPFS
6911 #define CONFIGURE_MAXIMUM_FILE_DESCRIPTORS 4
6912 
6913 /*
6914  * Simple RTEMS configuration
6915  */
6916 
6917 #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
6918 #define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
6919 
6920 #define CONFIGURE_MAXIMUM_TASKS 1
6921 
6922 #define CONFIGURE_RTEMS_INIT_TASKS_TABLE
6923 
6924 #define CONFIGURE_INIT_TASK_ATTRIBUTES RTEMS_FLOATING_POINT
6925 
6926 #define CONFIGURE_INIT
6927 
6928 #include <rtems/confdefs.h>