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