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