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