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