1/*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. 9 * 10 * This software is licensed as described in the file COPYING, which 11 * you should have received as part of this distribution. The terms 12 * are also available at https://curl.se/docs/copyright.html. 13 * 14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell 15 * copies of the Software, and permit persons to whom the Software is 16 * furnished to do so, under the terms of the COPYING file. 17 * 18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 19 * KIND, either express or implied. 20 * 21 * SPDX-License-Identifier: curl 22 * 23 ***************************************************************************/ 24 25#include "curl_setup.h" 26 27#ifndef CURL_DISABLE_TFTP 28 29#ifdef HAVE_NETINET_IN_H 30#include <netinet/in.h> 31#endif 32#ifdef HAVE_NETDB_H 33#include <netdb.h> 34#endif 35#ifdef HAVE_ARPA_INET_H 36#include <arpa/inet.h> 37#endif 38#ifdef HAVE_NET_IF_H 39#include <net/if.h> 40#endif 41#ifdef HAVE_SYS_IOCTL_H 42#include <sys/ioctl.h> 43#endif 44 45#ifdef HAVE_SYS_PARAM_H 46#include <sys/param.h> 47#endif 48 49#include "urldata.h" 50#include <curl/curl.h> 51#include "cf-socket.h" 52#include "transfer.h" 53#include "sendf.h" 54#include "tftp.h" 55#include "progress.h" 56#include "connect.h" 57#include "strerror.h" 58#include "sockaddr.h" /* required for Curl_sockaddr_storage */ 59#include "multiif.h" 60#include "url.h" 61#include "strcase.h" 62#include "speedcheck.h" 63#include "select.h" 64#include "escape.h" 65 66/* The last 3 #include files should be in this order */ 67#include "curl_printf.h" 68#include "curl_memory.h" 69#include "memdebug.h" 70 71/* RFC2348 allows the block size to be negotiated */ 72#define TFTP_BLKSIZE_DEFAULT 512 73#define TFTP_OPTION_BLKSIZE "blksize" 74 75/* from RFC2349: */ 76#define TFTP_OPTION_TSIZE "tsize" 77#define TFTP_OPTION_INTERVAL "timeout" 78 79typedef enum { 80 TFTP_MODE_NETASCII = 0, 81 TFTP_MODE_OCTET 82} tftp_mode_t; 83 84typedef enum { 85 TFTP_STATE_START = 0, 86 TFTP_STATE_RX, 87 TFTP_STATE_TX, 88 TFTP_STATE_FIN 89} tftp_state_t; 90 91typedef enum { 92 TFTP_EVENT_NONE = -1, 93 TFTP_EVENT_INIT = 0, 94 TFTP_EVENT_RRQ = 1, 95 TFTP_EVENT_WRQ = 2, 96 TFTP_EVENT_DATA = 3, 97 TFTP_EVENT_ACK = 4, 98 TFTP_EVENT_ERROR = 5, 99 TFTP_EVENT_OACK = 6, 100 TFTP_EVENT_TIMEOUT 101} tftp_event_t; 102 103typedef enum { 104 TFTP_ERR_UNDEF = 0, 105 TFTP_ERR_NOTFOUND, 106 TFTP_ERR_PERM, 107 TFTP_ERR_DISKFULL, 108 TFTP_ERR_ILLEGAL, 109 TFTP_ERR_UNKNOWNID, 110 TFTP_ERR_EXISTS, 111 TFTP_ERR_NOSUCHUSER, /* This will never be triggered by this code */ 112 113 /* The remaining error codes are internal to curl */ 114 TFTP_ERR_NONE = -100, 115 TFTP_ERR_TIMEOUT, 116 TFTP_ERR_NORESPONSE 117} tftp_error_t; 118 119struct tftp_packet { 120 unsigned char *data; 121}; 122 123struct tftp_state_data { 124 tftp_state_t state; 125 tftp_mode_t mode; 126 tftp_error_t error; 127 tftp_event_t event; 128 struct Curl_easy *data; 129 curl_socket_t sockfd; 130 int retries; 131 int retry_time; 132 int retry_max; 133 time_t rx_time; 134 struct Curl_sockaddr_storage local_addr; 135 struct Curl_sockaddr_storage remote_addr; 136 curl_socklen_t remote_addrlen; 137 int rbytes; 138 int sbytes; 139 int blksize; 140 int requested_blksize; 141 unsigned short block; 142 struct tftp_packet rpacket; 143 struct tftp_packet spacket; 144}; 145 146 147/* Forward declarations */ 148static CURLcode tftp_rx(struct tftp_state_data *state, tftp_event_t event); 149static CURLcode tftp_tx(struct tftp_state_data *state, tftp_event_t event); 150static CURLcode tftp_connect(struct Curl_easy *data, bool *done); 151static CURLcode tftp_disconnect(struct Curl_easy *data, 152 struct connectdata *conn, 153 bool dead_connection); 154static CURLcode tftp_do(struct Curl_easy *data, bool *done); 155static CURLcode tftp_done(struct Curl_easy *data, 156 CURLcode, bool premature); 157static CURLcode tftp_setup_connection(struct Curl_easy *data, 158 struct connectdata *conn); 159static CURLcode tftp_multi_statemach(struct Curl_easy *data, bool *done); 160static CURLcode tftp_doing(struct Curl_easy *data, bool *dophase_done); 161static int tftp_getsock(struct Curl_easy *data, struct connectdata *conn, 162 curl_socket_t *socks); 163static CURLcode tftp_translate_code(tftp_error_t error); 164 165 166/* 167 * TFTP protocol handler. 168 */ 169 170const struct Curl_handler Curl_handler_tftp = { 171 "TFTP", /* scheme */ 172 tftp_setup_connection, /* setup_connection */ 173 tftp_do, /* do_it */ 174 tftp_done, /* done */ 175 ZERO_NULL, /* do_more */ 176 tftp_connect, /* connect_it */ 177 tftp_multi_statemach, /* connecting */ 178 tftp_doing, /* doing */ 179 tftp_getsock, /* proto_getsock */ 180 tftp_getsock, /* doing_getsock */ 181 ZERO_NULL, /* domore_getsock */ 182 ZERO_NULL, /* perform_getsock */ 183 tftp_disconnect, /* disconnect */ 184 ZERO_NULL, /* write_resp */ 185 ZERO_NULL, /* connection_check */ 186 ZERO_NULL, /* attach connection */ 187 PORT_TFTP, /* defport */ 188 CURLPROTO_TFTP, /* protocol */ 189 CURLPROTO_TFTP, /* family */ 190 PROTOPT_NOTCPPROXY | PROTOPT_NOURLQUERY /* flags */ 191}; 192 193/********************************************************** 194 * 195 * tftp_set_timeouts - 196 * 197 * Set timeouts based on state machine state. 198 * Use user provided connect timeouts until DATA or ACK 199 * packet is received, then use user-provided transfer timeouts 200 * 201 * 202 **********************************************************/ 203static CURLcode tftp_set_timeouts(struct tftp_state_data *state) 204{ 205 time_t maxtime, timeout; 206 timediff_t timeout_ms; 207 bool start = (state->state == TFTP_STATE_START) ? TRUE : FALSE; 208 209 /* Compute drop-dead time */ 210 timeout_ms = Curl_timeleft(state->data, NULL, start); 211 212 if(timeout_ms < 0) { 213 /* time-out, bail out, go home */ 214 failf(state->data, "Connection time-out"); 215 return CURLE_OPERATION_TIMEDOUT; 216 } 217 218 if(timeout_ms > 0) 219 maxtime = (time_t)(timeout_ms + 500) / 1000; 220 else 221 maxtime = 3600; /* use for calculating block timeouts */ 222 223 /* Set per-block timeout to total */ 224 timeout = maxtime; 225 226 /* Average reposting an ACK after 5 seconds */ 227 state->retry_max = (int)timeout/5; 228 229 /* But bound the total number */ 230 if(state->retry_max<3) 231 state->retry_max = 3; 232 233 if(state->retry_max>50) 234 state->retry_max = 50; 235 236 /* Compute the re-ACK interval to suit the timeout */ 237 state->retry_time = (int)(timeout/state->retry_max); 238 if(state->retry_time<1) 239 state->retry_time = 1; 240 241 infof(state->data, 242 "set timeouts for state %d; Total % " CURL_FORMAT_CURL_OFF_T 243 ", retry %d maxtry %d", 244 (int)state->state, timeout_ms, state->retry_time, state->retry_max); 245 246 /* init RX time */ 247 time(&state->rx_time); 248 249 return CURLE_OK; 250} 251 252/********************************************************** 253 * 254 * tftp_set_send_first 255 * 256 * Event handler for the START state 257 * 258 **********************************************************/ 259 260static void setpacketevent(struct tftp_packet *packet, unsigned short num) 261{ 262 packet->data[0] = (unsigned char)(num >> 8); 263 packet->data[1] = (unsigned char)(num & 0xff); 264} 265 266 267static void setpacketblock(struct tftp_packet *packet, unsigned short num) 268{ 269 packet->data[2] = (unsigned char)(num >> 8); 270 packet->data[3] = (unsigned char)(num & 0xff); 271} 272 273static unsigned short getrpacketevent(const struct tftp_packet *packet) 274{ 275 return (unsigned short)((packet->data[0] << 8) | packet->data[1]); 276} 277 278static unsigned short getrpacketblock(const struct tftp_packet *packet) 279{ 280 return (unsigned short)((packet->data[2] << 8) | packet->data[3]); 281} 282 283static size_t tftp_strnlen(const char *string, size_t maxlen) 284{ 285 const char *end = memchr(string, '\0', maxlen); 286 return end ? (size_t) (end - string) : maxlen; 287} 288 289static const char *tftp_option_get(const char *buf, size_t len, 290 const char **option, const char **value) 291{ 292 size_t loc; 293 294 loc = tftp_strnlen(buf, len); 295 loc++; /* NULL term */ 296 297 if(loc >= len) 298 return NULL; 299 *option = buf; 300 301 loc += tftp_strnlen(buf + loc, len-loc); 302 loc++; /* NULL term */ 303 304 if(loc > len) 305 return NULL; 306 *value = &buf[strlen(*option) + 1]; 307 308 return &buf[loc]; 309} 310 311static CURLcode tftp_parse_option_ack(struct tftp_state_data *state, 312 const char *ptr, int len) 313{ 314 const char *tmp = ptr; 315 struct Curl_easy *data = state->data; 316 317 /* if OACK doesn't contain blksize option, the default (512) must be used */ 318 state->blksize = TFTP_BLKSIZE_DEFAULT; 319 320 while(tmp < ptr + len) { 321 const char *option, *value; 322 323 tmp = tftp_option_get(tmp, ptr + len - tmp, &option, &value); 324 if(!tmp) { 325 failf(data, "Malformed ACK packet, rejecting"); 326 return CURLE_TFTP_ILLEGAL; 327 } 328 329 infof(data, "got option=(%s) value=(%s)", option, value); 330 331 if(checkprefix(TFTP_OPTION_BLKSIZE, option)) { 332 long blksize; 333 334 blksize = strtol(value, NULL, 10); 335 336 if(!blksize) { 337 failf(data, "invalid blocksize value in OACK packet"); 338 return CURLE_TFTP_ILLEGAL; 339 } 340 if(blksize > TFTP_BLKSIZE_MAX) { 341 failf(data, "%s (%d)", "blksize is larger than max supported", 342 TFTP_BLKSIZE_MAX); 343 return CURLE_TFTP_ILLEGAL; 344 } 345 else if(blksize < TFTP_BLKSIZE_MIN) { 346 failf(data, "%s (%d)", "blksize is smaller than min supported", 347 TFTP_BLKSIZE_MIN); 348 return CURLE_TFTP_ILLEGAL; 349 } 350 else if(blksize > state->requested_blksize) { 351 /* could realloc pkt buffers here, but the spec doesn't call out 352 * support for the server requesting a bigger blksize than the client 353 * requests */ 354 failf(data, "%s (%ld)", 355 "server requested blksize larger than allocated", blksize); 356 return CURLE_TFTP_ILLEGAL; 357 } 358 359 state->blksize = (int)blksize; 360 infof(data, "%s (%d) %s (%d)", "blksize parsed from OACK", 361 state->blksize, "requested", state->requested_blksize); 362 } 363 else if(checkprefix(TFTP_OPTION_TSIZE, option)) { 364 long tsize = 0; 365 366 tsize = strtol(value, NULL, 10); 367 infof(data, "%s (%ld)", "tsize parsed from OACK", tsize); 368 369 /* tsize should be ignored on upload: Who cares about the size of the 370 remote file? */ 371 if(!data->state.upload) { 372 if(!tsize) { 373 failf(data, "invalid tsize -:%s:- value in OACK packet", value); 374 return CURLE_TFTP_ILLEGAL; 375 } 376 Curl_pgrsSetDownloadSize(data, tsize); 377 } 378 } 379 } 380 381 return CURLE_OK; 382} 383 384static CURLcode tftp_option_add(struct tftp_state_data *state, size_t *csize, 385 char *buf, const char *option) 386{ 387 if(( strlen(option) + *csize + 1) > (size_t)state->blksize) 388 return CURLE_TFTP_ILLEGAL; 389 strcpy(buf, option); 390 *csize += strlen(option) + 1; 391 return CURLE_OK; 392} 393 394static CURLcode tftp_connect_for_tx(struct tftp_state_data *state, 395 tftp_event_t event) 396{ 397 CURLcode result; 398#ifndef CURL_DISABLE_VERBOSE_STRINGS 399 struct Curl_easy *data = state->data; 400 401 infof(data, "%s", "Connected for transmit"); 402#endif 403 state->state = TFTP_STATE_TX; 404 result = tftp_set_timeouts(state); 405 if(result) 406 return result; 407 return tftp_tx(state, event); 408} 409 410static CURLcode tftp_connect_for_rx(struct tftp_state_data *state, 411 tftp_event_t event) 412{ 413 CURLcode result; 414#ifndef CURL_DISABLE_VERBOSE_STRINGS 415 struct Curl_easy *data = state->data; 416 417 infof(data, "%s", "Connected for receive"); 418#endif 419 state->state = TFTP_STATE_RX; 420 result = tftp_set_timeouts(state); 421 if(result) 422 return result; 423 return tftp_rx(state, event); 424} 425 426static CURLcode tftp_send_first(struct tftp_state_data *state, 427 tftp_event_t event) 428{ 429 size_t sbytes; 430 ssize_t senddata; 431 const char *mode = "octet"; 432 char *filename; 433 struct Curl_easy *data = state->data; 434 CURLcode result = CURLE_OK; 435 436 /* Set ascii mode if -B flag was used */ 437 if(data->state.prefer_ascii) 438 mode = "netascii"; 439 440 switch(event) { 441 442 case TFTP_EVENT_INIT: /* Send the first packet out */ 443 case TFTP_EVENT_TIMEOUT: /* Resend the first packet out */ 444 /* Increment the retry counter, quit if over the limit */ 445 state->retries++; 446 if(state->retries>state->retry_max) { 447 state->error = TFTP_ERR_NORESPONSE; 448 state->state = TFTP_STATE_FIN; 449 return result; 450 } 451 452 if(data->state.upload) { 453 /* If we are uploading, send an WRQ */ 454 setpacketevent(&state->spacket, TFTP_EVENT_WRQ); 455 state->data->req.upload_fromhere = 456 (char *)state->spacket.data + 4; 457 if(data->state.infilesize != -1) 458 Curl_pgrsSetUploadSize(data, data->state.infilesize); 459 } 460 else { 461 /* If we are downloading, send an RRQ */ 462 setpacketevent(&state->spacket, TFTP_EVENT_RRQ); 463 } 464 /* As RFC3617 describes the separator slash is not actually part of the 465 file name so we skip the always-present first letter of the path 466 string. */ 467 result = Curl_urldecode(&state->data->state.up.path[1], 0, 468 &filename, NULL, REJECT_ZERO); 469 if(result) 470 return result; 471 472 if(strlen(filename) > (state->blksize - strlen(mode) - 4)) { 473 failf(data, "TFTP file name too long"); 474 free(filename); 475 return CURLE_TFTP_ILLEGAL; /* too long file name field */ 476 } 477 478 msnprintf((char *)state->spacket.data + 2, 479 state->blksize, 480 "%s%c%s%c", filename, '\0', mode, '\0'); 481 sbytes = 4 + strlen(filename) + strlen(mode); 482 483 /* optional addition of TFTP options */ 484 if(!data->set.tftp_no_options) { 485 char buf[64]; 486 /* add tsize option */ 487 if(data->state.upload && (data->state.infilesize != -1)) 488 msnprintf(buf, sizeof(buf), "%" CURL_FORMAT_CURL_OFF_T, 489 data->state.infilesize); 490 else 491 strcpy(buf, "0"); /* the destination is large enough */ 492 493 result = tftp_option_add(state, &sbytes, 494 (char *)state->spacket.data + sbytes, 495 TFTP_OPTION_TSIZE); 496 if(result == CURLE_OK) 497 result = tftp_option_add(state, &sbytes, 498 (char *)state->spacket.data + sbytes, buf); 499 500 /* add blksize option */ 501 msnprintf(buf, sizeof(buf), "%d", state->requested_blksize); 502 if(result == CURLE_OK) 503 result = tftp_option_add(state, &sbytes, 504 (char *)state->spacket.data + sbytes, 505 TFTP_OPTION_BLKSIZE); 506 if(result == CURLE_OK) 507 result = tftp_option_add(state, &sbytes, 508 (char *)state->spacket.data + sbytes, buf); 509 510 /* add timeout option */ 511 msnprintf(buf, sizeof(buf), "%d", state->retry_time); 512 if(result == CURLE_OK) 513 result = tftp_option_add(state, &sbytes, 514 (char *)state->spacket.data + sbytes, 515 TFTP_OPTION_INTERVAL); 516 if(result == CURLE_OK) 517 result = tftp_option_add(state, &sbytes, 518 (char *)state->spacket.data + sbytes, buf); 519 520 if(result != CURLE_OK) { 521 failf(data, "TFTP buffer too small for options"); 522 free(filename); 523 return CURLE_TFTP_ILLEGAL; 524 } 525 } 526 527 /* the typecase for the 3rd argument is mostly for systems that do 528 not have a size_t argument, like older unixes that want an 'int' */ 529 senddata = sendto(state->sockfd, (void *)state->spacket.data, 530 (SEND_TYPE_ARG3)sbytes, 0, 531 &data->conn->remote_addr->sa_addr, 532 data->conn->remote_addr->addrlen); 533 if(senddata != (ssize_t)sbytes) { 534 char buffer[STRERROR_LEN]; 535 failf(data, "%s", Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); 536 } 537 free(filename); 538 break; 539 540 case TFTP_EVENT_OACK: 541 if(data->state.upload) { 542 result = tftp_connect_for_tx(state, event); 543 } 544 else { 545 result = tftp_connect_for_rx(state, event); 546 } 547 break; 548 549 case TFTP_EVENT_ACK: /* Connected for transmit */ 550 result = tftp_connect_for_tx(state, event); 551 break; 552 553 case TFTP_EVENT_DATA: /* Connected for receive */ 554 result = tftp_connect_for_rx(state, event); 555 break; 556 557 case TFTP_EVENT_ERROR: 558 state->state = TFTP_STATE_FIN; 559 break; 560 561 default: 562 failf(state->data, "tftp_send_first: internal error"); 563 break; 564 } 565 566 return result; 567} 568 569/* the next blocknum is x + 1 but it needs to wrap at an unsigned 16bit 570 boundary */ 571#define NEXT_BLOCKNUM(x) (((x) + 1)&0xffff) 572 573/********************************************************** 574 * 575 * tftp_rx 576 * 577 * Event handler for the RX state 578 * 579 **********************************************************/ 580static CURLcode tftp_rx(struct tftp_state_data *state, 581 tftp_event_t event) 582{ 583 ssize_t sbytes; 584 int rblock; 585 struct Curl_easy *data = state->data; 586 char buffer[STRERROR_LEN]; 587 588 switch(event) { 589 590 case TFTP_EVENT_DATA: 591 /* Is this the block we expect? */ 592 rblock = getrpacketblock(&state->rpacket); 593 if(NEXT_BLOCKNUM(state->block) == rblock) { 594 /* This is the expected block. Reset counters and ACK it. */ 595 state->retries = 0; 596 } 597 else if(state->block == rblock) { 598 /* This is the last recently received block again. Log it and ACK it 599 again. */ 600 infof(data, "Received last DATA packet block %d again.", rblock); 601 } 602 else { 603 /* totally unexpected, just log it */ 604 infof(data, 605 "Received unexpected DATA packet block %d, expecting block %d", 606 rblock, NEXT_BLOCKNUM(state->block)); 607 break; 608 } 609 610 /* ACK this block. */ 611 state->block = (unsigned short)rblock; 612 setpacketevent(&state->spacket, TFTP_EVENT_ACK); 613 setpacketblock(&state->spacket, state->block); 614 sbytes = sendto(state->sockfd, (void *)state->spacket.data, 615 4, SEND_4TH_ARG, 616 (struct sockaddr *)&state->remote_addr, 617 state->remote_addrlen); 618 if(sbytes < 0) { 619 failf(data, "%s", Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); 620 return CURLE_SEND_ERROR; 621 } 622 623 /* Check if completed (That is, a less than full packet is received) */ 624 if(state->rbytes < (ssize_t)state->blksize + 4) { 625 state->state = TFTP_STATE_FIN; 626 } 627 else { 628 state->state = TFTP_STATE_RX; 629 } 630 time(&state->rx_time); 631 break; 632 633 case TFTP_EVENT_OACK: 634 /* ACK option acknowledgement so we can move on to data */ 635 state->block = 0; 636 state->retries = 0; 637 setpacketevent(&state->spacket, TFTP_EVENT_ACK); 638 setpacketblock(&state->spacket, state->block); 639 sbytes = sendto(state->sockfd, (void *)state->spacket.data, 640 4, SEND_4TH_ARG, 641 (struct sockaddr *)&state->remote_addr, 642 state->remote_addrlen); 643 if(sbytes < 0) { 644 failf(data, "%s", Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); 645 return CURLE_SEND_ERROR; 646 } 647 648 /* we're ready to RX data */ 649 state->state = TFTP_STATE_RX; 650 time(&state->rx_time); 651 break; 652 653 case TFTP_EVENT_TIMEOUT: 654 /* Increment the retry count and fail if over the limit */ 655 state->retries++; 656 infof(data, 657 "Timeout waiting for block %d ACK. Retries = %d", 658 NEXT_BLOCKNUM(state->block), state->retries); 659 if(state->retries > state->retry_max) { 660 state->error = TFTP_ERR_TIMEOUT; 661 state->state = TFTP_STATE_FIN; 662 } 663 else { 664 /* Resend the previous ACK */ 665 sbytes = sendto(state->sockfd, (void *)state->spacket.data, 666 4, SEND_4TH_ARG, 667 (struct sockaddr *)&state->remote_addr, 668 state->remote_addrlen); 669 if(sbytes<0) { 670 failf(data, "%s", Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); 671 return CURLE_SEND_ERROR; 672 } 673 } 674 break; 675 676 case TFTP_EVENT_ERROR: 677 setpacketevent(&state->spacket, TFTP_EVENT_ERROR); 678 setpacketblock(&state->spacket, state->block); 679 (void)sendto(state->sockfd, (void *)state->spacket.data, 680 4, SEND_4TH_ARG, 681 (struct sockaddr *)&state->remote_addr, 682 state->remote_addrlen); 683 /* don't bother with the return code, but if the socket is still up we 684 * should be a good TFTP client and let the server know we're done */ 685 state->state = TFTP_STATE_FIN; 686 break; 687 688 default: 689 failf(data, "%s", "tftp_rx: internal error"); 690 return CURLE_TFTP_ILLEGAL; /* not really the perfect return code for 691 this */ 692 } 693 return CURLE_OK; 694} 695 696/********************************************************** 697 * 698 * tftp_tx 699 * 700 * Event handler for the TX state 701 * 702 **********************************************************/ 703static CURLcode tftp_tx(struct tftp_state_data *state, tftp_event_t event) 704{ 705 struct Curl_easy *data = state->data; 706 ssize_t sbytes; 707 CURLcode result = CURLE_OK; 708 struct SingleRequest *k = &data->req; 709 size_t cb; /* Bytes currently read */ 710 char buffer[STRERROR_LEN]; 711 712 switch(event) { 713 714 case TFTP_EVENT_ACK: 715 case TFTP_EVENT_OACK: 716 if(event == TFTP_EVENT_ACK) { 717 /* Ack the packet */ 718 int rblock = getrpacketblock(&state->rpacket); 719 720 if(rblock != state->block && 721 /* There's a bug in tftpd-hpa that causes it to send us an ack for 722 * 65535 when the block number wraps to 0. So when we're expecting 723 * 0, also accept 65535. See 724 * https://www.syslinux.org/archives/2010-September/015612.html 725 * */ 726 !(state->block == 0 && rblock == 65535)) { 727 /* This isn't the expected block. Log it and up the retry counter */ 728 infof(data, "Received ACK for block %d, expecting %d", 729 rblock, state->block); 730 state->retries++; 731 /* Bail out if over the maximum */ 732 if(state->retries>state->retry_max) { 733 failf(data, "tftp_tx: giving up waiting for block %d ack", 734 state->block); 735 result = CURLE_SEND_ERROR; 736 } 737 else { 738 /* Re-send the data packet */ 739 sbytes = sendto(state->sockfd, (void *)state->spacket.data, 740 4 + state->sbytes, SEND_4TH_ARG, 741 (struct sockaddr *)&state->remote_addr, 742 state->remote_addrlen); 743 /* Check all sbytes were sent */ 744 if(sbytes<0) { 745 failf(data, "%s", Curl_strerror(SOCKERRNO, 746 buffer, sizeof(buffer))); 747 result = CURLE_SEND_ERROR; 748 } 749 } 750 751 return result; 752 } 753 /* This is the expected packet. Reset the counters and send the next 754 block */ 755 time(&state->rx_time); 756 state->block++; 757 } 758 else 759 state->block = 1; /* first data block is 1 when using OACK */ 760 761 state->retries = 0; 762 setpacketevent(&state->spacket, TFTP_EVENT_DATA); 763 setpacketblock(&state->spacket, state->block); 764 if(state->block > 1 && state->sbytes < state->blksize) { 765 state->state = TFTP_STATE_FIN; 766 return CURLE_OK; 767 } 768 769 /* TFTP considers data block size < 512 bytes as an end of session. So 770 * in some cases we must wait for additional data to build full (512 bytes) 771 * data block. 772 * */ 773 state->sbytes = 0; 774 state->data->req.upload_fromhere = (char *)state->spacket.data + 4; 775 do { 776 result = Curl_fillreadbuffer(data, state->blksize - state->sbytes, &cb); 777 if(result) 778 return result; 779 state->sbytes += (int)cb; 780 state->data->req.upload_fromhere += cb; 781 } while(state->sbytes < state->blksize && cb); 782 783 sbytes = sendto(state->sockfd, (void *) state->spacket.data, 784 4 + state->sbytes, SEND_4TH_ARG, 785 (struct sockaddr *)&state->remote_addr, 786 state->remote_addrlen); 787 /* Check all sbytes were sent */ 788 if(sbytes<0) { 789 failf(data, "%s", Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); 790 return CURLE_SEND_ERROR; 791 } 792 /* Update the progress meter */ 793 k->writebytecount += state->sbytes; 794 Curl_pgrsSetUploadCounter(data, k->writebytecount); 795 break; 796 797 case TFTP_EVENT_TIMEOUT: 798 /* Increment the retry counter and log the timeout */ 799 state->retries++; 800 infof(data, "Timeout waiting for block %d ACK. " 801 " Retries = %d", NEXT_BLOCKNUM(state->block), state->retries); 802 /* Decide if we've had enough */ 803 if(state->retries > state->retry_max) { 804 state->error = TFTP_ERR_TIMEOUT; 805 state->state = TFTP_STATE_FIN; 806 } 807 else { 808 /* Re-send the data packet */ 809 sbytes = sendto(state->sockfd, (void *)state->spacket.data, 810 4 + state->sbytes, SEND_4TH_ARG, 811 (struct sockaddr *)&state->remote_addr, 812 state->remote_addrlen); 813 /* Check all sbytes were sent */ 814 if(sbytes<0) { 815 failf(data, "%s", Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); 816 return CURLE_SEND_ERROR; 817 } 818 /* since this was a re-send, we remain at the still byte position */ 819 Curl_pgrsSetUploadCounter(data, k->writebytecount); 820 } 821 break; 822 823 case TFTP_EVENT_ERROR: 824 state->state = TFTP_STATE_FIN; 825 setpacketevent(&state->spacket, TFTP_EVENT_ERROR); 826 setpacketblock(&state->spacket, state->block); 827 (void)sendto(state->sockfd, (void *)state->spacket.data, 4, SEND_4TH_ARG, 828 (struct sockaddr *)&state->remote_addr, 829 state->remote_addrlen); 830 /* don't bother with the return code, but if the socket is still up we 831 * should be a good TFTP client and let the server know we're done */ 832 state->state = TFTP_STATE_FIN; 833 break; 834 835 default: 836 failf(data, "tftp_tx: internal error, event: %i", (int)(event)); 837 break; 838 } 839 840 return result; 841} 842 843/********************************************************** 844 * 845 * tftp_translate_code 846 * 847 * Translate internal error codes to CURL error codes 848 * 849 **********************************************************/ 850static CURLcode tftp_translate_code(tftp_error_t error) 851{ 852 CURLcode result = CURLE_OK; 853 854 if(error != TFTP_ERR_NONE) { 855 switch(error) { 856 case TFTP_ERR_NOTFOUND: 857 result = CURLE_TFTP_NOTFOUND; 858 break; 859 case TFTP_ERR_PERM: 860 result = CURLE_TFTP_PERM; 861 break; 862 case TFTP_ERR_DISKFULL: 863 result = CURLE_REMOTE_DISK_FULL; 864 break; 865 case TFTP_ERR_UNDEF: 866 case TFTP_ERR_ILLEGAL: 867 result = CURLE_TFTP_ILLEGAL; 868 break; 869 case TFTP_ERR_UNKNOWNID: 870 result = CURLE_TFTP_UNKNOWNID; 871 break; 872 case TFTP_ERR_EXISTS: 873 result = CURLE_REMOTE_FILE_EXISTS; 874 break; 875 case TFTP_ERR_NOSUCHUSER: 876 result = CURLE_TFTP_NOSUCHUSER; 877 break; 878 case TFTP_ERR_TIMEOUT: 879 result = CURLE_OPERATION_TIMEDOUT; 880 break; 881 case TFTP_ERR_NORESPONSE: 882 result = CURLE_COULDNT_CONNECT; 883 break; 884 default: 885 result = CURLE_ABORTED_BY_CALLBACK; 886 break; 887 } 888 } 889 else 890 result = CURLE_OK; 891 892 return result; 893} 894 895/********************************************************** 896 * 897 * tftp_state_machine 898 * 899 * The tftp state machine event dispatcher 900 * 901 **********************************************************/ 902static CURLcode tftp_state_machine(struct tftp_state_data *state, 903 tftp_event_t event) 904{ 905 CURLcode result = CURLE_OK; 906 struct Curl_easy *data = state->data; 907 908 switch(state->state) { 909 case TFTP_STATE_START: 910 DEBUGF(infof(data, "TFTP_STATE_START")); 911 result = tftp_send_first(state, event); 912 break; 913 case TFTP_STATE_RX: 914 DEBUGF(infof(data, "TFTP_STATE_RX")); 915 result = tftp_rx(state, event); 916 break; 917 case TFTP_STATE_TX: 918 DEBUGF(infof(data, "TFTP_STATE_TX")); 919 result = tftp_tx(state, event); 920 break; 921 case TFTP_STATE_FIN: 922 infof(data, "%s", "TFTP finished"); 923 break; 924 default: 925 DEBUGF(infof(data, "STATE: %d", state->state)); 926 failf(data, "%s", "Internal state machine error"); 927 result = CURLE_TFTP_ILLEGAL; 928 break; 929 } 930 931 return result; 932} 933 934/********************************************************** 935 * 936 * tftp_disconnect 937 * 938 * The disconnect callback 939 * 940 **********************************************************/ 941static CURLcode tftp_disconnect(struct Curl_easy *data, 942 struct connectdata *conn, bool dead_connection) 943{ 944 struct tftp_state_data *state = conn->proto.tftpc; 945 (void) data; 946 (void) dead_connection; 947 948 /* done, free dynamically allocated pkt buffers */ 949 if(state) { 950 Curl_safefree(state->rpacket.data); 951 Curl_safefree(state->spacket.data); 952 free(state); 953 } 954 955 return CURLE_OK; 956} 957 958/********************************************************** 959 * 960 * tftp_connect 961 * 962 * The connect callback 963 * 964 **********************************************************/ 965static CURLcode tftp_connect(struct Curl_easy *data, bool *done) 966{ 967 struct tftp_state_data *state; 968 int blksize; 969 int need_blksize; 970 struct connectdata *conn = data->conn; 971 972 blksize = TFTP_BLKSIZE_DEFAULT; 973 974 state = conn->proto.tftpc = calloc(1, sizeof(struct tftp_state_data)); 975 if(!state) 976 return CURLE_OUT_OF_MEMORY; 977 978 /* alloc pkt buffers based on specified blksize */ 979 if(data->set.tftp_blksize) 980 /* range checked when set */ 981 blksize = (int)data->set.tftp_blksize; 982 983 need_blksize = blksize; 984 /* default size is the fallback when no OACK is received */ 985 if(need_blksize < TFTP_BLKSIZE_DEFAULT) 986 need_blksize = TFTP_BLKSIZE_DEFAULT; 987 988 if(!state->rpacket.data) { 989 state->rpacket.data = calloc(1, need_blksize + 2 + 2); 990 991 if(!state->rpacket.data) 992 return CURLE_OUT_OF_MEMORY; 993 } 994 995 if(!state->spacket.data) { 996 state->spacket.data = calloc(1, need_blksize + 2 + 2); 997 998 if(!state->spacket.data) 999 return CURLE_OUT_OF_MEMORY; 1000 } 1001 1002 /* we don't keep TFTP connections up basically because there's none or very 1003 * little gain for UDP */ 1004 connclose(conn, "TFTP"); 1005 1006 state->data = data; 1007 state->sockfd = conn->sock[FIRSTSOCKET]; 1008 state->state = TFTP_STATE_START; 1009 state->error = TFTP_ERR_NONE; 1010 state->blksize = TFTP_BLKSIZE_DEFAULT; /* Unless updated by OACK response */ 1011 state->requested_blksize = blksize; 1012 1013 ((struct sockaddr *)&state->local_addr)->sa_family = 1014 (CURL_SA_FAMILY_T)(conn->remote_addr->family); 1015 1016 tftp_set_timeouts(state); 1017 1018 if(!conn->bits.bound) { 1019 /* If not already bound, bind to any interface, random UDP port. If it is 1020 * reused or a custom local port was desired, this has already been done! 1021 * 1022 * We once used the size of the local_addr struct as the third argument 1023 * for bind() to better work with IPv6 or whatever size the struct could 1024 * have, but we learned that at least Tru64, AIX and IRIX *requires* the 1025 * size of that argument to match the exact size of a 'sockaddr_in' struct 1026 * when running IPv4-only. 1027 * 1028 * Therefore we use the size from the address we connected to, which we 1029 * assume uses the same IP version and thus hopefully this works for both 1030 * IPv4 and IPv6... 1031 */ 1032 int rc = bind(state->sockfd, (struct sockaddr *)&state->local_addr, 1033 conn->remote_addr->addrlen); 1034 if(rc) { 1035 char buffer[STRERROR_LEN]; 1036 failf(data, "bind() failed; %s", 1037 Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); 1038 return CURLE_COULDNT_CONNECT; 1039 } 1040 conn->bits.bound = TRUE; 1041 } 1042 1043 Curl_pgrsStartNow(data); 1044 1045 *done = TRUE; 1046 1047 return CURLE_OK; 1048} 1049 1050/********************************************************** 1051 * 1052 * tftp_done 1053 * 1054 * The done callback 1055 * 1056 **********************************************************/ 1057static CURLcode tftp_done(struct Curl_easy *data, CURLcode status, 1058 bool premature) 1059{ 1060 CURLcode result = CURLE_OK; 1061 struct connectdata *conn = data->conn; 1062 struct tftp_state_data *state = conn->proto.tftpc; 1063 1064 (void)status; /* unused */ 1065 (void)premature; /* not used */ 1066 1067 if(Curl_pgrsDone(data)) 1068 return CURLE_ABORTED_BY_CALLBACK; 1069 1070 /* If we have encountered an error */ 1071 if(state) 1072 result = tftp_translate_code(state->error); 1073 1074 return result; 1075} 1076 1077/********************************************************** 1078 * 1079 * tftp_getsock 1080 * 1081 * The getsock callback 1082 * 1083 **********************************************************/ 1084static int tftp_getsock(struct Curl_easy *data, 1085 struct connectdata *conn, curl_socket_t *socks) 1086{ 1087 (void)data; 1088 socks[0] = conn->sock[FIRSTSOCKET]; 1089 return GETSOCK_READSOCK(0); 1090} 1091 1092/********************************************************** 1093 * 1094 * tftp_receive_packet 1095 * 1096 * Called once select fires and data is ready on the socket 1097 * 1098 **********************************************************/ 1099static CURLcode tftp_receive_packet(struct Curl_easy *data) 1100{ 1101 struct Curl_sockaddr_storage fromaddr; 1102 curl_socklen_t fromlen; 1103 CURLcode result = CURLE_OK; 1104 struct connectdata *conn = data->conn; 1105 struct tftp_state_data *state = conn->proto.tftpc; 1106 1107 /* Receive the packet */ 1108 fromlen = sizeof(fromaddr); 1109 state->rbytes = (int)recvfrom(state->sockfd, 1110 (void *)state->rpacket.data, 1111 state->blksize + 4, 1112 0, 1113 (struct sockaddr *)&fromaddr, 1114 &fromlen); 1115 if(state->remote_addrlen == 0) { 1116 memcpy(&state->remote_addr, &fromaddr, fromlen); 1117 state->remote_addrlen = fromlen; 1118 } 1119 1120 /* Sanity check packet length */ 1121 if(state->rbytes < 4) { 1122 failf(data, "Received too short packet"); 1123 /* Not a timeout, but how best to handle it? */ 1124 state->event = TFTP_EVENT_TIMEOUT; 1125 } 1126 else { 1127 /* The event is given by the TFTP packet time */ 1128 unsigned short event = getrpacketevent(&state->rpacket); 1129 state->event = (tftp_event_t)event; 1130 1131 switch(state->event) { 1132 case TFTP_EVENT_DATA: 1133 /* Don't pass to the client empty or retransmitted packets */ 1134 if(state->rbytes > 4 && 1135 (NEXT_BLOCKNUM(state->block) == getrpacketblock(&state->rpacket))) { 1136 result = Curl_client_write(data, CLIENTWRITE_BODY, 1137 (char *)state->rpacket.data + 4, 1138 state->rbytes-4); 1139 if(result) { 1140 tftp_state_machine(state, TFTP_EVENT_ERROR); 1141 return result; 1142 } 1143 } 1144 break; 1145 case TFTP_EVENT_ERROR: 1146 { 1147 unsigned short error = getrpacketblock(&state->rpacket); 1148 char *str = (char *)state->rpacket.data + 4; 1149 size_t strn = state->rbytes - 4; 1150 state->error = (tftp_error_t)error; 1151 if(tftp_strnlen(str, strn) < strn) 1152 infof(data, "TFTP error: %s", str); 1153 break; 1154 } 1155 case TFTP_EVENT_ACK: 1156 break; 1157 case TFTP_EVENT_OACK: 1158 result = tftp_parse_option_ack(state, 1159 (const char *)state->rpacket.data + 2, 1160 state->rbytes-2); 1161 if(result) 1162 return result; 1163 break; 1164 case TFTP_EVENT_RRQ: 1165 case TFTP_EVENT_WRQ: 1166 default: 1167 failf(data, "%s", "Internal error: Unexpected packet"); 1168 break; 1169 } 1170 1171 /* Update the progress meter */ 1172 if(Curl_pgrsUpdate(data)) { 1173 tftp_state_machine(state, TFTP_EVENT_ERROR); 1174 return CURLE_ABORTED_BY_CALLBACK; 1175 } 1176 } 1177 return result; 1178} 1179 1180/********************************************************** 1181 * 1182 * tftp_state_timeout 1183 * 1184 * Check if timeouts have been reached 1185 * 1186 **********************************************************/ 1187static timediff_t tftp_state_timeout(struct Curl_easy *data, 1188 tftp_event_t *event) 1189{ 1190 time_t current; 1191 struct connectdata *conn = data->conn; 1192 struct tftp_state_data *state = conn->proto.tftpc; 1193 timediff_t timeout_ms; 1194 1195 if(event) 1196 *event = TFTP_EVENT_NONE; 1197 1198 timeout_ms = Curl_timeleft(state->data, NULL, 1199 (state->state == TFTP_STATE_START)); 1200 if(timeout_ms < 0) { 1201 state->error = TFTP_ERR_TIMEOUT; 1202 state->state = TFTP_STATE_FIN; 1203 return 0; 1204 } 1205 time(¤t); 1206 if(current > state->rx_time + state->retry_time) { 1207 if(event) 1208 *event = TFTP_EVENT_TIMEOUT; 1209 time(&state->rx_time); /* update even though we received nothing */ 1210 } 1211 1212 return timeout_ms; 1213} 1214 1215/********************************************************** 1216 * 1217 * tftp_multi_statemach 1218 * 1219 * Handle single RX socket event and return 1220 * 1221 **********************************************************/ 1222static CURLcode tftp_multi_statemach(struct Curl_easy *data, bool *done) 1223{ 1224 tftp_event_t event; 1225 CURLcode result = CURLE_OK; 1226 struct connectdata *conn = data->conn; 1227 struct tftp_state_data *state = conn->proto.tftpc; 1228 timediff_t timeout_ms = tftp_state_timeout(data, &event); 1229 1230 *done = FALSE; 1231 1232 if(timeout_ms < 0) { 1233 failf(data, "TFTP response timeout"); 1234 return CURLE_OPERATION_TIMEDOUT; 1235 } 1236 if(event != TFTP_EVENT_NONE) { 1237 result = tftp_state_machine(state, event); 1238 if(result) 1239 return result; 1240 *done = (state->state == TFTP_STATE_FIN) ? TRUE : FALSE; 1241 if(*done) 1242 /* Tell curl we're done */ 1243 Curl_setup_transfer(data, -1, -1, FALSE, -1); 1244 } 1245 else { 1246 /* no timeouts to handle, check our socket */ 1247 int rc = SOCKET_READABLE(state->sockfd, 0); 1248 1249 if(rc == -1) { 1250 /* bail out */ 1251 int error = SOCKERRNO; 1252 char buffer[STRERROR_LEN]; 1253 failf(data, "%s", Curl_strerror(error, buffer, sizeof(buffer))); 1254 state->event = TFTP_EVENT_ERROR; 1255 } 1256 else if(rc) { 1257 result = tftp_receive_packet(data); 1258 if(result) 1259 return result; 1260 result = tftp_state_machine(state, state->event); 1261 if(result) 1262 return result; 1263 *done = (state->state == TFTP_STATE_FIN) ? TRUE : FALSE; 1264 if(*done) 1265 /* Tell curl we're done */ 1266 Curl_setup_transfer(data, -1, -1, FALSE, -1); 1267 } 1268 /* if rc == 0, then select() timed out */ 1269 } 1270 1271 return result; 1272} 1273 1274/********************************************************** 1275 * 1276 * tftp_doing 1277 * 1278 * Called from multi.c while DOing 1279 * 1280 **********************************************************/ 1281static CURLcode tftp_doing(struct Curl_easy *data, bool *dophase_done) 1282{ 1283 CURLcode result; 1284 result = tftp_multi_statemach(data, dophase_done); 1285 1286 if(*dophase_done) { 1287 DEBUGF(infof(data, "DO phase is complete")); 1288 } 1289 else if(!result) { 1290 /* The multi code doesn't have this logic for the DOING state so we 1291 provide it for TFTP since it may do the entire transfer in this 1292 state. */ 1293 if(Curl_pgrsUpdate(data)) 1294 result = CURLE_ABORTED_BY_CALLBACK; 1295 else 1296 result = Curl_speedcheck(data, Curl_now()); 1297 } 1298 return result; 1299} 1300 1301/********************************************************** 1302 * 1303 * tftp_perform 1304 * 1305 * Entry point for transfer from tftp_do, starts state mach 1306 * 1307 **********************************************************/ 1308static CURLcode tftp_perform(struct Curl_easy *data, bool *dophase_done) 1309{ 1310 CURLcode result = CURLE_OK; 1311 struct connectdata *conn = data->conn; 1312 struct tftp_state_data *state = conn->proto.tftpc; 1313 1314 *dophase_done = FALSE; 1315 1316 result = tftp_state_machine(state, TFTP_EVENT_INIT); 1317 1318 if((state->state == TFTP_STATE_FIN) || result) 1319 return result; 1320 1321 tftp_multi_statemach(data, dophase_done); 1322 1323 if(*dophase_done) 1324 DEBUGF(infof(data, "DO phase is complete")); 1325 1326 return result; 1327} 1328 1329 1330/********************************************************** 1331 * 1332 * tftp_do 1333 * 1334 * The do callback 1335 * 1336 * This callback initiates the TFTP transfer 1337 * 1338 **********************************************************/ 1339 1340static CURLcode tftp_do(struct Curl_easy *data, bool *done) 1341{ 1342 struct tftp_state_data *state; 1343 CURLcode result; 1344 struct connectdata *conn = data->conn; 1345 1346 *done = FALSE; 1347 1348 if(!conn->proto.tftpc) { 1349 result = tftp_connect(data, done); 1350 if(result) 1351 return result; 1352 } 1353 1354 state = conn->proto.tftpc; 1355 if(!state) 1356 return CURLE_TFTP_ILLEGAL; 1357 1358 result = tftp_perform(data, done); 1359 1360 /* If tftp_perform() returned an error, use that for return code. If it 1361 was OK, see if tftp_translate_code() has an error. */ 1362 if(!result) 1363 /* If we have encountered an internal tftp error, translate it. */ 1364 result = tftp_translate_code(state->error); 1365 1366 return result; 1367} 1368 1369static CURLcode tftp_setup_connection(struct Curl_easy *data, 1370 struct connectdata *conn) 1371{ 1372 char *type; 1373 1374 conn->transport = TRNSPRT_UDP; 1375 1376 /* TFTP URLs support an extension like ";mode=<typecode>" that 1377 * we'll try to get now! */ 1378 type = strstr(data->state.up.path, ";mode="); 1379 1380 if(!type) 1381 type = strstr(conn->host.rawalloc, ";mode="); 1382 1383 if(type) { 1384 char command; 1385 *type = 0; /* it was in the middle of the hostname */ 1386 command = Curl_raw_toupper(type[6]); 1387 1388 switch(command) { 1389 case 'A': /* ASCII mode */ 1390 case 'N': /* NETASCII mode */ 1391 data->state.prefer_ascii = TRUE; 1392 break; 1393 1394 case 'O': /* octet mode */ 1395 case 'I': /* binary mode */ 1396 default: 1397 /* switch off ASCII */ 1398 data->state.prefer_ascii = FALSE; 1399 break; 1400 } 1401 } 1402 1403 return CURLE_OK; 1404} 1405#endif 1406