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