1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
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 https://curl.haxx.se/docs/copyright.html.
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.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 ***************************************************************************/
23 #include "curl_setup.h"
25 #ifdef HAVE_NETINET_IN_H
26 #include <netinet/in.h>
31 #ifdef HAVE_ARPA_INET_H
32 #include <arpa/inet.h>
37 #ifdef HAVE_IPHLPAPI_H
40 #ifdef HAVE_SYS_IOCTL_H
41 #include <sys/ioctl.h>
43 #ifdef HAVE_SYS_PARAM_H
44 #include <sys/param.h>
57 #error "We can't compile without socket() support!"
65 #elif defined(USE_WIN32_IDN)
66 /* prototype for curl_win32_idn_to_ascii() */
67 bool curl_win32_idn_to_ascii(const char *in, char **out);
69 #elif defined(USE_ICU_IDNA)
70 #include <unicode/uidna.h>
71 #endif /* USE_LIBIDN2 */
78 #include "vtls/vtls.h"
89 #include "content_encoding.h"
90 #include "http_digest.h"
91 #include "http_negotiate.h"
95 #include "speedcheck.h"
97 #include "non-ascii.h"
98 #include "inet_pton.h"
100 #include "urlapi-int.h"
101 #include "system_win32.h"
103 /* And now for the protocols */
111 #include "curl_ldap.h"
112 #include "vssh/ssh.h"
116 #include "inet_ntop.h"
117 #include "http_ntlm.h"
118 #include "curl_rtmp.h"
120 #include "http_proxy.h"
121 #include "conncache.h"
122 #include "multihandle.h"
128 /* The last 3 #include files should be in this order */
129 #include "curl_printf.h"
130 #include "curl_memory.h"
131 #include "memdebug.h"
133 #if defined(USE_ICU_IDNA)
134 #define MAX_DOMAIN_NAME_LEN 256
135 #endif /* USE_ICU_IDNA */
137 static void conn_free(struct connectdata *conn);
138 static void free_idnconverted_hostname(struct hostname *host);
139 static unsigned int get_protocol_family(unsigned int protocol);
141 /* Some parts of the code (e.g. chunked encoding) assume this buffer has at
142 * more than just a few bytes to play with. Don't let it become too small or
143 * bad things will happen.
145 #if READBUFFER_SIZE < READBUFFER_MIN
146 # error READBUFFER_SIZE is too small
154 static const struct Curl_handler * const protocols[] = {
156 #ifndef CURL_DISABLE_HTTP
160 #if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP)
164 #ifndef CURL_DISABLE_FTP
168 #if defined(USE_SSL) && !defined(CURL_DISABLE_FTP)
172 #ifndef CURL_DISABLE_TELNET
173 &Curl_handler_telnet,
176 #ifndef CURL_DISABLE_DICT
180 #ifndef CURL_DISABLE_LDAP
182 #if !defined(CURL_DISABLE_LDAPS) && \
183 ((defined(USE_OPENLDAP) && defined(USE_SSL)) || \
184 (!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL)))
189 #ifndef CURL_DISABLE_FILE
193 #ifndef CURL_DISABLE_TFTP
205 #ifndef CURL_DISABLE_IMAP
212 #ifndef CURL_DISABLE_POP3
219 #if !defined(CURL_DISABLE_SMB) && defined(USE_NTLM) && \
220 (CURL_SIZEOF_CURL_OFF_T > 4) && \
221 (!defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO))
228 #ifndef CURL_DISABLE_SMTP
235 #ifndef CURL_DISABLE_RTSP
239 #ifndef CURL_DISABLE_GOPHER
240 &Curl_handler_gopher,
247 &Curl_handler_rtmpte,
249 &Curl_handler_rtmpts,
252 (struct Curl_handler *) NULL
256 * Dummy handler for undefined protocol schemes.
259 static const struct Curl_handler Curl_handler_dummy = {
260 "<no protocol>", /* scheme */
261 ZERO_NULL, /* setup_connection */
262 ZERO_NULL, /* do_it */
263 ZERO_NULL, /* done */
264 ZERO_NULL, /* do_more */
265 ZERO_NULL, /* connect_it */
266 ZERO_NULL, /* connecting */
267 ZERO_NULL, /* doing */
268 ZERO_NULL, /* proto_getsock */
269 ZERO_NULL, /* doing_getsock */
270 ZERO_NULL, /* domore_getsock */
271 ZERO_NULL, /* perform_getsock */
272 ZERO_NULL, /* disconnect */
273 ZERO_NULL, /* readwrite */
274 ZERO_NULL, /* connection_check */
277 PROTOPT_NONE /* flags */
280 void Curl_freeset(struct Curl_easy *data)
282 /* Free all dynamic strings stored in the data->set substructure. */
284 for(i = (enum dupstring)0; i < STRING_LAST; i++) {
285 Curl_safefree(data->set.str[i]);
288 if(data->change.referer_alloc) {
289 Curl_safefree(data->change.referer);
290 data->change.referer_alloc = FALSE;
292 data->change.referer = NULL;
293 if(data->change.url_alloc) {
294 Curl_safefree(data->change.url);
295 data->change.url_alloc = FALSE;
297 data->change.url = NULL;
299 Curl_mime_cleanpart(&data->set.mimepost);
302 /* free the URL pieces */
303 static void up_free(struct Curl_easy *data)
305 struct urlpieces *up = &data->state.up;
306 Curl_safefree(up->scheme);
307 Curl_safefree(up->hostname);
308 Curl_safefree(up->port);
309 Curl_safefree(up->user);
310 Curl_safefree(up->password);
311 Curl_safefree(up->options);
312 Curl_safefree(up->path);
313 Curl_safefree(up->query);
314 curl_url_cleanup(data->state.uh);
315 data->state.uh = NULL;
319 * This is the internal function curl_easy_cleanup() calls. This should
320 * cleanup and free all resources associated with this sessionhandle.
322 * NOTE: if we ever add something that attempts to write to a socket or
323 * similar here, we must ignore SIGPIPE first. It is currently only done
324 * when curl_easy_perform() is invoked.
327 CURLcode Curl_close(struct Curl_easy **datap)
329 struct Curl_multi *m;
330 struct Curl_easy *data;
332 if(!datap || !*datap)
338 Curl_expire_clear(data); /* shut off timers */
342 /* This handle is still part of a multi handle, take care of this first
343 and detach this handle from there. */
344 curl_multi_remove_handle(data->multi, data);
346 if(data->multi_easy) {
347 /* when curl_easy_perform() is used, it creates its own multi handle to
348 use and this is the one */
349 curl_multi_cleanup(data->multi_easy);
350 data->multi_easy = NULL;
353 /* Destroy the timeout list that is held in the easy handle. It is
354 /normally/ done by curl_multi_remove_handle() but this is "just in
356 Curl_llist_destroy(&data->state.timeoutlist, NULL);
358 data->magic = 0; /* force a clear AFTER the possibly enforced removal from
359 the multi handle, since that function uses the magic
362 if(data->state.rangestringalloc)
363 free(data->state.range);
365 /* freed here just in case DONE wasn't called */
366 Curl_free_request_state(data);
368 /* Close down all open SSL info and sessions */
369 Curl_ssl_close_all(data);
370 Curl_safefree(data->state.first_host);
371 Curl_safefree(data->state.scratch);
372 Curl_ssl_free_certinfo(data);
374 /* Cleanup possible redirect junk */
375 free(data->req.newurl);
376 data->req.newurl = NULL;
378 if(data->change.referer_alloc) {
379 Curl_safefree(data->change.referer);
380 data->change.referer_alloc = FALSE;
382 data->change.referer = NULL;
385 Curl_safefree(data->state.buffer);
386 Curl_safefree(data->state.headerbuff);
387 Curl_safefree(data->state.ulbuf);
388 Curl_flush_cookies(data, TRUE);
390 Curl_altsvc_save(data->asi, data->set.str[STRING_ALTSVC]);
391 Curl_altsvc_cleanup(data->asi);
394 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH)
395 Curl_http_auth_cleanup_digest(data);
397 Curl_safefree(data->info.contenttype);
398 Curl_safefree(data->info.wouldredirect);
400 /* this destroys the channel and we cannot use it anymore after this */
401 Curl_resolver_cleanup(data->state.resolver);
403 Curl_http2_cleanup_dependencies(data);
404 Curl_convert_close(data);
406 /* No longer a dirty share, if it exists */
408 Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
409 data->share->dirty--;
410 Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
413 #ifndef CURL_DISABLE_DOH
414 free(data->req.doh.probe[0].serverdoh.memory);
415 free(data->req.doh.probe[1].serverdoh.memory);
416 curl_slist_free_all(data->req.doh.headers);
419 /* destruct wildcard structures if it is needed */
420 Curl_wildcard_dtor(&data->wildcard);
427 * Initialize the UserDefined fields within a Curl_easy.
428 * This may be safely called on a new or existing Curl_easy.
430 CURLcode Curl_init_userdefined(struct Curl_easy *data)
432 struct UserDefined *set = &data->set;
433 CURLcode result = CURLE_OK;
435 set->out = stdout; /* default output to stdout */
436 set->in_set = stdin; /* default input from stdin */
437 set->err = stderr; /* default stderr to stderr */
439 /* use fwrite as default function to store output */
440 set->fwrite_func = (curl_write_callback)fwrite;
442 /* use fread as default function to read input */
443 set->fread_func_set = (curl_read_callback)fread;
444 set->is_fread_set = 0;
445 set->is_fwrite_set = 0;
447 set->seek_func = ZERO_NULL;
448 set->seek_client = ZERO_NULL;
450 /* conversion callbacks for non-ASCII hosts */
451 set->convfromnetwork = ZERO_NULL;
452 set->convtonetwork = ZERO_NULL;
453 set->convfromutf8 = ZERO_NULL;
455 set->filesize = -1; /* we don't know the size */
456 set->postfieldsize = -1; /* unknown size */
457 set->maxredirs = -1; /* allow any amount by default */
459 set->httpreq = HTTPREQ_GET; /* Default HTTP request */
460 set->rtspreq = RTSPREQ_OPTIONS; /* Default RTSP request */
461 #ifndef CURL_DISABLE_FTP
462 set->ftp_use_epsv = TRUE; /* FTP defaults to EPSV operations */
463 set->ftp_use_eprt = TRUE; /* FTP defaults to EPRT operations */
464 set->ftp_use_pret = FALSE; /* mainly useful for drftpd servers */
465 set->ftp_filemethod = FTPFILE_MULTICWD;
467 set->dns_cache_timeout = 60; /* Timeout every 60 seconds by default */
469 /* Set the default size of the SSL session ID cache */
470 set->general_ssl.max_ssl_sessions = 5;
473 set->proxytype = CURLPROXY_HTTP; /* defaults to HTTP proxy */
474 set->httpauth = CURLAUTH_BASIC; /* defaults to basic */
475 set->proxyauth = CURLAUTH_BASIC; /* defaults to basic */
477 /* SOCKS5 proxy auth defaults to username/password + GSS-API */
478 set->socks5auth = CURLAUTH_BASIC | CURLAUTH_GSSAPI;
480 /* make libcurl quiet by default: */
481 set->hide_progress = TRUE; /* CURLOPT_NOPROGRESS changes these */
483 Curl_mime_initpart(&set->mimepost, data);
486 * libcurl 7.10 introduced SSL verification *by default*! This needs to be
487 * switched off unless wanted.
489 set->ssl.primary.verifypeer = TRUE;
490 set->ssl.primary.verifyhost = TRUE;
492 set->ssl.authtype = CURL_TLSAUTH_NONE;
494 set->ssh_auth_types = CURLSSH_AUTH_DEFAULT; /* defaults to any auth
496 set->ssl.primary.sessionid = TRUE; /* session ID caching enabled by
498 set->proxy_ssl = set->ssl;
500 set->new_file_perms = 0644; /* Default permissions */
501 set->new_directory_perms = 0755; /* Default permissions */
503 /* for the *protocols fields we don't use the CURLPROTO_ALL convenience
504 define since we internally only use the lower 16 bits for the passed
505 in bitmask to not conflict with the private bits */
506 set->allowed_protocols = CURLPROTO_ALL;
507 set->redir_protocols = CURLPROTO_HTTP | CURLPROTO_HTTPS | CURLPROTO_FTP |
510 #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
512 * disallow unprotected protection negotiation NEC reference implementation
513 * seem not to follow rfc1961 section 4.3/4.4
515 set->socks5_gssapi_nec = FALSE;
518 /* Set the default CA cert bundle/path detected/specified at build time.
520 * If Schannel is the selected SSL backend then these locations are
521 * ignored. We allow setting CA location for schannel only when explicitly
522 * specified by the user via CURLOPT_CAINFO / --cacert.
524 if(Curl_ssl_backend() != CURLSSLBACKEND_SCHANNEL) {
525 #if defined(CURL_CA_BUNDLE)
526 result = Curl_setstropt(&set->str[STRING_SSL_CAFILE_ORIG], CURL_CA_BUNDLE);
530 result = Curl_setstropt(&set->str[STRING_SSL_CAFILE_PROXY],
535 #if defined(CURL_CA_PATH)
536 result = Curl_setstropt(&set->str[STRING_SSL_CAPATH_ORIG], CURL_CA_PATH);
540 result = Curl_setstropt(&set->str[STRING_SSL_CAPATH_PROXY], CURL_CA_PATH);
546 set->wildcard_enabled = FALSE;
547 set->chunk_bgn = ZERO_NULL;
548 set->chunk_end = ZERO_NULL;
549 set->tcp_keepalive = FALSE;
550 set->tcp_keepintvl = 60;
551 set->tcp_keepidle = 60;
552 set->tcp_fastopen = FALSE;
553 set->tcp_nodelay = TRUE;
554 set->ssl_enable_npn = TRUE;
555 set->ssl_enable_alpn = TRUE;
556 set->expect_100_timeout = 1000L; /* Wait for a second by default. */
557 set->sep_headers = TRUE; /* separated header lists by default */
558 set->buffer_size = READBUFFER_SIZE;
559 set->upload_buffer_size = UPLOADBUFFER_DEFAULT;
560 set->happy_eyeballs_timeout = CURL_HET_DEFAULT;
561 set->fnmatch = ZERO_NULL;
562 set->upkeep_interval_ms = CURL_UPKEEP_INTERVAL_DEFAULT;
563 set->maxconnects = DEFAULT_CONNCACHE_SIZE; /* for easy handles */
564 set->maxage_conn = 118;
565 set->http09_allowed = FALSE;
568 CURL_HTTP_VERSION_2TLS
570 CURL_HTTP_VERSION_1_1
573 Curl_http2_init_userset(set);
580 * @param curl is a pointer to a sessionhandle pointer that gets set by this
585 CURLcode Curl_open(struct Curl_easy **curl)
588 struct Curl_easy *data;
590 /* Very simple start-up: alloc the struct, init it with zeroes and return */
591 data = calloc(1, sizeof(struct Curl_easy));
593 /* this is a very serious error */
594 DEBUGF(fprintf(stderr, "Error: calloc of Curl_easy failed\n"));
595 return CURLE_OUT_OF_MEMORY;
598 data->magic = CURLEASY_MAGIC_NUMBER;
600 result = Curl_resolver_init(data, &data->state.resolver);
602 DEBUGF(fprintf(stderr, "Error: resolver_init failed\n"));
607 /* We do some initial setup here, all those fields that can't be just 0 */
609 data->state.buffer = malloc(READBUFFER_SIZE + 1);
610 if(!data->state.buffer) {
611 DEBUGF(fprintf(stderr, "Error: malloc of buffer failed\n"));
612 result = CURLE_OUT_OF_MEMORY;
615 data->state.headerbuff = malloc(HEADERSIZE);
616 if(!data->state.headerbuff) {
617 DEBUGF(fprintf(stderr, "Error: malloc of headerbuff failed\n"));
618 result = CURLE_OUT_OF_MEMORY;
621 result = Curl_init_userdefined(data);
623 data->state.headersize = HEADERSIZE;
624 Curl_convert_init(data);
627 /* most recent connection is not yet defined */
628 data->state.lastconnect = NULL;
630 data->progress.flags |= PGRS_HIDE;
631 data->state.current_speed = -1; /* init to negative == impossible */
636 Curl_resolver_cleanup(data->state.resolver);
637 free(data->state.buffer);
638 free(data->state.headerbuff);
649 #ifdef USE_RECV_BEFORE_SEND_WORKAROUND
650 static void conn_reset_postponed_data(struct connectdata *conn, int num)
652 struct postponed_data * const psnd = &(conn->postponed[num]);
654 DEBUGASSERT(psnd->allocated_size > 0);
655 DEBUGASSERT(psnd->recv_size <= psnd->allocated_size);
656 DEBUGASSERT(psnd->recv_size ?
657 (psnd->recv_processed < psnd->recv_size) :
658 (psnd->recv_processed == 0));
659 DEBUGASSERT(psnd->bindsock != CURL_SOCKET_BAD);
662 psnd->allocated_size = 0;
664 psnd->recv_processed = 0;
666 psnd->bindsock = CURL_SOCKET_BAD; /* used only for DEBUGASSERT */
667 #endif /* DEBUGBUILD */
670 DEBUGASSERT(psnd->allocated_size == 0);
671 DEBUGASSERT(psnd->recv_size == 0);
672 DEBUGASSERT(psnd->recv_processed == 0);
673 DEBUGASSERT(psnd->bindsock == CURL_SOCKET_BAD);
677 static void conn_reset_all_postponed_data(struct connectdata *conn)
679 conn_reset_postponed_data(conn, 0);
680 conn_reset_postponed_data(conn, 1);
682 #else /* ! USE_RECV_BEFORE_SEND_WORKAROUND */
683 /* Use "do-nothing" macro instead of function when workaround not used */
684 #define conn_reset_all_postponed_data(c) do {} while(0)
685 #endif /* ! USE_RECV_BEFORE_SEND_WORKAROUND */
688 static void conn_shutdown(struct connectdata *conn)
693 infof(conn->data, "Closing connection %ld\n", conn->connection_id);
694 DEBUGASSERT(conn->data);
696 /* possible left-overs from the async name resolvers */
697 Curl_resolver_cancel(conn);
699 /* close the SSL stuff before we close any sockets since they will/may
700 write to the sockets */
701 Curl_ssl_close(conn, FIRSTSOCKET);
702 Curl_ssl_close(conn, SECONDARYSOCKET);
704 /* close possibly still open sockets */
705 if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET])
706 Curl_closesocket(conn, conn->sock[SECONDARYSOCKET]);
707 if(CURL_SOCKET_BAD != conn->sock[FIRSTSOCKET])
708 Curl_closesocket(conn, conn->sock[FIRSTSOCKET]);
709 if(CURL_SOCKET_BAD != conn->tempsock[0])
710 Curl_closesocket(conn, conn->tempsock[0]);
711 if(CURL_SOCKET_BAD != conn->tempsock[1])
712 Curl_closesocket(conn, conn->tempsock[1]);
714 /* unlink ourselves. this should be called last since other shutdown
715 procedures need a valid conn->data and this may clear it. */
716 Curl_conncache_remove_conn(conn->data, conn, TRUE);
719 static void conn_free(struct connectdata *conn)
724 free_idnconverted_hostname(&conn->host);
725 free_idnconverted_hostname(&conn->conn_to_host);
726 free_idnconverted_hostname(&conn->http_proxy.host);
727 free_idnconverted_hostname(&conn->socks_proxy.host);
729 Curl_safefree(conn->user);
730 Curl_safefree(conn->passwd);
731 Curl_safefree(conn->oauth_bearer);
732 Curl_safefree(conn->sasl_authzid);
733 Curl_safefree(conn->options);
734 Curl_safefree(conn->http_proxy.user);
735 Curl_safefree(conn->socks_proxy.user);
736 Curl_safefree(conn->http_proxy.passwd);
737 Curl_safefree(conn->socks_proxy.passwd);
738 Curl_safefree(conn->allocptr.proxyuserpwd);
739 Curl_safefree(conn->allocptr.uagent);
740 Curl_safefree(conn->allocptr.userpwd);
741 Curl_safefree(conn->allocptr.accept_encoding);
742 Curl_safefree(conn->allocptr.te);
743 Curl_safefree(conn->allocptr.rangeline);
744 Curl_safefree(conn->allocptr.ref);
745 Curl_safefree(conn->allocptr.host);
746 Curl_safefree(conn->allocptr.cookiehost);
747 Curl_safefree(conn->allocptr.rtsp_transport);
748 Curl_safefree(conn->trailer);
749 Curl_safefree(conn->host.rawalloc); /* host name buffer */
750 Curl_safefree(conn->conn_to_host.rawalloc); /* host name buffer */
751 Curl_safefree(conn->hostname_resolve);
752 Curl_safefree(conn->secondaryhostname);
753 Curl_safefree(conn->http_proxy.host.rawalloc); /* http proxy name buffer */
754 Curl_safefree(conn->socks_proxy.host.rawalloc); /* socks proxy name buffer */
755 Curl_safefree(conn->connect_state);
757 conn_reset_all_postponed_data(conn);
758 Curl_llist_destroy(&conn->easyq, NULL);
759 Curl_safefree(conn->localdev);
760 Curl_free_primary_ssl_config(&conn->ssl_config);
761 Curl_free_primary_ssl_config(&conn->proxy_ssl_config);
763 #ifdef USE_UNIX_SOCKETS
764 Curl_safefree(conn->unix_domain_socket);
768 Curl_safefree(conn->ssl_extra);
770 free(conn); /* free all the connection oriented data */
774 * Disconnects the given connection. Note the connection may not be the
775 * primary connection, like when freeing room in the connection cache or
776 * killing of a dead old connection.
778 * A connection needs an easy handle when closing down. We support this passed
779 * in separately since the connection to get closed here is often already
780 * disassociated from an easy handle.
782 * This function MUST NOT reset state in the Curl_easy struct if that
783 * isn't strictly bound to the life-time of *this* particular connection.
787 CURLcode Curl_disconnect(struct Curl_easy *data,
788 struct connectdata *conn, bool dead_connection)
791 return CURLE_OK; /* this is closed and fine already */
794 DEBUGF(infof(data, "DISCONNECT without easy handle, ignoring\n"));
799 * If this connection isn't marked to force-close, leave it open if there
800 * are other users of it
802 if(CONN_INUSE(conn) && !dead_connection) {
803 DEBUGF(infof(data, "Curl_disconnect when inuse: %zu\n", CONN_INUSE(conn)));
807 if(conn->dns_entry != NULL) {
808 Curl_resolv_unlock(data, conn->dns_entry);
809 conn->dns_entry = NULL;
812 Curl_hostcache_prune(data); /* kill old DNS cache entries */
814 #if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM)
815 /* Cleanup NTLM connection-related data */
816 Curl_http_auth_cleanup_ntlm(conn);
818 #if !defined(CURL_DISABLE_HTTP) && defined(USE_SPNEGO)
819 /* Cleanup NEGOTIATE connection-related data */
820 Curl_http_auth_cleanup_negotiate(conn);
823 /* the protocol specific disconnect handler and conn_shutdown need a transfer
824 for the connection! */
827 if(conn->bits.connect_only)
828 /* treat the connection as dead in CONNECT_ONLY situations */
829 dead_connection = TRUE;
831 if(conn->handler->disconnect)
832 /* This is set if protocol-specific cleanups should be made */
833 conn->handler->disconnect(conn, dead_connection);
841 * This function should return TRUE if the socket is to be assumed to
842 * be dead. Most commonly this happens when the server has closed the
843 * connection due to inactivity.
845 static bool SocketIsDead(curl_socket_t sock)
850 sval = SOCKET_READABLE(sock, 0);
859 * IsMultiplexingPossible()
861 * Return a bitmask with the available multiplexing options for the given
862 * requested connection.
864 static int IsMultiplexingPossible(const struct Curl_easy *handle,
865 const struct connectdata *conn)
869 /* If a HTTP protocol and multiplexing is enabled */
870 if((conn->handler->protocol & PROTO_FAMILY_HTTP) &&
871 (!conn->bits.protoconnstart || !conn->bits.close)) {
873 if(Curl_multiplex_wanted(handle->multi) &&
874 (handle->set.httpversion >= CURL_HTTP_VERSION_2))
876 avail |= CURLPIPE_MULTIPLEX;
881 #ifndef CURL_DISABLE_PROXY
883 proxy_info_matches(const struct proxy_info* data,
884 const struct proxy_info* needle)
886 if((data->proxytype == needle->proxytype) &&
887 (data->port == needle->port) &&
888 Curl_safe_strcasecompare(data->host.name, needle->host.name))
894 /* disabled, won't get called */
895 #define proxy_info_matches(x,y) FALSE
898 /* A connection has to have been idle for a shorter time than 'maxage_conn' to
899 be subject for reuse. The success rate is just too low after this. */
901 static bool conn_maxage(struct Curl_easy *data,
902 struct connectdata *conn,
906 timediff_t idletime = Curl_timediff(now, conn->lastused);
907 idletime /= 1000; /* integer seconds is fine */
909 if(idletime > data->set.maxage_conn) {
910 infof(data, "Too old connection (%ld seconds), disconnect it\n",
919 * This function checks if the given connection is dead and extracts it from
920 * the connection cache if so.
922 * When this is called as a Curl_conncache_foreach() callback, the connection
923 * cache lock is held!
925 * Returns TRUE if the connection was dead and extracted.
927 static bool extract_if_dead(struct connectdata *conn,
928 struct Curl_easy *data)
930 if(!CONN_INUSE(conn) && !conn->data) {
931 /* The check for a dead socket makes sense only if the connection isn't in
934 struct curltime now = Curl_now();
935 if(conn_maxage(data, conn, now)) {
938 else if(conn->handler->connection_check) {
939 /* The protocol has a special method for checking the state of the
940 connection. Use it to check if the connection is dead. */
942 struct Curl_easy *olddata = conn->data;
943 conn->data = data; /* use this transfer for now */
944 state = conn->handler->connection_check(conn, CONNCHECK_ISDEAD);
945 conn->data = olddata;
946 dead = (state & CONNRESULT_DEAD);
949 /* Use the general method for determining the death of a connection */
950 dead = SocketIsDead(conn->sock[FIRSTSOCKET]);
954 infof(data, "Connection %ld seems to be dead!\n", conn->connection_id);
955 Curl_conncache_remove_conn(data, conn, FALSE);
963 struct Curl_easy *data;
964 struct connectdata *extracted;
968 * Wrapper to use extract_if_dead() function in Curl_conncache_foreach()
971 static int call_extract_if_dead(struct connectdata *conn, void *param)
973 struct prunedead *p = (struct prunedead *)param;
974 if(extract_if_dead(conn, p->data)) {
975 /* stop the iteration here, pass back the connection that was extracted */
979 return 0; /* continue iteration */
983 * This function scans the connection cache for half-open/dead connections,
984 * closes and removes them.
985 * The cleanup is done at most once per second.
987 static void prune_dead_connections(struct Curl_easy *data)
989 struct curltime now = Curl_now();
991 Curl_timediff(now, data->state.conn_cache->last_cleanup);
993 if(elapsed >= 1000L) {
994 struct prunedead prune;
996 prune.extracted = NULL;
997 while(Curl_conncache_foreach(data, data->state.conn_cache, &prune,
998 call_extract_if_dead)) {
1000 (void)Curl_disconnect(data, prune.extracted, /* dead_connection */TRUE);
1002 data->state.conn_cache->last_cleanup = now;
1007 * Given one filled in connection struct (named needle), this function should
1008 * detect if there already is one that has all the significant details
1009 * exactly the same and thus should be used instead.
1011 * If there is a match, this function returns TRUE - and has marked the
1012 * connection as 'in-use'. It must later be called with ConnectionDone() to
1013 * return back to 'idle' (unused) state.
1015 * The force_reuse flag is set if the connection must be used.
1018 ConnectionExists(struct Curl_easy *data,
1019 struct connectdata *needle,
1020 struct connectdata **usethis,
1024 struct connectdata *check;
1025 struct connectdata *chosen = 0;
1026 bool foundPendingCandidate = FALSE;
1027 bool canmultiplex = IsMultiplexingPossible(data, needle);
1028 struct connectbundle *bundle;
1029 const char *hostbundle;
1032 bool wantNTLMhttp = ((data->state.authhost.want &
1033 (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) &&
1034 (needle->handler->protocol & PROTO_FAMILY_HTTP));
1035 bool wantProxyNTLMhttp = (needle->bits.proxy_user_passwd &&
1036 ((data->state.authproxy.want &
1037 (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) &&
1038 (needle->handler->protocol & PROTO_FAMILY_HTTP)));
1041 *force_reuse = FALSE;
1044 /* Look up the bundle with all the connections to this particular host.
1045 Locks the connection cache, beware of early returns! */
1046 bundle = Curl_conncache_find_bundle(needle, data->state.conn_cache,
1049 /* Max pipe length is zero (unlimited) for multiplexed connections */
1050 struct curl_llist_element *curr;
1052 infof(data, "Found bundle for host %s: %p [%s]\n",
1053 hostbundle, (void *)bundle, (bundle->multiuse == BUNDLE_MULTIPLEX ?
1054 "can multiplex" : "serially"));
1056 /* We can't multiplex if we don't know anything about the server */
1058 if(bundle->multiuse == BUNDLE_UNKNOWN) {
1059 if(data->set.pipewait) {
1060 infof(data, "Server doesn't support multiplex yet, wait\n");
1062 Curl_conncache_unlock(data);
1063 return FALSE; /* no re-use */
1066 infof(data, "Server doesn't support multiplex (yet)\n");
1067 canmultiplex = FALSE;
1069 if((bundle->multiuse == BUNDLE_MULTIPLEX) &&
1070 !Curl_multiplex_wanted(data->multi)) {
1071 infof(data, "Could multiplex, but not asked to!\n");
1072 canmultiplex = FALSE;
1074 if(bundle->multiuse == BUNDLE_NO_MULTIUSE) {
1075 infof(data, "Can not multiplex, even if we wanted to!\n");
1076 canmultiplex = FALSE;
1080 curr = bundle->conn_list.head;
1086 * Note that if we use a HTTP proxy in normal mode (no tunneling), we
1087 * check connections to that proxy and not to the actual remote server.
1092 if(check->bits.connect_only || check->bits.close)
1093 /* connect-only or to-be-closed connections will not be reused */
1096 multiplexed = CONN_INUSE(check) &&
1097 (bundle->multiuse == BUNDLE_MULTIPLEX);
1104 /* can only happen within multi handles, and means that another easy
1105 handle is using this connection */
1109 if(Curl_resolver_asynch()) {
1110 /* ip_addr_str[0] is NUL only if the resolving of the name hasn't
1111 completed yet and until then we don't re-use this connection */
1112 if(!check->ip_addr_str[0]) {
1114 "Connection #%ld is still name resolving, can't reuse\n",
1115 check->connection_id);
1120 if(check->sock[FIRSTSOCKET] == CURL_SOCKET_BAD) {
1121 foundPendingCandidate = TRUE;
1122 /* Don't pick a connection that hasn't connected yet */
1123 infof(data, "Connection #%ld isn't open enough, can't reuse\n",
1124 check->connection_id);
1129 #ifdef USE_UNIX_SOCKETS
1130 if(needle->unix_domain_socket) {
1131 if(!check->unix_domain_socket)
1133 if(strcmp(needle->unix_domain_socket, check->unix_domain_socket))
1135 if(needle->abstract_unix_socket != check->abstract_unix_socket)
1138 else if(check->unix_domain_socket)
1142 if((needle->handler->flags&PROTOPT_SSL) !=
1143 (check->handler->flags&PROTOPT_SSL))
1144 /* don't do mixed SSL and non-SSL connections */
1145 if(get_protocol_family(check->handler->protocol) !=
1146 needle->handler->protocol || !check->tls_upgraded)
1147 /* except protocols that have been upgraded via TLS */
1150 if(needle->bits.httpproxy != check->bits.httpproxy ||
1151 needle->bits.socksproxy != check->bits.socksproxy)
1154 if(needle->bits.socksproxy && !proxy_info_matches(&needle->socks_proxy,
1155 &check->socks_proxy))
1158 if(needle->bits.conn_to_host != check->bits.conn_to_host)
1159 /* don't mix connections that use the "connect to host" feature and
1160 * connections that don't use this feature */
1163 if(needle->bits.conn_to_port != check->bits.conn_to_port)
1164 /* don't mix connections that use the "connect to port" feature and
1165 * connections that don't use this feature */
1168 if(needle->bits.httpproxy) {
1169 if(!proxy_info_matches(&needle->http_proxy, &check->http_proxy))
1172 if(needle->bits.tunnel_proxy != check->bits.tunnel_proxy)
1175 if(needle->http_proxy.proxytype == CURLPROXY_HTTPS) {
1176 /* use https proxy */
1177 if(needle->handler->flags&PROTOPT_SSL) {
1178 /* use double layer ssl */
1179 if(!Curl_ssl_config_matches(&needle->proxy_ssl_config,
1180 &check->proxy_ssl_config))
1182 if(check->proxy_ssl[FIRSTSOCKET].state != ssl_connection_complete)
1186 if(!Curl_ssl_config_matches(&needle->ssl_config,
1187 &check->ssl_config))
1189 if(check->ssl[FIRSTSOCKET].state != ssl_connection_complete)
1195 DEBUGASSERT(!check->data || GOOD_EASY_HANDLE(check->data));
1197 if(!canmultiplex && check->data)
1198 /* this request can't be multiplexed but the checked connection is
1199 already in use so we skip it */
1202 if(check->data && (check->data->multi != needle->data->multi))
1203 /* this could be subject for multiplex use, but only if they belong to
1204 * the same multi handle */
1207 if(needle->localdev || needle->localport) {
1208 /* If we are bound to a specific local end (IP+port), we must not
1209 re-use a random other one, although if we didn't ask for a
1210 particular one we can reuse one that was bound.
1212 This comparison is a bit rough and too strict. Since the input
1213 parameters can be specified in numerous ways and still end up the
1214 same it would take a lot of processing to make it really accurate.
1215 Instead, this matching will assume that re-uses of bound connections
1216 will most likely also re-use the exact same binding parameters and
1217 missing out a few edge cases shouldn't hurt anyone very much.
1219 if((check->localport != needle->localport) ||
1220 (check->localportrange != needle->localportrange) ||
1221 (needle->localdev &&
1222 (!check->localdev || strcmp(check->localdev, needle->localdev))))
1226 if(!(needle->handler->flags & PROTOPT_CREDSPERREQUEST)) {
1227 /* This protocol requires credentials per connection,
1228 so verify that we're using the same name and password as well */
1229 if(strcmp(needle->user, check->user) ||
1230 strcmp(needle->passwd, check->passwd)) {
1231 /* one of them was different */
1236 if(!needle->bits.httpproxy || (needle->handler->flags&PROTOPT_SSL) ||
1237 needle->bits.tunnel_proxy) {
1238 /* The requested connection does not use a HTTP proxy or it uses SSL or
1239 it is a non-SSL protocol tunneled or it is a non-SSL protocol which
1240 is allowed to be upgraded via TLS */
1242 if((strcasecompare(needle->handler->scheme, check->handler->scheme) ||
1243 (get_protocol_family(check->handler->protocol) ==
1244 needle->handler->protocol && check->tls_upgraded)) &&
1245 (!needle->bits.conn_to_host || strcasecompare(
1246 needle->conn_to_host.name, check->conn_to_host.name)) &&
1247 (!needle->bits.conn_to_port ||
1248 needle->conn_to_port == check->conn_to_port) &&
1249 strcasecompare(needle->host.name, check->host.name) &&
1250 needle->remote_port == check->remote_port) {
1251 /* The schemes match or the the protocol family is the same and the
1252 previous connection was TLS upgraded, and the hostname and host
1254 if(needle->handler->flags & PROTOPT_SSL) {
1255 /* This is a SSL connection so verify that we're using the same
1256 SSL options as well */
1257 if(!Curl_ssl_config_matches(&needle->ssl_config,
1258 &check->ssl_config)) {
1260 "Connection #%ld has different SSL parameters, "
1262 check->connection_id));
1265 if(check->ssl[FIRSTSOCKET].state != ssl_connection_complete) {
1266 foundPendingCandidate = TRUE;
1268 "Connection #%ld has not started SSL connect, "
1270 check->connection_id));
1278 /* The requested connection is using the same HTTP proxy in normal
1279 mode (no tunneling) */
1284 #if defined(USE_NTLM)
1285 /* If we are looking for an HTTP+NTLM connection, check if this is
1286 already authenticating with the right credentials. If not, keep
1287 looking so that we can reuse NTLM connections if
1288 possible. (Especially we must not reuse the same connection if
1289 partway through a handshake!) */
1291 if(strcmp(needle->user, check->user) ||
1292 strcmp(needle->passwd, check->passwd)) {
1294 /* we prefer a credential match, but this is at least a connection
1295 that can be reused and "upgraded" to NTLM */
1296 if(check->http_ntlm_state == NTLMSTATE_NONE)
1301 else if(check->http_ntlm_state != NTLMSTATE_NONE) {
1302 /* Connection is using NTLM auth but we don't want NTLM */
1306 /* Same for Proxy NTLM authentication */
1307 if(wantProxyNTLMhttp) {
1308 /* Both check->http_proxy.user and check->http_proxy.passwd can be
1310 if(!check->http_proxy.user || !check->http_proxy.passwd)
1313 if(strcmp(needle->http_proxy.user, check->http_proxy.user) ||
1314 strcmp(needle->http_proxy.passwd, check->http_proxy.passwd))
1317 else if(check->proxy_ntlm_state != NTLMSTATE_NONE) {
1318 /* Proxy connection is using NTLM auth but we don't want NTLM */
1322 if(wantNTLMhttp || wantProxyNTLMhttp) {
1323 /* Credentials are already checked, we can use this connection */
1327 (check->http_ntlm_state != NTLMSTATE_NONE)) ||
1328 (wantProxyNTLMhttp &&
1329 (check->proxy_ntlm_state != NTLMSTATE_NONE))) {
1330 /* We must use this connection, no other */
1331 *force_reuse = TRUE;
1335 /* Continue look up for a better connection */
1340 /* We can multiplex if we want to. Let's continue looking for
1341 the optimal connection to use. */
1344 /* We have the optimal connection. Let's stop looking. */
1350 /* If multiplexed, make sure we don't go over concurrency limit */
1351 if(check->bits.multiplex) {
1352 /* Multiplexed connections can only be HTTP/2 for now */
1353 struct http_conn *httpc = &check->proto.httpc;
1354 if(multiplexed >= httpc->settings.max_concurrent_streams) {
1355 infof(data, "MAX_CONCURRENT_STREAMS reached, skip (%zu)\n",
1361 /* When not multiplexed, we have a match here! */
1363 infof(data, "Multiplexed connection found!\n");
1367 /* We have found a connection. Let's stop searching. */
1376 /* mark it as used before releasing the lock */
1377 chosen->data = data; /* own it! */
1378 Curl_conncache_unlock(data);
1380 return TRUE; /* yes, we found one to use! */
1382 Curl_conncache_unlock(data);
1384 if(foundPendingCandidate && data->set.pipewait) {
1386 "Found pending candidate for reuse and CURLOPT_PIPEWAIT is set\n");
1390 return FALSE; /* no matching connecting exists */
1394 * verboseconnect() displays verbose information after a connect
1396 #ifndef CURL_DISABLE_VERBOSE_STRINGS
1397 void Curl_verboseconnect(struct connectdata *conn)
1399 if(conn->data->set.verbose)
1400 infof(conn->data, "Connected to %s (%s) port %ld (#%ld)\n",
1401 conn->bits.socksproxy ? conn->socks_proxy.host.dispname :
1402 conn->bits.httpproxy ? conn->http_proxy.host.dispname :
1403 conn->bits.conn_to_host ? conn->conn_to_host.dispname :
1404 conn->host.dispname,
1405 conn->ip_addr_str, conn->port, conn->connection_id);
1410 * Helpers for IDNA conversions.
1412 static bool is_ASCII_name(const char *hostname)
1414 const unsigned char *ch = (const unsigned char *)hostname;
1424 * Strip single trailing dot in the hostname,
1425 * primarily for SNI and http host header.
1427 static void strip_trailing_dot(struct hostname *host)
1430 if(!host || !host->name)
1432 len = strlen(host->name);
1433 if(len && (host->name[len-1] == '.'))
1434 host->name[len-1] = 0;
1438 * Perform any necessary IDN conversion of hostname
1440 static CURLcode idnconvert_hostname(struct connectdata *conn,
1441 struct hostname *host)
1443 struct Curl_easy *data = conn->data;
1448 #elif defined(CURL_DISABLE_VERBOSE_STRINGS)
1452 /* set the name we use to display the host name */
1453 host->dispname = host->name;
1455 /* Check name for non-ASCII and convert hostname to ACE form if we can */
1456 if(!is_ASCII_name(host->name)) {
1458 if(idn2_check_version(IDN2_VERSION)) {
1459 char *ace_hostname = NULL;
1460 #if IDN2_VERSION_NUMBER >= 0x00140000
1461 /* IDN2_NFC_INPUT: Normalize input string using normalization form C.
1462 IDN2_NONTRANSITIONAL: Perform Unicode TR46 non-transitional
1464 int flags = IDN2_NFC_INPUT | IDN2_NONTRANSITIONAL;
1466 int flags = IDN2_NFC_INPUT;
1468 int rc = idn2_lookup_ul((const char *)host->name, &ace_hostname, flags);
1470 host->encalloc = (char *)ace_hostname;
1471 /* change the name pointer to point to the encoded hostname */
1472 host->name = host->encalloc;
1475 failf(data, "Failed to convert %s to ACE; %s\n", host->name,
1477 return CURLE_URL_MALFORMAT;
1480 #elif defined(USE_WIN32_IDN)
1481 char *ace_hostname = NULL;
1483 if(curl_win32_idn_to_ascii(host->name, &ace_hostname)) {
1484 host->encalloc = ace_hostname;
1485 /* change the name pointer to point to the encoded hostname */
1486 host->name = host->encalloc;
1489 failf(data, "Failed to convert %s to ACE;\n", host->name);
1490 return CURLE_URL_MALFORMAT;
1492 #elif defined(USE_ICU_IDNA)
1493 char *ace_hostname = malloc(MAX_DOMAIN_NAME_LEN * sizeof(char));
1494 UErrorCode errorCode = U_ZERO_ERROR;
1495 UIDNAInfo info = UIDNA_INFO_INITIALIZER;
1497 uidna_openUTS46(UIDNA_USE_STD3_RULES|UIDNA_NONTRANSITIONAL_TO_UNICODE,
1499 int32_t length = uidna_nameToASCII_UTF8(uts46,
1500 host->name, strlen(host->name),
1501 ace_hostname, MAX_DOMAIN_NAME_LEN, &info, &errorCode);
1504 if(errorCode != U_ZERO_ERROR || info.errors || length < 1) {
1505 infof(data, "Failed to convert %s to ACE;\n", host->name);
1506 return CURLE_URL_MALFORMAT;
1509 host->encalloc = ace_hostname;
1510 host->name = host->encalloc;
1513 infof(data, "IDN support not present, can't parse Unicode domains\n");
1520 * Frees data allocated by idnconvert_hostname()
1522 static void free_idnconverted_hostname(struct hostname *host)
1524 #if defined(USE_LIBIDN2)
1525 if(host->encalloc) {
1526 idn2_free(host->encalloc); /* must be freed with idn2_free() since this was
1527 allocated by libidn */
1528 host->encalloc = NULL;
1530 #elif defined(USE_WIN32_IDN) || defined(USE_ICU_IDNA)
1531 free(host->encalloc); /* must be freed with free() since this was
1532 allocated by curl_win32_idn_to_ascii */
1533 host->encalloc = NULL;
1540 * Allocate and initialize a new connectdata object.
1542 static struct connectdata *allocate_conn(struct Curl_easy *data)
1544 struct connectdata *conn = calloc(1, sizeof(struct connectdata));
1549 /* The SSL backend-specific data (ssl_backend_data) objects are allocated as
1550 a separate array to ensure suitable alignment.
1551 Note that these backend pointers can be swapped by vtls (eg ssl backend
1552 data becomes proxy backend data). */
1554 size_t sslsize = Curl_ssl->sizeof_ssl_backend_data;
1555 char *ssl = calloc(4, sslsize);
1560 conn->ssl_extra = ssl;
1561 conn->ssl[0].backend = (void *)ssl;
1562 conn->ssl[1].backend = (void *)(ssl + sslsize);
1563 conn->proxy_ssl[0].backend = (void *)(ssl + 2 * sslsize);
1564 conn->proxy_ssl[1].backend = (void *)(ssl + 3 * sslsize);
1568 conn->handler = &Curl_handler_dummy; /* Be sure we have a handler defined
1569 already from start to avoid NULL
1570 situations and checks */
1572 /* and we setup a few fields in case we end up actually using this struct */
1574 conn->sock[FIRSTSOCKET] = CURL_SOCKET_BAD; /* no file descriptor */
1575 conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD; /* no file descriptor */
1576 conn->tempsock[0] = CURL_SOCKET_BAD; /* no file descriptor */
1577 conn->tempsock[1] = CURL_SOCKET_BAD; /* no file descriptor */
1578 conn->connection_id = -1; /* no ID */
1579 conn->port = -1; /* unknown at this point */
1580 conn->remote_port = -1; /* unknown at this point */
1581 #if defined(USE_RECV_BEFORE_SEND_WORKAROUND) && defined(DEBUGBUILD)
1582 conn->postponed[0].bindsock = CURL_SOCKET_BAD; /* no file descriptor */
1583 conn->postponed[1].bindsock = CURL_SOCKET_BAD; /* no file descriptor */
1584 #endif /* USE_RECV_BEFORE_SEND_WORKAROUND && DEBUGBUILD */
1586 /* Default protocol-independent behavior doesn't support persistent
1587 connections, so we set this to force-close. Protocols that support
1588 this need to set this to FALSE in their "curl_do" functions. */
1589 connclose(conn, "Default to force-close");
1591 /* Store creation time to help future close decision making */
1592 conn->created = Curl_now();
1594 /* Store current time to give a baseline to keepalive connection times. */
1595 conn->keepalive = Curl_now();
1597 /* Store off the configured connection upkeep time. */
1598 conn->upkeep_interval_ms = data->set.upkeep_interval_ms;
1600 conn->data = data; /* Setup the association between this connection
1601 and the Curl_easy */
1603 conn->http_proxy.proxytype = data->set.proxytype;
1604 conn->socks_proxy.proxytype = CURLPROXY_SOCKS4;
1606 #if !defined(CURL_DISABLE_PROXY)
1607 /* note that these two proxy bits are now just on what looks to be
1608 requested, they may be altered down the road */
1609 conn->bits.proxy = (data->set.str[STRING_PROXY] &&
1610 *data->set.str[STRING_PROXY]) ? TRUE : FALSE;
1611 conn->bits.httpproxy = (conn->bits.proxy &&
1612 (conn->http_proxy.proxytype == CURLPROXY_HTTP ||
1613 conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0 ||
1614 conn->http_proxy.proxytype == CURLPROXY_HTTPS)) ?
1616 conn->bits.socksproxy = (conn->bits.proxy &&
1617 !conn->bits.httpproxy) ? TRUE : FALSE;
1619 if(data->set.str[STRING_PRE_PROXY] && *data->set.str[STRING_PRE_PROXY]) {
1620 conn->bits.proxy = TRUE;
1621 conn->bits.socksproxy = TRUE;
1624 conn->bits.proxy_user_passwd =
1625 (data->set.str[STRING_PROXYUSERNAME]) ? TRUE : FALSE;
1626 conn->bits.tunnel_proxy = data->set.tunnel_thru_httpproxy;
1627 #endif /* CURL_DISABLE_PROXY */
1629 conn->bits.user_passwd = (data->set.str[STRING_USERNAME]) ? TRUE : FALSE;
1630 #ifndef CURL_DISABLE_FTP
1631 conn->bits.ftp_use_epsv = data->set.ftp_use_epsv;
1632 conn->bits.ftp_use_eprt = data->set.ftp_use_eprt;
1634 conn->ssl_config.verifystatus = data->set.ssl.primary.verifystatus;
1635 conn->ssl_config.verifypeer = data->set.ssl.primary.verifypeer;
1636 conn->ssl_config.verifyhost = data->set.ssl.primary.verifyhost;
1637 conn->proxy_ssl_config.verifystatus =
1638 data->set.proxy_ssl.primary.verifystatus;
1639 conn->proxy_ssl_config.verifypeer = data->set.proxy_ssl.primary.verifypeer;
1640 conn->proxy_ssl_config.verifyhost = data->set.proxy_ssl.primary.verifyhost;
1641 conn->ip_version = data->set.ipver;
1642 conn->bits.connect_only = data->set.connect_only;
1643 conn->transport = TRNSPRT_TCP; /* most of them are TCP streams */
1645 #if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \
1646 defined(NTLM_WB_ENABLED)
1647 conn->ntlm_auth_hlpr_socket = CURL_SOCKET_BAD;
1650 /* Initialize the easy handle list */
1651 Curl_llist_init(&conn->easyq, NULL);
1654 conn->data_prot = PROT_CLEAR;
1657 /* Store the local bind parameters that will be used for this connection */
1658 if(data->set.str[STRING_DEVICE]) {
1659 conn->localdev = strdup(data->set.str[STRING_DEVICE]);
1663 conn->localportrange = data->set.localportrange;
1664 conn->localport = data->set.localport;
1666 /* the close socket stuff needs to be copied to the connection struct as
1667 it may live on without (this specific) Curl_easy */
1668 conn->fclosesocket = data->set.fclosesocket;
1669 conn->closesocket_client = data->set.closesocket_client;
1670 conn->lastused = Curl_now(); /* used now */
1675 Curl_llist_destroy(&conn->easyq, NULL);
1676 free(conn->localdev);
1678 free(conn->ssl_extra);
1684 /* returns the handler if the given scheme is built-in */
1685 const struct Curl_handler *Curl_builtin_scheme(const char *scheme)
1687 const struct Curl_handler * const *pp;
1688 const struct Curl_handler *p;
1689 /* Scan protocol handler table and match against 'scheme'. The handler may
1690 be changed later when the protocol specific setup function is called. */
1691 for(pp = protocols; (p = *pp) != NULL; pp++)
1692 if(strcasecompare(p->scheme, scheme))
1693 /* Protocol found in table. Check if allowed */
1695 return NULL; /* not found */
1699 static CURLcode findprotocol(struct Curl_easy *data,
1700 struct connectdata *conn,
1701 const char *protostr)
1703 const struct Curl_handler *p = Curl_builtin_scheme(protostr);
1705 if(p && /* Protocol found in table. Check if allowed */
1706 (data->set.allowed_protocols & p->protocol)) {
1708 /* it is allowed for "normal" request, now do an extra check if this is
1709 the result of a redirect */
1710 if(data->state.this_is_a_follow &&
1711 !(data->set.redir_protocols & p->protocol))
1715 /* Perform setup complement if some. */
1716 conn->handler = conn->given = p;
1718 /* 'port' and 'remote_port' are set in setup_connection_internals() */
1723 /* The protocol was not found in the table, but we don't have to assign it
1724 to anything since it is already assigned to a dummy-struct in the
1725 create_conn() function when the connectdata struct is allocated. */
1726 failf(data, "Protocol \"%s\" not supported or disabled in " LIBCURL_NAME,
1729 return CURLE_UNSUPPORTED_PROTOCOL;
1733 CURLcode Curl_uc_to_curlcode(CURLUcode uc)
1737 return CURLE_URL_MALFORMAT;
1738 case CURLUE_UNSUPPORTED_SCHEME:
1739 return CURLE_UNSUPPORTED_PROTOCOL;
1740 case CURLUE_OUT_OF_MEMORY:
1741 return CURLE_OUT_OF_MEMORY;
1742 case CURLUE_USER_NOT_ALLOWED:
1743 return CURLE_LOGIN_DENIED;
1748 * If the URL was set with an IPv6 numerical address with a zone id part, set
1749 * the scope_id based on that!
1752 static void zonefrom_url(CURLU *uh, struct connectdata *conn)
1757 uc = curl_url_get(uh, CURLUPART_ZONEID, &zoneid, 0);
1761 unsigned long scope = strtoul(zoneid, &endp, 10);
1762 if(!*endp && (scope < UINT_MAX))
1763 /* A plain number, use it directly as a scope id. */
1764 conn->scope_id = (unsigned int)scope;
1765 #if defined(HAVE_IF_NAMETOINDEX)
1767 #elif defined(WIN32)
1768 else if(Curl_if_nametoindex) {
1771 #if defined(HAVE_IF_NAMETOINDEX) || defined(WIN32)
1772 /* Zone identifier is not numeric */
1773 unsigned int scopeidx = 0;
1775 scopeidx = Curl_if_nametoindex(zoneid);
1777 scopeidx = if_nametoindex(zoneid);
1780 infof(conn->data, "Invalid zoneid: %s; %s\n", zoneid,
1783 conn->scope_id = scopeidx;
1785 #endif /* HAVE_IF_NAMETOINDEX || WIN32 */
1792 * Parse URL and fill in the relevant members of the connection struct.
1794 static CURLcode parseurlandfillconn(struct Curl_easy *data,
1795 struct connectdata *conn)
1802 up_free(data); /* cleanup previous leftovers first */
1806 uh = data->state.uh = curl_url_dup(data->set.uh);
1809 uh = data->state.uh = curl_url();
1813 return CURLE_OUT_OF_MEMORY;
1815 if(data->set.str[STRING_DEFAULT_PROTOCOL] &&
1816 !Curl_is_absolute_url(data->change.url, NULL, MAX_SCHEME_LEN)) {
1818 if(data->change.url_alloc)
1819 free(data->change.url);
1820 url = aprintf("%s://%s", data->set.str[STRING_DEFAULT_PROTOCOL],
1823 return CURLE_OUT_OF_MEMORY;
1824 data->change.url = url;
1825 data->change.url_alloc = TRUE;
1830 uc = curl_url_set(uh, CURLUPART_URL, data->change.url,
1831 CURLU_GUESS_SCHEME |
1832 CURLU_NON_SUPPORT_SCHEME |
1833 (data->set.disallow_username_in_url ?
1834 CURLU_DISALLOW_USER : 0) |
1835 (data->set.path_as_is ? CURLU_PATH_AS_IS : 0));
1837 DEBUGF(infof(data, "curl_url_set rejected %s\n", data->change.url));
1838 return Curl_uc_to_curlcode(uc);
1841 /* after it was parsed, get the generated normalized version */
1842 uc = curl_url_get(uh, CURLUPART_URL, &newurl, 0);
1844 return Curl_uc_to_curlcode(uc);
1845 if(data->change.url_alloc)
1846 free(data->change.url);
1847 data->change.url = newurl;
1848 data->change.url_alloc = TRUE;
1851 uc = curl_url_get(uh, CURLUPART_SCHEME, &data->state.up.scheme, 0);
1853 return Curl_uc_to_curlcode(uc);
1855 result = findprotocol(data, conn, data->state.up.scheme);
1859 uc = curl_url_get(uh, CURLUPART_USER, &data->state.up.user,
1862 conn->user = strdup(data->state.up.user);
1864 return CURLE_OUT_OF_MEMORY;
1865 conn->bits.user_passwd = TRUE;
1867 else if(uc != CURLUE_NO_USER)
1868 return Curl_uc_to_curlcode(uc);
1870 uc = curl_url_get(uh, CURLUPART_PASSWORD, &data->state.up.password,
1873 conn->passwd = strdup(data->state.up.password);
1875 return CURLE_OUT_OF_MEMORY;
1876 conn->bits.user_passwd = TRUE;
1878 else if(uc != CURLUE_NO_PASSWORD)
1879 return Curl_uc_to_curlcode(uc);
1881 uc = curl_url_get(uh, CURLUPART_OPTIONS, &data->state.up.options,
1884 conn->options = strdup(data->state.up.options);
1886 return CURLE_OUT_OF_MEMORY;
1888 else if(uc != CURLUE_NO_OPTIONS)
1889 return Curl_uc_to_curlcode(uc);
1891 uc = curl_url_get(uh, CURLUPART_HOST, &data->state.up.hostname, 0);
1893 if(!strcasecompare("file", data->state.up.scheme))
1894 return CURLE_OUT_OF_MEMORY;
1897 uc = curl_url_get(uh, CURLUPART_PATH, &data->state.up.path, 0);
1899 return Curl_uc_to_curlcode(uc);
1901 uc = curl_url_get(uh, CURLUPART_PORT, &data->state.up.port,
1902 CURLU_DEFAULT_PORT);
1904 if(!strcasecompare("file", data->state.up.scheme))
1905 return CURLE_OUT_OF_MEMORY;
1908 unsigned long port = strtoul(data->state.up.port, NULL, 10);
1909 conn->port = conn->remote_port = curlx_ultous(port);
1912 (void)curl_url_get(uh, CURLUPART_QUERY, &data->state.up.query, 0);
1914 hostname = data->state.up.hostname;
1915 if(hostname && hostname[0] == '[') {
1916 /* This looks like an IPv6 address literal. See if there is an address
1919 conn->bits.ipv6_ip = TRUE;
1920 /* cut off the brackets! */
1922 hlen = strlen(hostname);
1923 hostname[hlen - 1] = 0;
1925 zonefrom_url(uh, conn);
1928 /* make sure the connect struct gets its own copy of the host name */
1929 conn->host.rawalloc = strdup(hostname ? hostname : "");
1930 if(!conn->host.rawalloc)
1931 return CURLE_OUT_OF_MEMORY;
1932 conn->host.name = conn->host.rawalloc;
1934 if(data->set.scope_id)
1935 /* Override any scope that was set above. */
1936 conn->scope_id = data->set.scope_id;
1943 * If we're doing a resumed transfer, we need to setup our stuff
1946 static CURLcode setup_range(struct Curl_easy *data)
1948 struct UrlState *s = &data->state;
1949 s->resume_from = data->set.set_resume_from;
1950 if(s->resume_from || data->set.str[STRING_SET_RANGE]) {
1951 if(s->rangestringalloc)
1955 s->range = aprintf("%" CURL_FORMAT_CURL_OFF_T "-", s->resume_from);
1957 s->range = strdup(data->set.str[STRING_SET_RANGE]);
1959 s->rangestringalloc = (s->range) ? TRUE : FALSE;
1962 return CURLE_OUT_OF_MEMORY;
1964 /* tell ourselves to fetch this range */
1965 s->use_range = TRUE; /* enable range download */
1968 s->use_range = FALSE; /* disable range download */
1975 * setup_connection_internals() -
1977 * Setup connection internals specific to the requested protocol in the
1978 * Curl_easy. This is inited and setup before the connection is made but
1979 * is about the particular protocol that is to be used.
1981 * This MUST get called after proxy magic has been figured out.
1983 static CURLcode setup_connection_internals(struct connectdata *conn)
1985 const struct Curl_handler * p;
1988 /* Perform setup complement if some. */
1991 if(p->setup_connection) {
1992 result = (*p->setup_connection)(conn);
1997 p = conn->handler; /* May have changed. */
2001 /* we check for -1 here since if proxy was detected already, this
2002 was very likely already set to the proxy port */
2003 conn->port = p->defport;
2009 * Curl_free_request_state() should free temp data that was allocated in the
2010 * Curl_easy for this single request.
2013 void Curl_free_request_state(struct Curl_easy *data)
2015 Curl_safefree(data->req.protop);
2016 Curl_safefree(data->req.newurl);
2018 #ifndef CURL_DISABLE_DOH
2019 Curl_close(&data->req.doh.probe[0].easy);
2020 Curl_close(&data->req.doh.probe[1].easy);
2025 #ifndef CURL_DISABLE_PROXY
2026 /****************************************************************
2027 * Checks if the host is in the noproxy list. returns true if it matches
2028 * and therefore the proxy should NOT be used.
2029 ****************************************************************/
2030 static bool check_noproxy(const char *name, const char *no_proxy)
2032 /* no_proxy=domain1.dom,host.domain2.dom
2033 * (a comma-separated list of hosts which should
2034 * not be proxied, or an asterisk to override
2035 * all proxy variables)
2037 if(no_proxy && no_proxy[0]) {
2040 const char *separator = ", ";
2041 size_t no_proxy_len;
2044 if(strcasecompare("*", no_proxy)) {
2048 /* NO_PROXY was specified and it wasn't just an asterisk */
2050 no_proxy_len = strlen(no_proxy);
2051 if(name[0] == '[') {
2052 /* IPv6 numerical address */
2053 endptr = strchr(name, ']');
2057 namelen = endptr - name;
2060 namelen = strlen(name);
2062 for(tok_start = 0; tok_start < no_proxy_len; tok_start = tok_end + 1) {
2063 while(tok_start < no_proxy_len &&
2064 strchr(separator, no_proxy[tok_start]) != NULL) {
2065 /* Look for the beginning of the token. */
2069 if(tok_start == no_proxy_len)
2070 break; /* It was all trailing separator chars, no more tokens. */
2072 for(tok_end = tok_start; tok_end < no_proxy_len &&
2073 strchr(separator, no_proxy[tok_end]) == NULL; ++tok_end)
2074 /* Look for the end of the token. */
2077 /* To match previous behaviour, where it was necessary to specify
2078 * ".local.com" to prevent matching "notlocal.com", we will leave
2081 if(no_proxy[tok_start] == '.')
2084 if((tok_end - tok_start) <= namelen) {
2085 /* Match the last part of the name to the domain we are checking. */
2086 const char *checkn = name + namelen - (tok_end - tok_start);
2087 if(strncasecompare(no_proxy + tok_start, checkn,
2088 tok_end - tok_start)) {
2089 if((tok_end - tok_start) == namelen || *(checkn - 1) == '.') {
2090 /* We either have an exact match, or the previous character is a .
2091 * so it is within the same domain, so no proxy for this host.
2096 } /* if((tok_end - tok_start) <= namelen) */
2097 } /* for(tok_start = 0; tok_start < no_proxy_len;
2098 tok_start = tok_end + 1) */
2099 } /* NO_PROXY was specified and it wasn't just an asterisk */
2104 #ifndef CURL_DISABLE_HTTP
2105 /****************************************************************
2106 * Detect what (if any) proxy to use. Remember that this selects a host
2107 * name and is not limited to HTTP proxies only.
2108 * The returned pointer must be freed by the caller (unless NULL)
2109 ****************************************************************/
2110 static char *detect_proxy(struct connectdata *conn)
2114 /* If proxy was not specified, we check for default proxy environment
2115 * variables, to enable i.e Lynx compliance:
2117 * http_proxy=http://some.server.dom:port/
2118 * https_proxy=http://some.server.dom:port/
2119 * ftp_proxy=http://some.server.dom:port/
2120 * no_proxy=domain1.dom,host.domain2.dom
2121 * (a comma-separated list of hosts which should
2122 * not be proxied, or an asterisk to override
2123 * all proxy variables)
2124 * all_proxy=http://some.server.dom:port/
2125 * (seems to exist for the CERN www lib. Probably
2126 * the first to check for.)
2128 * For compatibility, the all-uppercase versions of these variables are
2129 * checked if the lowercase versions don't exist.
2131 char proxy_env[128];
2132 const char *protop = conn->handler->scheme;
2133 char *envp = proxy_env;
2136 /* Now, build <protocol>_proxy and check for such a one to use */
2138 *envp++ = (char)tolower((int)*protop++);
2141 strcpy(envp, "_proxy");
2143 /* read the protocol proxy: */
2144 prox = curl_getenv(proxy_env);
2147 * We don't try the uppercase version of HTTP_PROXY because of
2150 * When curl is used in a webserver application
2151 * environment (cgi or php), this environment variable can
2152 * be controlled by the web server user by setting the
2153 * http header 'Proxy:' to some value.
2155 * This can cause 'internal' http/ftp requests to be
2156 * arbitrarily redirected by any external attacker.
2158 if(!prox && !strcasecompare("http_proxy", proxy_env)) {
2159 /* There was no lowercase variable, try the uppercase version: */
2160 Curl_strntoupper(proxy_env, proxy_env, sizeof(proxy_env));
2161 prox = curl_getenv(proxy_env);
2166 proxy = prox; /* use this */
2169 envp = (char *)"all_proxy";
2170 proxy = curl_getenv(envp); /* default proxy to use */
2172 envp = (char *)"ALL_PROXY";
2173 proxy = curl_getenv(envp);
2177 infof(conn->data, "Uses proxy env variable %s == '%s'\n", envp, proxy);
2181 #endif /* CURL_DISABLE_HTTP */
2184 * If this is supposed to use a proxy, we need to figure out the proxy
2185 * host name, so that we can re-use an existing connection
2186 * that may exist registered to the same proxy host.
2188 static CURLcode parse_proxy(struct Curl_easy *data,
2189 struct connectdata *conn, char *proxy,
2190 curl_proxytype proxytype)
2192 char *portptr = NULL;
2194 char *proxyuser = NULL;
2195 char *proxypasswd = NULL;
2199 struct proxy_info *proxyinfo;
2200 CURLU *uhp = curl_url();
2201 CURLcode result = CURLE_OK;
2202 char *scheme = NULL;
2204 /* When parsing the proxy, allowing non-supported schemes since we have
2205 these made up ones for proxies. Guess scheme for URLs without it. */
2206 uc = curl_url_set(uhp, CURLUPART_URL, proxy,
2207 CURLU_NON_SUPPORT_SCHEME|CURLU_GUESS_SCHEME);
2209 /* parsed okay as a URL */
2210 uc = curl_url_get(uhp, CURLUPART_SCHEME, &scheme, 0);
2212 result = CURLE_OUT_OF_MEMORY;
2216 if(strcasecompare("https", scheme))
2217 proxytype = CURLPROXY_HTTPS;
2218 else if(strcasecompare("socks5h", scheme))
2219 proxytype = CURLPROXY_SOCKS5_HOSTNAME;
2220 else if(strcasecompare("socks5", scheme))
2221 proxytype = CURLPROXY_SOCKS5;
2222 else if(strcasecompare("socks4a", scheme))
2223 proxytype = CURLPROXY_SOCKS4A;
2224 else if(strcasecompare("socks4", scheme) ||
2225 strcasecompare("socks", scheme))
2226 proxytype = CURLPROXY_SOCKS4;
2227 else if(strcasecompare("http", scheme))
2228 ; /* leave it as HTTP or HTTP/1.0 */
2230 /* Any other xxx:// reject! */
2231 failf(data, "Unsupported proxy scheme for \'%s\'", proxy);
2232 result = CURLE_COULDNT_CONNECT;
2237 failf(data, "Unsupported proxy syntax in \'%s\'", proxy);
2238 result = CURLE_COULDNT_RESOLVE_PROXY;
2243 if(!(Curl_ssl->supports & SSLSUPP_HTTPS_PROXY))
2245 if(proxytype == CURLPROXY_HTTPS) {
2246 failf(data, "Unsupported proxy \'%s\', libcurl is built without the "
2247 "HTTPS-proxy support.", proxy);
2248 result = CURLE_NOT_BUILT_IN;
2253 proxytype == CURLPROXY_SOCKS5_HOSTNAME ||
2254 proxytype == CURLPROXY_SOCKS5 ||
2255 proxytype == CURLPROXY_SOCKS4A ||
2256 proxytype == CURLPROXY_SOCKS4;
2258 proxyinfo = sockstype ? &conn->socks_proxy : &conn->http_proxy;
2259 proxyinfo->proxytype = proxytype;
2261 /* Is there a username and password given in this proxy url? */
2262 curl_url_get(uhp, CURLUPART_USER, &proxyuser, CURLU_URLDECODE);
2263 curl_url_get(uhp, CURLUPART_PASSWORD, &proxypasswd, CURLU_URLDECODE);
2264 if(proxyuser || proxypasswd) {
2265 Curl_safefree(proxyinfo->user);
2266 proxyinfo->user = proxyuser;
2267 Curl_safefree(proxyinfo->passwd);
2269 proxypasswd = strdup("");
2271 result = CURLE_OUT_OF_MEMORY;
2275 proxyinfo->passwd = proxypasswd;
2276 conn->bits.proxy_user_passwd = TRUE; /* enable it */
2279 curl_url_get(uhp, CURLUPART_PORT, &portptr, 0);
2282 port = strtol(portptr, NULL, 10);
2286 if(data->set.proxyport)
2287 /* None given in the proxy string, then get the default one if it is
2289 port = data->set.proxyport;
2291 if(proxytype == CURLPROXY_HTTPS)
2292 port = CURL_DEFAULT_HTTPS_PROXY_PORT;
2294 port = CURL_DEFAULT_PROXY_PORT;
2298 proxyinfo->port = port;
2299 if(conn->port < 0 || sockstype || !conn->socks_proxy.host.rawalloc)
2303 /* now, clone the proxy host name */
2304 uc = curl_url_get(uhp, CURLUPART_HOST, &host, CURLU_URLDECODE);
2306 result = CURLE_OUT_OF_MEMORY;
2309 Curl_safefree(proxyinfo->host.rawalloc);
2310 proxyinfo->host.rawalloc = host;
2311 if(host[0] == '[') {
2312 /* this is a numerical IPv6, strip off the brackets */
2313 size_t len = strlen(host);
2314 host[len-1] = 0; /* clear the trailing bracket */
2316 zonefrom_url(uhp, conn);
2318 proxyinfo->host.name = host;
2322 curl_url_cleanup(uhp);
2327 * Extract the user and password from the authentication string
2329 static CURLcode parse_proxy_auth(struct Curl_easy *data,
2330 struct connectdata *conn)
2332 char proxyuser[MAX_CURL_USER_LENGTH]="";
2333 char proxypasswd[MAX_CURL_PASSWORD_LENGTH]="";
2336 if(data->set.str[STRING_PROXYUSERNAME] != NULL) {
2337 strncpy(proxyuser, data->set.str[STRING_PROXYUSERNAME],
2338 MAX_CURL_USER_LENGTH);
2339 proxyuser[MAX_CURL_USER_LENGTH-1] = '\0'; /*To be on safe side*/
2341 if(data->set.str[STRING_PROXYPASSWORD] != NULL) {
2342 strncpy(proxypasswd, data->set.str[STRING_PROXYPASSWORD],
2343 MAX_CURL_PASSWORD_LENGTH);
2344 proxypasswd[MAX_CURL_PASSWORD_LENGTH-1] = '\0'; /*To be on safe side*/
2347 result = Curl_urldecode(data, proxyuser, 0, &conn->http_proxy.user, NULL,
2350 result = Curl_urldecode(data, proxypasswd, 0, &conn->http_proxy.passwd,
2355 /* create_conn helper to parse and init proxy values. to be called after unix
2356 socket init but before any proxy vars are evaluated. */
2357 static CURLcode create_conn_helper_init_proxy(struct connectdata *conn)
2360 char *socksproxy = NULL;
2361 char *no_proxy = NULL;
2362 CURLcode result = CURLE_OK;
2363 struct Curl_easy *data = conn->data;
2365 /*************************************************************
2366 * Extract the user and password from the authentication string
2367 *************************************************************/
2368 if(conn->bits.proxy_user_passwd) {
2369 result = parse_proxy_auth(data, conn);
2374 /*************************************************************
2375 * Detect what (if any) proxy to use
2376 *************************************************************/
2377 if(data->set.str[STRING_PROXY]) {
2378 proxy = strdup(data->set.str[STRING_PROXY]);
2379 /* if global proxy is set, this is it */
2381 failf(data, "memory shortage");
2382 result = CURLE_OUT_OF_MEMORY;
2387 if(data->set.str[STRING_PRE_PROXY]) {
2388 socksproxy = strdup(data->set.str[STRING_PRE_PROXY]);
2389 /* if global socks proxy is set, this is it */
2390 if(NULL == socksproxy) {
2391 failf(data, "memory shortage");
2392 result = CURLE_OUT_OF_MEMORY;
2397 if(!data->set.str[STRING_NOPROXY]) {
2398 const char *p = "no_proxy";
2399 no_proxy = curl_getenv(p);
2402 no_proxy = curl_getenv(p);
2405 infof(conn->data, "Uses proxy env variable %s == '%s'\n", p, no_proxy);
2409 if(check_noproxy(conn->host.name, data->set.str[STRING_NOPROXY] ?
2410 data->set.str[STRING_NOPROXY] : no_proxy)) {
2411 Curl_safefree(proxy);
2412 Curl_safefree(socksproxy);
2414 #ifndef CURL_DISABLE_HTTP
2415 else if(!proxy && !socksproxy)
2416 /* if the host is not in the noproxy list, detect proxy. */
2417 proxy = detect_proxy(conn);
2418 #endif /* CURL_DISABLE_HTTP */
2420 Curl_safefree(no_proxy);
2422 #ifdef USE_UNIX_SOCKETS
2423 /* For the time being do not mix proxy and unix domain sockets. See #1274 */
2424 if(proxy && conn->unix_domain_socket) {
2430 if(proxy && (!*proxy || (conn->handler->flags & PROTOPT_NONETWORK))) {
2431 free(proxy); /* Don't bother with an empty proxy string or if the
2432 protocol doesn't work with network */
2435 if(socksproxy && (!*socksproxy ||
2436 (conn->handler->flags & PROTOPT_NONETWORK))) {
2437 free(socksproxy); /* Don't bother with an empty socks proxy string or if
2438 the protocol doesn't work with network */
2442 /***********************************************************************
2443 * If this is supposed to use a proxy, we need to figure out the proxy host
2444 * name, proxy type and port number, so that we can re-use an existing
2445 * connection that may exist registered to the same proxy host.
2446 ***********************************************************************/
2447 if(proxy || socksproxy) {
2449 result = parse_proxy(data, conn, proxy, conn->http_proxy.proxytype);
2450 Curl_safefree(proxy); /* parse_proxy copies the proxy string */
2456 result = parse_proxy(data, conn, socksproxy,
2457 conn->socks_proxy.proxytype);
2458 /* parse_proxy copies the socks proxy string */
2459 Curl_safefree(socksproxy);
2464 if(conn->http_proxy.host.rawalloc) {
2465 #ifdef CURL_DISABLE_HTTP
2466 /* asking for a HTTP proxy is a bit funny when HTTP is disabled... */
2467 result = CURLE_UNSUPPORTED_PROTOCOL;
2470 /* force this connection's protocol to become HTTP if compatible */
2471 if(!(conn->handler->protocol & PROTO_FAMILY_HTTP)) {
2472 if((conn->handler->flags & PROTOPT_PROXY_AS_HTTP) &&
2473 !conn->bits.tunnel_proxy)
2474 conn->handler = &Curl_handler_http;
2476 /* if not converting to HTTP over the proxy, enforce tunneling */
2477 conn->bits.tunnel_proxy = TRUE;
2479 conn->bits.httpproxy = TRUE;
2483 conn->bits.httpproxy = FALSE; /* not a HTTP proxy */
2484 conn->bits.tunnel_proxy = FALSE; /* no tunneling if not HTTP */
2487 if(conn->socks_proxy.host.rawalloc) {
2488 if(!conn->http_proxy.host.rawalloc) {
2489 /* once a socks proxy */
2490 if(!conn->socks_proxy.user) {
2491 conn->socks_proxy.user = conn->http_proxy.user;
2492 conn->http_proxy.user = NULL;
2493 Curl_safefree(conn->socks_proxy.passwd);
2494 conn->socks_proxy.passwd = conn->http_proxy.passwd;
2495 conn->http_proxy.passwd = NULL;
2498 conn->bits.socksproxy = TRUE;
2501 conn->bits.socksproxy = FALSE; /* not a socks proxy */
2504 conn->bits.socksproxy = FALSE;
2505 conn->bits.httpproxy = FALSE;
2507 conn->bits.proxy = conn->bits.httpproxy || conn->bits.socksproxy;
2509 if(!conn->bits.proxy) {
2510 /* we aren't using the proxy after all... */
2511 conn->bits.proxy = FALSE;
2512 conn->bits.httpproxy = FALSE;
2513 conn->bits.socksproxy = FALSE;
2514 conn->bits.proxy_user_passwd = FALSE;
2515 conn->bits.tunnel_proxy = FALSE;
2524 #endif /* CURL_DISABLE_PROXY */
2527 * Curl_parse_login_details()
2529 * This is used to parse a login string for user name, password and options in
2530 * the following formats:
2534 * user:password;options
2536 * user;options:password
2544 * login [in] - The login string.
2545 * len [in] - The length of the login string.
2546 * userp [in/out] - The address where a pointer to newly allocated memory
2547 * holding the user will be stored upon completion.
2548 * passwdp [in/out] - The address where a pointer to newly allocated memory
2549 * holding the password will be stored upon completion.
2550 * optionsp [in/out] - The address where a pointer to newly allocated memory
2551 * holding the options will be stored upon completion.
2553 * Returns CURLE_OK on success.
2555 CURLcode Curl_parse_login_details(const char *login, const size_t len,
2556 char **userp, char **passwdp,
2559 CURLcode result = CURLE_OK;
2563 const char *psep = NULL;
2564 const char *osep = NULL;
2569 /* Attempt to find the password separator */
2571 psep = strchr(login, ':');
2573 /* Within the constraint of the login string */
2574 if(psep >= login + len)
2578 /* Attempt to find the options separator */
2580 osep = strchr(login, ';');
2582 /* Within the constraint of the login string */
2583 if(osep >= login + len)
2587 /* Calculate the portion lengths */
2589 (size_t)(osep && psep > osep ? osep - login : psep - login) :
2590 (osep ? (size_t)(osep - login) : len));
2592 (osep && osep > psep ? (size_t)(osep - psep) :
2593 (size_t)(login + len - psep)) - 1 : 0);
2595 (psep && psep > osep ? (size_t)(psep - osep) :
2596 (size_t)(login + len - osep)) - 1 : 0);
2598 /* Allocate the user portion buffer */
2600 ubuf = malloc(ulen + 1);
2602 result = CURLE_OUT_OF_MEMORY;
2605 /* Allocate the password portion buffer */
2606 if(!result && passwdp && plen) {
2607 pbuf = malloc(plen + 1);
2610 result = CURLE_OUT_OF_MEMORY;
2614 /* Allocate the options portion buffer */
2615 if(!result && optionsp && olen) {
2616 obuf = malloc(olen + 1);
2620 result = CURLE_OUT_OF_MEMORY;
2625 /* Store the user portion if necessary */
2627 memcpy(ubuf, login, ulen);
2629 Curl_safefree(*userp);
2633 /* Store the password portion if necessary */
2635 memcpy(pbuf, psep + 1, plen);
2637 Curl_safefree(*passwdp);
2641 /* Store the options portion if necessary */
2643 memcpy(obuf, osep + 1, olen);
2645 Curl_safefree(*optionsp);
2653 /*************************************************************
2654 * Figure out the remote port number and fix it in the URL
2656 * No matter if we use a proxy or not, we have to figure out the remote
2657 * port number of various reasons.
2659 * The port number embedded in the URL is replaced, if necessary.
2660 *************************************************************/
2661 static CURLcode parse_remote_port(struct Curl_easy *data,
2662 struct connectdata *conn)
2665 if(data->set.use_port && data->state.allow_port) {
2666 /* if set, we use this instead of the port possibly given in the URL */
2669 conn->remote_port = (unsigned short)data->set.use_port;
2670 msnprintf(portbuf, sizeof(portbuf), "%d", conn->remote_port);
2671 uc = curl_url_set(data->state.uh, CURLUPART_PORT, portbuf, 0);
2673 return CURLE_OUT_OF_MEMORY;
2680 * Override the login details from the URL with that in the CURLOPT_USERPWD
2681 * option or a .netrc file, if applicable.
2683 static CURLcode override_login(struct Curl_easy *data,
2684 struct connectdata *conn,
2685 char **userp, char **passwdp, char **optionsp)
2687 bool user_changed = FALSE;
2688 bool passwd_changed = FALSE;
2691 if(data->set.use_netrc == CURL_NETRC_REQUIRED && conn->bits.user_passwd) {
2692 /* ignore user+password in the URL */
2694 Curl_safefree(*userp);
2695 user_changed = TRUE;
2698 Curl_safefree(*passwdp);
2699 passwd_changed = TRUE;
2701 conn->bits.user_passwd = FALSE; /* disable user+password */
2704 if(data->set.str[STRING_USERNAME]) {
2706 *userp = strdup(data->set.str[STRING_USERNAME]);
2708 return CURLE_OUT_OF_MEMORY;
2709 conn->bits.user_passwd = TRUE; /* enable user+password */
2710 user_changed = TRUE;
2713 if(data->set.str[STRING_PASSWORD]) {
2715 *passwdp = strdup(data->set.str[STRING_PASSWORD]);
2717 return CURLE_OUT_OF_MEMORY;
2718 conn->bits.user_passwd = TRUE; /* enable user+password */
2719 passwd_changed = TRUE;
2722 if(data->set.str[STRING_OPTIONS]) {
2724 *optionsp = strdup(data->set.str[STRING_OPTIONS]);
2726 return CURLE_OUT_OF_MEMORY;
2729 conn->bits.netrc = FALSE;
2730 if(data->set.use_netrc != CURL_NETRC_IGNORED &&
2731 (!*userp || !**userp || !*passwdp || !**passwdp)) {
2732 bool netrc_user_changed = FALSE;
2733 bool netrc_passwd_changed = FALSE;
2736 ret = Curl_parsenetrc(conn->host.name,
2738 &netrc_user_changed, &netrc_passwd_changed,
2739 data->set.str[STRING_NETRC_FILE]);
2741 infof(data, "Couldn't find host %s in the .netrc file; using defaults\n",
2745 return CURLE_OUT_OF_MEMORY;
2748 /* set bits.netrc TRUE to remember that we got the name from a .netrc
2749 file, so that it is safe to use even if we followed a Location: to a
2750 different host or similar. */
2751 conn->bits.netrc = TRUE;
2752 conn->bits.user_passwd = TRUE; /* enable user+password */
2754 if(netrc_user_changed) {
2755 user_changed = TRUE;
2757 if(netrc_passwd_changed) {
2758 passwd_changed = TRUE;
2763 /* for updated strings, we update them in the URL */
2765 uc = curl_url_set(data->state.uh, CURLUPART_USER, *userp, 0);
2767 return Curl_uc_to_curlcode(uc);
2769 if(passwd_changed) {
2770 uc = curl_url_set(data->state.uh, CURLUPART_PASSWORD, *passwdp, 0);
2772 return Curl_uc_to_curlcode(uc);
2778 * Set the login details so they're available in the connection
2780 static CURLcode set_login(struct connectdata *conn)
2782 CURLcode result = CURLE_OK;
2783 const char *setuser = CURL_DEFAULT_USER;
2784 const char *setpasswd = CURL_DEFAULT_PASSWORD;
2786 /* If our protocol needs a password and we have none, use the defaults */
2787 if((conn->handler->flags & PROTOPT_NEEDSPWD) && !conn->bits.user_passwd)
2793 /* Store the default user */
2795 conn->user = strdup(setuser);
2797 return CURLE_OUT_OF_MEMORY;
2800 /* Store the default password */
2802 conn->passwd = strdup(setpasswd);
2804 result = CURLE_OUT_OF_MEMORY;
2811 * Parses a "host:port" string to connect to.
2812 * The hostname and the port may be empty; in this case, NULL is returned for
2813 * the hostname and -1 for the port.
2815 static CURLcode parse_connect_to_host_port(struct Curl_easy *data,
2817 char **hostname_result,
2826 #if defined(CURL_DISABLE_VERBOSE_STRINGS)
2830 *hostname_result = NULL;
2836 host_dup = strdup(host);
2838 return CURLE_OUT_OF_MEMORY;
2842 /* start scanning for port number at this point */
2845 /* detect and extract RFC6874-style IPv6-addresses */
2846 if(*hostptr == '[') {
2848 char *ptr = ++hostptr; /* advance beyond the initial bracket */
2849 while(*ptr && (ISXDIGIT(*ptr) || (*ptr == ':') || (*ptr == '.')))
2852 /* There might be a zone identifier */
2853 if(strncmp("%25", ptr, 3))
2854 infof(data, "Please URL encode %% as %%25, see RFC 6874.\n");
2856 /* Allow unreserved characters as defined in RFC 3986 */
2857 while(*ptr && (ISALPHA(*ptr) || ISXDIGIT(*ptr) || (*ptr == '-') ||
2858 (*ptr == '.') || (*ptr == '_') || (*ptr == '~')))
2862 /* yeps, it ended nicely with a bracket as well */
2865 infof(data, "Invalid IPv6 address format\n");
2867 /* Note that if this didn't end with a bracket, we still advanced the
2868 * hostptr first, but I can't see anything wrong with that as no host
2869 * name nor a numeric can legally start with a bracket.
2872 failf(data, "Use of IPv6 in *_CONNECT_TO without IPv6 support built-in!");
2874 return CURLE_NOT_BUILT_IN;
2878 /* Get port number off server.com:1080 */
2879 host_portno = strchr(portptr, ':');
2882 *host_portno = '\0'; /* cut off number from host name */
2885 long portparse = strtol(host_portno, &endp, 10);
2886 if((endp && *endp) || (portparse < 0) || (portparse > 65535)) {
2887 infof(data, "No valid port number in connect to host string (%s)\n",
2893 port = (int)portparse; /* we know it will fit */
2897 /* now, clone the cleaned host name */
2899 *hostname_result = strdup(hostptr);
2900 if(!*hostname_result) {
2902 return CURLE_OUT_OF_MEMORY;
2906 *port_result = port;
2913 * Parses one "connect to" string in the form:
2914 * "HOST:PORT:CONNECT-TO-HOST:CONNECT-TO-PORT".
2916 static CURLcode parse_connect_to_string(struct Curl_easy *data,
2917 struct connectdata *conn,
2918 const char *conn_to_host,
2922 CURLcode result = CURLE_OK;
2923 const char *ptr = conn_to_host;
2924 int host_match = FALSE;
2925 int port_match = FALSE;
2927 *host_result = NULL;
2931 /* an empty hostname always matches */
2936 /* check whether the URL's hostname matches */
2937 size_t hostname_to_match_len;
2938 char *hostname_to_match = aprintf("%s%s%s",
2939 conn->bits.ipv6_ip ? "[" : "",
2941 conn->bits.ipv6_ip ? "]" : "");
2942 if(!hostname_to_match)
2943 return CURLE_OUT_OF_MEMORY;
2944 hostname_to_match_len = strlen(hostname_to_match);
2945 host_match = strncasecompare(ptr, hostname_to_match,
2946 hostname_to_match_len);
2947 free(hostname_to_match);
2948 ptr += hostname_to_match_len;
2950 host_match = host_match && *ptr == ':';
2956 /* an empty port always matches */
2961 /* check whether the URL's port matches */
2962 char *ptr_next = strchr(ptr, ':');
2965 long port_to_match = strtol(ptr, &endp, 10);
2966 if((endp == ptr_next) && (port_to_match == conn->remote_port)) {
2974 if(host_match && port_match) {
2975 /* parse the hostname and port to connect to */
2976 result = parse_connect_to_host_port(data, ptr, host_result, port_result);
2983 * Processes all strings in the "connect to" slist, and uses the "connect
2984 * to host" and "connect to port" of the first string that matches.
2986 static CURLcode parse_connect_to_slist(struct Curl_easy *data,
2987 struct connectdata *conn,
2988 struct curl_slist *conn_to_host)
2990 CURLcode result = CURLE_OK;
2994 while(conn_to_host && !host && port == -1) {
2995 result = parse_connect_to_string(data, conn, conn_to_host->data,
3001 conn->conn_to_host.rawalloc = host;
3002 conn->conn_to_host.name = host;
3003 conn->bits.conn_to_host = TRUE;
3005 infof(data, "Connecting to hostname: %s\n", host);
3008 /* no "connect to host" */
3009 conn->bits.conn_to_host = FALSE;
3010 Curl_safefree(host);
3014 conn->conn_to_port = port;
3015 conn->bits.conn_to_port = TRUE;
3016 infof(data, "Connecting to port: %d\n", port);
3019 /* no "connect to port" */
3020 conn->bits.conn_to_port = FALSE;
3024 conn_to_host = conn_to_host->next;
3028 if(data->asi && !host && (port == -1) &&
3029 (conn->handler->protocol == CURLPROTO_HTTPS)) {
3030 /* no connect_to match, try alt-svc! */
3031 enum alpnid srcalpnid;
3034 const int allowed_versions = ( ALPN_h1
3041 ) & data->asi->flags;
3043 host = conn->host.rawalloc;
3045 /* with h2 support, check that first */
3046 srcalpnid = ALPN_h2;
3047 hit = Curl_altsvc_lookup(data->asi,
3048 srcalpnid, host, conn->remote_port, /* from */
3054 srcalpnid = ALPN_h1;
3055 hit = Curl_altsvc_lookup(data->asi,
3056 srcalpnid, host, conn->remote_port, /* from */
3061 char *hostd = strdup((char *)as->dst.host);
3063 return CURLE_OUT_OF_MEMORY;
3064 conn->conn_to_host.rawalloc = hostd;
3065 conn->conn_to_host.name = hostd;
3066 conn->bits.conn_to_host = TRUE;
3067 conn->conn_to_port = as->dst.port;
3068 conn->bits.conn_to_port = TRUE;
3069 conn->bits.altused = TRUE;
3070 infof(data, "Alt-svc connecting from [%s]%s:%d to [%s]%s:%d\n",
3071 Curl_alpnid2str(srcalpnid), host, conn->remote_port,
3072 Curl_alpnid2str(as->dst.alpnid), hostd, as->dst.port);
3073 if(srcalpnid != as->dst.alpnid) {
3074 /* protocol version switch */
3075 switch(as->dst.alpnid) {
3077 conn->httpversion = 11;
3080 conn->httpversion = 20;
3083 conn->transport = TRNSPRT_QUIC;
3084 conn->httpversion = 30;
3086 default: /* shouldn't be possible */
3097 /*************************************************************
3098 * Resolve the address of the server or proxy
3099 *************************************************************/
3100 static CURLcode resolve_server(struct Curl_easy *data,
3101 struct connectdata *conn,
3104 CURLcode result = CURLE_OK;
3105 timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
3109 /*************************************************************
3110 * Resolve the name of the server or proxy
3111 *************************************************************/
3112 if(conn->bits.reuse)
3113 /* We're reusing the connection - no need to resolve anything, and
3114 idnconvert_hostname() was called already in create_conn() for the re-use
3119 /* this is a fresh connect */
3121 struct Curl_dns_entry *hostaddr;
3123 #ifdef USE_UNIX_SOCKETS
3124 if(conn->unix_domain_socket) {
3125 /* Unix domain sockets are local. The host gets ignored, just use the
3126 * specified domain socket address. Do not cache "DNS entries". There is
3127 * no DNS involved and we already have the filesystem path available */
3128 const char *path = conn->unix_domain_socket;
3130 hostaddr = calloc(1, sizeof(struct Curl_dns_entry));
3132 result = CURLE_OUT_OF_MEMORY;
3134 bool longpath = FALSE;
3135 hostaddr->addr = Curl_unix2addr(path, &longpath,
3136 conn->abstract_unix_socket);
3140 /* Long paths are not supported for now */
3142 failf(data, "Unix socket path too long: '%s'", path);
3143 result = CURLE_COULDNT_RESOLVE_HOST;
3146 result = CURLE_OUT_OF_MEMORY;
3154 if(!conn->bits.proxy) {
3155 struct hostname *connhost;
3156 if(conn->bits.conn_to_host)
3157 connhost = &conn->conn_to_host;
3159 connhost = &conn->host;
3161 /* If not connecting via a proxy, extract the port from the URL, if it is
3162 * there, thus overriding any defaults that might have been set above. */
3163 if(conn->bits.conn_to_port)
3164 conn->port = conn->conn_to_port;
3166 conn->port = conn->remote_port;
3168 /* Resolve target host right on */
3169 conn->hostname_resolve = strdup(connhost->name);
3170 if(!conn->hostname_resolve)
3171 return CURLE_OUT_OF_MEMORY;
3172 rc = Curl_resolv_timeout(conn, conn->hostname_resolve, (int)conn->port,
3173 &hostaddr, timeout_ms);
3174 if(rc == CURLRESOLV_PENDING)
3177 else if(rc == CURLRESOLV_TIMEDOUT)
3178 result = CURLE_OPERATION_TIMEDOUT;
3180 else if(!hostaddr) {
3181 failf(data, "Couldn't resolve host '%s'", connhost->dispname);
3182 result = CURLE_COULDNT_RESOLVE_HOST;
3183 /* don't return yet, we need to clean up the timeout first */
3187 /* This is a proxy that hasn't been resolved yet. */
3189 struct hostname * const host = conn->bits.socksproxy ?
3190 &conn->socks_proxy.host : &conn->http_proxy.host;
3193 conn->hostname_resolve = strdup(host->name);
3194 if(!conn->hostname_resolve)
3195 return CURLE_OUT_OF_MEMORY;
3196 rc = Curl_resolv_timeout(conn, conn->hostname_resolve, (int)conn->port,
3197 &hostaddr, timeout_ms);
3199 if(rc == CURLRESOLV_PENDING)
3202 else if(rc == CURLRESOLV_TIMEDOUT)
3203 result = CURLE_OPERATION_TIMEDOUT;
3205 else if(!hostaddr) {
3206 failf(data, "Couldn't resolve proxy '%s'", host->dispname);
3207 result = CURLE_COULDNT_RESOLVE_PROXY;
3208 /* don't return yet, we need to clean up the timeout first */
3211 DEBUGASSERT(conn->dns_entry == NULL);
3212 conn->dns_entry = hostaddr;
3219 * Cleanup the connection just allocated before we can move along and use the
3220 * previously existing one. All relevant data is copied over and old_conn is
3221 * ready for freeing once this function returns.
3223 static void reuse_conn(struct connectdata *old_conn,
3224 struct connectdata *conn)
3226 free_idnconverted_hostname(&old_conn->http_proxy.host);
3227 free_idnconverted_hostname(&old_conn->socks_proxy.host);
3229 free(old_conn->http_proxy.host.rawalloc);
3230 free(old_conn->socks_proxy.host.rawalloc);
3232 /* free the SSL config struct from this connection struct as this was
3233 allocated in vain and is targeted for destruction */
3234 Curl_free_primary_ssl_config(&old_conn->ssl_config);
3235 Curl_free_primary_ssl_config(&old_conn->proxy_ssl_config);
3237 conn->data = old_conn->data;
3239 /* get the user+password information from the old_conn struct since it may
3240 * be new for this request even when we re-use an existing connection */
3241 conn->bits.user_passwd = old_conn->bits.user_passwd;
3242 if(conn->bits.user_passwd) {
3243 /* use the new user name and password though */
3244 Curl_safefree(conn->user);
3245 Curl_safefree(conn->passwd);
3246 conn->user = old_conn->user;
3247 conn->passwd = old_conn->passwd;
3248 old_conn->user = NULL;
3249 old_conn->passwd = NULL;
3252 conn->bits.proxy_user_passwd = old_conn->bits.proxy_user_passwd;
3253 if(conn->bits.proxy_user_passwd) {
3254 /* use the new proxy user name and proxy password though */
3255 Curl_safefree(conn->http_proxy.user);
3256 Curl_safefree(conn->socks_proxy.user);
3257 Curl_safefree(conn->http_proxy.passwd);
3258 Curl_safefree(conn->socks_proxy.passwd);
3259 conn->http_proxy.user = old_conn->http_proxy.user;
3260 conn->socks_proxy.user = old_conn->socks_proxy.user;
3261 conn->http_proxy.passwd = old_conn->http_proxy.passwd;
3262 conn->socks_proxy.passwd = old_conn->socks_proxy.passwd;
3263 old_conn->http_proxy.user = NULL;
3264 old_conn->socks_proxy.user = NULL;
3265 old_conn->http_proxy.passwd = NULL;
3266 old_conn->socks_proxy.passwd = NULL;
3269 /* host can change, when doing keepalive with a proxy or if the case is
3270 different this time etc */
3271 free_idnconverted_hostname(&conn->host);
3272 free_idnconverted_hostname(&conn->conn_to_host);
3273 Curl_safefree(conn->host.rawalloc);
3274 Curl_safefree(conn->conn_to_host.rawalloc);
3275 conn->host = old_conn->host;
3276 conn->conn_to_host = old_conn->conn_to_host;
3277 conn->conn_to_port = old_conn->conn_to_port;
3278 conn->remote_port = old_conn->remote_port;
3279 Curl_safefree(conn->hostname_resolve);
3281 conn->hostname_resolve = old_conn->hostname_resolve;
3282 old_conn->hostname_resolve = NULL;
3284 /* persist connection info in session handle */
3285 Curl_persistconninfo(conn);
3287 conn_reset_all_postponed_data(old_conn); /* free buffers */
3290 conn->bits.reuse = TRUE; /* yes, we're re-using here */
3292 Curl_safefree(old_conn->user);
3293 Curl_safefree(old_conn->passwd);
3294 Curl_safefree(old_conn->options);
3295 Curl_safefree(old_conn->http_proxy.user);
3296 Curl_safefree(old_conn->socks_proxy.user);
3297 Curl_safefree(old_conn->http_proxy.passwd);
3298 Curl_safefree(old_conn->socks_proxy.passwd);
3299 Curl_safefree(old_conn->localdev);
3300 Curl_llist_destroy(&old_conn->easyq, NULL);
3302 #ifdef USE_UNIX_SOCKETS
3303 Curl_safefree(old_conn->unix_domain_socket);
3308 * create_conn() sets up a new connectdata struct, or re-uses an already
3309 * existing one, and resolves host name.
3311 * if this function returns CURLE_OK and *async is set to TRUE, the resolve
3312 * response will be coming asynchronously. If *async is FALSE, the name is
3315 * @param data The sessionhandle pointer
3316 * @param in_connect is set to the next connection data pointer
3317 * @param async is set TRUE when an async DNS resolution is pending
3318 * @see Curl_setup_conn()
3320 * *NOTE* this function assigns the conn->data pointer!
3323 static CURLcode create_conn(struct Curl_easy *data,
3324 struct connectdata **in_connect,
3327 CURLcode result = CURLE_OK;
3328 struct connectdata *conn;
3329 struct connectdata *conn_temp = NULL;
3331 bool connections_available = TRUE;
3332 bool force_reuse = FALSE;
3333 bool waitpipe = FALSE;
3334 size_t max_host_connections = Curl_multi_max_host_connections(data->multi);
3335 size_t max_total_connections = Curl_multi_max_total_connections(data->multi);
3340 /*************************************************************
3342 *************************************************************/
3343 if(!data->change.url) {
3344 result = CURLE_URL_MALFORMAT;
3348 /* First, split up the current URL in parts so that we can use the
3349 parts for checking against the already present connections. In order
3350 to not have to modify everything at once, we allocate a temporary
3351 connection data struct and fill in for comparison purposes. */
3352 conn = allocate_conn(data);
3355 result = CURLE_OUT_OF_MEMORY;
3359 /* We must set the return variable as soon as possible, so that our
3360 parent can cleanup any possible allocs we may have done before
3364 result = parseurlandfillconn(data, conn);
3368 if(data->set.str[STRING_BEARER]) {
3369 conn->oauth_bearer = strdup(data->set.str[STRING_BEARER]);
3370 if(!conn->oauth_bearer) {
3371 result = CURLE_OUT_OF_MEMORY;
3376 if(data->set.str[STRING_SASL_AUTHZID]) {
3377 conn->sasl_authzid = strdup(data->set.str[STRING_SASL_AUTHZID]);
3378 if(!conn->sasl_authzid) {
3379 result = CURLE_OUT_OF_MEMORY;
3384 #ifdef USE_UNIX_SOCKETS
3385 if(data->set.str[STRING_UNIX_SOCKET_PATH]) {
3386 conn->unix_domain_socket = strdup(data->set.str[STRING_UNIX_SOCKET_PATH]);
3387 if(conn->unix_domain_socket == NULL) {
3388 result = CURLE_OUT_OF_MEMORY;
3391 conn->abstract_unix_socket = data->set.abstract_unix_socket;
3395 /* After the unix socket init but before the proxy vars are used, parse and
3396 initialize the proxy vars */
3397 #ifndef CURL_DISABLE_PROXY
3398 result = create_conn_helper_init_proxy(conn);
3403 /*************************************************************
3404 * If the protocol is using SSL and HTTP proxy is used, we set
3405 * the tunnel_proxy bit.
3406 *************************************************************/
3407 if((conn->given->flags&PROTOPT_SSL) && conn->bits.httpproxy)
3408 conn->bits.tunnel_proxy = TRUE;
3410 /*************************************************************
3411 * Figure out the remote port number and fix it in the URL
3412 *************************************************************/
3413 result = parse_remote_port(data, conn);
3417 /* Check for overridden login details and set them accordingly so they
3418 they are known when protocol->setup_connection is called! */
3419 result = override_login(data, conn, &conn->user, &conn->passwd,
3424 result = set_login(conn); /* default credentials */
3428 /*************************************************************
3429 * Process the "connect to" linked list of hostname/port mappings.
3430 * Do this after the remote port number has been fixed in the URL.
3431 *************************************************************/
3432 result = parse_connect_to_slist(data, conn, data->set.connect_to);
3436 /*************************************************************
3437 * IDN-convert the hostnames
3438 *************************************************************/
3439 result = idnconvert_hostname(conn, &conn->host);
3442 if(conn->bits.conn_to_host) {
3443 result = idnconvert_hostname(conn, &conn->conn_to_host);
3447 if(conn->bits.httpproxy) {
3448 result = idnconvert_hostname(conn, &conn->http_proxy.host);
3452 if(conn->bits.socksproxy) {
3453 result = idnconvert_hostname(conn, &conn->socks_proxy.host);
3458 /*************************************************************
3459 * Check whether the host and the "connect to host" are equal.
3460 * Do this after the hostnames have been IDN-converted.
3461 *************************************************************/
3462 if(conn->bits.conn_to_host &&
3463 strcasecompare(conn->conn_to_host.name, conn->host.name)) {
3464 conn->bits.conn_to_host = FALSE;
3467 /*************************************************************
3468 * Check whether the port and the "connect to port" are equal.
3469 * Do this after the remote port number has been fixed in the URL.
3470 *************************************************************/
3471 if(conn->bits.conn_to_port && conn->conn_to_port == conn->remote_port) {
3472 conn->bits.conn_to_port = FALSE;
3475 /*************************************************************
3476 * If the "connect to" feature is used with an HTTP proxy,
3477 * we set the tunnel_proxy bit.
3478 *************************************************************/
3479 if((conn->bits.conn_to_host || conn->bits.conn_to_port) &&
3480 conn->bits.httpproxy)
3481 conn->bits.tunnel_proxy = TRUE;
3483 /*************************************************************
3484 * Setup internals depending on protocol. Needs to be done after
3485 * we figured out what/if proxy to use.
3486 *************************************************************/
3487 result = setup_connection_internals(conn);
3491 conn->recv[FIRSTSOCKET] = Curl_recv_plain;
3492 conn->send[FIRSTSOCKET] = Curl_send_plain;
3493 conn->recv[SECONDARYSOCKET] = Curl_recv_plain;
3494 conn->send[SECONDARYSOCKET] = Curl_send_plain;
3496 conn->bits.tcp_fastopen = data->set.tcp_fastopen;
3498 /***********************************************************************
3499 * file: is a special case in that it doesn't need a network connection
3500 ***********************************************************************/
3501 #ifndef CURL_DISABLE_FILE
3502 if(conn->handler->flags & PROTOPT_NONETWORK) {
3504 /* this is supposed to be the connect function so we better at least check
3505 that the file is present here! */
3506 DEBUGASSERT(conn->handler->connect_it);
3507 Curl_persistconninfo(conn);
3508 result = conn->handler->connect_it(conn, &done);
3510 /* Setup a "faked" transfer that'll do nothing */
3512 conn->bits.tcpconnect[FIRSTSOCKET] = TRUE; /* we are "connected */
3514 result = Curl_conncache_add_conn(data->state.conn_cache, conn);
3519 * Setup whatever necessary for a resumed transfer
3521 result = setup_range(data);
3523 DEBUGASSERT(conn->handler->done);
3524 /* we ignore the return code for the protocol-specific DONE */
3525 (void)conn->handler->done(conn, result, FALSE);
3528 Curl_attach_connnection(data, conn);
3529 Curl_setup_transfer(data, -1, -1, FALSE, -1);
3532 /* since we skip do_init() */
3533 Curl_init_do(data, conn);
3539 /* Get a cloned copy of the SSL config situation stored in the
3540 connection struct. But to get this going nicely, we must first make
3541 sure that the strings in the master copy are pointing to the correct
3542 strings in the session handle strings array!
3544 Keep in mind that the pointers in the master copy are pointing to strings
3545 that will be freed as part of the Curl_easy struct, but all cloned
3546 copies will be separately allocated.
3548 data->set.ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH_ORIG];
3549 data->set.proxy_ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH_PROXY];
3550 data->set.ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE_ORIG];
3551 data->set.proxy_ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE_PROXY];
3552 data->set.ssl.primary.random_file = data->set.str[STRING_SSL_RANDOM_FILE];
3553 data->set.proxy_ssl.primary.random_file =
3554 data->set.str[STRING_SSL_RANDOM_FILE];
3555 data->set.ssl.primary.egdsocket = data->set.str[STRING_SSL_EGDSOCKET];
3556 data->set.proxy_ssl.primary.egdsocket = data->set.str[STRING_SSL_EGDSOCKET];
3557 data->set.ssl.primary.cipher_list =
3558 data->set.str[STRING_SSL_CIPHER_LIST_ORIG];
3559 data->set.proxy_ssl.primary.cipher_list =
3560 data->set.str[STRING_SSL_CIPHER_LIST_PROXY];
3561 data->set.ssl.primary.cipher_list13 =
3562 data->set.str[STRING_SSL_CIPHER13_LIST_ORIG];
3563 data->set.proxy_ssl.primary.cipher_list13 =
3564 data->set.str[STRING_SSL_CIPHER13_LIST_PROXY];
3565 data->set.ssl.primary.pinned_key =
3566 data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
3567 data->set.proxy_ssl.primary.pinned_key =
3568 data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY];
3570 data->set.ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE_ORIG];
3571 data->set.proxy_ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE_PROXY];
3572 data->set.ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT_ORIG];
3573 data->set.proxy_ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT_PROXY];
3574 data->set.ssl.cert = data->set.str[STRING_CERT_ORIG];
3575 data->set.proxy_ssl.cert = data->set.str[STRING_CERT_PROXY];
3576 data->set.ssl.cert_type = data->set.str[STRING_CERT_TYPE_ORIG];
3577 data->set.proxy_ssl.cert_type = data->set.str[STRING_CERT_TYPE_PROXY];
3578 data->set.ssl.key = data->set.str[STRING_KEY_ORIG];
3579 data->set.proxy_ssl.key = data->set.str[STRING_KEY_PROXY];
3580 data->set.ssl.key_type = data->set.str[STRING_KEY_TYPE_ORIG];
3581 data->set.proxy_ssl.key_type = data->set.str[STRING_KEY_TYPE_PROXY];
3582 data->set.ssl.key_passwd = data->set.str[STRING_KEY_PASSWD_ORIG];
3583 data->set.proxy_ssl.key_passwd = data->set.str[STRING_KEY_PASSWD_PROXY];
3584 data->set.ssl.primary.clientcert = data->set.str[STRING_CERT_ORIG];
3585 data->set.proxy_ssl.primary.clientcert = data->set.str[STRING_CERT_PROXY];
3587 data->set.ssl.username = data->set.str[STRING_TLSAUTH_USERNAME_ORIG];
3588 data->set.proxy_ssl.username = data->set.str[STRING_TLSAUTH_USERNAME_PROXY];
3589 data->set.ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD_ORIG];
3590 data->set.proxy_ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD_PROXY];
3593 if(!Curl_clone_primary_ssl_config(&data->set.ssl.primary,
3594 &conn->ssl_config)) {
3595 result = CURLE_OUT_OF_MEMORY;
3599 if(!Curl_clone_primary_ssl_config(&data->set.proxy_ssl.primary,
3600 &conn->proxy_ssl_config)) {
3601 result = CURLE_OUT_OF_MEMORY;
3605 prune_dead_connections(data);
3607 /*************************************************************
3608 * Check the current list of connections to see if we can
3609 * re-use an already existing one or if we have to create a
3611 *************************************************************/
3613 DEBUGASSERT(conn->user);
3614 DEBUGASSERT(conn->passwd);
3616 /* reuse_fresh is TRUE if we are told to use a new connection by force, but
3617 we only acknowledge this option if this is not a re-used connection
3618 already (which happens due to follow-location or during a HTTP
3619 authentication phase). CONNECT_ONLY transfers also refuse reuse. */
3620 if((data->set.reuse_fresh && !data->state.this_is_a_follow) ||
3621 data->set.connect_only)
3624 reuse = ConnectionExists(data, conn, &conn_temp, &force_reuse, &waitpipe);
3628 * We already have a connection for this, we got the former connection
3629 * in the conn_temp variable and thus we need to cleanup the one we
3630 * just allocated before we can move along and use the previously
3633 reuse_conn(conn, conn_temp);
3635 free(conn->ssl_extra);
3637 free(conn); /* we don't need this anymore */
3641 infof(data, "Re-using existing connection! (#%ld) with %s %s\n",
3642 conn->connection_id,
3643 conn->bits.proxy?"proxy":"host",
3644 conn->socks_proxy.host.name ? conn->socks_proxy.host.dispname :
3645 conn->http_proxy.host.name ? conn->http_proxy.host.dispname :
3646 conn->host.dispname);
3649 /* We have decided that we want a new connection. However, we may not
3650 be able to do that if we have reached the limit of how many
3651 connections we are allowed to open. */
3653 if(conn->handler->flags & PROTOPT_ALPN_NPN) {
3654 /* The protocol wants it, so set the bits if enabled in the easy handle
3656 if(data->set.ssl_enable_alpn)
3657 conn->bits.tls_enable_alpn = TRUE;
3658 if(data->set.ssl_enable_npn)
3659 conn->bits.tls_enable_npn = TRUE;
3663 /* There is a connection that *might* become usable for multiplexing
3664 "soon", and we wait for that */
3665 connections_available = FALSE;
3667 /* this gets a lock on the conncache */
3668 const char *bundlehost;
3669 struct connectbundle *bundle =
3670 Curl_conncache_find_bundle(conn, data->state.conn_cache, &bundlehost);
3672 if(max_host_connections > 0 && bundle &&
3673 (bundle->num_connections >= max_host_connections)) {
3674 struct connectdata *conn_candidate;
3676 /* The bundle is full. Extract the oldest connection. */
3677 conn_candidate = Curl_conncache_extract_bundle(data, bundle);
3678 Curl_conncache_unlock(data);
3681 (void)Curl_disconnect(data, conn_candidate,
3682 /* dead_connection */ FALSE);
3684 infof(data, "No more connections allowed to host %s: %zu\n",
3685 bundlehost, max_host_connections);
3686 connections_available = FALSE;
3690 Curl_conncache_unlock(data);
3694 if(connections_available &&
3695 (max_total_connections > 0) &&
3696 (Curl_conncache_size(data) >= max_total_connections)) {
3697 struct connectdata *conn_candidate;
3699 /* The cache is full. Let's see if we can kill a connection. */
3700 conn_candidate = Curl_conncache_extract_oldest(data);
3702 (void)Curl_disconnect(data, conn_candidate,
3703 /* dead_connection */ FALSE);
3705 infof(data, "No connections available in cache\n");
3706 connections_available = FALSE;
3710 if(!connections_available) {
3711 infof(data, "No connections available.\n");
3716 result = CURLE_NO_CONNECTION_AVAILABLE;
3721 * This is a brand new connection, so let's store it in the connection
3724 result = Curl_conncache_add_conn(data->state.conn_cache, conn);
3729 #if defined(USE_NTLM)
3730 /* If NTLM is requested in a part of this connection, make sure we don't
3731 assume the state is fine as this is a fresh connection and NTLM is
3732 connection based. */
3733 if((data->state.authhost.picked & (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) &&
3734 data->state.authhost.done) {
3735 infof(data, "NTLM picked AND auth done set, clear picked!\n");
3736 data->state.authhost.picked = CURLAUTH_NONE;
3737 data->state.authhost.done = FALSE;
3740 if((data->state.authproxy.picked & (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) &&
3741 data->state.authproxy.done) {
3742 infof(data, "NTLM-proxy picked AND auth done set, clear picked!\n");
3743 data->state.authproxy.picked = CURLAUTH_NONE;
3744 data->state.authproxy.done = FALSE;
3749 /* Setup and init stuff before DO starts, in preparing for the transfer. */
3750 Curl_init_do(data, conn);
3753 * Setup whatever necessary for a resumed transfer
3755 result = setup_range(data);
3759 /* Continue connectdata initialization here. */
3762 * Inherit the proper values from the urldata struct AFTER we have arranged
3763 * the persistent connection stuff
3765 conn->seek_func = data->set.seek_func;
3766 conn->seek_client = data->set.seek_client;
3768 /*************************************************************
3769 * Resolve the address of the server or proxy
3770 *************************************************************/
3771 result = resolve_server(data, conn, async);
3773 /* Strip trailing dots. resolve_server copied the name. */
3774 strip_trailing_dot(&conn->host);
3775 if(conn->bits.httpproxy)
3776 strip_trailing_dot(&conn->http_proxy.host);
3777 if(conn->bits.socksproxy)
3778 strip_trailing_dot(&conn->socks_proxy.host);
3779 if(conn->bits.conn_to_host)
3780 strip_trailing_dot(&conn->conn_to_host);
3786 /* Curl_setup_conn() is called after the name resolve initiated in
3787 * create_conn() is all done.
3789 * Curl_setup_conn() also handles reused connections
3791 * conn->data MUST already have been setup fine (in create_conn)
3794 CURLcode Curl_setup_conn(struct connectdata *conn,
3795 bool *protocol_done)
3797 CURLcode result = CURLE_OK;
3798 struct Curl_easy *data = conn->data;
3800 Curl_pgrsTime(data, TIMER_NAMELOOKUP);
3802 if(conn->handler->flags & PROTOPT_NONETWORK) {
3803 /* nothing to setup when not using a network */
3804 *protocol_done = TRUE;
3807 *protocol_done = FALSE; /* default to not done */
3809 /* set proxy_connect_closed to false unconditionally already here since it
3810 is used strictly to provide extra information to a parent function in the
3811 case of proxy CONNECT failures and we must make sure we don't have it
3812 lingering set from a previous invoke */
3813 conn->bits.proxy_connect_closed = FALSE;
3816 * Set user-agent. Used for HTTP, but since we can attempt to tunnel
3817 * basically anything through a http proxy we can't limit this based on
3820 if(data->set.str[STRING_USERAGENT]) {
3821 Curl_safefree(conn->allocptr.uagent);
3822 conn->allocptr.uagent =
3823 aprintf("User-Agent: %s\r\n", data->set.str[STRING_USERAGENT]);
3824 if(!conn->allocptr.uagent)
3825 return CURLE_OUT_OF_MEMORY;
3828 data->req.headerbytecount = 0;
3830 #ifdef CURL_DO_LINEEND_CONV
3831 data->state.crlf_conversions = 0; /* reset CRLF conversion counter */
3832 #endif /* CURL_DO_LINEEND_CONV */
3834 /* set start time here for timeout purposes in the connect procedure, it
3835 is later set again for the progress meter purpose */
3836 conn->now = Curl_now();
3838 if(CURL_SOCKET_BAD == conn->sock[FIRSTSOCKET]) {
3839 conn->bits.tcpconnect[FIRSTSOCKET] = FALSE;
3840 result = Curl_connecthost(conn, conn->dns_entry);
3845 Curl_pgrsTime(data, TIMER_CONNECT); /* we're connected already */
3846 if(conn->ssl[FIRSTSOCKET].use ||
3847 (conn->handler->protocol & PROTO_FAMILY_SSH))
3848 Curl_pgrsTime(data, TIMER_APPCONNECT); /* we're connected already */
3849 conn->bits.tcpconnect[FIRSTSOCKET] = TRUE;
3850 *protocol_done = TRUE;
3851 Curl_updateconninfo(conn, conn->sock[FIRSTSOCKET]);
3852 Curl_verboseconnect(conn);
3855 conn->now = Curl_now(); /* time this *after* the connect is done, we set
3856 this here perhaps a second time */
3860 CURLcode Curl_connect(struct Curl_easy *data,
3862 bool *protocol_done)
3865 struct connectdata *conn;
3867 *asyncp = FALSE; /* assume synchronous resolves by default */
3869 /* init the single-transfer specific data */
3870 Curl_free_request_state(data);
3871 memset(&data->req, 0, sizeof(struct SingleRequest));
3872 data->req.maxdownload = -1;
3874 /* call the stuff that needs to be called */
3875 result = create_conn(data, &conn, asyncp);
3878 if(CONN_INUSE(conn))
3880 *protocol_done = TRUE;
3882 /* DNS resolution is done: that's either because this is a reused
3883 connection, in which case DNS was unnecessary, or because DNS
3884 really did finish already (synch resolver/fast async resolve) */
3885 result = Curl_setup_conn(conn, protocol_done);
3889 if(result == CURLE_NO_CONNECTION_AVAILABLE) {
3892 else if(result && conn) {
3893 /* We're not allowed to return failure with memory left allocated in the
3894 connectdata struct, free those here */
3895 Curl_disconnect(data, conn, TRUE);
3897 else if(!result && !data->conn)
3898 /* FILE: transfers already have the connection attached */
3899 Curl_attach_connnection(data, conn);
3905 * Curl_init_do() inits the readwrite session. This is inited each time (in
3906 * the DO function before the protocol-specific DO functions are invoked) for
3907 * a transfer, sometimes multiple times on the same Curl_easy. Make sure
3908 * nothing in here depends on stuff that are setup dynamically for the
3911 * Allow this function to get called with 'conn' set to NULL.
3914 CURLcode Curl_init_do(struct Curl_easy *data, struct connectdata *conn)
3916 struct SingleRequest *k = &data->req;
3919 conn->bits.do_more = FALSE; /* by default there's no curl_do_more() to
3921 /* if the protocol used doesn't support wildcards, switch it off */
3922 if(data->state.wildcardmatch &&
3923 !(conn->handler->flags & PROTOPT_WILDCARD))
3924 data->state.wildcardmatch = FALSE;
3927 data->state.done = FALSE; /* *_done() is not called yet */
3928 data->state.expect100header = FALSE;
3931 if(data->set.opt_no_body)
3932 /* in HTTP lingo, no body means using the HEAD request... */
3933 data->set.httpreq = HTTPREQ_HEAD;
3934 else if(HTTPREQ_HEAD == data->set.httpreq)
3935 /* ... but if unset there really is no perfect method that is the
3936 "opposite" of HEAD but in reality most people probably think GET
3937 then. The important thing is that we can't let it remain HEAD if the
3938 opt_no_body is set FALSE since then we'll behave wrong when getting
3940 data->set.httpreq = HTTPREQ_GET;
3942 k->start = Curl_now(); /* start time */
3943 k->now = k->start; /* current time is now */
3944 k->header = TRUE; /* assume header */
3948 k->buf = data->state.buffer;
3949 k->hbufp = data->state.headerbuff;
3950 k->ignorebody = FALSE;
3952 Curl_speedinit(data);
3954 Curl_pgrsSetUploadCounter(data, 0);
3955 Curl_pgrsSetDownloadCounter(data, 0);
3961 * get_protocol_family()
3963 * This is used to return the protocol family for a given protocol.
3967 * protocol [in] - A single bit protocol identifier such as HTTP or HTTPS.
3969 * Returns the family as a single bit protocol identifier.
3972 static unsigned int get_protocol_family(unsigned int protocol)
3974 unsigned int family;
3977 case CURLPROTO_HTTP:
3978 case CURLPROTO_HTTPS:
3979 family = CURLPROTO_HTTP;
3983 case CURLPROTO_FTPS:
3984 family = CURLPROTO_FTP;
3988 family = CURLPROTO_SCP;
3991 case CURLPROTO_SFTP:
3992 family = CURLPROTO_SFTP;
3995 case CURLPROTO_TELNET:
3996 family = CURLPROTO_TELNET;
3999 case CURLPROTO_LDAP:
4000 case CURLPROTO_LDAPS:
4001 family = CURLPROTO_LDAP;
4004 case CURLPROTO_DICT:
4005 family = CURLPROTO_DICT;
4008 case CURLPROTO_FILE:
4009 family = CURLPROTO_FILE;
4012 case CURLPROTO_TFTP:
4013 family = CURLPROTO_TFTP;
4016 case CURLPROTO_IMAP:
4017 case CURLPROTO_IMAPS:
4018 family = CURLPROTO_IMAP;
4021 case CURLPROTO_POP3:
4022 case CURLPROTO_POP3S:
4023 family = CURLPROTO_POP3;
4026 case CURLPROTO_SMTP:
4027 case CURLPROTO_SMTPS:
4028 family = CURLPROTO_SMTP;
4031 case CURLPROTO_RTSP:
4032 family = CURLPROTO_RTSP;
4035 case CURLPROTO_RTMP:
4036 case CURLPROTO_RTMPS:
4037 family = CURLPROTO_RTMP;
4040 case CURLPROTO_RTMPT:
4041 case CURLPROTO_RTMPTS:
4042 family = CURLPROTO_RTMPT;
4045 case CURLPROTO_RTMPE:
4046 family = CURLPROTO_RTMPE;
4049 case CURLPROTO_RTMPTE:
4050 family = CURLPROTO_RTMPTE;
4053 case CURLPROTO_GOPHER:
4054 family = CURLPROTO_GOPHER;
4058 case CURLPROTO_SMBS:
4059 family = CURLPROTO_SMB;