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