1 /*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 1998 - 2015, 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 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 #include "curl_printf.h" 61 #include "select.h" 62 63 /* The last #include files should be: */ 64 #include "curl_memory.h" 65 #include "memdebug.h" 66 67 /* RFC2348 allows the block size to be negotiated */ 68 #define TFTP_BLKSIZE_DEFAULT 512 69 #define TFTP_BLKSIZE_MIN 8 70 #define TFTP_BLKSIZE_MAX 65464 71 #define TFTP_OPTION_BLKSIZE "blksize" 72 73 /* from RFC2349: */ 74 #define TFTP_OPTION_TSIZE "tsize" 75 #define TFTP_OPTION_INTERVAL "timeout" 76 77 typedef enum { 78 TFTP_MODE_NETASCII=0, 79 TFTP_MODE_OCTET 80 } tftp_mode_t; 81 82 typedef enum { 83 TFTP_STATE_START=0, 84 TFTP_STATE_RX, 85 TFTP_STATE_TX, 86 TFTP_STATE_FIN 87 } tftp_state_t; 88 89 typedef enum { 90 TFTP_EVENT_NONE = -1, 91 TFTP_EVENT_INIT = 0, 92 TFTP_EVENT_RRQ = 1, 93 TFTP_EVENT_WRQ = 2, 94 TFTP_EVENT_DATA = 3, 95 TFTP_EVENT_ACK = 4, 96 TFTP_EVENT_ERROR = 5, 97 TFTP_EVENT_OACK = 6, 98 TFTP_EVENT_TIMEOUT 99 } tftp_event_t; 100 101 typedef enum { 102 TFTP_ERR_UNDEF=0, 103 TFTP_ERR_NOTFOUND, 104 TFTP_ERR_PERM, 105 TFTP_ERR_DISKFULL, 106 TFTP_ERR_ILLEGAL, 107 TFTP_ERR_UNKNOWNID, 108 TFTP_ERR_EXISTS, 109 TFTP_ERR_NOSUCHUSER, /* This will never be triggered by this code */ 110 111 /* The remaining error codes are internal to curl */ 112 TFTP_ERR_NONE = -100, 113 TFTP_ERR_TIMEOUT, 114 TFTP_ERR_NORESPONSE 115 } tftp_error_t; 116 117 typedef struct tftp_packet { 118 unsigned char *data; 119 } tftp_packet_t; 120 121 typedef struct tftp_state_data { 122 tftp_state_t state; 123 tftp_mode_t mode; 124 tftp_error_t error; 125 tftp_event_t event; 126 struct connectdata *conn; 127 curl_socket_t sockfd; 128 int retries; 129 int retry_time; 130 int retry_max; 131 time_t start_time; 132 time_t max_time; 133 time_t rx_time; 134 unsigned short block; 135 struct Curl_sockaddr_storage local_addr; 136 struct Curl_sockaddr_storage remote_addr; 137 curl_socklen_t remote_addrlen; 138 int rbytes; 139 int sbytes; 140 int blksize; 141 int requested_blksize; 142 tftp_packet_t rpacket; 143 tftp_packet_t spacket; 144 } tftp_state_data_t; 145 146 147 /* Forward declarations */ 148 static CURLcode tftp_rx(tftp_state_data_t *state, tftp_event_t event); 149 static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event); 150 static CURLcode tftp_connect(struct connectdata *conn, bool *done); 151 static CURLcode tftp_disconnect(struct connectdata *conn, 152 bool dead_connection); 153 static CURLcode tftp_do(struct connectdata *conn, bool *done); 154 static CURLcode tftp_done(struct connectdata *conn, 155 CURLcode, bool premature); 156 static CURLcode tftp_setup_connection(struct connectdata * conn); 157 static CURLcode tftp_multi_statemach(struct connectdata *conn, bool *done); 158 static CURLcode tftp_doing(struct connectdata *conn, bool *dophase_done); 159 static int tftp_getsock(struct connectdata *conn, curl_socket_t *socks, 160 int numsocks); 161 static CURLcode tftp_translate_code(tftp_error_t error); 162 163 164 /* 165 * TFTP protocol handler. 166 */ 167 168 const struct Curl_handler Curl_handler_tftp = { 169 "TFTP", /* scheme */ 170 tftp_setup_connection, /* setup_connection */ 171 tftp_do, /* do_it */ 172 tftp_done, /* done */ 173 ZERO_NULL, /* do_more */ 174 tftp_connect, /* connect_it */ 175 tftp_multi_statemach, /* connecting */ 176 tftp_doing, /* doing */ 177 tftp_getsock, /* proto_getsock */ 178 tftp_getsock, /* doing_getsock */ 179 ZERO_NULL, /* domore_getsock */ 180 ZERO_NULL, /* perform_getsock */ 181 tftp_disconnect, /* disconnect */ 182 ZERO_NULL, /* readwrite */ 183 PORT_TFTP, /* defport */ 184 CURLPROTO_TFTP, /* protocol */ 185 PROTOPT_NONE | PROTOPT_NOURLQUERY /* flags */ 186 }; 187 188 /********************************************************** 189 * 190 * tftp_set_timeouts - 191 * 192 * Set timeouts based on state machine state. 193 * Use user provided connect timeouts until DATA or ACK 194 * packet is received, then use user-provided transfer timeouts 195 * 196 * 197 **********************************************************/ 198 static CURLcode tftp_set_timeouts(tftp_state_data_t *state) 199 { 200 time_t maxtime, timeout; 201 long timeout_ms; 202 bool start = (state->state == TFTP_STATE_START) ? TRUE : FALSE; 203 204 time(&state->start_time); 205 206 /* Compute drop-dead time */ 207 timeout_ms = Curl_timeleft(state->conn->data, NULL, start); 208 209 if(timeout_ms < 0) { 210 /* time-out, bail out, go home */ 211 failf(state->conn->data, "Connection time-out"); 212 return CURLE_OPERATION_TIMEDOUT; 213 } 214 215 if(start) { 216 217 maxtime = (time_t)(timeout_ms + 500) / 1000; 218 state->max_time = state->start_time+maxtime; 219 220 /* Set per-block timeout to total */ 221 timeout = maxtime; 222 223 /* Average restart after 5 seconds */ 224 state->retry_max = (int)timeout/5; 225 226 if(state->retry_max < 1) 227 /* avoid division by zero below */ 228 state->retry_max = 1; 229 230 /* Compute the re-start interval to suit the timeout */ 231 state->retry_time = (int)timeout/state->retry_max; 232 if(state->retry_time<1) 233 state->retry_time=1; 234 235 } 236 else { 237 if(timeout_ms > 0) 238 maxtime = (time_t)(timeout_ms + 500) / 1000; 239 else 240 maxtime = 3600; 241 242 state->max_time = state->start_time+maxtime; 243 244 /* Set per-block timeout to total */ 245 timeout = maxtime; 246 247 /* Average reposting an ACK after 5 seconds */ 248 state->retry_max = (int)timeout/5; 249 } 250 /* But bound the total number */ 251 if(state->retry_max<3) 252 state->retry_max=3; 253 254 if(state->retry_max>50) 255 state->retry_max=50; 256 257 /* Compute the re-ACK interval to suit the timeout */ 258 state->retry_time = (int)(timeout/state->retry_max); 259 if(state->retry_time<1) 260 state->retry_time=1; 261 262 infof(state->conn->data, 263 "set timeouts for state %d; Total %ld, retry %d maxtry %d\n", 264 (int)state->state, (long)(state->max_time-state->start_time), 265 state->retry_time, state->retry_max); 266 267 /* init RX time */ 268 time(&state->rx_time); 269 270 return CURLE_OK; 271 } 272 273 /********************************************************** 274 * 275 * tftp_set_send_first 276 * 277 * Event handler for the START state 278 * 279 **********************************************************/ 280 281 static void setpacketevent(tftp_packet_t *packet, unsigned short num) 282 { 283 packet->data[0] = (unsigned char)(num >> 8); 284 packet->data[1] = (unsigned char)(num & 0xff); 285 } 286 287 288 static void setpacketblock(tftp_packet_t *packet, unsigned short num) 289 { 290 packet->data[2] = (unsigned char)(num >> 8); 291 packet->data[3] = (unsigned char)(num & 0xff); 292 } 293 294 static unsigned short getrpacketevent(const tftp_packet_t *packet) 295 { 296 return (unsigned short)((packet->data[0] << 8) | packet->data[1]); 297 } 298 299 static unsigned short getrpacketblock(const tftp_packet_t *packet) 300 { 301 return (unsigned short)((packet->data[2] << 8) | packet->data[3]); 302 } 303 304 static size_t Curl_strnlen(const char *string, size_t maxlen) 305 { 306 const char *end = memchr (string, '\0', maxlen); 307 return end ? (size_t) (end - string) : maxlen; 308 } 309 310 static const char *tftp_option_get(const char *buf, size_t len, 311 const char **option, const char **value) 312 { 313 size_t loc; 314 315 loc = Curl_strnlen( buf, len ); 316 loc++; /* NULL term */ 317 318 if(loc >= len) 319 return NULL; 320 *option = buf; 321 322 loc += Curl_strnlen( buf+loc, len-loc ); 323 loc++; /* NULL term */ 324 325 if(loc > len) 326 return NULL; 327 *value = &buf[strlen(*option) + 1]; 328 329 return &buf[loc]; 330 } 331 332 static CURLcode tftp_parse_option_ack(tftp_state_data_t *state, 333 const char *ptr, int len) 334 { 335 const char *tmp = ptr; 336 struct SessionHandle *data = state->conn->data; 337 338 /* if OACK doesn't contain blksize option, the default (512) must be used */ 339 state->blksize = TFTP_BLKSIZE_DEFAULT; 340 341 while(tmp < ptr + len) { 342 const char *option, *value; 343 344 tmp = tftp_option_get(tmp, ptr + len - tmp, &option, &value); 345 if(tmp == NULL) { 346 failf(data, "Malformed ACK packet, rejecting"); 347 return CURLE_TFTP_ILLEGAL; 348 } 349 350 infof(data, "got option=(%s) value=(%s)\n", option, value); 351 352 if(checkprefix(option, TFTP_OPTION_BLKSIZE)) { 353 long blksize; 354 355 blksize = strtol( value, NULL, 10 ); 356 357 if(!blksize) { 358 failf(data, "invalid blocksize value in OACK packet"); 359 return CURLE_TFTP_ILLEGAL; 360 } 361 else if(blksize > TFTP_BLKSIZE_MAX) { 362 failf(data, "%s (%d)", "blksize is larger than max supported", 363 TFTP_BLKSIZE_MAX); 364 return CURLE_TFTP_ILLEGAL; 365 } 366 else if(blksize < TFTP_BLKSIZE_MIN) { 367 failf(data, "%s (%d)", "blksize is smaller than min supported", 368 TFTP_BLKSIZE_MIN); 369 return CURLE_TFTP_ILLEGAL; 370 } 371 else if(blksize > state->requested_blksize) { 372 /* could realloc pkt buffers here, but the spec doesn't call out 373 * support for the server requesting a bigger blksize than the client 374 * requests */ 375 failf(data, "%s (%ld)", 376 "server requested blksize larger than allocated", blksize); 377 return CURLE_TFTP_ILLEGAL; 378 } 379 380 state->blksize = (int)blksize; 381 infof(data, "%s (%d) %s (%d)\n", "blksize parsed from OACK", 382 state->blksize, "requested", state->requested_blksize); 383 } 384 else if(checkprefix(option, TFTP_OPTION_TSIZE)) { 385 long tsize = 0; 386 387 tsize = strtol( value, NULL, 10 ); 388 infof(data, "%s (%ld)\n", "tsize parsed from OACK", tsize); 389 390 /* tsize should be ignored on upload: Who cares about the size of the 391 remote file? */ 392 if(!data->set.upload) { 393 if(!tsize) { 394 failf(data, "invalid tsize -:%s:- value in OACK packet", value); 395 return CURLE_TFTP_ILLEGAL; 396 } 397 Curl_pgrsSetDownloadSize(data, tsize); 398 } 399 } 400 } 401 402 return CURLE_OK; 403 } 404 405 static size_t tftp_option_add(tftp_state_data_t *state, size_t csize, 406 char *buf, const char *option) 407 { 408 if(( strlen(option) + csize + 1 ) > (size_t)state->blksize) 409 return 0; 410 strcpy(buf, option); 411 return strlen(option) + 1; 412 } 413 414 static CURLcode tftp_connect_for_tx(tftp_state_data_t *state, 415 tftp_event_t event) 416 { 417 CURLcode result; 418 #ifndef CURL_DISABLE_VERBOSE_STRINGS 419 struct SessionHandle *data = state->conn->data; 420 421 infof(data, "%s\n", "Connected for transmit"); 422 #endif 423 state->state = TFTP_STATE_TX; 424 result = tftp_set_timeouts(state); 425 if(result) 426 return result; 427 return tftp_tx(state, event); 428 } 429 430 static CURLcode tftp_connect_for_rx(tftp_state_data_t *state, 431 tftp_event_t event) 432 { 433 CURLcode result; 434 #ifndef CURL_DISABLE_VERBOSE_STRINGS 435 struct SessionHandle *data = state->conn->data; 436 437 infof(data, "%s\n", "Connected for receive"); 438 #endif 439 state->state = TFTP_STATE_RX; 440 result = tftp_set_timeouts(state); 441 if(result) 442 return result; 443 return tftp_rx(state, event); 444 } 445 446 static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event) 447 { 448 size_t sbytes; 449 ssize_t senddata; 450 const char *mode = "octet"; 451 char *filename; 452 char buf[64]; 453 struct SessionHandle *data = state->conn->data; 454 CURLcode result = CURLE_OK; 455 456 /* Set ascii mode if -B flag was used */ 457 if(data->set.prefer_ascii) 458 mode = "netascii"; 459 460 switch(event) { 461 462 case TFTP_EVENT_INIT: /* Send the first packet out */ 463 case TFTP_EVENT_TIMEOUT: /* Resend the first packet out */ 464 /* Increment the retry counter, quit if over the limit */ 465 state->retries++; 466 if(state->retries>state->retry_max) { 467 state->error = TFTP_ERR_NORESPONSE; 468 state->state = TFTP_STATE_FIN; 469 return result; 470 } 471 472 if(data->set.upload) { 473 /* If we are uploading, send an WRQ */ 474 setpacketevent(&state->spacket, TFTP_EVENT_WRQ); 475 state->conn->data->req.upload_fromhere = 476 (char *)state->spacket.data+4; 477 if(data->state.infilesize != -1) 478 Curl_pgrsSetUploadSize(data, data->state.infilesize); 479 } 480 else { 481 /* If we are downloading, send an RRQ */ 482 setpacketevent(&state->spacket, TFTP_EVENT_RRQ); 483 } 484 /* As RFC3617 describes the separator slash is not actually part of the 485 file name so we skip the always-present first letter of the path 486 string. */ 487 filename = curl_easy_unescape(data, &state->conn->data->state.path[1], 0, 488 NULL); 489 if(!filename) 490 return CURLE_OUT_OF_MEMORY; 491 492 snprintf((char *)state->spacket.data+2, 493 state->blksize, 494 "%s%c%s%c", filename, '\0', mode, '\0'); 495 sbytes = 4 + strlen(filename) + strlen(mode); 496 497 /* add tsize option */ 498 if(data->set.upload && (data->state.infilesize != -1)) 499 snprintf(buf, sizeof(buf), "%" CURL_FORMAT_CURL_OFF_T, 500 data->state.infilesize); 501 else 502 strcpy(buf, "0"); /* the destination is large enough */ 503 504 sbytes += tftp_option_add(state, sbytes, 505 (char *)state->spacket.data+sbytes, 506 TFTP_OPTION_TSIZE); 507 sbytes += tftp_option_add(state, sbytes, 508 (char *)state->spacket.data+sbytes, buf); 509 /* add blksize option */ 510 snprintf( buf, sizeof(buf), "%d", state->requested_blksize ); 511 sbytes += tftp_option_add(state, sbytes, 512 (char *)state->spacket.data+sbytes, 513 TFTP_OPTION_BLKSIZE); 514 sbytes += tftp_option_add(state, sbytes, 515 (char *)state->spacket.data+sbytes, buf ); 516 517 /* add timeout option */ 518 snprintf( buf, sizeof(buf), "%d", state->retry_time); 519 sbytes += tftp_option_add(state, sbytes, 520 (char *)state->spacket.data+sbytes, 521 TFTP_OPTION_INTERVAL); 522 sbytes += tftp_option_add(state, sbytes, 523 (char *)state->spacket.data+sbytes, buf ); 524 525 /* the typecase for the 3rd argument is mostly for systems that do 526 not have a size_t argument, like older unixes that want an 'int' */ 527 senddata = sendto(state->sockfd, (void *)state->spacket.data, 528 (SEND_TYPE_ARG3)sbytes, 0, 529 state->conn->ip_addr->ai_addr, 530 state->conn->ip_addr->ai_addrlen); 531 if(senddata != (ssize_t)sbytes) { 532 failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO)); 533 } 534 free(filename); 535 break; 536 537 case TFTP_EVENT_OACK: 538 if(data->set.upload) { 539 result = tftp_connect_for_tx(state, event); 540 } 541 else { 542 result = tftp_connect_for_rx(state, event); 543 } 544 break; 545 546 case TFTP_EVENT_ACK: /* Connected for transmit */ 547 result = tftp_connect_for_tx(state, event); 548 break; 549 550 case TFTP_EVENT_DATA: /* Connected for receive */ 551 result = tftp_connect_for_rx(state, event); 552 break; 553 554 case TFTP_EVENT_ERROR: 555 state->state = TFTP_STATE_FIN; 556 break; 557 558 default: 559 failf(state->conn->data, "tftp_send_first: internal error"); 560 break; 561 } 562 563 return result; 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 **********************************************************/ 577 static 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 **********************************************************/ 698 static 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 result = 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 result = 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 result = CURLE_SEND_ERROR; 741 } 742 } 743 744 return result; 745 } 746 /* This is the expected packet. Reset the counters and send the next 747 block */ 748 time(&state->rx_time); 749 state->block++; 750 } 751 else 752 state->block = 1; /* first data block is 1 when using OACK */ 753 754 state->retries = 0; 755 setpacketevent(&state->spacket, TFTP_EVENT_DATA); 756 setpacketblock(&state->spacket, state->block); 757 if(state->block > 1 && state->sbytes < (int)state->blksize) { 758 state->state = TFTP_STATE_FIN; 759 return CURLE_OK; 760 } 761 762 result = Curl_fillreadbuffer(state->conn, state->blksize, &state->sbytes); 763 if(result) 764 return result; 765 766 sbytes = sendto(state->sockfd, (void *) state->spacket.data, 767 4 + state->sbytes, SEND_4TH_ARG, 768 (struct sockaddr *)&state->remote_addr, 769 state->remote_addrlen); 770 /* Check all sbytes were sent */ 771 if(sbytes<0) { 772 failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO)); 773 return CURLE_SEND_ERROR; 774 } 775 /* Update the progress meter */ 776 k->writebytecount += state->sbytes; 777 Curl_pgrsSetUploadCounter(data, k->writebytecount); 778 break; 779 780 case TFTP_EVENT_TIMEOUT: 781 /* Increment the retry counter and log the timeout */ 782 state->retries++; 783 infof(data, "Timeout waiting for block %d ACK. " 784 " Retries = %d\n", NEXT_BLOCKNUM(state->block), state->retries); 785 /* Decide if we've had enough */ 786 if(state->retries > state->retry_max) { 787 state->error = TFTP_ERR_TIMEOUT; 788 state->state = TFTP_STATE_FIN; 789 } 790 else { 791 /* Re-send the data packet */ 792 sbytes = sendto(state->sockfd, (void *)state->spacket.data, 793 4+state->sbytes, SEND_4TH_ARG, 794 (struct sockaddr *)&state->remote_addr, 795 state->remote_addrlen); 796 /* Check all sbytes were sent */ 797 if(sbytes<0) { 798 failf(data, "%s", Curl_strerror(state->conn, SOCKERRNO)); 799 return CURLE_SEND_ERROR; 800 } 801 /* since this was a re-send, we remain at the still byte position */ 802 Curl_pgrsSetUploadCounter(data, k->writebytecount); 803 } 804 break; 805 806 case TFTP_EVENT_ERROR: 807 state->state = TFTP_STATE_FIN; 808 setpacketevent(&state->spacket, TFTP_EVENT_ERROR); 809 setpacketblock(&state->spacket, state->block); 810 (void)sendto(state->sockfd, (void *)state->spacket.data, 4, SEND_4TH_ARG, 811 (struct sockaddr *)&state->remote_addr, 812 state->remote_addrlen); 813 /* don't bother with the return code, but if the socket is still up we 814 * should be a good TFTP client and let the server know we're done */ 815 state->state = TFTP_STATE_FIN; 816 break; 817 818 default: 819 failf(data, "tftp_tx: internal error, event: %i", (int)(event)); 820 break; 821 } 822 823 return result; 824 } 825 826 /********************************************************** 827 * 828 * tftp_translate_code 829 * 830 * Translate internal error codes to CURL error codes 831 * 832 **********************************************************/ 833 static CURLcode tftp_translate_code(tftp_error_t error) 834 { 835 CURLcode result = CURLE_OK; 836 837 if(error != TFTP_ERR_NONE) { 838 switch(error) { 839 case TFTP_ERR_NOTFOUND: 840 result = CURLE_TFTP_NOTFOUND; 841 break; 842 case TFTP_ERR_PERM: 843 result = CURLE_TFTP_PERM; 844 break; 845 case TFTP_ERR_DISKFULL: 846 result = CURLE_REMOTE_DISK_FULL; 847 break; 848 case TFTP_ERR_UNDEF: 849 case TFTP_ERR_ILLEGAL: 850 result = CURLE_TFTP_ILLEGAL; 851 break; 852 case TFTP_ERR_UNKNOWNID: 853 result = CURLE_TFTP_UNKNOWNID; 854 break; 855 case TFTP_ERR_EXISTS: 856 result = CURLE_REMOTE_FILE_EXISTS; 857 break; 858 case TFTP_ERR_NOSUCHUSER: 859 result = CURLE_TFTP_NOSUCHUSER; 860 break; 861 case TFTP_ERR_TIMEOUT: 862 result = CURLE_OPERATION_TIMEDOUT; 863 break; 864 case TFTP_ERR_NORESPONSE: 865 result = CURLE_COULDNT_CONNECT; 866 break; 867 default: 868 result = CURLE_ABORTED_BY_CALLBACK; 869 break; 870 } 871 } 872 else 873 result = CURLE_OK; 874 875 return result; 876 } 877 878 /********************************************************** 879 * 880 * tftp_state_machine 881 * 882 * The tftp state machine event dispatcher 883 * 884 **********************************************************/ 885 static CURLcode tftp_state_machine(tftp_state_data_t *state, 886 tftp_event_t event) 887 { 888 CURLcode result = CURLE_OK; 889 struct SessionHandle *data = state->conn->data; 890 891 switch(state->state) { 892 case TFTP_STATE_START: 893 DEBUGF(infof(data, "TFTP_STATE_START\n")); 894 result = tftp_send_first(state, event); 895 break; 896 case TFTP_STATE_RX: 897 DEBUGF(infof(data, "TFTP_STATE_RX\n")); 898 result = tftp_rx(state, event); 899 break; 900 case TFTP_STATE_TX: 901 DEBUGF(infof(data, "TFTP_STATE_TX\n")); 902 result = tftp_tx(state, event); 903 break; 904 case TFTP_STATE_FIN: 905 infof(data, "%s\n", "TFTP finished"); 906 break; 907 default: 908 DEBUGF(infof(data, "STATE: %d\n", state->state)); 909 failf(data, "%s", "Internal state machine error"); 910 result = CURLE_TFTP_ILLEGAL; 911 break; 912 } 913 914 return result; 915 } 916 917 /********************************************************** 918 * 919 * tftp_disconnect 920 * 921 * The disconnect callback 922 * 923 **********************************************************/ 924 static CURLcode tftp_disconnect(struct connectdata *conn, bool dead_connection) 925 { 926 tftp_state_data_t *state = conn->proto.tftpc; 927 (void) dead_connection; 928 929 /* done, free dynamically allocated pkt buffers */ 930 if(state) { 931 Curl_safefree(state->rpacket.data); 932 Curl_safefree(state->spacket.data); 933 free(state); 934 } 935 936 return CURLE_OK; 937 } 938 939 /********************************************************** 940 * 941 * tftp_connect 942 * 943 * The connect callback 944 * 945 **********************************************************/ 946 static CURLcode tftp_connect(struct connectdata *conn, bool *done) 947 { 948 tftp_state_data_t *state; 949 int blksize, rc; 950 951 blksize = TFTP_BLKSIZE_DEFAULT; 952 953 state = conn->proto.tftpc = calloc(1, sizeof(tftp_state_data_t)); 954 if(!state) 955 return CURLE_OUT_OF_MEMORY; 956 957 /* alloc pkt buffers based on specified blksize */ 958 if(conn->data->set.tftp_blksize) { 959 blksize = (int)conn->data->set.tftp_blksize; 960 if(blksize > TFTP_BLKSIZE_MAX || blksize < TFTP_BLKSIZE_MIN ) 961 return CURLE_TFTP_ILLEGAL; 962 } 963 964 if(!state->rpacket.data) { 965 state->rpacket.data = calloc(1, blksize + 2 + 2); 966 967 if(!state->rpacket.data) 968 return CURLE_OUT_OF_MEMORY; 969 } 970 971 if(!state->spacket.data) { 972 state->spacket.data = calloc(1, blksize + 2 + 2); 973 974 if(!state->spacket.data) 975 return CURLE_OUT_OF_MEMORY; 976 } 977 978 /* we don't keep TFTP connections up bascially because there's none or very 979 * little gain for UDP */ 980 connclose(conn, "TFTP"); 981 982 state->conn = conn; 983 state->sockfd = state->conn->sock[FIRSTSOCKET]; 984 state->state = TFTP_STATE_START; 985 state->error = TFTP_ERR_NONE; 986 state->blksize = TFTP_BLKSIZE_DEFAULT; 987 state->requested_blksize = blksize; 988 989 ((struct sockaddr *)&state->local_addr)->sa_family = 990 (unsigned short)(conn->ip_addr->ai_family); 991 992 tftp_set_timeouts(state); 993 994 if(!conn->bits.bound) { 995 /* If not already bound, bind to any interface, random UDP port. If it is 996 * reused or a custom local port was desired, this has already been done! 997 * 998 * We once used the size of the local_addr struct as the third argument 999 * for bind() to better work with IPv6 or whatever size the struct could 1000 * have, but we learned that at least Tru64, AIX and IRIX *requires* the 1001 * size of that argument to match the exact size of a 'sockaddr_in' struct 1002 * when running IPv4-only. 1003 * 1004 * Therefore we use the size from the address we connected to, which we 1005 * assume uses the same IP version and thus hopefully this works for both 1006 * IPv4 and IPv6... 1007 */ 1008 rc = bind(state->sockfd, (struct sockaddr *)&state->local_addr, 1009 conn->ip_addr->ai_addrlen); 1010 if(rc) { 1011 failf(conn->data, "bind() failed; %s", 1012 Curl_strerror(conn, SOCKERRNO)); 1013 return CURLE_COULDNT_CONNECT; 1014 } 1015 conn->bits.bound = TRUE; 1016 } 1017 1018 Curl_pgrsStartNow(conn->data); 1019 1020 *done = TRUE; 1021 1022 return CURLE_OK; 1023 } 1024 1025 /********************************************************** 1026 * 1027 * tftp_done 1028 * 1029 * The done callback 1030 * 1031 **********************************************************/ 1032 static CURLcode tftp_done(struct connectdata *conn, CURLcode status, 1033 bool premature) 1034 { 1035 CURLcode result = CURLE_OK; 1036 tftp_state_data_t *state = (tftp_state_data_t *)conn->proto.tftpc; 1037 1038 (void)status; /* unused */ 1039 (void)premature; /* not used */ 1040 1041 if(Curl_pgrsDone(conn)) 1042 return CURLE_ABORTED_BY_CALLBACK; 1043 1044 /* If we have encountered an error */ 1045 if(state) 1046 result = tftp_translate_code(state->error); 1047 1048 return result; 1049 } 1050 1051 /********************************************************** 1052 * 1053 * tftp_getsock 1054 * 1055 * The getsock callback 1056 * 1057 **********************************************************/ 1058 static 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 **********************************************************/ 1076 static 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 **********************************************************/ 1160 static 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 **********************************************************/ 1195 static 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) 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) 1232 return result; 1233 result = tftp_state_machine(state, state->event); 1234 if(result) 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 **********************************************************/ 1254 static 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 else if(!result) { 1263 /* The multi code doesn't have this logic for the DOING state so we 1264 provide it for TFTP since it may do the entire transfer in this 1265 state. */ 1266 if(Curl_pgrsUpdate(conn)) 1267 result = CURLE_ABORTED_BY_CALLBACK; 1268 else 1269 result = Curl_speedcheck(conn->data, Curl_tvnow()); 1270 } 1271 return result; 1272 } 1273 1274 /********************************************************** 1275 * 1276 * tftp_peform 1277 * 1278 * Entry point for transfer from tftp_do, sarts state mach 1279 * 1280 **********************************************************/ 1281 static CURLcode tftp_perform(struct connectdata *conn, bool *dophase_done) 1282 { 1283 CURLcode result = CURLE_OK; 1284 tftp_state_data_t *state = (tftp_state_data_t *)conn->proto.tftpc; 1285 1286 *dophase_done = FALSE; 1287 1288 result = tftp_state_machine(state, TFTP_EVENT_INIT); 1289 1290 if((state->state == TFTP_STATE_FIN) || result) 1291 return result; 1292 1293 tftp_multi_statemach(conn, dophase_done); 1294 1295 if(*dophase_done) 1296 DEBUGF(infof(conn->data, "DO phase is complete\n")); 1297 1298 return result; 1299 } 1300 1301 1302 /********************************************************** 1303 * 1304 * tftp_do 1305 * 1306 * The do callback 1307 * 1308 * This callback initiates the TFTP transfer 1309 * 1310 **********************************************************/ 1311 1312 static CURLcode tftp_do(struct connectdata *conn, bool *done) 1313 { 1314 tftp_state_data_t *state; 1315 CURLcode result; 1316 1317 *done = FALSE; 1318 1319 if(!conn->proto.tftpc) { 1320 result = tftp_connect(conn, done); 1321 if(result) 1322 return result; 1323 } 1324 1325 state = (tftp_state_data_t *)conn->proto.tftpc; 1326 if(!state) 1327 return CURLE_BAD_CALLING_ORDER; 1328 1329 result = tftp_perform(conn, done); 1330 1331 /* If tftp_perform() returned an error, use that for return code. If it 1332 was OK, see if tftp_translate_code() has an error. */ 1333 if(!result) 1334 /* If we have encountered an internal tftp error, translate it. */ 1335 result = tftp_translate_code(state->error); 1336 1337 return result; 1338 } 1339 1340 static CURLcode tftp_setup_connection(struct connectdata * conn) 1341 { 1342 struct SessionHandle *data = conn->data; 1343 char * type; 1344 char command; 1345 1346 conn->socktype = SOCK_DGRAM; /* UDP datagram based */ 1347 1348 /* TFTP URLs support an extension like ";mode=<typecode>" that 1349 * we'll try to get now! */ 1350 type = strstr(data->state.path, ";mode="); 1351 1352 if(!type) 1353 type = strstr(conn->host.rawalloc, ";mode="); 1354 1355 if(type) { 1356 *type = 0; /* it was in the middle of the hostname */ 1357 command = Curl_raw_toupper(type[6]); 1358 1359 switch (command) { 1360 case 'A': /* ASCII mode */ 1361 case 'N': /* NETASCII mode */ 1362 data->set.prefer_ascii = TRUE; 1363 break; 1364 1365 case 'O': /* octet mode */ 1366 case 'I': /* binary mode */ 1367 default: 1368 /* switch off ASCII */ 1369 data->set.prefer_ascii = FALSE; 1370 break; 1371 } 1372 } 1373 1374 return CURLE_OK; 1375 } 1376 #endif 1377