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