00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "curl_setup.h"
00024
00025 #ifdef HAVE_NETINET_IN_H
00026 #include <netinet/in.h>
00027 #endif
00028 #ifdef HAVE_SYS_UN_H
00029 #include <sys/un.h>
00030 #endif
00031 #ifdef HAVE_NETINET_TCP_H
00032 #include <netinet/tcp.h>
00033 #endif
00034 #ifdef HAVE_SYS_IOCTL_H
00035 #include <sys/ioctl.h>
00036 #endif
00037 #ifdef HAVE_NETDB_H
00038 #include <netdb.h>
00039 #endif
00040 #ifdef HAVE_FCNTL_H
00041 #include <fcntl.h>
00042 #endif
00043 #ifdef HAVE_ARPA_INET_H
00044 #include <arpa/inet.h>
00045 #endif
00046
00047 #if (defined(HAVE_IOCTL_FIONBIO) && defined(NETWARE))
00048 #include <sys/filio.h>
00049 #endif
00050 #ifdef NETWARE
00051 #undef in_addr_t
00052 #define in_addr_t unsigned long
00053 #endif
00054 #ifdef __VMS
00055 #include <in.h>
00056 #include <inet.h>
00057 #endif
00058
00059 #include "urldata.h"
00060 #include "sendf.h"
00061 #include "if2ip.h"
00062 #include "strerror.h"
00063 #include "connect.h"
00064 #include "select.h"
00065 #include "url.h"
00066 #include "multiif.h"
00067 #include "sockaddr.h"
00068 #include "inet_ntop.h"
00069 #include "inet_pton.h"
00070 #include "vtls/vtls.h"
00071 #include "progress.h"
00072 #include "warnless.h"
00073 #include "conncache.h"
00074 #include "multihandle.h"
00075 #include "system_win32.h"
00076
00077
00078 #include "curl_printf.h"
00079 #include "curl_memory.h"
00080 #include "memdebug.h"
00081
00082 #ifdef __SYMBIAN32__
00083
00084 #undef SO_NOSIGPIPE
00085 #endif
00086
00087 static bool verifyconnect(curl_socket_t sockfd, int *error);
00088
00089 #if defined(__DragonFly__) || defined(HAVE_WINSOCK_H)
00090
00091 #define KEEPALIVE_FACTOR(x) (x *= 1000)
00092 #else
00093 #define KEEPALIVE_FACTOR(x)
00094 #endif
00095
00096 #if defined(HAVE_WINSOCK2_H) && !defined(SIO_KEEPALIVE_VALS)
00097 #define SIO_KEEPALIVE_VALS _WSAIOW(IOC_VENDOR,4)
00098
00099 struct tcp_keepalive {
00100 u_long onoff;
00101 u_long keepalivetime;
00102 u_long keepaliveinterval;
00103 };
00104 #endif
00105
00106 static void
00107 tcpkeepalive(struct Curl_easy *data,
00108 curl_socket_t sockfd)
00109 {
00110 int optval = data->set.tcp_keepalive?1:0;
00111
00112
00113 if(setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE,
00114 (void *)&optval, sizeof(optval)) < 0) {
00115 infof(data, "Failed to set SO_KEEPALIVE on fd %d\n", sockfd);
00116 }
00117 else {
00118 #if defined(SIO_KEEPALIVE_VALS)
00119 struct tcp_keepalive vals;
00120 DWORD dummy;
00121 vals.onoff = 1;
00122 optval = curlx_sltosi(data->set.tcp_keepidle);
00123 KEEPALIVE_FACTOR(optval);
00124 vals.keepalivetime = optval;
00125 optval = curlx_sltosi(data->set.tcp_keepintvl);
00126 KEEPALIVE_FACTOR(optval);
00127 vals.keepaliveinterval = optval;
00128 if(WSAIoctl(sockfd, SIO_KEEPALIVE_VALS, (LPVOID) &vals, sizeof(vals),
00129 NULL, 0, &dummy, NULL, NULL) != 0) {
00130 infof(data, "Failed to set SIO_KEEPALIVE_VALS on fd %d: %d\n",
00131 (int)sockfd, WSAGetLastError());
00132 }
00133 #else
00134 #ifdef TCP_KEEPIDLE
00135 optval = curlx_sltosi(data->set.tcp_keepidle);
00136 KEEPALIVE_FACTOR(optval);
00137 if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPIDLE,
00138 (void *)&optval, sizeof(optval)) < 0) {
00139 infof(data, "Failed to set TCP_KEEPIDLE on fd %d\n", sockfd);
00140 }
00141 #endif
00142 #ifdef TCP_KEEPINTVL
00143 optval = curlx_sltosi(data->set.tcp_keepintvl);
00144 KEEPALIVE_FACTOR(optval);
00145 if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPINTVL,
00146 (void *)&optval, sizeof(optval)) < 0) {
00147 infof(data, "Failed to set TCP_KEEPINTVL on fd %d\n", sockfd);
00148 }
00149 #endif
00150 #ifdef TCP_KEEPALIVE
00151
00152 optval = curlx_sltosi(data->set.tcp_keepidle);
00153 KEEPALIVE_FACTOR(optval);
00154 if(setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPALIVE,
00155 (void *)&optval, sizeof(optval)) < 0) {
00156 infof(data, "Failed to set TCP_KEEPALIVE on fd %d\n", sockfd);
00157 }
00158 #endif
00159 #endif
00160 }
00161 }
00162
00163 static CURLcode
00164 singleipconnect(struct connectdata *conn,
00165 const Curl_addrinfo *ai,
00166 curl_socket_t *sock);
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182 time_t Curl_timeleft(struct Curl_easy *data,
00183 struct timeval *nowp,
00184 bool duringconnect)
00185 {
00186 int timeout_set = 0;
00187 time_t timeout_ms = duringconnect?DEFAULT_CONNECT_TIMEOUT:0;
00188 struct timeval now;
00189
00190
00191
00192 if(data->set.timeout > 0)
00193 timeout_set |= 1;
00194 if(duringconnect && (data->set.connecttimeout > 0))
00195 timeout_set |= 2;
00196
00197 switch(timeout_set) {
00198 case 1:
00199 timeout_ms = data->set.timeout;
00200 break;
00201 case 2:
00202 timeout_ms = data->set.connecttimeout;
00203 break;
00204 case 3:
00205 if(data->set.timeout < data->set.connecttimeout)
00206 timeout_ms = data->set.timeout;
00207 else
00208 timeout_ms = data->set.connecttimeout;
00209 break;
00210 default:
00211
00212 if(!duringconnect)
00213
00214
00215
00216 return 0;
00217 break;
00218 }
00219
00220 if(!nowp) {
00221 now = Curl_tvnow();
00222 nowp = &now;
00223 }
00224
00225
00226 if(duringconnect)
00227
00228 timeout_ms -= Curl_tvdiff(*nowp, data->progress.t_startsingle);
00229 else
00230
00231 timeout_ms -= Curl_tvdiff(*nowp, data->progress.t_startop);
00232 if(!timeout_ms)
00233
00234 return -1;
00235
00236 return timeout_ms;
00237 }
00238
00239 static CURLcode bindlocal(struct connectdata *conn,
00240 curl_socket_t sockfd, int af, unsigned int scope)
00241 {
00242 struct Curl_easy *data = conn->data;
00243
00244 struct Curl_sockaddr_storage sa;
00245 struct sockaddr *sock = (struct sockaddr *)&sa;
00246 curl_socklen_t sizeof_sa = 0;
00247 struct sockaddr_in *si4 = (struct sockaddr_in *)&sa;
00248 #ifdef ENABLE_IPV6
00249 struct sockaddr_in6 *si6 = (struct sockaddr_in6 *)&sa;
00250 #endif
00251
00252 struct Curl_dns_entry *h=NULL;
00253 unsigned short port = data->set.localport;
00254
00255
00256 int portnum = data->set.localportrange;
00257 const char *dev = data->set.str[STRING_DEVICE];
00258 int error;
00259
00260
00261
00262
00263 if(!dev && !port)
00264
00265 return CURLE_OK;
00266
00267 memset(&sa, 0, sizeof(struct Curl_sockaddr_storage));
00268
00269 if(dev && (strlen(dev)<255) ) {
00270 char myhost[256] = "";
00271 int done = 0;
00272 bool is_interface = FALSE;
00273 bool is_host = FALSE;
00274 static const char *if_prefix = "if!";
00275 static const char *host_prefix = "host!";
00276
00277 if(strncmp(if_prefix, dev, strlen(if_prefix)) == 0) {
00278 dev += strlen(if_prefix);
00279 is_interface = TRUE;
00280 }
00281 else if(strncmp(host_prefix, dev, strlen(host_prefix)) == 0) {
00282 dev += strlen(host_prefix);
00283 is_host = TRUE;
00284 }
00285
00286
00287 if(!is_host) {
00288 switch(Curl_if2ip(af, scope, conn->scope_id, dev,
00289 myhost, sizeof(myhost))) {
00290 case IF2IP_NOT_FOUND:
00291 if(is_interface) {
00292
00293 failf(data, "Couldn't bind to interface '%s'", dev);
00294 return CURLE_INTERFACE_FAILED;
00295 }
00296 break;
00297 case IF2IP_AF_NOT_SUPPORTED:
00298
00299 return CURLE_UNSUPPORTED_PROTOCOL;
00300 case IF2IP_FOUND:
00301 is_interface = TRUE;
00302
00303
00304
00305 infof(data, "Local Interface %s is ip %s using address family %i\n",
00306 dev, myhost, af);
00307 done = 1;
00308
00309 #ifdef SO_BINDTODEVICE
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321 if(setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE,
00322 dev, (curl_socklen_t)strlen(dev)+1) != 0) {
00323 error = SOCKERRNO;
00324 infof(data, "SO_BINDTODEVICE %s failed with errno %d: %s;"
00325 " will do regular bind\n",
00326 dev, error, Curl_strerror(conn, error));
00327
00328
00329
00330 }
00331 #endif
00332 break;
00333 }
00334 }
00335 if(!is_interface) {
00336
00337
00338
00339
00340
00341
00342
00343
00344 long ipver = conn->ip_version;
00345 int rc;
00346
00347 if(af == AF_INET)
00348 conn->ip_version = CURL_IPRESOLVE_V4;
00349 #ifdef ENABLE_IPV6
00350 else if(af == AF_INET6)
00351 conn->ip_version = CURL_IPRESOLVE_V6;
00352 #endif
00353
00354 rc = Curl_resolv(conn, dev, 0, &h);
00355 if(rc == CURLRESOLV_PENDING)
00356 (void)Curl_resolver_wait_resolv(conn, &h);
00357 conn->ip_version = ipver;
00358
00359 if(h) {
00360
00361 Curl_printable_address(h->addr, myhost, sizeof(myhost));
00362 infof(data, "Name '%s' family %i resolved to '%s' family %i\n",
00363 dev, af, myhost, h->addr->ai_family);
00364 Curl_resolv_unlock(data, h);
00365 done = 1;
00366 }
00367 else {
00368
00369
00370
00371
00372 done = -1;
00373 }
00374 }
00375
00376 if(done > 0) {
00377 #ifdef ENABLE_IPV6
00378
00379 if(af == AF_INET6) {
00380 #ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
00381 char *scope_ptr = strchr(myhost, '%');
00382 if(scope_ptr)
00383 *(scope_ptr++) = 0;
00384 #endif
00385 if(Curl_inet_pton(AF_INET6, myhost, &si6->sin6_addr) > 0) {
00386 si6->sin6_family = AF_INET6;
00387 si6->sin6_port = htons(port);
00388 #ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
00389 if(scope_ptr)
00390
00391
00392
00393
00394 si6->sin6_scope_id = atoi(scope_ptr);
00395 #endif
00396 }
00397 sizeof_sa = sizeof(struct sockaddr_in6);
00398 }
00399 else
00400 #endif
00401
00402 if((af == AF_INET) &&
00403 (Curl_inet_pton(AF_INET, myhost, &si4->sin_addr) > 0)) {
00404 si4->sin_family = AF_INET;
00405 si4->sin_port = htons(port);
00406 sizeof_sa = sizeof(struct sockaddr_in);
00407 }
00408 }
00409
00410 if(done < 1) {
00411 failf(data, "Couldn't bind to '%s'", dev);
00412 return CURLE_INTERFACE_FAILED;
00413 }
00414 }
00415 else {
00416
00417 #ifdef ENABLE_IPV6
00418 if(af == AF_INET6) {
00419 si6->sin6_family = AF_INET6;
00420 si6->sin6_port = htons(port);
00421 sizeof_sa = sizeof(struct sockaddr_in6);
00422 }
00423 else
00424 #endif
00425 if(af == AF_INET) {
00426 si4->sin_family = AF_INET;
00427 si4->sin_port = htons(port);
00428 sizeof_sa = sizeof(struct sockaddr_in);
00429 }
00430 }
00431
00432 for(;;) {
00433 if(bind(sockfd, sock, sizeof_sa) >= 0) {
00434
00435 struct Curl_sockaddr_storage add;
00436 curl_socklen_t size = sizeof(add);
00437 memset(&add, 0, sizeof(struct Curl_sockaddr_storage));
00438 if(getsockname(sockfd, (struct sockaddr *) &add, &size) < 0) {
00439 data->state.os_errno = error = SOCKERRNO;
00440 failf(data, "getsockname() failed with errno %d: %s",
00441 error, Curl_strerror(conn, error));
00442 return CURLE_INTERFACE_FAILED;
00443 }
00444 infof(data, "Local port: %hu\n", port);
00445 conn->bits.bound = TRUE;
00446 return CURLE_OK;
00447 }
00448
00449 if(--portnum > 0) {
00450 infof(data, "Bind to local port %hu failed, trying next\n", port);
00451 port++;
00452
00453 if(sock->sa_family == AF_INET)
00454 si4->sin_port = ntohs(port);
00455 #ifdef ENABLE_IPV6
00456 else
00457 si6->sin6_port = ntohs(port);
00458 #endif
00459 }
00460 else
00461 break;
00462 }
00463
00464 data->state.os_errno = error = SOCKERRNO;
00465 failf(data, "bind failed with errno %d: %s",
00466 error, Curl_strerror(conn, error));
00467
00468 return CURLE_INTERFACE_FAILED;
00469 }
00470
00471
00472
00473
00474 static bool verifyconnect(curl_socket_t sockfd, int *error)
00475 {
00476 bool rc = TRUE;
00477 #ifdef SO_ERROR
00478 int err = 0;
00479 curl_socklen_t errSize = sizeof(err);
00480
00481 #ifdef WIN32
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498 #ifdef _WIN32_WCE
00499 Sleep(0);
00500 #else
00501 SleepEx(0, FALSE);
00502 #endif
00503
00504 #endif
00505
00506 if(0 != getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void *)&err, &errSize))
00507 err = SOCKERRNO;
00508 #ifdef _WIN32_WCE
00509
00510 if(WSAENOPROTOOPT == err) {
00511 SET_SOCKERRNO(0);
00512 err = 0;
00513 }
00514 #endif
00515 #ifdef __minix
00516
00517 if(EBADIOCTL == err) {
00518 SET_SOCKERRNO(0);
00519 err = 0;
00520 }
00521 #endif
00522 if((0 == err) || (EISCONN == err))
00523
00524 rc = TRUE;
00525 else
00526
00527 rc = FALSE;
00528 if(error)
00529 *error = err;
00530 #else
00531 (void)sockfd;
00532 if(error)
00533 *error = SOCKERRNO;
00534 #endif
00535 return rc;
00536 }
00537
00538
00539
00540 static CURLcode trynextip(struct connectdata *conn,
00541 int sockindex,
00542 int tempindex)
00543 {
00544 const int other = tempindex ^ 1;
00545 CURLcode result = CURLE_COULDNT_CONNECT;
00546
00547
00548
00549
00550
00551 curl_socket_t fd_to_close = conn->tempsock[tempindex];
00552 conn->tempsock[tempindex] = CURL_SOCKET_BAD;
00553
00554 if(sockindex == FIRSTSOCKET) {
00555 Curl_addrinfo *ai = NULL;
00556 int family = AF_UNSPEC;
00557
00558 if(conn->tempaddr[tempindex]) {
00559
00560 family = conn->tempaddr[tempindex]->ai_family;
00561 ai = conn->tempaddr[tempindex]->ai_next;
00562 }
00563 #ifdef ENABLE_IPV6
00564 else if(conn->tempaddr[0]) {
00565
00566 int firstfamily = conn->tempaddr[0]->ai_family;
00567 family = (firstfamily == AF_INET) ? AF_INET6 : AF_INET;
00568 ai = conn->tempaddr[0]->ai_next;
00569 }
00570 #endif
00571
00572 while(ai) {
00573 if(conn->tempaddr[other]) {
00574
00575 while(ai && ai->ai_family != family)
00576 ai = ai->ai_next;
00577 }
00578
00579 if(ai) {
00580 result = singleipconnect(conn, ai, &conn->tempsock[tempindex]);
00581 if(result == CURLE_COULDNT_CONNECT) {
00582 ai = ai->ai_next;
00583 continue;
00584 }
00585
00586 conn->tempaddr[tempindex] = ai;
00587 }
00588 break;
00589 }
00590 }
00591
00592 if(fd_to_close != CURL_SOCKET_BAD)
00593 Curl_closesocket(conn, fd_to_close);
00594
00595 return result;
00596 }
00597
00598
00599
00600 void Curl_persistconninfo(struct connectdata *conn)
00601 {
00602 memcpy(conn->data->info.conn_primary_ip, conn->primary_ip, MAX_IPADR_LEN);
00603 memcpy(conn->data->info.conn_local_ip, conn->local_ip, MAX_IPADR_LEN);
00604 conn->data->info.conn_scheme = conn->handler->scheme;
00605 conn->data->info.conn_protocol = conn->handler->protocol;
00606 conn->data->info.conn_primary_port = conn->primary_port;
00607 conn->data->info.conn_local_port = conn->local_port;
00608 }
00609
00610
00611 static bool getaddressinfo(struct sockaddr *sa, char *addr,
00612 long *port)
00613 {
00614 unsigned short us_port;
00615 struct sockaddr_in *si = NULL;
00616 #ifdef ENABLE_IPV6
00617 struct sockaddr_in6 *si6 = NULL;
00618 #endif
00619 #if defined(HAVE_SYS_UN_H) && defined(AF_UNIX)
00620 struct sockaddr_un *su = NULL;
00621 #endif
00622
00623 switch(sa->sa_family) {
00624 case AF_INET:
00625 si = (struct sockaddr_in *)(void *) sa;
00626 if(Curl_inet_ntop(sa->sa_family, &si->sin_addr,
00627 addr, MAX_IPADR_LEN)) {
00628 us_port = ntohs(si->sin_port);
00629 *port = us_port;
00630 return TRUE;
00631 }
00632 break;
00633 #ifdef ENABLE_IPV6
00634 case AF_INET6:
00635 si6 = (struct sockaddr_in6 *)(void *) sa;
00636 if(Curl_inet_ntop(sa->sa_family, &si6->sin6_addr,
00637 addr, MAX_IPADR_LEN)) {
00638 us_port = ntohs(si6->sin6_port);
00639 *port = us_port;
00640 return TRUE;
00641 }
00642 break;
00643 #endif
00644 #if defined(HAVE_SYS_UN_H) && defined(AF_UNIX)
00645 case AF_UNIX:
00646 su = (struct sockaddr_un*)sa;
00647 snprintf(addr, MAX_IPADR_LEN, "%s", su->sun_path);
00648 *port = 0;
00649 return TRUE;
00650 #endif
00651 default:
00652 break;
00653 }
00654
00655 addr[0] = '\0';
00656 *port = 0;
00657
00658 return FALSE;
00659 }
00660
00661
00662
00663 void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd)
00664 {
00665 curl_socklen_t len;
00666 struct Curl_sockaddr_storage ssrem;
00667 struct Curl_sockaddr_storage ssloc;
00668 struct Curl_easy *data = conn->data;
00669
00670 if(conn->socktype == SOCK_DGRAM)
00671
00672 return;
00673
00674 if(!conn->bits.reuse && !conn->bits.tcp_fastopen) {
00675 int error;
00676
00677 len = sizeof(struct Curl_sockaddr_storage);
00678 if(getpeername(sockfd, (struct sockaddr*) &ssrem, &len)) {
00679 error = SOCKERRNO;
00680 failf(data, "getpeername() failed with errno %d: %s",
00681 error, Curl_strerror(conn, error));
00682 return;
00683 }
00684
00685 len = sizeof(struct Curl_sockaddr_storage);
00686 memset(&ssloc, 0, sizeof(ssloc));
00687 if(getsockname(sockfd, (struct sockaddr*) &ssloc, &len)) {
00688 error = SOCKERRNO;
00689 failf(data, "getsockname() failed with errno %d: %s",
00690 error, Curl_strerror(conn, error));
00691 return;
00692 }
00693
00694 if(!getaddressinfo((struct sockaddr*)&ssrem,
00695 conn->primary_ip, &conn->primary_port)) {
00696 error = ERRNO;
00697 failf(data, "ssrem inet_ntop() failed with errno %d: %s",
00698 error, Curl_strerror(conn, error));
00699 return;
00700 }
00701 memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN);
00702
00703 if(!getaddressinfo((struct sockaddr*)&ssloc,
00704 conn->local_ip, &conn->local_port)) {
00705 error = ERRNO;
00706 failf(data, "ssloc inet_ntop() failed with errno %d: %s",
00707 error, Curl_strerror(conn, error));
00708 return;
00709 }
00710
00711 }
00712
00713
00714 Curl_persistconninfo(conn);
00715 }
00716
00717
00718
00719
00720
00721 CURLcode Curl_is_connected(struct connectdata *conn,
00722 int sockindex,
00723 bool *connected)
00724 {
00725 struct Curl_easy *data = conn->data;
00726 CURLcode result = CURLE_OK;
00727 time_t allow;
00728 int error = 0;
00729 struct timeval now;
00730 int rc;
00731 int i;
00732
00733 DEBUGASSERT(sockindex >= FIRSTSOCKET && sockindex <= SECONDARYSOCKET);
00734
00735 *connected = FALSE;
00736
00737 if(conn->bits.tcpconnect[sockindex]) {
00738
00739 *connected = TRUE;
00740 return CURLE_OK;
00741 }
00742
00743 now = Curl_tvnow();
00744
00745
00746 allow = Curl_timeleft(data, &now, TRUE);
00747
00748 if(allow < 0) {
00749
00750 failf(data, "Connection time-out");
00751 return CURLE_OPERATION_TIMEDOUT;
00752 }
00753
00754 for(i=0; i<2; i++) {
00755 const int other = i ^ 1;
00756 if(conn->tempsock[i] == CURL_SOCKET_BAD)
00757 continue;
00758
00759 #ifdef mpeix
00760
00761
00762
00763 (void)verifyconnect(conn->tempsock[i], NULL);
00764 #endif
00765
00766
00767 rc = SOCKET_WRITABLE(conn->tempsock[i], 0);
00768
00769 if(rc == 0) {
00770 error = 0;
00771 if(curlx_tvdiff(now, conn->connecttime) >= conn->timeoutms_per_addr) {
00772 infof(data, "After %ldms connect time, move on!\n",
00773 conn->timeoutms_per_addr);
00774 error = ETIMEDOUT;
00775 }
00776
00777
00778 if(i == 0 && conn->tempaddr[1] == NULL &&
00779 curlx_tvdiff(now, conn->connecttime) >= HAPPY_EYEBALLS_TIMEOUT) {
00780 trynextip(conn, sockindex, 1);
00781 }
00782 }
00783 else if(rc == CURL_CSELECT_OUT || conn->bits.tcp_fastopen) {
00784 if(verifyconnect(conn->tempsock[i], &error)) {
00785
00786
00787
00788 conn->sock[sockindex] = conn->tempsock[i];
00789 conn->ip_addr = conn->tempaddr[i];
00790 conn->tempsock[i] = CURL_SOCKET_BAD;
00791
00792
00793 if(conn->tempsock[other] != CURL_SOCKET_BAD) {
00794 Curl_closesocket(conn, conn->tempsock[other]);
00795 conn->tempsock[other] = CURL_SOCKET_BAD;
00796 }
00797
00798
00799 result = Curl_connected_proxy(conn, sockindex);
00800 if(result)
00801 return result;
00802
00803 conn->bits.tcpconnect[sockindex] = TRUE;
00804
00805 *connected = TRUE;
00806 if(sockindex == FIRSTSOCKET)
00807 Curl_pgrsTime(data, TIMER_CONNECT);
00808 Curl_updateconninfo(conn, conn->sock[sockindex]);
00809 Curl_verboseconnect(conn);
00810
00811 return CURLE_OK;
00812 }
00813 else
00814 infof(data, "Connection failed\n");
00815 }
00816 else if(rc & CURL_CSELECT_ERR)
00817 (void)verifyconnect(conn->tempsock[i], &error);
00818
00819
00820
00821
00822
00823 if(error) {
00824 data->state.os_errno = error;
00825 SET_SOCKERRNO(error);
00826 if(conn->tempaddr[i]) {
00827 CURLcode status;
00828 char ipaddress[MAX_IPADR_LEN];
00829 Curl_printable_address(conn->tempaddr[i], ipaddress, MAX_IPADR_LEN);
00830 infof(data, "connect to %s port %ld failed: %s\n",
00831 ipaddress, conn->port, Curl_strerror(conn, error));
00832
00833 conn->timeoutms_per_addr = conn->tempaddr[i]->ai_next == NULL ?
00834 allow : allow / 2;
00835
00836 status = trynextip(conn, sockindex, i);
00837 if(status != CURLE_COULDNT_CONNECT
00838 || conn->tempsock[other] == CURL_SOCKET_BAD)
00839
00840 result = status;
00841 }
00842 }
00843 }
00844
00845 if(result) {
00846
00847
00848 const char *hostname;
00849
00850
00851
00852 if(conn->tempaddr[1] == NULL) {
00853 result = trynextip(conn, sockindex, 1);
00854 if(!result)
00855 return result;
00856 }
00857
00858 if(conn->bits.socksproxy)
00859 hostname = conn->socks_proxy.host.name;
00860 else if(conn->bits.httpproxy)
00861 hostname = conn->http_proxy.host.name;
00862 else if(conn->bits.conn_to_host)
00863 hostname = conn->conn_to_host.name;
00864 else
00865 hostname = conn->host.name;
00866
00867 failf(data, "Failed to connect to %s port %ld: %s",
00868 hostname, conn->port, Curl_strerror(conn, error));
00869 }
00870
00871 return result;
00872 }
00873
00874 void Curl_tcpnodelay(struct connectdata *conn, curl_socket_t sockfd)
00875 {
00876 #if defined(TCP_NODELAY)
00877 #if !defined(CURL_DISABLE_VERBOSE_STRINGS)
00878 struct Curl_easy *data = conn->data;
00879 #endif
00880 curl_socklen_t onoff = (curl_socklen_t) 1;
00881 int level = IPPROTO_TCP;
00882
00883 #if 0
00884
00885
00886
00887
00888
00889
00890
00891 struct protoent *pe = getprotobyname("tcp");
00892 if(pe)
00893 level = pe->p_proto;
00894 #endif
00895
00896 #if defined(CURL_DISABLE_VERBOSE_STRINGS)
00897 (void) conn;
00898 #endif
00899
00900 if(setsockopt(sockfd, level, TCP_NODELAY, (void *)&onoff,
00901 sizeof(onoff)) < 0)
00902 infof(data, "Could not set TCP_NODELAY: %s\n",
00903 Curl_strerror(conn, SOCKERRNO));
00904 else
00905 infof(data, "TCP_NODELAY set\n");
00906 #else
00907 (void)conn;
00908 (void)sockfd;
00909 #endif
00910 }
00911
00912 #ifdef SO_NOSIGPIPE
00913
00914
00915
00916
00917 static void nosigpipe(struct connectdata *conn,
00918 curl_socket_t sockfd)
00919 {
00920 struct Curl_easy *data= conn->data;
00921 int onoff = 1;
00922 if(setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&onoff,
00923 sizeof(onoff)) < 0)
00924 infof(data, "Could not set SO_NOSIGPIPE: %s\n",
00925 Curl_strerror(conn, SOCKERRNO));
00926 }
00927 #else
00928 #define nosigpipe(x,y) Curl_nop_stmt
00929 #endif
00930
00931 #ifdef USE_WINSOCK
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944 #define DETECT_OS_NONE 0
00945 #define DETECT_OS_PREVISTA 1
00946 #define DETECT_OS_VISTA_OR_LATER 2
00947
00948 void Curl_sndbufset(curl_socket_t sockfd)
00949 {
00950 int val = CURL_MAX_WRITE_SIZE + 32;
00951 int curval = 0;
00952 int curlen = sizeof(curval);
00953
00954 static int detectOsState = DETECT_OS_NONE;
00955
00956 if(detectOsState == DETECT_OS_NONE) {
00957 if(Curl_verify_windows_version(6, 0, PLATFORM_WINNT,
00958 VERSION_GREATER_THAN_EQUAL))
00959 detectOsState = DETECT_OS_VISTA_OR_LATER;
00960 else
00961 detectOsState = DETECT_OS_PREVISTA;
00962 }
00963
00964 if(detectOsState == DETECT_OS_VISTA_OR_LATER)
00965 return;
00966
00967 if(getsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (char *)&curval, &curlen) == 0)
00968 if(curval > val)
00969 return;
00970
00971 setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (const char *)&val, sizeof(val));
00972 }
00973 #endif
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984 static CURLcode singleipconnect(struct connectdata *conn,
00985 const Curl_addrinfo *ai,
00986 curl_socket_t *sockp)
00987 {
00988 struct Curl_sockaddr_ex addr;
00989 int rc = -1;
00990 int error = 0;
00991 bool isconnected = FALSE;
00992 struct Curl_easy *data = conn->data;
00993 curl_socket_t sockfd;
00994 CURLcode result;
00995 char ipaddress[MAX_IPADR_LEN];
00996 long port;
00997 bool is_tcp;
00998
00999 *sockp = CURL_SOCKET_BAD;
01000
01001 result = Curl_socket(conn, ai, &addr, &sockfd);
01002 if(result)
01003
01004
01005
01006 return CURLE_OK;
01007
01008
01009 if(!getaddressinfo((struct sockaddr*)&addr.sa_addr,
01010 ipaddress, &port)) {
01011
01012 error = ERRNO;
01013 failf(data, "sa_addr inet_ntop() failed with errno %d: %s",
01014 error, Curl_strerror(conn, error));
01015 Curl_closesocket(conn, sockfd);
01016 return CURLE_OK;
01017 }
01018 infof(data, " Trying %s...\n", ipaddress);
01019
01020 #ifdef ENABLE_IPV6
01021 is_tcp = (addr.family == AF_INET || addr.family == AF_INET6) &&
01022 addr.socktype == SOCK_STREAM;
01023 #else
01024 is_tcp = (addr.family == AF_INET) && addr.socktype == SOCK_STREAM;
01025 #endif
01026 if(is_tcp && data->set.tcp_nodelay)
01027 Curl_tcpnodelay(conn, sockfd);
01028
01029 nosigpipe(conn, sockfd);
01030
01031 Curl_sndbufset(sockfd);
01032
01033 if(is_tcp && data->set.tcp_keepalive)
01034 tcpkeepalive(data, sockfd);
01035
01036 if(data->set.fsockopt) {
01037
01038 error = data->set.fsockopt(data->set.sockopt_client,
01039 sockfd,
01040 CURLSOCKTYPE_IPCXN);
01041
01042 if(error == CURL_SOCKOPT_ALREADY_CONNECTED)
01043 isconnected = TRUE;
01044 else if(error) {
01045 Curl_closesocket(conn, sockfd);
01046 return CURLE_ABORTED_BY_CALLBACK;
01047 }
01048 }
01049
01050
01051 if(addr.family == AF_INET
01052 #ifdef ENABLE_IPV6
01053 || addr.family == AF_INET6
01054 #endif
01055 ) {
01056 result = bindlocal(conn, sockfd, addr.family,
01057 Curl_ipv6_scope((struct sockaddr*)&addr.sa_addr));
01058 if(result) {
01059 Curl_closesocket(conn, sockfd);
01060 if(result == CURLE_UNSUPPORTED_PROTOCOL) {
01061
01062
01063 return CURLE_COULDNT_CONNECT;
01064 }
01065 return result;
01066 }
01067 }
01068
01069
01070 (void)curlx_nonblock(sockfd, TRUE);
01071
01072 conn->connecttime = Curl_tvnow();
01073 if(conn->num_addr > 1)
01074 Curl_expire_latest(data, conn->timeoutms_per_addr);
01075
01076
01077 if(!isconnected && (conn->socktype == SOCK_STREAM)) {
01078 if(conn->bits.tcp_fastopen) {
01079 #if defined(CONNECT_DATA_IDEMPOTENT)
01080 sa_endpoints_t endpoints;
01081 endpoints.sae_srcif = 0;
01082 endpoints.sae_srcaddr = NULL;
01083 endpoints.sae_srcaddrlen = 0;
01084 endpoints.sae_dstaddr = &addr.sa_addr;
01085 endpoints.sae_dstaddrlen = addr.addrlen;
01086
01087 rc = connectx(sockfd, &endpoints, SAE_ASSOCID_ANY,
01088 CONNECT_RESUME_ON_READ_WRITE | CONNECT_DATA_IDEMPOTENT,
01089 NULL, 0, NULL, NULL);
01090 #elif defined(MSG_FASTOPEN)
01091 if(conn->given->flags & PROTOPT_SSL)
01092 rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
01093 else
01094 rc = 0;
01095 #endif
01096 }
01097 else {
01098 rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
01099 }
01100
01101 if(-1 == rc)
01102 error = SOCKERRNO;
01103 }
01104 else {
01105 *sockp = sockfd;
01106 return CURLE_OK;
01107 }
01108
01109 #ifdef ENABLE_IPV6
01110 conn->bits.ipv6 = (addr.family == AF_INET6)?TRUE:FALSE;
01111 #endif
01112
01113 if(-1 == rc) {
01114 switch(error) {
01115 case EINPROGRESS:
01116 case EWOULDBLOCK:
01117 #if defined(EAGAIN)
01118 #if (EAGAIN) != (EWOULDBLOCK)
01119
01120
01121
01122
01123 case EAGAIN:
01124 #endif
01125 #endif
01126 result = CURLE_OK;
01127 break;
01128
01129 default:
01130
01131 infof(data, "Immediate connect fail for %s: %s\n",
01132 ipaddress, Curl_strerror(conn, error));
01133 data->state.os_errno = error;
01134
01135
01136 Curl_closesocket(conn, sockfd);
01137 result = CURLE_COULDNT_CONNECT;
01138 }
01139 }
01140
01141 if(!result)
01142 *sockp = sockfd;
01143
01144 return result;
01145 }
01146
01147
01148
01149
01150
01151
01152
01153 CURLcode Curl_connecthost(struct connectdata *conn,
01154 const struct Curl_dns_entry *remotehost)
01155 {
01156 struct Curl_easy *data = conn->data;
01157 struct timeval before = Curl_tvnow();
01158 CURLcode result = CURLE_COULDNT_CONNECT;
01159
01160 time_t timeout_ms = Curl_timeleft(data, &before, TRUE);
01161
01162 if(timeout_ms < 0) {
01163
01164 failf(data, "Connection time-out");
01165 return CURLE_OPERATION_TIMEDOUT;
01166 }
01167
01168 conn->num_addr = Curl_num_addresses(remotehost->addr);
01169 conn->tempaddr[0] = remotehost->addr;
01170 conn->tempaddr[1] = NULL;
01171 conn->tempsock[0] = CURL_SOCKET_BAD;
01172 conn->tempsock[1] = CURL_SOCKET_BAD;
01173 Curl_expire(conn->data, HAPPY_EYEBALLS_TIMEOUT);
01174
01175
01176 conn->timeoutms_per_addr =
01177 conn->tempaddr[0]->ai_next == NULL ? timeout_ms : timeout_ms / 2;
01178
01179
01180 while(conn->tempaddr[0]) {
01181 result = singleipconnect(conn, conn->tempaddr[0], &(conn->tempsock[0]));
01182 if(!result)
01183 break;
01184 conn->tempaddr[0] = conn->tempaddr[0]->ai_next;
01185 }
01186
01187 if(conn->tempsock[0] == CURL_SOCKET_BAD) {
01188 if(!result)
01189 result = CURLE_COULDNT_CONNECT;
01190 return result;
01191 }
01192
01193 data->info.numconnects++;
01194
01195 return CURLE_OK;
01196 }
01197
01198 struct connfind {
01199 struct connectdata *tofind;
01200 bool found;
01201 };
01202
01203 static int conn_is_conn(struct connectdata *conn, void *param)
01204 {
01205 struct connfind *f = (struct connfind *)param;
01206 if(conn == f->tofind) {
01207 f->found = TRUE;
01208 return 1;
01209 }
01210 return 0;
01211 }
01212
01213
01214
01215
01216
01217
01218
01219 curl_socket_t Curl_getconnectinfo(struct Curl_easy *data,
01220 struct connectdata **connp)
01221 {
01222 curl_socket_t sockfd;
01223
01224 DEBUGASSERT(data);
01225
01226
01227
01228
01229
01230
01231 if(data->state.lastconnect && (data->multi_easy || data->multi)) {
01232 struct connectdata *c = data->state.lastconnect;
01233 struct connfind find;
01234 find.tofind = data->state.lastconnect;
01235 find.found = FALSE;
01236
01237 Curl_conncache_foreach(data->multi_easy?
01238 &data->multi_easy->conn_cache:
01239 &data->multi->conn_cache, &find, conn_is_conn);
01240
01241 if(!find.found) {
01242 data->state.lastconnect = NULL;
01243 return CURL_SOCKET_BAD;
01244 }
01245
01246 if(connp)
01247
01248 *connp = c;
01249 sockfd = c->sock[FIRSTSOCKET];
01250 }
01251 else
01252 return CURL_SOCKET_BAD;
01253
01254 return sockfd;
01255 }
01256
01257
01258
01259
01260 bool Curl_connalive(struct connectdata *conn)
01261 {
01262
01263 if(conn->ssl[FIRSTSOCKET].use) {
01264
01265 if(!Curl_ssl_check_cxn(conn))
01266 return false;
01267 }
01268
01269 #ifdef MSG_PEEK
01270 else if(conn->sock[FIRSTSOCKET] == CURL_SOCKET_BAD)
01271 return false;
01272 else {
01273
01274 char buf;
01275 if(recv((RECV_TYPE_ARG1)conn->sock[FIRSTSOCKET], (RECV_TYPE_ARG2)&buf,
01276 (RECV_TYPE_ARG3)1, (RECV_TYPE_ARG4)MSG_PEEK) == 0) {
01277 return false;
01278 }
01279 }
01280 #endif
01281 return true;
01282 }
01283
01284
01285
01286
01287
01288
01289 int Curl_closesocket(struct connectdata *conn,
01290 curl_socket_t sock)
01291 {
01292 if(conn && conn->fclosesocket) {
01293 if((sock == conn->sock[SECONDARYSOCKET]) &&
01294 conn->sock_accepted[SECONDARYSOCKET])
01295
01296
01297
01298 conn->sock_accepted[SECONDARYSOCKET] = FALSE;
01299 else {
01300 Curl_multi_closed(conn, sock);
01301 return conn->fclosesocket(conn->closesocket_client, sock);
01302 }
01303 }
01304
01305 if(conn)
01306
01307 Curl_multi_closed(conn, sock);
01308
01309 sclose(sock);
01310
01311 return 0;
01312 }
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323 CURLcode Curl_socket(struct connectdata *conn,
01324 const Curl_addrinfo *ai,
01325 struct Curl_sockaddr_ex *addr,
01326 curl_socket_t *sockfd)
01327 {
01328 struct Curl_easy *data = conn->data;
01329 struct Curl_sockaddr_ex dummy;
01330
01331 if(!addr)
01332
01333 addr = &dummy;
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343 addr->family = ai->ai_family;
01344 addr->socktype = conn->socktype;
01345 addr->protocol = conn->socktype==SOCK_DGRAM?IPPROTO_UDP:ai->ai_protocol;
01346 addr->addrlen = ai->ai_addrlen;
01347
01348 if(addr->addrlen > sizeof(struct Curl_sockaddr_storage))
01349 addr->addrlen = sizeof(struct Curl_sockaddr_storage);
01350 memcpy(&addr->sa_addr, ai->ai_addr, addr->addrlen);
01351
01352 if(data->set.fopensocket)
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362 *sockfd = data->set.fopensocket(data->set.opensocket_client,
01363 CURLSOCKTYPE_IPCXN,
01364 (struct curl_sockaddr *)addr);
01365 else
01366
01367 *sockfd = socket(addr->family, addr->socktype, addr->protocol);
01368
01369 if(*sockfd == CURL_SOCKET_BAD)
01370
01371 return CURLE_COULDNT_CONNECT;
01372
01373 #if defined(ENABLE_IPV6) && defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID)
01374 if(conn->scope_id && (addr->family == AF_INET6)) {
01375 struct sockaddr_in6 * const sa6 = (void *)&addr->sa_addr;
01376 sa6->sin6_scope_id = conn->scope_id;
01377 }
01378 #endif
01379
01380 return CURLE_OK;
01381
01382 }
01383
01384
01385
01386
01387 void Curl_conncontrol(struct connectdata *conn,
01388 int ctrl
01389 #ifdef DEBUGBUILD
01390 , const char *reason
01391 #endif
01392 )
01393 {
01394
01395 bool closeit = (ctrl == CONNCTRL_CONNECTION) ||
01396 ((ctrl == CONNCTRL_STREAM) && !(conn->handler->flags & PROTOPT_STREAM));
01397 if((ctrl == CONNCTRL_STREAM) &&
01398 (conn->handler->flags & PROTOPT_STREAM))
01399 DEBUGF(infof(conn->data, "Kill stream: %s\n", reason));
01400 else if(closeit != conn->bits.close) {
01401 DEBUGF(infof(conn->data, "Marked for [%s]: %s\n",
01402 closeit?"closure":"keep alive", reason));
01403 conn->bits.close = closeit;
01404
01405 }
01406 }
01407
01408
01409 bool Curl_conn_data_pending(struct connectdata *conn, int sockindex)
01410 {
01411 int readable;
01412
01413 if(Curl_ssl_data_pending(conn, sockindex) ||
01414 Curl_recv_has_postponed_data(conn, sockindex))
01415 return true;
01416
01417 readable = SOCKET_READABLE(conn->sock[sockindex], 0);
01418 return (readable > 0 && (readable & CURL_CSELECT_IN));
01419 }