File indexing completed on 2025-05-11 08:24:31
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049 #ifdef HAVE_CONFIG_H
0050 #include "config.h"
0051 #endif
0052
0053 #include <stdio.h> /* sprintf() */
0054 #include <inttypes.h> /* printf() macros like PRId8 */
0055 #include <arpa/inet.h> /* ntohs() */
0056 #include <rtems/test.h>
0057
0058
0059 #include "tftpfs_interactions.h"
0060 #include "tftpfs_udp_network_fake.h"
0061
0062
0063
0064
0065
0066 typedef struct interaction_data_socket {
0067 int domain;
0068 int type;
0069 int protocol;
0070 int result;
0071 } interaction_data_socket;
0072
0073 static bool interact_socket( Tftp_Action *act, void *data )
0074 {
0075 interaction_data_socket *d = data;
0076 T_eq_int( act->data.socket.domain, d->domain );
0077 T_eq_int( act->data.socket.type, d->type );
0078 T_eq_int( act->data.socket.protocol, d->protocol );
0079 if (
0080 act->data.socket.domain != d->domain ||
0081 act->data.socket.type != d->type ||
0082 act->data.socket.protocol != d->protocol
0083 ) {
0084 return false;
0085 }
0086
0087 act->data.socket.result = d->result;
0088 return true;
0089 }
0090
0091 void _Tftp_Add_interaction_socket(
0092 int domain,
0093 int type,
0094 int protocol,
0095 int result
0096 )
0097 {
0098 interaction_data_socket *d;
0099
0100 d = _Tftp_Append_interaction(
0101 TFTP_IA_KIND_SOCKET,
0102 interact_socket,
0103 sizeof( interaction_data_socket )
0104 );
0105
0106 d->domain = domain;
0107 d->type = type;
0108 d->protocol = protocol;
0109 d->result = result;
0110 }
0111
0112
0113
0114
0115
0116 typedef struct interaction_data_close {
0117 int fd;
0118 int result;
0119 } interaction_data_close;
0120
0121 static bool interact_close( Tftp_Action *act, void *data )
0122 {
0123 interaction_data_close *d = data;
0124 T_eq_int( act->data.close.fd, d->fd );
0125 if ( act->data.close.fd != d->fd ) {
0126 return false;
0127 }
0128
0129 act->data.close.result = d->result;
0130 return true;
0131 }
0132
0133 void _Tftp_Add_interaction_close( int fd, int result )
0134 {
0135 interaction_data_close *d;
0136
0137 d = _Tftp_Append_interaction(
0138 TFTP_IA_KIND_CLOSE,
0139 interact_close,
0140 sizeof( interaction_data_close )
0141 );
0142
0143 d->fd = fd;
0144 d->result = result;
0145 }
0146
0147
0148
0149
0150
0151 typedef struct interaction_data_bind {
0152 int fd;
0153 int family;
0154 int result;
0155 } interaction_data_bind;
0156
0157 static bool interact_bind( Tftp_Action *act, void *data )
0158 {
0159 interaction_data_bind *d = data;
0160 T_eq_int( act->data.bind.fd, d->fd );
0161 T_eq_int( act->data.bind.family, d->family );
0162 if (
0163 act->data.bind.fd != d->fd ||
0164 act->data.bind.family != d->family
0165 ) {
0166 return false;
0167 }
0168
0169 act->data.bind.result = d->result;
0170 return true;
0171 }
0172
0173 void _Tftp_Add_interaction_bind( int fd, int family, int result )
0174 {
0175 interaction_data_bind *d;
0176
0177 d = _Tftp_Append_interaction(
0178 TFTP_IA_KIND_BIND,
0179 interact_bind,
0180 sizeof( interaction_data_bind )
0181 );
0182
0183 d->fd = fd;
0184 d->family = family;
0185 d->result = result;
0186 }
0187
0188
0189
0190
0191
0192 #define TFTP_MAX_FILENAME_STRLEN 12
0193
0194 typedef struct interaction_data_sendto {
0195 int fd;
0196 uint16_t dest_port;
0197 char dest_addr_str[TFTP_MAX_IP_ADDR_STRLEN];
0198 bool result;
0199 union {
0200 struct {
0201 uint16_t opcode;
0202 char filename[TFTP_MAX_FILENAME_STRLEN];
0203 uint16_t block_size;
0204 uint16_t window_size;
0205 } rwrq;
0206 struct {
0207 uint16_t block_num;
0208 } ack;
0209 struct {
0210 uint16_t block_num;
0211 size_t start;
0212 size_t len;
0213 uint8_t (*get_data)( size_t pos );
0214 } data;
0215 struct {
0216 uint16_t error_code;
0217 } error;
0218 } content;
0219 } interaction_data_sendto;
0220
0221 static bool check_filename_and_mode(
0222 const char **buf,
0223 size_t *max_len,
0224 const char *filename
0225 )
0226 {
0227 const char *str;
0228 size_t len;
0229
0230
0231 if ( *max_len <= 0 ) { return false; };
0232 T_quiet_eq_u8( *( *buf + *max_len - 1 ), '\0' );
0233
0234 str = *buf;
0235 len = strlen( *buf ) + 1;
0236 *buf += len;
0237 *max_len -= len;
0238 if ( strcmp( str, filename ) != 0 ) {
0239 T_true( false, "Filename '%s' does not match '%s'", str, filename );
0240 return false;
0241 }
0242 if ( *max_len <= 0 ) {
0243 T_true( false, "Mode string missing." );
0244 return false;
0245 }
0246
0247 str = *buf;
0248 len = strlen( *buf ) + 1;
0249 *buf += len;
0250 *max_len -= len;
0251 if ( strcasecmp( str, TFTP_MODE_OCTET ) != 0 ) {
0252 T_true( false, "Mode '%s' does not match '%s'", str, TFTP_MODE_OCTET );
0253 return false;
0254 }
0255
0256 return true;
0257 }
0258
0259 static bool check_for_option(
0260 const char **buf,
0261 size_t *max_len,
0262 const char *option_name,
0263 const char *option_value
0264 )
0265 {
0266 const char *str;
0267 size_t len;
0268
0269
0270 if ( *max_len <= 0 ) { return false; };
0271 T_quiet_eq_u8( *( *buf + *max_len - 1 ), '\0' );
0272
0273 str = *buf;
0274 len = strlen( *buf ) + 1;
0275 if ( strcasecmp( str, option_name ) != 0 ) {
0276 return false;
0277 }
0278 *buf += len;
0279 *max_len -= len;
0280
0281 if ( *max_len <= 0 ) {
0282 T_true( false, "Option value for '%s' missing.", option_name );
0283 return false;
0284 }
0285
0286 str = *buf;
0287 len = strlen( *buf ) + 1;
0288 *buf += len;
0289 *max_len -= len;
0290 if ( strcmp( str, option_value ) != 0 ) {
0291 T_true(
0292 false,
0293 "Option '%s': Actual value '%s' does not match '%s'",
0294 option_name,
0295 str,
0296 option_value
0297 );
0298 return false;
0299 }
0300
0301 return true;
0302 }
0303
0304 static bool interact_sendto_common( Tftp_Action *act, void *data )
0305 {
0306 interaction_data_sendto *d = data;
0307 const Tftp_Packet *pkt = act->data.sendto.buf;
0308
0309 T_eq_int( act->data.sendto.fd, d->fd );
0310 T_eq_int( act->data.sendto.flags, 0 );
0311 T_eq_u16( act->data.sendto.dest_port, d->dest_port );
0312 T_eq_str( act->data.sendto.dest_addr_str, d->dest_addr_str );
0313 T_gt_sz( act->data.sendto.len, sizeof( pkt->opcode ) );
0314 if (
0315 act->data.sendto.fd != d->fd ||
0316 act->data.sendto.flags != 0 ||
0317 act->data.sendto.dest_port != d->dest_port ||
0318 strcmp( act->data.sendto.dest_addr_str, d->dest_addr_str ) != 0 ||
0319 act->data.sendto.len <= sizeof( pkt->opcode )
0320 ) {
0321 return false;
0322 }
0323
0324 act->data.sendto.result = d->result ? act->data.sendto.len : -1;
0325 return true;
0326 }
0327
0328 static bool interact_sendto_rwrq( Tftp_Action *act, void *data )
0329 {
0330 interaction_data_sendto *d = data;
0331 const Tftp_Packet *pkt = act->data.sendto.buf;
0332 size_t len = act->data.sendto.len - sizeof( pkt->opcode );
0333 const char *buf = pkt->content.rrq.opts;
0334 const char *tmp;
0335 char block_size_buffer[6];
0336 char window_size_buffer[6];
0337
0338 if ( !interact_sendto_common( act, data ) ) {
0339 return false;
0340 }
0341
0342 T_eq_u16( ntohs( pkt->opcode ), d->content.rwrq.opcode );
0343 if ( ntohs( pkt->opcode ) != d->content.rwrq.opcode ) { return false; }
0344 if ( !check_filename_and_mode( &buf, &len, d->content.rwrq.filename ) ) {
0345 return false;
0346 }
0347
0348 snprintf(
0349 block_size_buffer,
0350 sizeof( block_size_buffer ),
0351 "%"PRIu16,
0352 d->content.rwrq.block_size
0353 );
0354 snprintf(
0355 window_size_buffer,
0356 sizeof( window_size_buffer ),
0357 "%"PRIu16,
0358 d->content.rwrq.window_size
0359 );
0360
0361 for ( tmp = buf; len > 0; ) {
0362 if ( d->content.rwrq.block_size != NO_BLOCK_SIZE_OPTION &&
0363 check_for_option(
0364 &buf,
0365 &len,
0366 TFTP_OPTION_BLKSIZE,
0367 block_size_buffer )) {
0368 d->content.rwrq.block_size = NO_BLOCK_SIZE_OPTION;
0369 } else if ( d->content.rwrq.window_size != NO_WINDOW_SIZE_OPTION &&
0370 check_for_option(
0371 &buf,
0372 &len,
0373 TFTP_OPTION_WINDOWSIZE,
0374 window_size_buffer )) {
0375 d->content.rwrq.window_size = NO_WINDOW_SIZE_OPTION;
0376 } else {
0377 T_true( false, "Error at option '%s'", tmp );
0378 return false;
0379 }
0380 }
0381
0382 T_eq_sz( len, 0 );
0383
0384 return true;
0385 }
0386
0387 static bool interact_sendto_ack( Tftp_Action *act, void *data )
0388 {
0389 interaction_data_sendto *d = data;
0390 const Tftp_Packet *pkt = act->data.sendto.buf;
0391 size_t pkt_size = sizeof( pkt->opcode ) + sizeof( pkt->content.ack );
0392
0393 if ( !interact_sendto_common( act, data ) ) {
0394 return false;
0395 }
0396
0397 T_eq_u16( ntohs( pkt->opcode ), TFTP_OPCODE_ACK );
0398 T_eq_sz( act->data.sendto.len, pkt_size );
0399 if ( ntohs( pkt->opcode ) != TFTP_OPCODE_ACK ||
0400 act->data.sendto.len != pkt_size
0401 ) {
0402 return false;
0403 }
0404
0405 T_eq_u16( ntohs( pkt->content.ack.block_num ), d->content.ack.block_num );
0406 if ( ntohs( pkt->content.ack.block_num ) != d->content.ack.block_num ) {
0407 return false;
0408 }
0409
0410 return true;
0411 }
0412
0413 static bool interact_sendto_data( Tftp_Action *act, void *data )
0414 {
0415 interaction_data_sendto *d = data;
0416 const Tftp_Packet *pkt = act->data.sendto.buf;
0417 size_t pkt_size = sizeof( pkt->opcode ) +
0418 sizeof( pkt->content.data.block_num ) + d->content.data.len;
0419 size_t i;
0420
0421 if ( !interact_sendto_common( act, data ) ) {
0422 return false;
0423 }
0424
0425 T_eq_u16( ntohs( pkt->opcode ), TFTP_OPCODE_DATA );
0426 T_eq_sz( act->data.sendto.len, pkt_size );
0427 if ( ntohs( pkt->opcode ) != TFTP_OPCODE_DATA ||
0428 act->data.sendto.len != pkt_size
0429 ) {
0430 return false;
0431 }
0432
0433 T_eq_u16( ntohs( pkt->content.ack.block_num ), d->content.ack.block_num );
0434 if ( ntohs( pkt->content.ack.block_num ) != d->content.ack.block_num ) {
0435 return false;
0436 }
0437
0438 for ( i = 0; i < d->content.data.len; ++i ) {
0439 if ( pkt->content.data.bytes[i] !=
0440 d->content.data.get_data( d->content.data.start + i ) ) {
0441 T_true(
0442 false,
0443 "Expected byte %02"PRIx8" but TFTP client sent %02"PRIx8
0444 " at position %zu",
0445 d->content.data.get_data( d->content.data.start + i ),
0446 pkt->content.data.bytes[i],
0447 d->content.data.start + i
0448 );
0449 return false;
0450 }
0451 }
0452
0453 return true;
0454 }
0455
0456 static bool interact_sendto_error( Tftp_Action *act, void *data )
0457 {
0458 interaction_data_sendto *d = data;
0459 const Tftp_Packet *pkt = act->data.sendto.buf;
0460 size_t pkt_size = sizeof( pkt->opcode ) + sizeof( pkt->content.error );
0461
0462 if ( !interact_sendto_common( act, data ) ) {
0463 return false;
0464 }
0465
0466 T_eq_u16( ntohs( pkt->opcode ), TFTP_OPCODE_ERROR );
0467 T_gt_sz( act->data.sendto.len, pkt_size );
0468 if ( ntohs( pkt->opcode ) != TFTP_OPCODE_ERROR ||
0469 act->data.sendto.len <= pkt_size
0470 ) {
0471 return false;
0472 }
0473
0474 T_eq_u16(
0475 ntohs( pkt->content.error.error_code ),
0476 d->content.error.error_code
0477 );
0478 if ( ntohs( pkt->content.error.error_code ) != d->content.error.error_code ) {
0479 return false;
0480 }
0481
0482 return true;
0483 }
0484
0485 static void add_interaction_send_rwrq(
0486 int fd,
0487 const char *filename,
0488 uint16_t dest_port,
0489 const char *dest_addr_str,
0490 uint16_t block_size,
0491 uint16_t window_size,
0492 bool result,
0493 uint16_t opcode
0494 )
0495 {
0496 interaction_data_sendto *d;
0497
0498 d = _Tftp_Append_interaction(
0499 TFTP_IA_KIND_SENDTO,
0500 interact_sendto_rwrq,
0501 sizeof( interaction_data_sendto )
0502 );
0503
0504 T_assert_lt_sz( strlen( filename ), TFTP_MAX_FILENAME_STRLEN );
0505 T_assert_lt_sz( strlen( dest_addr_str ), TFTP_MAX_IP_ADDR_STRLEN );
0506 strcpy( d->content.rwrq.filename, filename );
0507 strcpy( d->dest_addr_str, dest_addr_str );
0508 d->fd = fd;
0509 d->dest_port = dest_port;
0510 d->content.rwrq.opcode = opcode;
0511 d->content.rwrq.block_size = block_size;
0512 d->content.rwrq.window_size = window_size;
0513 d->result = result;
0514 }
0515
0516 void _Tftp_Add_interaction_send_rrq(
0517 int fd,
0518 const char *filename,
0519 uint16_t dest_port,
0520 const char *dest_addr_str,
0521 uint16_t block_size,
0522 uint16_t window_size,
0523 bool result
0524 )
0525 {
0526 add_interaction_send_rwrq(
0527 fd,
0528 filename,
0529 dest_port,
0530 dest_addr_str,
0531 block_size,
0532 window_size,
0533 result,
0534 TFTP_OPCODE_RRQ
0535 );
0536 }
0537
0538 void _Tftp_Add_interaction_send_wrq(
0539 int fd,
0540 const char *filename,
0541 uint16_t dest_port,
0542 const char *dest_addr_str,
0543 uint16_t block_size,
0544 uint16_t window_size,
0545 bool result
0546 )
0547 {
0548 add_interaction_send_rwrq(
0549 fd,
0550 filename,
0551 dest_port,
0552 dest_addr_str,
0553 block_size,
0554 window_size,
0555 result,
0556 TFTP_OPCODE_WRQ
0557 );
0558 }
0559
0560 void _Tftp_Add_interaction_send_ack(
0561 int fd,
0562 uint16_t block_num,
0563 uint16_t dest_port,
0564 const char *dest_addr_str,
0565 bool result
0566 )
0567 {
0568 interaction_data_sendto *d;
0569
0570 d = _Tftp_Append_interaction(
0571 TFTP_IA_KIND_SENDTO,
0572 interact_sendto_ack,
0573 sizeof( interaction_data_sendto )
0574 );
0575
0576 T_assert_lt_sz( strlen( dest_addr_str ), TFTP_MAX_IP_ADDR_STRLEN );
0577 strcpy( d->dest_addr_str, dest_addr_str );
0578 d->fd = fd;
0579 d->dest_port = dest_port;
0580 d->result = result;
0581 d->content.ack.block_num = block_num;
0582 }
0583
0584 void _Tftp_Add_interaction_send_data(
0585 int fd,
0586 uint16_t block_num,
0587 size_t start,
0588 size_t len,
0589 uint8_t (*get_data)( size_t pos ),
0590 uint16_t dest_port,
0591 const char *dest_addr_str,
0592 bool result
0593 )
0594 {
0595 interaction_data_sendto *d;
0596
0597 d = _Tftp_Append_interaction(
0598 TFTP_IA_KIND_SENDTO,
0599 interact_sendto_data,
0600 sizeof( interaction_data_sendto )
0601 );
0602
0603 T_assert_lt_sz( strlen( dest_addr_str ), TFTP_MAX_IP_ADDR_STRLEN );
0604 strcpy( d->dest_addr_str, dest_addr_str );
0605 d->fd = fd;
0606 d->dest_port = dest_port;
0607 d->result = result;
0608 d->content.data.block_num = block_num;
0609 d->content.data.start = start;
0610 d->content.data.len = len;
0611 d->content.data.get_data = get_data;
0612 }
0613
0614 void _Tftp_Add_interaction_send_error(
0615 int fd,
0616 uint16_t error_code,
0617 uint16_t dest_port,
0618 const char *dest_addr_str,
0619 bool result
0620 )
0621 {
0622 interaction_data_sendto *d;
0623
0624 d = _Tftp_Append_interaction(
0625 TFTP_IA_KIND_SENDTO,
0626 interact_sendto_error,
0627 sizeof( interaction_data_sendto )
0628 );
0629
0630 T_assert_lt_sz( strlen( dest_addr_str ), TFTP_MAX_IP_ADDR_STRLEN );
0631 strcpy( d->dest_addr_str, dest_addr_str );
0632 d->fd = fd;
0633 d->dest_port = dest_port;
0634 d->result = result;
0635 d->content.error.error_code = error_code;
0636 }
0637
0638
0639
0640
0641
0642 typedef struct interaction_data_recvfrom {
0643 int fd;
0644 uint32_t timeout_ms;
0645 uint16_t src_port;
0646 char src_addr_str[TFTP_MAX_IP_ADDR_STRLEN];
0647 bool result;
0648 union {
0649 struct {
0650 uint16_t block_num;
0651 } ack;
0652 struct {
0653 size_t options_size;
0654 char options[TFTP_MAX_OPTIONS_SIZE];
0655 } oack;
0656 struct {
0657 uint16_t block_num;
0658 size_t start;
0659 size_t len;
0660 uint8_t (*get_data)( size_t pos );
0661 } data;
0662 struct {
0663 uint16_t error_code;
0664 char err_msg[TFTP_MAX_ERROR_STRLEN];
0665 } error;
0666 struct {
0667 size_t len;
0668 uint8_t bytes[0];
0669 } raw;
0670 } content;
0671 } interaction_data_recvfrom;
0672
0673 static bool interact_recvfrom_common(
0674 Tftp_Action *act,
0675 void *data,
0676 size_t actual_size
0677 )
0678 {
0679 interaction_data_recvfrom *d = data;
0680
0681 T_eq_int( act->data.recvfrom.fd, d->fd );
0682 T_quiet_ge_sz( act->data.recvfrom.len, actual_size );
0683 if (
0684 act->data.recvfrom.fd != d->fd ||
0685 act->data.recvfrom.len < actual_size
0686 ) {
0687 return false;
0688 }
0689 if ( d->timeout_ms == DO_NOT_WAIT_FOR_ANY_TIMEOUT ) {
0690 T_ne_int( act->data.recvfrom.flags, 0 );
0691 if ( act->data.recvfrom.flags == 0 ) {
0692 return false;
0693 }
0694 } else {
0695 T_eq_int( act->data.recvfrom.flags, 0 );
0696 T_eq_u32( act->data.recvfrom.timeout_ms, d->timeout_ms );
0697 if (
0698 act->data.recvfrom.flags != 0 ||
0699 act->data.recvfrom.timeout_ms != d->timeout_ms
0700 ) {
0701 return false;
0702 }
0703 }
0704
0705 strncpy(
0706 act->data.recvfrom.src_addr_str,
0707 d->src_addr_str,
0708 sizeof( act->data.recvfrom.src_addr_str )
0709 );
0710 act->data.recvfrom.src_addr_str[
0711 sizeof( act->data.recvfrom.src_addr_str ) - 1] = '\0';
0712 act->data.recvfrom.src_port = d->src_port;
0713 act->data.recvfrom.result = d->result ? actual_size : -1;
0714 return true;
0715 }
0716
0717 static bool interact_recvfrom_data( Tftp_Action *act, void *data )
0718 {
0719 interaction_data_recvfrom *d = data;
0720 Tftp_Packet *pkt = act->data.recvfrom.buf;
0721 size_t actual_size;
0722 size_t i;
0723
0724 actual_size = sizeof( pkt->opcode ) +
0725 sizeof( pkt->content.data.block_num ) + d->content.data.len;
0726 if ( !interact_recvfrom_common( act, data, actual_size ) ) {
0727 return false;
0728 }
0729
0730 pkt->opcode = htons( TFTP_OPCODE_DATA );
0731 pkt->content.data.block_num = htons( d->content.data.block_num );
0732 for ( i = 0; i < d->content.data.len; ++i ) {
0733 pkt->content.data.bytes[i] =
0734 d->content.data.get_data( d->content.data.start + i );
0735 }
0736
0737 return true;
0738 }
0739
0740 static bool interact_recvfrom_ack( Tftp_Action *act, void *data )
0741 {
0742 interaction_data_recvfrom *d = data;
0743 Tftp_Packet *pkt = act->data.recvfrom.buf;
0744 size_t actual_size;
0745
0746 actual_size = sizeof( pkt->opcode ) + sizeof( pkt->content.ack.block_num );
0747 if ( !interact_recvfrom_common( act, data, actual_size ) ) {
0748 return false;
0749 }
0750
0751 pkt->opcode = htons( TFTP_OPCODE_ACK );
0752 pkt->content.ack.block_num = htons( d->content.ack.block_num );
0753
0754 return true;
0755 }
0756
0757 static bool interact_recvfrom_oack( Tftp_Action *act, void *data )
0758 {
0759 interaction_data_recvfrom *d = data;
0760 Tftp_Packet *pkt = act->data.recvfrom.buf;
0761 size_t actual_size;
0762
0763 actual_size = sizeof( pkt->opcode ) + d->content.oack.options_size;
0764 if ( !interact_recvfrom_common( act, data, actual_size ) ) {
0765 return false;
0766 }
0767
0768 pkt->opcode = htons( TFTP_OPCODE_OACK );
0769 memcpy(
0770 pkt->content.oack.opts,
0771 d->content.oack.options,
0772 d->content.oack.options_size
0773 );
0774
0775 return true;
0776 }
0777
0778 static bool interact_recvfrom_error( Tftp_Action *act, void *data )
0779 {
0780 interaction_data_recvfrom *d = data;
0781 Tftp_Packet *pkt = act->data.recvfrom.buf;
0782 size_t actual_size;
0783
0784 actual_size = sizeof( pkt->opcode ) +
0785 sizeof( pkt->content.error.error_code ) +
0786 strlen( d->content.error.err_msg ) + 1;
0787 if ( !interact_recvfrom_common( act, data, actual_size ) ) {
0788 return false;
0789 }
0790
0791 pkt->opcode = htons( TFTP_OPCODE_ERROR );
0792 pkt->content.error.error_code = htons( d->content.error.error_code );
0793 strncpy(
0794 pkt->content.error.err_msg,
0795 d->content.error.err_msg,
0796 act->data.recvfrom.len - sizeof( pkt->opcode ) -
0797 sizeof( pkt->content.error.error_code ) - 1
0798 );
0799
0800 return true;
0801 }
0802
0803 static bool interact_recvfrom_raw( Tftp_Action *act, void *data )
0804 {
0805 interaction_data_recvfrom *d = data;
0806 uint8_t *pkt = act->data.recvfrom.buf;
0807 size_t actual_size = d->content.raw.len;
0808
0809 if ( !interact_recvfrom_common( act, data, actual_size ) ) {
0810 return false;
0811 }
0812
0813 memcpy( pkt, d->content.raw.bytes, actual_size );
0814
0815 return true;
0816 }
0817
0818 void _Tftp_Add_interaction_recv_data(
0819 int fd,
0820 uint32_t timeout_ms,
0821 uint16_t src_port,
0822 const char *src_addr_str,
0823 uint16_t block_num,
0824 size_t start,
0825 size_t len,
0826 uint8_t (*get_data)( size_t pos ),
0827 bool result
0828 )
0829 {
0830 interaction_data_recvfrom *d;
0831
0832 d = _Tftp_Append_interaction(
0833 TFTP_IA_KIND_RECVFROM,
0834 interact_recvfrom_data,
0835 sizeof( interaction_data_recvfrom )
0836 );
0837
0838 T_assert_lt_sz( strlen( src_addr_str ), sizeof( d->src_addr_str ) - 1 );
0839 strcpy( d->src_addr_str, src_addr_str );
0840 d->fd = fd;
0841 d->timeout_ms = timeout_ms;
0842 d->src_port = src_port;
0843 d->content.data.block_num = block_num;
0844 d->content.data.start = start;
0845 d->content.data.len = len;
0846 d->content.data.get_data = get_data;
0847 d->result = result;
0848 }
0849
0850 void _Tftp_Add_interaction_recv_ack(
0851 int fd,
0852 uint32_t timeout_ms,
0853 uint16_t src_port,
0854 const char *src_addr_str,
0855 uint16_t block_num,
0856 bool result
0857 )
0858 {
0859 interaction_data_recvfrom *d;
0860
0861 d = _Tftp_Append_interaction(
0862 TFTP_IA_KIND_RECVFROM,
0863 interact_recvfrom_ack,
0864 sizeof( interaction_data_recvfrom )
0865 );
0866
0867 T_assert_lt_sz( strlen( src_addr_str ), sizeof( d->src_addr_str ) - 1 );
0868 strcpy( d->src_addr_str, src_addr_str );
0869 d->fd = fd;
0870 d->timeout_ms = timeout_ms;
0871 d->src_port = src_port;
0872 d->content.ack.block_num = block_num;
0873 d->result = result;
0874 }
0875
0876 void _Tftp_Add_interaction_recv_oack(
0877 int fd,
0878 uint32_t timeout_ms,
0879 uint16_t src_port,
0880 const char *src_addr_str,
0881 const char *options,
0882 size_t options_size,
0883 bool result
0884 )
0885 {
0886 interaction_data_recvfrom *d;
0887
0888 d = _Tftp_Append_interaction(
0889 TFTP_IA_KIND_RECVFROM,
0890 interact_recvfrom_oack,
0891 sizeof( interaction_data_recvfrom )
0892 );
0893
0894 T_assert_lt_sz( strlen( src_addr_str ), sizeof( d->src_addr_str ) - 1 );
0895 strcpy( d->src_addr_str, src_addr_str );
0896 T_assert_lt_sz( options_size, sizeof( d->content.oack.options ) );
0897 memcpy( d->content.oack.options, options, options_size );
0898 d->fd = fd;
0899 d->timeout_ms = timeout_ms;
0900 d->src_port = src_port;
0901 d->content.oack.options_size = options_size;
0902 d->result = result;
0903 }
0904
0905 void _Tftp_Add_interaction_recv_error(
0906 int fd,
0907 uint32_t timeout_ms,
0908 uint16_t src_port,
0909 const char *src_addr_str,
0910 uint16_t error_code,
0911 const char *err_msg,
0912 bool result
0913 )
0914 {
0915 interaction_data_recvfrom *d;
0916
0917 d = _Tftp_Append_interaction(
0918 TFTP_IA_KIND_RECVFROM,
0919 interact_recvfrom_error,
0920 sizeof( interaction_data_recvfrom )
0921 );
0922
0923 T_assert_lt_sz( strlen( src_addr_str ), sizeof( d->src_addr_str ) - 1 );
0924 strcpy( d->src_addr_str, src_addr_str );
0925 T_assert_lt_sz( strlen( src_addr_str ), sizeof( d->src_addr_str ) - 1 );
0926 strcpy( d->content.error.err_msg, err_msg );
0927 d->fd = fd;
0928 d->timeout_ms = timeout_ms;
0929 d->src_port = src_port;
0930 d->content.error.error_code = error_code;
0931 d->result = result;
0932 }
0933
0934 void _Tftp_Add_interaction_recv_raw(
0935 int fd,
0936 uint32_t timeout_ms,
0937 uint16_t src_port,
0938 const char *src_addr_str,
0939 size_t len,
0940 const uint8_t *bytes,
0941 bool result
0942 )
0943 {
0944 interaction_data_recvfrom *d;
0945
0946 d = _Tftp_Append_interaction(
0947 TFTP_IA_KIND_RECVFROM,
0948 interact_recvfrom_raw,
0949 sizeof( interaction_data_recvfrom ) + len
0950 );
0951
0952 T_assert_lt_sz( strlen( src_addr_str ), sizeof( d->src_addr_str ) - 1 );
0953 strcpy( d->src_addr_str, src_addr_str );
0954 memcpy( d->content.raw.bytes, bytes, len );
0955 d->fd = fd;
0956 d->timeout_ms = timeout_ms;
0957 d->src_port = src_port;
0958 d->content.raw.len = len;
0959 d->result = result;
0960 }
0961
0962 void _Tftp_Add_interaction_recv_nothing(
0963 int fd,
0964 uint32_t timeout_ms
0965 )
0966 {
0967 static const char *dummy_ip = "0.0.0.0";
0968 interaction_data_recvfrom *d;
0969
0970 d = _Tftp_Append_interaction(
0971 TFTP_IA_KIND_RECVFROM,
0972 interact_recvfrom_ack,
0973 sizeof( interaction_data_recvfrom )
0974 );
0975
0976
0977 T_assert_lt_sz( strlen( dummy_ip ), sizeof( d->src_addr_str ) - 1 );
0978 strcpy( d->src_addr_str, dummy_ip );
0979 d->fd = fd;
0980 d->timeout_ms = timeout_ms;
0981 d->src_port = 0;
0982 d->content.ack.block_num = 0;
0983 d->result = false;
0984 }