1/*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 1998 - 2011, 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 "setup.h" 24 25#ifdef HAVE_SYS_TIME_H 26#include <sys/time.h> 27#endif 28#ifdef HAVE_SYS_SOCKET_H 29#include <sys/socket.h> 30#endif 31#ifdef HAVE_NETINET_IN_H 32#include <netinet/in.h> /* <netinet/tcp.h> may need it */ 33#endif 34#ifdef HAVE_SYS_UN_H 35#include <sys/un.h> /* for sockaddr_un */ 36#endif 37#ifdef HAVE_NETINET_TCP_H 38#include <netinet/tcp.h> /* for TCP_NODELAY */ 39#endif 40#ifdef HAVE_SYS_IOCTL_H 41#include <sys/ioctl.h> 42#endif 43#ifdef HAVE_UNISTD_H 44#include <unistd.h> 45#endif 46#ifdef HAVE_NETDB_H 47#include <netdb.h> 48#endif 49#ifdef HAVE_FCNTL_H 50#include <fcntl.h> 51#endif 52#ifdef HAVE_ARPA_INET_H 53#include <arpa/inet.h> 54#endif 55#ifdef HAVE_STDLIB_H 56#include <stdlib.h> 57#endif 58 59#if (defined(HAVE_IOCTL_FIONBIO) && defined(NETWARE)) 60#include <sys/filio.h> 61#endif 62#ifdef NETWARE 63#undef in_addr_t 64#define in_addr_t unsigned long 65#endif 66#ifdef __VMS 67#include <in.h> 68#include <inet.h> 69#endif 70 71#include <stdio.h> 72#include <errno.h> 73#include <string.h> 74 75#define _MPRINTF_REPLACE /* use our functions only */ 76#include <curl/mprintf.h> 77 78#include "urldata.h" 79#include "sendf.h" 80#include "if2ip.h" 81#include "strerror.h" 82#include "connect.h" 83#include "curl_memory.h" 84#include "select.h" 85#include "url.h" /* for Curl_safefree() */ 86#include "multiif.h" 87#include "sockaddr.h" /* required for Curl_sockaddr_storage */ 88#include "inet_ntop.h" 89#include "inet_pton.h" 90#include "sslgen.h" /* for Curl_ssl_check_cxn() */ 91#include "progress.h" 92#include "warnless.h" 93 94/* The last #include file should be: */ 95#include "memdebug.h" 96 97#ifdef __SYMBIAN32__ 98/* This isn't actually supported under Symbian OS */ 99#undef SO_NOSIGPIPE 100#endif 101 102struct Curl_sockaddr_ex { 103 int family; 104 int socktype; 105 int protocol; 106 unsigned int addrlen; 107 union { 108 struct sockaddr addr; 109 struct Curl_sockaddr_storage buff; 110 } _sa_ex_u; 111}; 112#define sa_addr _sa_ex_u.addr 113 114static bool verifyconnect(curl_socket_t sockfd, int *error); 115 116static CURLcode 117singleipconnect(struct connectdata *conn, 118 const Curl_addrinfo *ai, /* start connecting to this */ 119 long timeout_ms, 120 curl_socket_t *sock, 121 bool *connected); 122 123/* 124 * Curl_timeleft() returns the amount of milliseconds left allowed for the 125 * transfer/connection. If the value is negative, the timeout time has already 126 * elapsed. 127 * 128 * The start time is stored in progress.t_startsingle - as set with 129 * Curl_pgrsTime(..., TIMER_STARTSINGLE); 130 * 131 * If 'nowp' is non-NULL, it points to the current time. 132 * 'duringconnect' is FALSE if not during a connect, as then of course the 133 * connect timeout is not taken into account! 134 * 135 * @unittest: 1303 136 */ 137long Curl_timeleft(struct SessionHandle *data, 138 struct timeval *nowp, 139 bool duringconnect) 140{ 141 int timeout_set = 0; 142 long timeout_ms = duringconnect?DEFAULT_CONNECT_TIMEOUT:0; 143 struct timeval now; 144 145 /* if a timeout is set, use the most restrictive one */ 146 147 if(data->set.timeout > 0) 148 timeout_set |= 1; 149 if(duringconnect && (data->set.connecttimeout > 0)) 150 timeout_set |= 2; 151 152 switch (timeout_set) { 153 case 1: 154 timeout_ms = data->set.timeout; 155 break; 156 case 2: 157 timeout_ms = data->set.connecttimeout; 158 break; 159 case 3: 160 if(data->set.timeout < data->set.connecttimeout) 161 timeout_ms = data->set.timeout; 162 else 163 timeout_ms = data->set.connecttimeout; 164 break; 165 default: 166 /* use the default */ 167 if(!duringconnect) 168 /* if we're not during connect, there's no default timeout so if we're 169 at zero we better just return zero and not make it a negative number 170 by the math below */ 171 return 0; 172 break; 173 } 174 175 if(!nowp) { 176 now = Curl_tvnow(); 177 nowp = &now; 178 } 179 180 /* subtract elapsed time */ 181 timeout_ms -= Curl_tvdiff(*nowp, data->progress.t_startsingle); 182 if(!timeout_ms) 183 /* avoid returning 0 as that means no timeout! */ 184 return -1; 185 186 return timeout_ms; 187} 188 189/* 190 * waitconnect() waits for a TCP connect on the given socket for the specified 191 * number if milliseconds. It returns: 192 */ 193 194#define WAITCONN_CONNECTED 0 195#define WAITCONN_SELECT_ERROR -1 196#define WAITCONN_TIMEOUT 1 197#define WAITCONN_FDSET_ERROR 2 198#define WAITCONN_ABORTED 3 199 200static 201int waitconnect(struct connectdata *conn, 202 curl_socket_t sockfd, /* socket */ 203 long timeout_msec) 204{ 205 int rc; 206#ifdef mpeix 207 /* Call this function once now, and ignore the results. We do this to 208 "clear" the error state on the socket so that we can later read it 209 reliably. This is reported necessary on the MPE/iX operating system. */ 210 (void)verifyconnect(sockfd, NULL); 211#endif 212 213 for(;;) { 214 215 /* now select() until we get connect or timeout */ 216 rc = Curl_socket_ready(CURL_SOCKET_BAD, sockfd, timeout_msec>1000? 217 1000:timeout_msec); 218 if(Curl_pgrsUpdate(conn)) 219 return WAITCONN_ABORTED; 220 221 if(-1 == rc) 222 /* error, no connect here, try next */ 223 return WAITCONN_SELECT_ERROR; 224 225 else if(0 == rc) { 226 /* timeout */ 227 timeout_msec -= 1000; 228 if(timeout_msec <= 0) 229 return WAITCONN_TIMEOUT; 230 231 continue; 232 } 233 234 if(rc & CURL_CSELECT_ERR) 235 /* error condition caught */ 236 return WAITCONN_FDSET_ERROR; 237 238 break; 239 } 240 return WAITCONN_CONNECTED; 241} 242 243static CURLcode bindlocal(struct connectdata *conn, 244 curl_socket_t sockfd, int af) 245{ 246 struct SessionHandle *data = conn->data; 247 248 struct Curl_sockaddr_storage sa; 249 struct sockaddr *sock = (struct sockaddr *)&sa; /* bind to this address */ 250 curl_socklen_t sizeof_sa = 0; /* size of the data sock points to */ 251 struct sockaddr_in *si4 = (struct sockaddr_in *)&sa; 252#ifdef ENABLE_IPV6 253 struct sockaddr_in6 *si6 = (struct sockaddr_in6 *)&sa; 254#endif 255 256 struct Curl_dns_entry *h=NULL; 257 unsigned short port = data->set.localport; /* use this port number, 0 for 258 "random" */ 259 /* how many port numbers to try to bind to, increasing one at a time */ 260 int portnum = data->set.localportrange; 261 const char *dev = data->set.str[STRING_DEVICE]; 262 int error; 263 char myhost[256] = ""; 264 int done = 0; /* -1 for error, 1 for address found */ 265 266 /************************************************************* 267 * Select device to bind socket to 268 *************************************************************/ 269 if(!dev && !port) 270 /* no local kind of binding was requested */ 271 return CURLE_OK; 272 273 memset(&sa, 0, sizeof(struct Curl_sockaddr_storage)); 274 275 if(dev && (strlen(dev)<255) ) { 276 277 /* interface */ 278 if(Curl_if2ip(af, dev, myhost, sizeof(myhost))) { 279 /* 280 * We now have the numerical IP address in the 'myhost' buffer 281 */ 282 infof(data, "Local Interface %s is ip %s using address family %i\n", 283 dev, myhost, af); 284 done = 1; 285 286#ifdef SO_BINDTODEVICE 287 /* I am not sure any other OSs than Linux that provide this feature, and 288 * at the least I cannot test. --Ben 289 * 290 * This feature allows one to tightly bind the local socket to a 291 * particular interface. This will force even requests to other local 292 * interfaces to go out the external interface. 293 * 294 * 295 * Only bind to the interface when specified as interface, not just as a 296 * hostname or ip address. 297 */ 298 if(setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE, 299 dev, (curl_socklen_t)strlen(dev)+1) != 0) { 300 error = SOCKERRNO; 301 infof(data, "SO_BINDTODEVICE %s failed with errno %d: %s;" 302 " will do regular bind\n", 303 dev, error, Curl_strerror(conn, error)); 304 /* This is typically "errno 1, error: Operation not permitted" if 305 you're not running as root or another suitable privileged user */ 306 } 307#endif 308 } 309 else { 310 /* 311 * This was not an interface, resolve the name as a host name 312 * or IP number 313 * 314 * Temporarily force name resolution to use only the address type 315 * of the connection. The resolve functions should really be changed 316 * to take a type parameter instead. 317 */ 318 long ipver = conn->ip_version; 319 int rc; 320 321 if(af == AF_INET) 322 conn->ip_version = CURL_IPRESOLVE_V4; 323#ifdef ENABLE_IPV6 324 else if(af == AF_INET6) 325 conn->ip_version = CURL_IPRESOLVE_V6; 326#endif 327 328 rc = Curl_resolv(conn, dev, 0, &h); 329 if(rc == CURLRESOLV_PENDING) 330 (void)Curl_resolver_wait_resolv(conn, &h); 331 conn->ip_version = ipver; 332 333 if(h) { 334 /* convert the resolved address, sizeof myhost >= INET_ADDRSTRLEN */ 335 Curl_printable_address(h->addr, myhost, sizeof(myhost)); 336 infof(data, "Name '%s' family %i resolved to '%s' family %i\n", 337 dev, af, myhost, h->addr->ai_family); 338 Curl_resolv_unlock(data, h); 339 done = 1; 340 } 341 else { 342 /* 343 * provided dev was no interface (or interfaces are not supported 344 * e.g. solaris) no ip address and no domain we fail here 345 */ 346 done = -1; 347 } 348 } 349 350 if(done > 0) { 351#ifdef ENABLE_IPV6 352 /* ipv6 address */ 353 if((af == AF_INET6) && 354 (Curl_inet_pton(AF_INET6, myhost, &si6->sin6_addr) > 0)) { 355 si6->sin6_family = AF_INET6; 356 si6->sin6_port = htons(port); 357 sizeof_sa = sizeof(struct sockaddr_in6); 358 } 359 else 360#endif 361 /* ipv4 address */ 362 if((af == AF_INET) && 363 (Curl_inet_pton(AF_INET, myhost, &si4->sin_addr) > 0)) { 364 si4->sin_family = AF_INET; 365 si4->sin_port = htons(port); 366 sizeof_sa = sizeof(struct sockaddr_in); 367 } 368 } 369 370 if(done < 1) { 371 failf(data, "Couldn't bind to '%s'", dev); 372 return CURLE_INTERFACE_FAILED; 373 } 374 } 375 else { 376 /* no device was given, prepare sa to match af's needs */ 377#ifdef ENABLE_IPV6 378 if(af == AF_INET6) { 379 si6->sin6_family = AF_INET6; 380 si6->sin6_port = htons(port); 381 sizeof_sa = sizeof(struct sockaddr_in6); 382 } 383 else 384#endif 385 if(af == AF_INET) { 386 si4->sin_family = AF_INET; 387 si4->sin_port = htons(port); 388 sizeof_sa = sizeof(struct sockaddr_in); 389 } 390 } 391 392 for(;;) { 393 if(bind(sockfd, sock, sizeof_sa) >= 0) { 394 /* we succeeded to bind */ 395 struct Curl_sockaddr_storage add; 396 curl_socklen_t size = sizeof(add); 397 memset(&add, 0, sizeof(struct Curl_sockaddr_storage)); 398 if(getsockname(sockfd, (struct sockaddr *) &add, &size) < 0) { 399 data->state.os_errno = error = SOCKERRNO; 400 failf(data, "getsockname() failed with errno %d: %s", 401 error, Curl_strerror(conn, error)); 402 return CURLE_INTERFACE_FAILED; 403 } 404 infof(data, "Local port: %hu\n", port); 405 conn->bits.bound = TRUE; 406 return CURLE_OK; 407 } 408 409 if(--portnum > 0) { 410 infof(data, "Bind to local port %hu failed, trying next\n", port); 411 port++; /* try next port */ 412 /* We re-use/clobber the port variable here below */ 413 if(sock->sa_family == AF_INET) 414 si4->sin_port = ntohs(port); 415#ifdef ENABLE_IPV6 416 else 417 si6->sin6_port = ntohs(port); 418#endif 419 } 420 else 421 break; 422 } 423 424 data->state.os_errno = error = SOCKERRNO; 425 failf(data, "bind failed with errno %d: %s", 426 error, Curl_strerror(conn, error)); 427 428 return CURLE_INTERFACE_FAILED; 429} 430 431/* 432 * verifyconnect() returns TRUE if the connect really has happened. 433 */ 434static bool verifyconnect(curl_socket_t sockfd, int *error) 435{ 436 bool rc = TRUE; 437#ifdef SO_ERROR 438 int err = 0; 439 curl_socklen_t errSize = sizeof(err); 440 441#ifdef WIN32 442 /* 443 * In October 2003 we effectively nullified this function on Windows due to 444 * problems with it using all CPU in multi-threaded cases. 445 * 446 * In May 2004, we bring it back to offer more info back on connect failures. 447 * Gisle Vanem could reproduce the former problems with this function, but 448 * could avoid them by adding this SleepEx() call below: 449 * 450 * "I don't have Rational Quantify, but the hint from his post was 451 * ntdll::NtRemoveIoCompletion(). So I'd assume the SleepEx (or maybe 452 * just Sleep(0) would be enough?) would release whatever 453 * mutex/critical-section the ntdll call is waiting on. 454 * 455 * Someone got to verify this on Win-NT 4.0, 2000." 456 */ 457 458#ifdef _WIN32_WCE 459 Sleep(0); 460#else 461 SleepEx(0, FALSE); 462#endif 463 464#endif 465 466 if(0 != getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void *)&err, &errSize)) 467 err = SOCKERRNO; 468#ifdef _WIN32_WCE 469 /* Old WinCE versions don't support SO_ERROR */ 470 if(WSAENOPROTOOPT == err) { 471 SET_SOCKERRNO(0); 472 err = 0; 473 } 474#endif 475#ifdef __minix 476 /* Minix 3.1.x doesn't support getsockopt on UDP sockets */ 477 if(EBADIOCTL == err) { 478 SET_SOCKERRNO(0); 479 err = 0; 480 } 481#endif 482 if((0 == err) || (EISCONN == err)) 483 /* we are connected, awesome! */ 484 rc = TRUE; 485 else 486 /* This wasn't a successful connect */ 487 rc = FALSE; 488 if(error) 489 *error = err; 490#else 491 (void)sockfd; 492 if(error) 493 *error = SOCKERRNO; 494#endif 495 return rc; 496} 497 498/* Used within the multi interface. Try next IP address, return TRUE if no 499 more address exists or error */ 500static CURLcode trynextip(struct connectdata *conn, 501 int sockindex, 502 bool *connected) 503{ 504 curl_socket_t sockfd; 505 Curl_addrinfo *ai; 506 507 /* First clean up after the failed socket. 508 Don't close it yet to ensure that the next IP's socket gets a different 509 file descriptor, which can prevent bugs when the curl_multi_socket_action 510 interface is used with certain select() replacements such as kqueue. */ 511 curl_socket_t fd_to_close = conn->sock[sockindex]; 512 conn->sock[sockindex] = CURL_SOCKET_BAD; 513 *connected = FALSE; 514 515 if(sockindex != FIRSTSOCKET) { 516 Curl_closesocket(conn, fd_to_close); 517 return CURLE_COULDNT_CONNECT; /* no next */ 518 } 519 520 /* try the next address */ 521 ai = conn->ip_addr->ai_next; 522 523 while(ai) { 524 CURLcode res = singleipconnect(conn, ai, 0L, &sockfd, connected); 525 if(res) 526 return res; 527 if(sockfd != CURL_SOCKET_BAD) { 528 /* store the new socket descriptor */ 529 conn->sock[sockindex] = sockfd; 530 conn->ip_addr = ai; 531 Curl_closesocket(conn, fd_to_close); 532 return CURLE_OK; 533 } 534 ai = ai->ai_next; 535 } 536 Curl_closesocket(conn, fd_to_close); 537 return CURLE_COULDNT_CONNECT; 538} 539 540/* Copies connection info into the session handle to make it available 541 when the session handle is no longer associated with a connection. */ 542void Curl_persistconninfo(struct connectdata *conn) 543{ 544 memcpy(conn->data->info.conn_primary_ip, conn->primary_ip, MAX_IPADR_LEN); 545 memcpy(conn->data->info.conn_local_ip, conn->local_ip, MAX_IPADR_LEN); 546 conn->data->info.conn_primary_port = conn->primary_port; 547 conn->data->info.conn_local_port = conn->local_port; 548} 549 550/* retrieves ip address and port from a sockaddr structure */ 551static bool getaddressinfo(struct sockaddr* sa, char* addr, 552 long* port) 553{ 554 unsigned short us_port; 555 struct sockaddr_in* si = NULL; 556#ifdef ENABLE_IPV6 557 struct sockaddr_in6* si6 = NULL; 558#endif 559#if defined(HAVE_SYS_UN_H) && defined(AF_UNIX) 560 struct sockaddr_un* su = NULL; 561#endif 562 563 switch (sa->sa_family) { 564 case AF_INET: 565 si = (struct sockaddr_in*) sa; 566 if(Curl_inet_ntop(sa->sa_family, &si->sin_addr, 567 addr, MAX_IPADR_LEN)) { 568 us_port = ntohs(si->sin_port); 569 *port = us_port; 570 return TRUE; 571 } 572 break; 573#ifdef ENABLE_IPV6 574 case AF_INET6: 575 si6 = (struct sockaddr_in6*)sa; 576 if(Curl_inet_ntop(sa->sa_family, &si6->sin6_addr, 577 addr, MAX_IPADR_LEN)) { 578 us_port = ntohs(si6->sin6_port); 579 *port = us_port; 580 return TRUE; 581 } 582 break; 583#endif 584#if defined(HAVE_SYS_UN_H) && defined(AF_UNIX) 585 case AF_UNIX: 586 su = (struct sockaddr_un*)sa; 587 snprintf(addr, MAX_IPADR_LEN, "%s", su->sun_path); 588 *port = 0; 589 return TRUE; 590#endif 591 default: 592 break; 593 } 594 595 addr[0] = '\0'; 596 *port = 0; 597 598 return FALSE; 599} 600 601/* retrieves the start/end point information of a socket of an established 602 connection */ 603void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd) 604{ 605 int error; 606 curl_socklen_t len; 607 struct Curl_sockaddr_storage ssrem; 608 struct Curl_sockaddr_storage ssloc; 609 struct SessionHandle *data = conn->data; 610 611 if(!conn->bits.reuse) { 612 613 len = sizeof(struct Curl_sockaddr_storage); 614 if(getpeername(sockfd, (struct sockaddr*) &ssrem, &len)) { 615 error = SOCKERRNO; 616 failf(data, "getpeername() failed with errno %d: %s", 617 error, Curl_strerror(conn, error)); 618 return; 619 } 620 621 len = sizeof(struct Curl_sockaddr_storage); 622 if(getsockname(sockfd, (struct sockaddr*) &ssloc, &len)) { 623 error = SOCKERRNO; 624 failf(data, "getsockname() failed with errno %d: %s", 625 error, Curl_strerror(conn, error)); 626 return; 627 } 628 629 if(!getaddressinfo((struct sockaddr*)&ssrem, 630 conn->primary_ip, &conn->primary_port)) { 631 error = ERRNO; 632 failf(data, "ssrem inet_ntop() failed with errno %d: %s", 633 error, Curl_strerror(conn, error)); 634 return; 635 } 636 637 if(!getaddressinfo((struct sockaddr*)&ssloc, 638 conn->local_ip, &conn->local_port)) { 639 error = ERRNO; 640 failf(data, "ssloc inet_ntop() failed with errno %d: %s", 641 error, Curl_strerror(conn, error)); 642 return; 643 } 644 645 } 646 647 /* persist connection info in session handle */ 648 Curl_persistconninfo(conn); 649} 650 651/* 652 * Curl_is_connected() is used from the multi interface to check if the 653 * firstsocket has connected. 654 */ 655 656CURLcode Curl_is_connected(struct connectdata *conn, 657 int sockindex, 658 bool *connected) 659{ 660 int rc; 661 struct SessionHandle *data = conn->data; 662 CURLcode code = CURLE_OK; 663 curl_socket_t sockfd = conn->sock[sockindex]; 664 long allow = DEFAULT_CONNECT_TIMEOUT; 665 int error = 0; 666 struct timeval now; 667 668 DEBUGASSERT(sockindex >= FIRSTSOCKET && sockindex <= SECONDARYSOCKET); 669 670 *connected = FALSE; /* a very negative world view is best */ 671 672 if(conn->bits.tcpconnect) { 673 /* we are connected already! */ 674 *connected = TRUE; 675 return CURLE_OK; 676 } 677 678 now = Curl_tvnow(); 679 680 /* figure out how long time we have left to connect */ 681 allow = Curl_timeleft(data, &now, TRUE); 682 683 if(allow < 0) { 684 /* time-out, bail out, go home */ 685 failf(data, "Connection time-out"); 686 return CURLE_OPERATION_TIMEDOUT; 687 } 688 689 /* check for connect without timeout as we want to return immediately */ 690 rc = waitconnect(conn, sockfd, 0); 691 if(WAITCONN_TIMEOUT == rc) { 692 if(curlx_tvdiff(now, conn->connecttime) >= conn->timeoutms_per_addr) { 693 infof(data, "After %ldms connect time, move on!\n", 694 conn->timeoutms_per_addr); 695 goto next; 696 } 697 698 /* not an error, but also no connection yet */ 699 return code; 700 } 701 702 if(WAITCONN_CONNECTED == rc) { 703 if(verifyconnect(sockfd, &error)) { 704 /* we are connected with TCP, awesome! */ 705 706 /* see if we need to do any proxy magic first once we connected */ 707 code = Curl_connected_proxy(conn); 708 if(code) 709 return code; 710 711 conn->bits.tcpconnect = TRUE; 712 *connected = TRUE; 713 Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */ 714 Curl_verboseconnect(conn); 715 Curl_updateconninfo(conn, sockfd); 716 717 return CURLE_OK; 718 } 719 /* nope, not connected for real */ 720 } 721 else { 722 /* nope, not connected */ 723 if(WAITCONN_FDSET_ERROR == rc) { 724 (void)verifyconnect(sockfd, &error); 725 infof(data, "%s\n",Curl_strerror(conn, error)); 726 } 727 else 728 infof(data, "Connection failed\n"); 729 } 730 731 /* 732 * The connection failed here, we should attempt to connect to the "next 733 * address" for the given host. But first remember the latest error. 734 */ 735 if(error) { 736 data->state.os_errno = error; 737 SET_SOCKERRNO(error); 738 } 739 next: 740 741 code = trynextip(conn, sockindex, connected); 742 743 if(code) { 744 error = SOCKERRNO; 745 data->state.os_errno = error; 746 failf(data, "Failed connect to %s:%ld; %s", 747 conn->host.name, conn->port, Curl_strerror(conn, error)); 748 } 749 750 return code; 751} 752 753static void tcpnodelay(struct connectdata *conn, 754 curl_socket_t sockfd) 755{ 756#ifdef TCP_NODELAY 757 struct SessionHandle *data= conn->data; 758 curl_socklen_t onoff = (curl_socklen_t) data->set.tcp_nodelay; 759 int proto = IPPROTO_TCP; 760 761#if 0 762 /* The use of getprotobyname() is disabled since it isn't thread-safe on 763 numerous systems. On these getprotobyname_r() should be used instead, but 764 that exists in at least one 4 arg version and one 5 arg version, and 765 since the proto number rarely changes anyway we now just use the hard 766 coded number. The "proper" fix would need a configure check for the 767 correct function much in the same style the gethostbyname_r versions are 768 detected. */ 769 struct protoent *pe = getprotobyname("tcp"); 770 if(pe) 771 proto = pe->p_proto; 772#endif 773 774 if(setsockopt(sockfd, proto, TCP_NODELAY, (void *)&onoff, 775 sizeof(onoff)) < 0) 776 infof(data, "Could not set TCP_NODELAY: %s\n", 777 Curl_strerror(conn, SOCKERRNO)); 778 else 779 infof(data,"TCP_NODELAY set\n"); 780#else 781 (void)conn; 782 (void)sockfd; 783#endif 784} 785 786#ifdef SO_NOSIGPIPE 787/* The preferred method on Mac OS X (10.2 and later) to prevent SIGPIPEs when 788 sending data to a dead peer (instead of relying on the 4th argument to send 789 being MSG_NOSIGNAL). Possibly also existing and in use on other BSD 790 systems? */ 791static void nosigpipe(struct connectdata *conn, 792 curl_socket_t sockfd) 793{ 794 struct SessionHandle *data= conn->data; 795 int onoff = 1; 796 if(setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&onoff, 797 sizeof(onoff)) < 0) 798 infof(data, "Could not set SO_NOSIGPIPE: %s\n", 799 Curl_strerror(conn, SOCKERRNO)); 800} 801#else 802#define nosigpipe(x,y) 803#endif 804 805#ifdef WIN32 806/* When you run a program that uses the Windows Sockets API, you may 807 experience slow performance when you copy data to a TCP server. 808 809 http://support.microsoft.com/kb/823764 810 811 Work-around: Make the Socket Send Buffer Size Larger Than the Program Send 812 Buffer Size 813 814*/ 815void Curl_sndbufset(curl_socket_t sockfd) 816{ 817 int val = CURL_MAX_WRITE_SIZE + 32; 818 int curval = 0; 819 int curlen = sizeof(curval); 820 821 if(getsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (char *)&curval, &curlen) == 0) 822 if(curval > val) 823 return; 824 825 setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (const char *)&val, sizeof(val)); 826} 827#endif 828 829 830/* 831 * singleipconnect() 832 * 833 * Note that even on connect fail it returns CURLE_OK, but with 'sock' set to 834 * CURL_SOCKET_BAD. Other errors will however return proper errors. 835 * 836 * singleipconnect() connects to the given IP only, and it may return without 837 * having connected if used from the multi interface. 838 */ 839static CURLcode 840singleipconnect(struct connectdata *conn, 841 const Curl_addrinfo *ai, 842 long timeout_ms, 843 curl_socket_t *sockp, 844 bool *connected) 845{ 846 struct Curl_sockaddr_ex addr; 847 int rc; 848 int error; 849 bool isconnected = FALSE; 850 struct SessionHandle *data = conn->data; 851 curl_socket_t sockfd; 852 CURLcode res = CURLE_OK; 853#if defined(ENABLE_IPV6) && defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID) 854 struct sockaddr_in6 * const sa6 = (void *)&addr.sa_addr; 855#endif 856 857 *sockp = CURL_SOCKET_BAD; 858 859 /* 860 * The Curl_sockaddr_ex structure is basically libcurl's external API 861 * curl_sockaddr structure with enough space available to directly hold 862 * any protocol-specific address structures. The variable declared here 863 * will be used to pass / receive data to/from the fopensocket callback 864 * if this has been set, before that, it is initialized from parameters. 865 */ 866 867 addr.family = ai->ai_family; 868 addr.socktype = conn->socktype; 869 addr.protocol = conn->socktype==SOCK_DGRAM?IPPROTO_UDP:ai->ai_protocol; 870 addr.addrlen = ai->ai_addrlen; 871 872 if(addr.addrlen > sizeof(struct Curl_sockaddr_storage)) 873 addr.addrlen = sizeof(struct Curl_sockaddr_storage); 874 memcpy(&addr.sa_addr, ai->ai_addr, addr.addrlen); 875 876 *connected = FALSE; /* default is not connected */ 877 878 if(data->set.fopensocket) 879 /* 880 * If the opensocket callback is set, all the destination address 881 * information is passed to the callback. Depending on this information the 882 * callback may opt to abort the connection, this is indicated returning 883 * CURL_SOCKET_BAD; otherwise it will return a not-connected socket. When 884 * the callback returns a valid socket the destination address information 885 * might have been changed and this 'new' address will actually be used 886 * here to connect. 887 */ 888 sockfd = data->set.fopensocket(data->set.opensocket_client, 889 CURLSOCKTYPE_IPCXN, 890 (struct curl_sockaddr *)&addr); 891 else 892 /* opensocket callback not set, so simply create the socket now */ 893 sockfd = socket(addr.family, addr.socktype, addr.protocol); 894 895 if(sockfd == CURL_SOCKET_BAD) 896 /* no socket, no connection */ 897 return CURLE_OK; 898 899#if defined(ENABLE_IPV6) && defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID) 900 if(conn->scope && (addr.family == AF_INET6)) 901 sa6->sin6_scope_id = conn->scope; 902#endif 903 904 /* store remote address and port used in this connection attempt */ 905 if(!getaddressinfo((struct sockaddr*)&addr.sa_addr, 906 conn->primary_ip, &conn->primary_port)) { 907 /* malformed address or bug in inet_ntop, try next address */ 908 error = ERRNO; 909 failf(data, "sa_addr inet_ntop() failed with errno %d: %s", 910 error, Curl_strerror(conn, error)); 911 Curl_closesocket(conn, sockfd); 912 return CURLE_OK; 913 } 914 memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN); 915 infof(data, " Trying %s... ", conn->ip_addr_str); 916 917 Curl_persistconninfo(conn); 918 919#ifdef ENABLE_IPV6 920 if(addr.family == AF_INET6) 921 conn->bits.ipv6 = TRUE; 922#endif 923 924 if(data->set.tcp_nodelay) 925 tcpnodelay(conn, sockfd); 926 927 nosigpipe(conn, sockfd); 928 929 Curl_sndbufset(sockfd); 930 931 if(data->set.fsockopt) { 932 /* activate callback for setting socket options */ 933 error = data->set.fsockopt(data->set.sockopt_client, 934 sockfd, 935 CURLSOCKTYPE_IPCXN); 936 937 if(error == CURL_SOCKOPT_ALREADY_CONNECTED) 938 isconnected = TRUE; 939 else if(error) { 940 Curl_closesocket(conn, sockfd); /* close the socket and bail out */ 941 return CURLE_ABORTED_BY_CALLBACK; 942 } 943 } 944 945 /* possibly bind the local end to an IP, interface or port */ 946 res = bindlocal(conn, sockfd, addr.family); 947 if(res) { 948 Curl_closesocket(conn, sockfd); /* close socket and bail out */ 949 return res; 950 } 951 952 /* set socket non-blocking */ 953 curlx_nonblock(sockfd, TRUE); 954 955 /* Connect TCP sockets, bind UDP */ 956 if(!isconnected && (conn->socktype == SOCK_STREAM)) { 957 rc = connect(sockfd, &addr.sa_addr, addr.addrlen); 958 conn->connecttime = Curl_tvnow(); 959 if(conn->num_addr > 1) 960 Curl_expire(data, conn->timeoutms_per_addr); 961 } 962 else 963 rc = 0; 964 965 if(-1 == rc) { 966 error = SOCKERRNO; 967 968 switch (error) { 969 case EINPROGRESS: 970 case EWOULDBLOCK: 971#if defined(EAGAIN) 972#if (EAGAIN) != (EWOULDBLOCK) 973 /* On some platforms EAGAIN and EWOULDBLOCK are the 974 * same value, and on others they are different, hence 975 * the odd #if 976 */ 977 case EAGAIN: 978#endif 979#endif 980 rc = waitconnect(conn, sockfd, timeout_ms); 981 if(WAITCONN_ABORTED == rc) { 982 Curl_closesocket(conn, sockfd); 983 return CURLE_ABORTED_BY_CALLBACK; 984 } 985 break; 986 default: 987 /* unknown error, fallthrough and try another address! */ 988 failf(data, "Failed to connect to %s: %s", 989 conn->ip_addr_str, Curl_strerror(conn,error)); 990 data->state.os_errno = error; 991 break; 992 } 993 } 994 995 /* The 'WAITCONN_TIMEOUT == rc' comes from the waitconnect(), and not from 996 connect(). We can be sure of this since connect() cannot return 1. */ 997 if((WAITCONN_TIMEOUT == rc) && 998 (data->state.used_interface == Curl_if_multi)) { 999 /* Timeout when running the multi interface */ 1000 *sockp = sockfd; 1001 return CURLE_OK; 1002 } 1003 1004 if(!isconnected) 1005 isconnected = verifyconnect(sockfd, &error); 1006 1007 if(!rc && isconnected) { 1008 /* we are connected, awesome! */ 1009 *connected = TRUE; /* this is a true connect */ 1010 infof(data, "connected\n"); 1011 Curl_updateconninfo(conn, sockfd); 1012 *sockp = sockfd; 1013 return CURLE_OK; 1014 } 1015 else if(WAITCONN_TIMEOUT == rc) 1016 infof(data, "Timeout\n"); 1017 else { 1018 data->state.os_errno = error; 1019 infof(data, "%s\n", Curl_strerror(conn, error)); 1020 } 1021 1022 /* connect failed or timed out */ 1023 Curl_closesocket(conn, sockfd); 1024 1025 return CURLE_OK; 1026} 1027 1028/* 1029 * TCP connect to the given host with timeout, proxy or remote doesn't matter. 1030 * There might be more than one IP address to try out. Fill in the passed 1031 * pointer with the connected socket. 1032 */ 1033 1034CURLcode Curl_connecthost(struct connectdata *conn, /* context */ 1035 const struct Curl_dns_entry *remotehost, 1036 curl_socket_t *sockconn, /* the connected socket */ 1037 Curl_addrinfo **addr, /* the one we used */ 1038 bool *connected) /* really connected? */ 1039{ 1040 struct SessionHandle *data = conn->data; 1041 curl_socket_t sockfd = CURL_SOCKET_BAD; 1042 int aliasindex; 1043 Curl_addrinfo *ai; 1044 Curl_addrinfo *curr_addr; 1045 1046 struct timeval after; 1047 struct timeval before = Curl_tvnow(); 1048 1049 /************************************************************* 1050 * Figure out what maximum time we have left 1051 *************************************************************/ 1052 long timeout_ms; 1053 1054 DEBUGASSERT(sockconn); 1055 *connected = FALSE; /* default to not connected */ 1056 1057 /* get the timeout left */ 1058 timeout_ms = Curl_timeleft(data, &before, TRUE); 1059 1060 if(timeout_ms < 0) { 1061 /* a precaution, no need to continue if time already is up */ 1062 failf(data, "Connection time-out"); 1063 return CURLE_OPERATION_TIMEDOUT; 1064 } 1065 1066 /* Max time for each address */ 1067 conn->num_addr = Curl_num_addresses(remotehost->addr); 1068 conn->timeoutms_per_addr = timeout_ms / conn->num_addr; 1069 1070 ai = remotehost->addr; 1071 1072 /* Below is the loop that attempts to connect to all IP-addresses we 1073 * know for the given host. One by one until one IP succeeds. 1074 */ 1075 1076 /* 1077 * Connecting with a Curl_addrinfo chain 1078 */ 1079 for(curr_addr = ai, aliasindex=0; curr_addr; 1080 curr_addr = curr_addr->ai_next, aliasindex++) { 1081 1082 /* start connecting to the IP curr_addr points to */ 1083 CURLcode res = 1084 singleipconnect(conn, curr_addr, 1085 /* don't hang when doing multi */ 1086 (data->state.used_interface == Curl_if_multi)?0: 1087 conn->timeoutms_per_addr, &sockfd, connected); 1088 1089 if(res) 1090 return res; 1091 1092 if(sockfd != CURL_SOCKET_BAD) 1093 break; 1094 1095 /* get a new timeout for next attempt */ 1096 after = Curl_tvnow(); 1097 timeout_ms -= Curl_tvdiff(after, before); 1098 if(timeout_ms < 0) { 1099 failf(data, "connect() timed out!"); 1100 return CURLE_OPERATION_TIMEDOUT; 1101 } 1102 before = after; 1103 } /* end of connect-to-each-address loop */ 1104 1105 *sockconn = sockfd; /* the socket descriptor we've connected */ 1106 1107 if(sockfd == CURL_SOCKET_BAD) { 1108 /* no good connect was made */ 1109 failf(data, "couldn't connect to host"); 1110 return CURLE_COULDNT_CONNECT; 1111 } 1112 1113 /* leave the socket in non-blocking mode */ 1114 1115 /* store the address we use */ 1116 if(addr) 1117 *addr = curr_addr; 1118 1119 data->info.numconnects++; /* to track the number of connections made */ 1120 1121 return CURLE_OK; 1122} 1123 1124/* 1125 * Used to extract socket and connectdata struct for the most recent 1126 * transfer on the given SessionHandle. 1127 * 1128 * The returned socket will be CURL_SOCKET_BAD in case of failure! 1129 */ 1130curl_socket_t Curl_getconnectinfo(struct SessionHandle *data, 1131 struct connectdata **connp) 1132{ 1133 curl_socket_t sockfd; 1134 1135 DEBUGASSERT(data); 1136 1137 if((data->state.lastconnect != -1) && 1138 (data->state.connc->connects[data->state.lastconnect] != NULL)) { 1139 struct connectdata *c = 1140 data->state.connc->connects[data->state.lastconnect]; 1141 if(connp) 1142 /* only store this if the caller cares for it */ 1143 *connp = c; 1144 sockfd = c->sock[FIRSTSOCKET]; 1145 /* we have a socket connected, let's determine if the server shut down */ 1146 /* determine if ssl */ 1147 if(c->ssl[FIRSTSOCKET].use) { 1148 /* use the SSL context */ 1149 if(!Curl_ssl_check_cxn(c)) 1150 return CURL_SOCKET_BAD; /* FIN received */ 1151 } 1152/* Minix 3.1 doesn't support any flags on recv; just assume socket is OK */ 1153#ifdef MSG_PEEK 1154 else { 1155 /* use the socket */ 1156 char buf; 1157 if(recv((RECV_TYPE_ARG1)c->sock[FIRSTSOCKET], (RECV_TYPE_ARG2)&buf, 1158 (RECV_TYPE_ARG3)1, (RECV_TYPE_ARG4)MSG_PEEK) == 0) { 1159 return CURL_SOCKET_BAD; /* FIN received */ 1160 } 1161 } 1162#endif 1163 } 1164 else 1165 return CURL_SOCKET_BAD; 1166 1167 return sockfd; 1168} 1169 1170/* 1171 * Close a socket. 1172 * 1173 * 'conn' can be NULL, beware! 1174 */ 1175int Curl_closesocket(struct connectdata *conn, 1176 curl_socket_t sock) 1177{ 1178 if(conn && conn->fclosesocket) 1179 return conn->fclosesocket(conn->closesocket_client, sock); 1180 else 1181 return sclose(sock); 1182} 1183