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