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