Git init
[external/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 CURLcode
116 singleipconnect(struct connectdata *conn,
117                 const Curl_addrinfo *ai, /* start connecting to this */
118                 long timeout_ms,
119                 curl_socket_t *sock,
120                 bool *connected);
121
122 /*
123  * Curl_timeleft() returns the amount of milliseconds left allowed for the
124  * transfer/connection. If the value is negative, the timeout time has already
125  * elapsed.
126  *
127  * If 'nowp' is non-NULL, it points to the current time.
128  * 'duringconnect' is FALSE if not during a connect, as then of course the
129  * connect timeout is not taken into account!
130  */
131 long Curl_timeleft(struct connectdata *conn,
132                    struct timeval *nowp,
133                    bool duringconnect)
134 {
135   struct SessionHandle *data = conn->data;
136   int timeout_set = 0;
137   long timeout_ms = duringconnect?DEFAULT_CONNECT_TIMEOUT:0;
138   struct timeval now;
139
140   /* if a timeout is set, use the most restrictive one */
141
142   if(data->set.timeout > 0)
143     timeout_set |= 1;
144   if(duringconnect && (data->set.connecttimeout > 0))
145     timeout_set |= 2;
146
147   switch (timeout_set) {
148   case 1:
149     timeout_ms = data->set.timeout;
150     break;
151   case 2:
152     timeout_ms = data->set.connecttimeout;
153     break;
154   case 3:
155     if(data->set.timeout < data->set.connecttimeout)
156       timeout_ms = data->set.timeout;
157     else
158       timeout_ms = data->set.connecttimeout;
159     break;
160   default:
161     /* use the default */
162     if(!duringconnect)
163       /* if we're not during connect, there's no default timeout so if we're
164          at zero we better just return zero and not make it a negative number
165          by the math below */
166       return 0;
167     break;
168   }
169
170   if(!nowp) {
171     now = Curl_tvnow();
172     nowp = &now;
173   }
174
175   /* substract elapsed time */
176   timeout_ms -= Curl_tvdiff(*nowp, data->progress.t_startsingle);
177   if(!timeout_ms)
178     /* avoid returning 0 as that means no timeout! */
179     return -1;
180
181   return timeout_ms;
182 }
183
184 /*
185  * waitconnect() waits for a TCP connect on the given socket for the specified
186  * number if milliseconds. It returns:
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 #define WAITCONN_ABORTED       3
194
195 static
196 int waitconnect(struct connectdata *conn,
197                 curl_socket_t sockfd, /* socket */
198                 long timeout_msec)
199 {
200   int rc;
201 #ifdef mpeix
202   /* Call this function once now, and ignore the results. We do this to
203      "clear" the error state on the socket so that we can later read it
204      reliably. This is reported necessary on the MPE/iX operating system. */
205   (void)verifyconnect(sockfd, NULL);
206 #endif
207
208   for(;;) {
209
210     /* now select() until we get connect or timeout */
211     rc = Curl_socket_ready(CURL_SOCKET_BAD, sockfd, (int)(timeout_msec>1000?
212                                                           1000:timeout_msec));
213     if(Curl_pgrsUpdate(conn))
214       return WAITCONN_ABORTED;
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 = conn->ip_version;
314       int rc;
315
316       if (af == AF_INET)
317         conn->ip_version = CURL_IPRESOLVE_V4;
318 #ifdef ENABLE_IPV6
319       else if (af == AF_INET6)
320         conn->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       conn->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 CURLcode trynextip(struct connectdata *conn,
496                           int sockindex,
497                           bool *connected)
498 {
499   curl_socket_t sockfd;
500   Curl_addrinfo *ai;
501
502   /* First clean up after the failed socket.
503      Don't close it yet to ensure that the next IP's socket gets a different
504      file descriptor, which can prevent bugs when the curl_multi_socket_action
505      interface is used with certain select() replacements such as kqueue. */
506   curl_socket_t fd_to_close = conn->sock[sockindex];
507   conn->sock[sockindex] = CURL_SOCKET_BAD;
508   *connected = FALSE;
509
510   if(sockindex != FIRSTSOCKET) {
511     sclose(fd_to_close);
512     return CURLE_COULDNT_CONNECT; /* no next */
513   }
514
515   /* try the next address */
516   ai = conn->ip_addr->ai_next;
517
518   while(ai) {
519     CURLcode res = singleipconnect(conn, ai, 0L, &sockfd, connected);
520     if(res)
521       return res;
522     if(sockfd != CURL_SOCKET_BAD) {
523       /* store the new socket descriptor */
524       conn->sock[sockindex] = sockfd;
525       conn->ip_addr = ai;
526       sclose(fd_to_close);
527       return CURLE_OK;
528     }
529     ai = ai->ai_next;
530   }
531   sclose(fd_to_close);
532   return CURLE_COULDNT_CONNECT;
533 }
534
535 /* Copies connection info into the session handle to make it available
536    when the session handle is no longer associated with a connection. */
537 void Curl_persistconninfo(struct connectdata *conn)
538 {
539   memcpy(conn->data->info.conn_primary_ip, conn->primary_ip, MAX_IPADR_LEN);
540   memcpy(conn->data->info.conn_local_ip, conn->local_ip, MAX_IPADR_LEN);
541   conn->data->info.conn_primary_port = conn->primary_port;
542   conn->data->info.conn_local_port = conn->local_port;
543 }
544
545 /* retrieves ip address and port from a sockaddr structure */
546 static bool getaddressinfo(struct sockaddr* sa, char* addr,
547                            long* port)
548 {
549   unsigned short us_port;
550   struct sockaddr_in* si = NULL;
551 #ifdef ENABLE_IPV6
552   struct sockaddr_in6* si6 = NULL;
553 #endif
554 #if defined(HAVE_SYS_UN_H) && defined(AF_UNIX)
555   struct sockaddr_un* su = NULL;
556 #endif
557
558   switch (sa->sa_family) {
559     case AF_INET:
560       si = (struct sockaddr_in*) sa;
561       if(Curl_inet_ntop(sa->sa_family, &si->sin_addr,
562                         addr, MAX_IPADR_LEN)) {
563         us_port = ntohs(si->sin_port);
564         *port = us_port;
565         return TRUE;
566       }
567       break;
568 #ifdef ENABLE_IPV6
569     case AF_INET6:
570       si6 = (struct sockaddr_in6*)sa;
571       if(Curl_inet_ntop(sa->sa_family, &si6->sin6_addr,
572                         addr, MAX_IPADR_LEN)) {
573         us_port = ntohs(si6->sin6_port);
574         *port = us_port;
575         return TRUE;
576       }
577       break;
578 #endif
579 #if defined(HAVE_SYS_UN_H) && defined(AF_UNIX)
580     case AF_UNIX:
581       su = (struct sockaddr_un*)sa;
582       snprintf(addr, MAX_IPADR_LEN, "%s", su->sun_path);
583       *port = 0;
584       return TRUE;
585 #endif
586     default:
587       break;
588   }
589
590   addr[0] = '\0';
591   *port = 0;
592
593   return FALSE;
594 }
595
596 /* retrieves the start/end point information of a socket of an established
597    connection */
598 void Curl_updateconninfo(struct connectdata *conn, curl_socket_t sockfd)
599 {
600   int error;
601   curl_socklen_t len;
602   struct Curl_sockaddr_storage ssrem;
603   struct Curl_sockaddr_storage ssloc;
604   struct SessionHandle *data = conn->data;
605
606   if(!conn->bits.reuse) {
607
608     len = sizeof(struct Curl_sockaddr_storage);
609     if(getpeername(sockfd, (struct sockaddr*) &ssrem, &len)) {
610       error = SOCKERRNO;
611       failf(data, "getpeername() failed with errno %d: %s",
612             error, Curl_strerror(conn, error));
613       return;
614     }
615
616     len = sizeof(struct Curl_sockaddr_storage);
617     if(getsockname(sockfd, (struct sockaddr*) &ssloc, &len)) {
618       error = SOCKERRNO;
619       failf(data, "getsockname() failed with errno %d: %s",
620             error, Curl_strerror(conn, error));
621       return;
622     }
623
624     if(!getaddressinfo((struct sockaddr*)&ssrem,
625                         conn->primary_ip, &conn->primary_port)) {
626       error = ERRNO;
627       failf(data, "ssrem inet_ntop() failed with errno %d: %s",
628             error, Curl_strerror(conn, error));
629       return;
630     }
631
632     if(!getaddressinfo((struct sockaddr*)&ssloc,
633                        conn->local_ip, &conn->local_port)) {
634       error = ERRNO;
635       failf(data, "ssloc inet_ntop() failed with errno %d: %s",
636             error, Curl_strerror(conn, error));
637       return;
638     }
639
640   }
641
642   /* persist connection info in session handle */
643   Curl_persistconninfo(conn);
644 }
645
646 /*
647  * Curl_is_connected() is used from the multi interface to check if the
648  * firstsocket has connected.
649  */
650
651 CURLcode Curl_is_connected(struct connectdata *conn,
652                            int sockindex,
653                            bool *connected)
654 {
655   int rc;
656   struct SessionHandle *data = conn->data;
657   CURLcode code = CURLE_OK;
658   curl_socket_t sockfd = conn->sock[sockindex];
659   long allow = DEFAULT_CONNECT_TIMEOUT;
660   int error = 0;
661
662   DEBUGASSERT(sockindex >= FIRSTSOCKET && sockindex <= SECONDARYSOCKET);
663
664   *connected = FALSE; /* a very negative world view is best */
665
666   if(conn->bits.tcpconnect) {
667     /* we are connected already! */
668     *connected = TRUE;
669     return CURLE_OK;
670   }
671
672   /* figure out how long time we have left to connect */
673   allow = Curl_timeleft(conn, NULL, TRUE);
674
675   if(allow < 0) {
676     /* time-out, bail out, go home */
677     failf(data, "Connection time-out");
678     return CURLE_OPERATION_TIMEDOUT;
679   }
680
681   /* check for connect without timeout as we want to return immediately */
682   rc = waitconnect(conn, sockfd, 0);
683   if(WAITCONN_TIMEOUT == rc)
684     /* not an error, but also no connection yet */
685     return code;
686
687   if(WAITCONN_CONNECTED == rc) {
688     if(verifyconnect(sockfd, &error)) {
689       /* we are connected, awesome! */
690       conn->bits.tcpconnect = TRUE;
691       *connected = TRUE;
692       Curl_pgrsTime(data, TIMER_CONNECT); /* connect done */
693       Curl_verboseconnect(conn);
694       Curl_updateconninfo(conn, sockfd);
695
696       return CURLE_OK;
697     }
698     /* nope, not connected for real */
699   }
700   else {
701     /* nope, not connected  */
702     if(WAITCONN_FDSET_ERROR == rc) {
703       (void)verifyconnect(sockfd, &error);
704       infof(data, "%s\n",Curl_strerror(conn, error));
705     }
706     else
707       infof(data, "Connection failed\n");
708   }
709
710   /*
711    * The connection failed here, we should attempt to connect to the "next
712    * address" for the given host. But first remember the latest error.
713    */
714   if(error) {
715     data->state.os_errno = error;
716     SET_SOCKERRNO(error);
717   }
718
719   code = trynextip(conn, sockindex, connected);
720
721   if(code) {
722     error = SOCKERRNO;
723     data->state.os_errno = error;
724     failf(data, "Failed connect to %s:%ld; %s",
725           conn->host.name, conn->port, Curl_strerror(conn, error));
726   }
727
728   return code;
729 }
730
731 static void tcpnodelay(struct connectdata *conn,
732                        curl_socket_t sockfd)
733 {
734 #ifdef TCP_NODELAY
735   struct SessionHandle *data= conn->data;
736   curl_socklen_t onoff = (curl_socklen_t) data->set.tcp_nodelay;
737   int proto = IPPROTO_TCP;
738
739 #if 0
740   /* The use of getprotobyname() is disabled since it isn't thread-safe on
741      numerous systems. On these getprotobyname_r() should be used instead, but
742      that exists in at least one 4 arg version and one 5 arg version, and
743      since the proto number rarely changes anyway we now just use the hard
744      coded number. The "proper" fix would need a configure check for the
745      correct function much in the same style the gethostbyname_r versions are
746      detected. */
747   struct protoent *pe = getprotobyname("tcp");
748   if(pe)
749     proto = pe->p_proto;
750 #endif
751
752   if(setsockopt(sockfd, proto, TCP_NODELAY, (void *)&onoff,
753                 sizeof(onoff)) < 0)
754     infof(data, "Could not set TCP_NODELAY: %s\n",
755           Curl_strerror(conn, SOCKERRNO));
756   else
757     infof(data,"TCP_NODELAY set\n");
758 #else
759   (void)conn;
760   (void)sockfd;
761 #endif
762 }
763
764 #ifdef SO_NOSIGPIPE
765 /* The preferred method on Mac OS X (10.2 and later) to prevent SIGPIPEs when
766    sending data to a dead peer (instead of relying on the 4th argument to send
767    being MSG_NOSIGNAL). Possibly also existing and in use on other BSD
768    systems? */
769 static void nosigpipe(struct connectdata *conn,
770                       curl_socket_t sockfd)
771 {
772   struct SessionHandle *data= conn->data;
773   int onoff = 1;
774   if(setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&onoff,
775                 sizeof(onoff)) < 0)
776     infof(data, "Could not set SO_NOSIGPIPE: %s\n",
777           Curl_strerror(conn, SOCKERRNO));
778 }
779 #else
780 #define nosigpipe(x,y)
781 #endif
782
783 #ifdef WIN32
784 /* When you run a program that uses the Windows Sockets API, you may
785    experience slow performance when you copy data to a TCP server.
786
787    http://support.microsoft.com/kb/823764
788
789    Work-around: Make the Socket Send Buffer Size Larger Than the Program Send
790    Buffer Size
791
792 */
793 void Curl_sndbufset(curl_socket_t sockfd)
794 {
795   int val = CURL_MAX_WRITE_SIZE + 32;
796   int curval = 0;
797   int curlen = sizeof(curval);
798
799   if (getsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (char *)&curval, &curlen) == 0)
800     if (curval > val)
801       return;
802
803   setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (const char *)&val, sizeof(val));
804 }
805 #endif
806
807
808 /*
809  * singleipconnect()
810  *
811  * Note that even on connect fail it returns CURLE_OK, but with 'sock' set to
812  * CURL_SOCKET_BAD. Other errors will however return proper errors.
813  *
814  * singleipconnect() connects to the given IP only, and it may return without
815  * having connected if used from the multi interface.
816  */
817 static CURLcode
818 singleipconnect(struct connectdata *conn,
819                 const Curl_addrinfo *ai,
820                 long timeout_ms,
821                 curl_socket_t *sockp,
822                 bool *connected)
823 {
824   struct Curl_sockaddr_ex addr;
825   int rc;
826   int error;
827   bool isconnected;
828   struct SessionHandle *data = conn->data;
829   curl_socket_t sockfd;
830   CURLcode res = CURLE_OK;
831 #if defined(ENABLE_IPV6) && defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID)
832   struct sockaddr_in6 * const sa6 = (void *)&addr.sa_addr;
833 #endif
834
835   *sockp = CURL_SOCKET_BAD;
836
837   /*
838    * The Curl_sockaddr_ex structure is basically libcurl's external API
839    * curl_sockaddr structure with enough space available to directly hold
840    * any protocol-specific address structures. The variable declared here
841    * will be used to pass / receive data to/from the fopensocket callback
842    * if this has been set, before that, it is initialized from parameters.
843    */
844
845   addr.family = ai->ai_family;
846   addr.socktype = conn->socktype;
847   addr.protocol = ai->ai_protocol;
848   addr.addrlen = ai->ai_addrlen;
849
850   if(addr.addrlen > sizeof(struct Curl_sockaddr_storage))
851      addr.addrlen = sizeof(struct Curl_sockaddr_storage);
852   memcpy(&addr.sa_addr, ai->ai_addr, addr.addrlen);
853
854   *connected = FALSE; /* default is not connected */
855
856   if(data->set.fopensocket)
857    /*
858     * If the opensocket callback is set, all the destination address
859     * information is passed to the callback. Depending on this information the
860     * callback may opt to abort the connection, this is indicated returning
861     * CURL_SOCKET_BAD; otherwise it will return a not-connected socket. When
862     * the callback returns a valid socket the destination address information
863     * might have been changed and this 'new' address will actually be used
864     * here to connect.
865     */
866     sockfd = data->set.fopensocket(data->set.opensocket_client,
867                                    CURLSOCKTYPE_IPCXN,
868                                    (struct curl_sockaddr *)&addr);
869   else
870     /* opensocket callback not set, so simply create the socket now */
871     sockfd = socket(addr.family, addr.socktype, addr.protocol);
872
873   if(sockfd == CURL_SOCKET_BAD)
874     /* no socket, no connection */
875     return CURLE_OK;
876
877 #if defined(ENABLE_IPV6) && defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID)
878   if (conn->scope && (addr.family == AF_INET6))
879     sa6->sin6_scope_id = conn->scope;
880 #endif
881
882   /* store remote address and port used in this connection attempt */
883   if(!getaddressinfo((struct sockaddr*)&addr.sa_addr,
884                      conn->primary_ip, &conn->primary_port)) {
885     /* malformed address or bug in inet_ntop, try next address */
886     error = ERRNO;
887     failf(data, "sa_addr inet_ntop() failed with errno %d: %s",
888           error, Curl_strerror(conn, error));
889     sclose(sockfd);
890     return CURLE_OK;
891   }
892   memcpy(conn->ip_addr_str, conn->primary_ip, MAX_IPADR_LEN);
893   infof(data, "  Trying %s... ", conn->ip_addr_str);
894
895   Curl_persistconninfo(conn);
896
897 #ifdef ENABLE_IPV6
898   if(addr.family == AF_INET6)
899     conn->bits.ipv6 = TRUE;
900 #endif
901
902   if(data->set.tcp_nodelay)
903     tcpnodelay(conn, sockfd);
904
905   nosigpipe(conn, sockfd);
906
907   Curl_sndbufset(sockfd);
908
909   if(data->set.fsockopt) {
910     /* activate callback for setting socket options */
911     error = data->set.fsockopt(data->set.sockopt_client,
912                                sockfd,
913                                CURLSOCKTYPE_IPCXN);
914     if(error) {
915       sclose(sockfd); /* close the socket and bail out */
916       return res;
917     }
918   }
919
920   /* possibly bind the local end to an IP, interface or port */
921   res = bindlocal(conn, sockfd, addr.family);
922   if(res) {
923     sclose(sockfd); /* close socket and bail out */
924     return res;
925   }
926
927   /* set socket non-blocking */
928   curlx_nonblock(sockfd, TRUE);
929
930   /* Connect TCP sockets, bind UDP */
931   if(conn->socktype == SOCK_STREAM)
932     rc = connect(sockfd, &addr.sa_addr, addr.addrlen);
933   else
934     rc = 0;
935
936   if(-1 == rc) {
937     error = SOCKERRNO;
938
939     switch (error) {
940     case EINPROGRESS:
941     case EWOULDBLOCK:
942 #if defined(EAGAIN)
943 #if (EAGAIN) != (EWOULDBLOCK)
944       /* On some platforms EAGAIN and EWOULDBLOCK are the
945        * same value, and on others they are different, hence
946        * the odd #if
947        */
948     case EAGAIN:
949 #endif
950 #endif
951       rc = waitconnect(conn, sockfd, timeout_ms);
952       if(WAITCONN_ABORTED == rc) {
953         sclose(sockfd);
954         return CURLE_ABORTED_BY_CALLBACK;
955       }
956       break;
957     default:
958       /* unknown error, fallthrough and try another address! */
959       failf(data, "Failed to connect to %s: %s",
960             conn->ip_addr_str, Curl_strerror(conn,error));
961       data->state.os_errno = error;
962       break;
963     }
964   }
965
966   /* The 'WAITCONN_TIMEOUT == rc' comes from the waitconnect(), and not from
967      connect(). We can be sure of this since connect() cannot return 1. */
968   if((WAITCONN_TIMEOUT == rc) &&
969      (data->state.used_interface == Curl_if_multi)) {
970     /* Timeout when running the multi interface */
971     *sockp = sockfd;
972     return CURLE_OK;
973   }
974
975   isconnected = verifyconnect(sockfd, &error);
976
977   if(!rc && isconnected) {
978     /* we are connected, awesome! */
979     *connected = TRUE; /* this is a true connect */
980     infof(data, "connected\n");
981     Curl_updateconninfo(conn, sockfd);
982     *sockp = sockfd;
983     return CURLE_OK;
984   }
985   else if(WAITCONN_TIMEOUT == rc)
986     infof(data, "Timeout\n");
987   else {
988     data->state.os_errno = error;
989     infof(data, "%s\n", Curl_strerror(conn, error));
990   }
991
992   /* connect failed or timed out */
993   sclose(sockfd);
994
995   return CURLE_OK;
996 }
997
998 /*
999  * TCP connect to the given host with timeout, proxy or remote doesn't matter.
1000  * There might be more than one IP address to try out. Fill in the passed
1001  * pointer with the connected socket.
1002  */
1003
1004 CURLcode Curl_connecthost(struct connectdata *conn,  /* context */
1005                           const struct Curl_dns_entry *remotehost,
1006                           curl_socket_t *sockconn,   /* the connected socket */
1007                           Curl_addrinfo **addr,      /* the one we used */
1008                           bool *connected)           /* really connected? */
1009 {
1010   struct SessionHandle *data = conn->data;
1011   curl_socket_t sockfd = CURL_SOCKET_BAD;
1012   int aliasindex;
1013   int num_addr;
1014   Curl_addrinfo *ai;
1015   Curl_addrinfo *curr_addr;
1016
1017   struct timeval after;
1018   struct timeval before = Curl_tvnow();
1019
1020   /*************************************************************
1021    * Figure out what maximum time we have left
1022    *************************************************************/
1023   long timeout_ms;
1024   long timeout_per_addr;
1025
1026   DEBUGASSERT(sockconn);
1027   *connected = FALSE; /* default to not connected */
1028
1029   /* get the timeout left */
1030   timeout_ms = Curl_timeleft(conn, &before, TRUE);
1031
1032   if(timeout_ms < 0) {
1033     /* a precaution, no need to continue if time already is up */
1034     failf(data, "Connection time-out");
1035     return CURLE_OPERATION_TIMEDOUT;
1036   }
1037
1038   /* Max time for each address */
1039   num_addr = Curl_num_addresses(remotehost->addr);
1040   timeout_per_addr = timeout_ms / num_addr;
1041
1042   ai = remotehost->addr;
1043
1044   /* Below is the loop that attempts to connect to all IP-addresses we
1045    * know for the given host. One by one until one IP succeeds.
1046    */
1047
1048   if(data->state.used_interface == Curl_if_multi)
1049     /* don't hang when doing multi */
1050     timeout_per_addr = 0;
1051
1052   /*
1053    * Connecting with a Curl_addrinfo chain
1054    */
1055   for (curr_addr = ai, aliasindex=0; curr_addr;
1056        curr_addr = curr_addr->ai_next, aliasindex++) {
1057
1058     /* start connecting to the IP curr_addr points to */
1059     CURLcode res =
1060       singleipconnect(conn, curr_addr, timeout_per_addr, &sockfd, connected);
1061
1062     if(res)
1063       return res;
1064
1065     if(sockfd != CURL_SOCKET_BAD)
1066       break;
1067
1068     /* get a new timeout for next attempt */
1069     after = Curl_tvnow();
1070     timeout_ms -= Curl_tvdiff(after, before);
1071     if(timeout_ms < 0) {
1072       failf(data, "connect() timed out!");
1073       return CURLE_OPERATION_TIMEDOUT;
1074     }
1075     before = after;
1076   }  /* end of connect-to-each-address loop */
1077
1078   *sockconn = sockfd;    /* the socket descriptor we've connected */
1079
1080   if(sockfd == CURL_SOCKET_BAD) {
1081     /* no good connect was made */
1082     failf(data, "couldn't connect to host");
1083     return CURLE_COULDNT_CONNECT;
1084   }
1085
1086   /* leave the socket in non-blocking mode */
1087
1088   /* store the address we use */
1089   if(addr)
1090     *addr = curr_addr;
1091
1092   data->info.numconnects++; /* to track the number of connections made */
1093
1094   return CURLE_OK;
1095 }
1096
1097 /*
1098  * Used to extract socket and connectdata struct for the most recent
1099  * transfer on the given SessionHandle.
1100  *
1101  * The returned socket will be CURL_SOCKET_BAD in case of failure!
1102  */
1103 curl_socket_t Curl_getconnectinfo(struct SessionHandle *data,
1104                                   struct connectdata **connp)
1105 {
1106   curl_socket_t sockfd;
1107   if((data->state.lastconnect != -1) &&
1108      (data->state.connc->connects[data->state.lastconnect] != NULL)) {
1109     struct connectdata *c =
1110       data->state.connc->connects[data->state.lastconnect];
1111     if(connp)
1112       /* only store this if the caller cares for it */
1113       *connp = c;
1114     sockfd = c->sock[FIRSTSOCKET];
1115     /* we have a socket connected, let's determine if the server shut down */
1116     /* determine if ssl */
1117     if(c->ssl[FIRSTSOCKET].use) {
1118       /* use the SSL context */
1119       if(!Curl_ssl_check_cxn(c))
1120         return CURL_SOCKET_BAD;   /* FIN received */
1121     }
1122 /* Minix 3.1 doesn't support any flags on recv; just assume socket is OK */
1123 #ifdef MSG_PEEK
1124     else {
1125       /* use the socket */
1126       char buf;
1127       if(recv((RECV_TYPE_ARG1)c->sock[FIRSTSOCKET], (RECV_TYPE_ARG2)&buf,
1128               (RECV_TYPE_ARG3)1, (RECV_TYPE_ARG4)MSG_PEEK) == 0) {
1129         return CURL_SOCKET_BAD;   /* FIN received */
1130       }
1131     }
1132 #endif
1133   }
1134   else
1135     return CURL_SOCKET_BAD;
1136
1137   return sockfd;
1138 }