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