url.c
Go to the documentation of this file.
00001 /***************************************************************************
00002  *                                  _   _ ____  _
00003  *  Project                     ___| | | |  _ \| |
00004  *                             / __| | | | |_) | |
00005  *                            | (__| |_| |  _ <| |___
00006  *                             \___|\___/|_| \_\_____|
00007  *
00008  * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
00009  *
00010  * This software is licensed as described in the file COPYING, which
00011  * you should have received as part of this distribution. The terms
00012  * are also available at https://curl.haxx.se/docs/copyright.html.
00013  *
00014  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
00015  * copies of the Software, and permit persons to whom the Software is
00016  * furnished to do so, under the terms of the COPYING file.
00017  *
00018  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
00019  * KIND, either express or implied.
00020  *
00021  ***************************************************************************/
00022 
00023 #include "curl_setup.h"
00024 
00025 #ifdef HAVE_NETINET_IN_H
00026 #include <netinet/in.h>
00027 #endif
00028 #ifdef HAVE_NETDB_H
00029 #include <netdb.h>
00030 #endif
00031 #ifdef HAVE_ARPA_INET_H
00032 #include <arpa/inet.h>
00033 #endif
00034 #ifdef HAVE_NET_IF_H
00035 #include <net/if.h>
00036 #endif
00037 #ifdef HAVE_SYS_IOCTL_H
00038 #include <sys/ioctl.h>
00039 #endif
00040 
00041 #ifdef HAVE_SYS_PARAM_H
00042 #include <sys/param.h>
00043 #endif
00044 
00045 #ifdef __VMS
00046 #include <in.h>
00047 #include <inet.h>
00048 #endif
00049 
00050 #ifdef HAVE_SYS_UN_H
00051 #include <sys/un.h>
00052 #endif
00053 
00054 #ifndef HAVE_SOCKET
00055 #error "We can't compile without socket() support!"
00056 #endif
00057 
00058 #ifdef HAVE_LIMITS_H
00059 #include <limits.h>
00060 #endif
00061 
00062 #ifdef USE_LIBIDN2
00063 #include <idn2.h>
00064 
00065 #elif defined(USE_WIN32_IDN)
00066 /* prototype for curl_win32_idn_to_ascii() */
00067 bool curl_win32_idn_to_ascii(const char *in, char **out);
00068 #endif  /* USE_LIBIDN2 */
00069 
00070 #include "urldata.h"
00071 #include "netrc.h"
00072 
00073 #include "formdata.h"
00074 #include "vtls/vtls.h"
00075 #include "hostip.h"
00076 #include "transfer.h"
00077 #include "sendf.h"
00078 #include "progress.h"
00079 #include "cookie.h"
00080 #include "strcase.h"
00081 #include "strerror.h"
00082 #include "escape.h"
00083 #include "strtok.h"
00084 #include "share.h"
00085 #include "content_encoding.h"
00086 #include "http_digest.h"
00087 #include "http_negotiate.h"
00088 #include "select.h"
00089 #include "multiif.h"
00090 #include "easyif.h"
00091 #include "speedcheck.h"
00092 #include "warnless.h"
00093 #include "non-ascii.h"
00094 #include "inet_pton.h"
00095 #include "getinfo.h"
00096 
00097 /* And now for the protocols */
00098 #include "ftp.h"
00099 #include "dict.h"
00100 #include "telnet.h"
00101 #include "tftp.h"
00102 #include "http.h"
00103 #include "http2.h"
00104 #include "file.h"
00105 #include "curl_ldap.h"
00106 #include "ssh.h"
00107 #include "imap.h"
00108 #include "url.h"
00109 #include "connect.h"
00110 #include "inet_ntop.h"
00111 #include "http_ntlm.h"
00112 #include "curl_ntlm_wb.h"
00113 #include "socks.h"
00114 #include "curl_rtmp.h"
00115 #include "gopher.h"
00116 #include "http_proxy.h"
00117 #include "conncache.h"
00118 #include "multihandle.h"
00119 #include "pipeline.h"
00120 #include "dotdot.h"
00121 #include "strdup.h"
00122 /* The last 3 #include files should be in this order */
00123 #include "curl_printf.h"
00124 #include "curl_memory.h"
00125 #include "memdebug.h"
00126 
00127 /* Local static prototypes */
00128 static struct connectdata *
00129 find_oldest_idle_connection_in_bundle(struct Curl_easy *data,
00130                                       struct connectbundle *bundle);
00131 static void conn_free(struct connectdata *conn);
00132 static void free_fixed_hostname(struct hostname *host);
00133 static void signalPipeClose(struct curl_llist *pipeline, bool pipe_broke);
00134 static CURLcode parse_url_login(struct Curl_easy *data,
00135                                 struct connectdata *conn,
00136                                 char **userptr, char **passwdptr,
00137                                 char **optionsptr);
00138 static CURLcode parse_login_details(const char *login, const size_t len,
00139                                     char **userptr, char **passwdptr,
00140                                     char **optionsptr);
00141 static unsigned int get_protocol_family(unsigned int protocol);
00142 
00143 /*
00144  * Protocol table.
00145  */
00146 
00147 static const struct Curl_handler * const protocols[] = {
00148 
00149 #ifndef CURL_DISABLE_HTTP
00150   &Curl_handler_http,
00151 #endif
00152 
00153 #if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP)
00154   &Curl_handler_https,
00155 #endif
00156 
00157 #ifndef CURL_DISABLE_FTP
00158   &Curl_handler_ftp,
00159 #endif
00160 
00161 #if defined(USE_SSL) && !defined(CURL_DISABLE_FTP)
00162   &Curl_handler_ftps,
00163 #endif
00164 
00165 #ifndef CURL_DISABLE_TELNET
00166   &Curl_handler_telnet,
00167 #endif
00168 
00169 #ifndef CURL_DISABLE_DICT
00170   &Curl_handler_dict,
00171 #endif
00172 
00173 #ifndef CURL_DISABLE_LDAP
00174   &Curl_handler_ldap,
00175 #if !defined(CURL_DISABLE_LDAPS) && \
00176     ((defined(USE_OPENLDAP) && defined(USE_SSL)) || \
00177      (!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL)))
00178   &Curl_handler_ldaps,
00179 #endif
00180 #endif
00181 
00182 #ifndef CURL_DISABLE_FILE
00183   &Curl_handler_file,
00184 #endif
00185 
00186 #ifndef CURL_DISABLE_TFTP
00187   &Curl_handler_tftp,
00188 #endif
00189 
00190 #ifdef USE_LIBSSH2
00191   &Curl_handler_scp,
00192   &Curl_handler_sftp,
00193 #endif
00194 
00195 #ifndef CURL_DISABLE_IMAP
00196   &Curl_handler_imap,
00197 #ifdef USE_SSL
00198   &Curl_handler_imaps,
00199 #endif
00200 #endif
00201 
00202 #ifndef CURL_DISABLE_POP3
00203   &Curl_handler_pop3,
00204 #ifdef USE_SSL
00205   &Curl_handler_pop3s,
00206 #endif
00207 #endif
00208 
00209 #if !defined(CURL_DISABLE_SMB) && defined(USE_NTLM) && \
00210    (CURL_SIZEOF_CURL_OFF_T > 4) && \
00211    (!defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO))
00212   &Curl_handler_smb,
00213 #ifdef USE_SSL
00214   &Curl_handler_smbs,
00215 #endif
00216 #endif
00217 
00218 #ifndef CURL_DISABLE_SMTP
00219   &Curl_handler_smtp,
00220 #ifdef USE_SSL
00221   &Curl_handler_smtps,
00222 #endif
00223 #endif
00224 
00225 #ifndef CURL_DISABLE_RTSP
00226   &Curl_handler_rtsp,
00227 #endif
00228 
00229 #ifndef CURL_DISABLE_GOPHER
00230   &Curl_handler_gopher,
00231 #endif
00232 
00233 #ifdef USE_LIBRTMP
00234   &Curl_handler_rtmp,
00235   &Curl_handler_rtmpt,
00236   &Curl_handler_rtmpe,
00237   &Curl_handler_rtmpte,
00238   &Curl_handler_rtmps,
00239   &Curl_handler_rtmpts,
00240 #endif
00241 
00242   (struct Curl_handler *) NULL
00243 };
00244 
00245 /*
00246  * Dummy handler for undefined protocol schemes.
00247  */
00248 
00249 static const struct Curl_handler Curl_handler_dummy = {
00250   "<no protocol>",                      /* scheme */
00251   ZERO_NULL,                            /* setup_connection */
00252   ZERO_NULL,                            /* do_it */
00253   ZERO_NULL,                            /* done */
00254   ZERO_NULL,                            /* do_more */
00255   ZERO_NULL,                            /* connect_it */
00256   ZERO_NULL,                            /* connecting */
00257   ZERO_NULL,                            /* doing */
00258   ZERO_NULL,                            /* proto_getsock */
00259   ZERO_NULL,                            /* doing_getsock */
00260   ZERO_NULL,                            /* domore_getsock */
00261   ZERO_NULL,                            /* perform_getsock */
00262   ZERO_NULL,                            /* disconnect */
00263   ZERO_NULL,                            /* readwrite */
00264   0,                                    /* defport */
00265   0,                                    /* protocol */
00266   PROTOPT_NONE                          /* flags */
00267 };
00268 
00269 void Curl_freeset(struct Curl_easy *data)
00270 {
00271   /* Free all dynamic strings stored in the data->set substructure. */
00272   enum dupstring i;
00273   for(i=(enum dupstring)0; i < STRING_LAST; i++) {
00274     Curl_safefree(data->set.str[i]);
00275   }
00276 
00277   if(data->change.referer_alloc) {
00278     Curl_safefree(data->change.referer);
00279     data->change.referer_alloc = FALSE;
00280   }
00281   data->change.referer = NULL;
00282   if(data->change.url_alloc) {
00283     Curl_safefree(data->change.url);
00284     data->change.url_alloc = FALSE;
00285   }
00286   data->change.url = NULL;
00287 }
00288 
00289 static CURLcode setstropt(char **charp, const char *s)
00290 {
00291   /* Release the previous storage at `charp' and replace by a dynamic storage
00292      copy of `s'. Return CURLE_OK or CURLE_OUT_OF_MEMORY. */
00293 
00294   Curl_safefree(*charp);
00295 
00296   if(s) {
00297     char *str = strdup(s);
00298 
00299     if(!str)
00300       return CURLE_OUT_OF_MEMORY;
00301 
00302     *charp = str;
00303   }
00304 
00305   return CURLE_OK;
00306 }
00307 
00308 static CURLcode setstropt_userpwd(char *option, char **userp, char **passwdp)
00309 {
00310   CURLcode result = CURLE_OK;
00311   char *user = NULL;
00312   char *passwd = NULL;
00313 
00314   /* Parse the login details if specified. It not then we treat NULL as a hint
00315      to clear the existing data */
00316   if(option) {
00317     result = parse_login_details(option, strlen(option),
00318                                  (userp ? &user : NULL),
00319                                  (passwdp ? &passwd : NULL),
00320                                  NULL);
00321   }
00322 
00323   if(!result) {
00324     /* Store the username part of option if required */
00325     if(userp) {
00326       if(!user && option && option[0] == ':') {
00327         /* Allocate an empty string instead of returning NULL as user name */
00328         user = strdup("");
00329         if(!user)
00330           result = CURLE_OUT_OF_MEMORY;
00331       }
00332 
00333       Curl_safefree(*userp);
00334       *userp = user;
00335     }
00336 
00337     /* Store the password part of option if required */
00338     if(passwdp) {
00339       Curl_safefree(*passwdp);
00340       *passwdp = passwd;
00341     }
00342   }
00343 
00344   return result;
00345 }
00346 
00347 CURLcode Curl_dupset(struct Curl_easy *dst, struct Curl_easy *src)
00348 {
00349   CURLcode result = CURLE_OK;
00350   enum dupstring i;
00351 
00352   /* Copy src->set into dst->set first, then deal with the strings
00353      afterwards */
00354   dst->set = src->set;
00355 
00356   /* clear all string pointers first */
00357   memset(dst->set.str, 0, STRING_LAST * sizeof(char *));
00358 
00359   /* duplicate all strings */
00360   for(i=(enum dupstring)0; i< STRING_LASTZEROTERMINATED; i++) {
00361     result = setstropt(&dst->set.str[i], src->set.str[i]);
00362     if(result)
00363       return result;
00364   }
00365 
00366   /* duplicate memory areas pointed to */
00367   i = STRING_COPYPOSTFIELDS;
00368   if(src->set.postfieldsize && src->set.str[i]) {
00369     /* postfieldsize is curl_off_t, Curl_memdup() takes a size_t ... */
00370     dst->set.str[i] = Curl_memdup(src->set.str[i],
00371                                   curlx_sotouz(src->set.postfieldsize));
00372     if(!dst->set.str[i])
00373       return CURLE_OUT_OF_MEMORY;
00374     /* point to the new copy */
00375     dst->set.postfields = dst->set.str[i];
00376   }
00377 
00378   return CURLE_OK;
00379 }
00380 
00381 /*
00382  * This is the internal function curl_easy_cleanup() calls. This should
00383  * cleanup and free all resources associated with this sessionhandle.
00384  *
00385  * NOTE: if we ever add something that attempts to write to a socket or
00386  * similar here, we must ignore SIGPIPE first. It is currently only done
00387  * when curl_easy_perform() is invoked.
00388  */
00389 
00390 CURLcode Curl_close(struct Curl_easy *data)
00391 {
00392   struct Curl_multi *m;
00393 
00394   if(!data)
00395     return CURLE_OK;
00396 
00397   Curl_expire_clear(data); /* shut off timers */
00398 
00399   m = data->multi;
00400 
00401   if(m)
00402     /* This handle is still part of a multi handle, take care of this first
00403        and detach this handle from there. */
00404     curl_multi_remove_handle(data->multi, data);
00405 
00406   if(data->multi_easy)
00407     /* when curl_easy_perform() is used, it creates its own multi handle to
00408        use and this is the one */
00409     curl_multi_cleanup(data->multi_easy);
00410 
00411   /* Destroy the timeout list that is held in the easy handle. It is
00412      /normally/ done by curl_multi_remove_handle() but this is "just in
00413      case" */
00414   if(data->state.timeoutlist) {
00415     Curl_llist_destroy(data->state.timeoutlist, NULL);
00416     data->state.timeoutlist = NULL;
00417   }
00418 
00419   data->magic = 0; /* force a clear AFTER the possibly enforced removal from
00420                       the multi handle, since that function uses the magic
00421                       field! */
00422 
00423   if(data->state.rangestringalloc)
00424     free(data->state.range);
00425 
00426   /* Free the pathbuffer */
00427   Curl_safefree(data->state.pathbuffer);
00428   data->state.path = NULL;
00429 
00430   /* freed here just in case DONE wasn't called */
00431   Curl_free_request_state(data);
00432 
00433   /* Close down all open SSL info and sessions */
00434   Curl_ssl_close_all(data);
00435   Curl_safefree(data->state.first_host);
00436   Curl_safefree(data->state.scratch);
00437   Curl_ssl_free_certinfo(data);
00438 
00439   /* Cleanup possible redirect junk */
00440   free(data->req.newurl);
00441   data->req.newurl = NULL;
00442 
00443   if(data->change.referer_alloc) {
00444     Curl_safefree(data->change.referer);
00445     data->change.referer_alloc = FALSE;
00446   }
00447   data->change.referer = NULL;
00448 
00449   if(data->change.url_alloc) {
00450     Curl_safefree(data->change.url);
00451     data->change.url_alloc = FALSE;
00452   }
00453   data->change.url = NULL;
00454 
00455   Curl_safefree(data->state.headerbuff);
00456 
00457   Curl_flush_cookies(data, 1);
00458 
00459   Curl_digest_cleanup(data);
00460 
00461   Curl_safefree(data->info.contenttype);
00462   Curl_safefree(data->info.wouldredirect);
00463 
00464   /* this destroys the channel and we cannot use it anymore after this */
00465   Curl_resolver_cleanup(data->state.resolver);
00466 
00467   Curl_http2_cleanup_dependencies(data);
00468   Curl_convert_close(data);
00469 
00470   /* No longer a dirty share, if it exists */
00471   if(data->share) {
00472     Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
00473     data->share->dirty--;
00474     Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
00475   }
00476 
00477   if(data->set.wildcardmatch) {
00478     /* destruct wildcard structures if it is needed */
00479     struct WildcardData *wc = &data->wildcard;
00480     Curl_wildcard_dtor(wc);
00481   }
00482 
00483   Curl_freeset(data);
00484   free(data);
00485   return CURLE_OK;
00486 }
00487 
00488 /*
00489  * Initialize the UserDefined fields within a Curl_easy.
00490  * This may be safely called on a new or existing Curl_easy.
00491  */
00492 CURLcode Curl_init_userdefined(struct UserDefined *set)
00493 {
00494   CURLcode result = CURLE_OK;
00495 
00496   set->out = stdout; /* default output to stdout */
00497   set->in_set = stdin;  /* default input from stdin */
00498   set->err  = stderr;  /* default stderr to stderr */
00499 
00500   /* use fwrite as default function to store output */
00501   set->fwrite_func = (curl_write_callback)fwrite;
00502 
00503   /* use fread as default function to read input */
00504   set->fread_func_set = (curl_read_callback)fread;
00505   set->is_fread_set = 0;
00506   set->is_fwrite_set = 0;
00507 
00508   set->seek_func = ZERO_NULL;
00509   set->seek_client = ZERO_NULL;
00510 
00511   /* conversion callbacks for non-ASCII hosts */
00512   set->convfromnetwork = ZERO_NULL;
00513   set->convtonetwork   = ZERO_NULL;
00514   set->convfromutf8    = ZERO_NULL;
00515 
00516   set->filesize = -1;        /* we don't know the size */
00517   set->postfieldsize = -1;   /* unknown size */
00518   set->maxredirs = -1;       /* allow any amount by default */
00519 
00520   set->httpreq = HTTPREQ_GET; /* Default HTTP request */
00521   set->rtspreq = RTSPREQ_OPTIONS; /* Default RTSP request */
00522   set->ftp_use_epsv = TRUE;   /* FTP defaults to EPSV operations */
00523   set->ftp_use_eprt = TRUE;   /* FTP defaults to EPRT operations */
00524   set->ftp_use_pret = FALSE;  /* mainly useful for drftpd servers */
00525   set->ftp_filemethod = FTPFILE_MULTICWD;
00526 
00527   set->dns_cache_timeout = 60; /* Timeout every 60 seconds by default */
00528 
00529   /* Set the default size of the SSL session ID cache */
00530   set->general_ssl.max_ssl_sessions = 5;
00531 
00532   set->proxyport = 0;
00533   set->proxytype = CURLPROXY_HTTP; /* defaults to HTTP proxy */
00534   set->httpauth = CURLAUTH_BASIC;  /* defaults to basic */
00535   set->proxyauth = CURLAUTH_BASIC; /* defaults to basic */
00536 
00537   /* make libcurl quiet by default: */
00538   set->hide_progress = TRUE;  /* CURLOPT_NOPROGRESS changes these */
00539 
00540   /*
00541    * libcurl 7.10 introduced SSL verification *by default*! This needs to be
00542    * switched off unless wanted.
00543    */
00544   set->ssl.primary.verifypeer = TRUE;
00545   set->ssl.primary.verifyhost = TRUE;
00546 #ifdef USE_TLS_SRP
00547   set->ssl.authtype = CURL_TLSAUTH_NONE;
00548 #endif
00549   set->ssh_auth_types = CURLSSH_AUTH_DEFAULT; /* defaults to any auth
00550                                                       type */
00551   set->general_ssl.sessionid = TRUE; /* session ID caching enabled by
00552                                         default */
00553   set->proxy_ssl = set->ssl;
00554 
00555   set->new_file_perms = 0644;    /* Default permissions */
00556   set->new_directory_perms = 0755; /* Default permissions */
00557 
00558   /* for the *protocols fields we don't use the CURLPROTO_ALL convenience
00559      define since we internally only use the lower 16 bits for the passed
00560      in bitmask to not conflict with the private bits */
00561   set->allowed_protocols = CURLPROTO_ALL;
00562   set->redir_protocols = CURLPROTO_ALL &  /* All except FILE, SCP and SMB */
00563                           ~(CURLPROTO_FILE | CURLPROTO_SCP | CURLPROTO_SMB |
00564                             CURLPROTO_SMBS);
00565 
00566 #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
00567   /*
00568    * disallow unprotected protection negotiation NEC reference implementation
00569    * seem not to follow rfc1961 section 4.3/4.4
00570    */
00571   set->socks5_gssapi_nec = FALSE;
00572 #endif
00573 
00574   /* This is our preferred CA cert bundle/path since install time */
00575 #if defined(CURL_CA_BUNDLE)
00576   result = setstropt(&set->str[STRING_SSL_CAFILE_ORIG], CURL_CA_BUNDLE);
00577   if(result)
00578     return result;
00579 #endif
00580 #if defined(CURL_CA_PATH)
00581   result = setstropt(&set->str[STRING_SSL_CAPATH_ORIG], CURL_CA_PATH);
00582   if(result)
00583     return result;
00584 
00585   result = setstropt(&set->str[STRING_SSL_CAPATH_PROXY],
00586                      (char *) CURL_CA_PATH);
00587 #endif
00588 
00589   set->wildcardmatch  = FALSE;
00590   set->chunk_bgn      = ZERO_NULL;
00591   set->chunk_end      = ZERO_NULL;
00592 
00593   /* tcp keepalives are disabled by default, but provide reasonable values for
00594    * the interval and idle times.
00595    */
00596   set->tcp_keepalive = FALSE;
00597   set->tcp_keepintvl = 60;
00598   set->tcp_keepidle = 60;
00599   set->tcp_fastopen = FALSE;
00600   set->tcp_nodelay = TRUE;
00601 
00602   set->ssl_enable_npn = TRUE;
00603   set->ssl_enable_alpn = TRUE;
00604 
00605   set->expect_100_timeout = 1000L; /* Wait for a second by default. */
00606   set->sep_headers = TRUE; /* separated header lists by default */
00607 
00608   Curl_http2_init_userset(set);
00609   return result;
00610 }
00611 
00620 CURLcode Curl_open(struct Curl_easy **curl)
00621 {
00622   CURLcode result;
00623   struct Curl_easy *data;
00624 
00625   /* Very simple start-up: alloc the struct, init it with zeroes and return */
00626   data = calloc(1, sizeof(struct Curl_easy));
00627   if(!data) {
00628     /* this is a very serious error */
00629     DEBUGF(fprintf(stderr, "Error: calloc of Curl_easy failed\n"));
00630     return CURLE_OUT_OF_MEMORY;
00631   }
00632 
00633   data->magic = CURLEASY_MAGIC_NUMBER;
00634 
00635   result = Curl_resolver_init(&data->state.resolver);
00636   if(result) {
00637     DEBUGF(fprintf(stderr, "Error: resolver_init failed\n"));
00638     free(data);
00639     return result;
00640   }
00641 
00642   /* We do some initial setup here, all those fields that can't be just 0 */
00643 
00644   data->state.headerbuff = malloc(HEADERSIZE);
00645   if(!data->state.headerbuff) {
00646     DEBUGF(fprintf(stderr, "Error: malloc of headerbuff failed\n"));
00647     result = CURLE_OUT_OF_MEMORY;
00648   }
00649   else {
00650     result = Curl_init_userdefined(&data->set);
00651 
00652     data->state.headersize=HEADERSIZE;
00653 
00654     Curl_convert_init(data);
00655 
00656     Curl_initinfo(data);
00657 
00658     /* most recent connection is not yet defined */
00659     data->state.lastconnect = NULL;
00660 
00661     data->progress.flags |= PGRS_HIDE;
00662     data->state.current_speed = -1; /* init to negative == impossible */
00663 
00664     data->wildcard.state = CURLWC_INIT;
00665     data->wildcard.filelist = NULL;
00666     data->set.fnmatch = ZERO_NULL;
00667     data->set.maxconnects = DEFAULT_CONNCACHE_SIZE; /* for easy handles */
00668 
00669     Curl_http2_init_state(&data->state);
00670   }
00671 
00672   if(result) {
00673     Curl_resolver_cleanup(data->state.resolver);
00674     free(data->state.headerbuff);
00675     Curl_freeset(data);
00676     free(data);
00677     data = NULL;
00678   }
00679   else
00680     *curl = data;
00681 
00682   return result;
00683 }
00684 
00685 CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
00686                      va_list param)
00687 {
00688   char *argptr;
00689   CURLcode result = CURLE_OK;
00690   long arg;
00691 #ifndef CURL_DISABLE_HTTP
00692   curl_off_t bigsize;
00693 #endif
00694 
00695   switch(option) {
00696   case CURLOPT_DNS_CACHE_TIMEOUT:
00697     data->set.dns_cache_timeout = va_arg(param, long);
00698     break;
00699   case CURLOPT_DNS_USE_GLOBAL_CACHE:
00700     /* remember we want this enabled */
00701     arg = va_arg(param, long);
00702     data->set.global_dns_cache = (0 != arg) ? TRUE : FALSE;
00703     break;
00704   case CURLOPT_SSL_CIPHER_LIST:
00705     /* set a list of cipher we want to use in the SSL connection */
00706     result = setstropt(&data->set.str[STRING_SSL_CIPHER_LIST_ORIG],
00707                        va_arg(param, char *));
00708     break;
00709   case CURLOPT_PROXY_SSL_CIPHER_LIST:
00710     /* set a list of cipher we want to use in the SSL connection for proxy */
00711     result = setstropt(&data->set.str[STRING_SSL_CIPHER_LIST_PROXY],
00712                        va_arg(param, char *));
00713     break;
00714 
00715   case CURLOPT_RANDOM_FILE:
00716     /*
00717      * This is the path name to a file that contains random data to seed
00718      * the random SSL stuff with. The file is only used for reading.
00719      */
00720     result = setstropt(&data->set.str[STRING_SSL_RANDOM_FILE],
00721                        va_arg(param, char *));
00722     break;
00723   case CURLOPT_EGDSOCKET:
00724     /*
00725      * The Entropy Gathering Daemon socket pathname
00726      */
00727     result = setstropt(&data->set.str[STRING_SSL_EGDSOCKET],
00728                        va_arg(param, char *));
00729     break;
00730   case CURLOPT_MAXCONNECTS:
00731     /*
00732      * Set the absolute number of maximum simultaneous alive connection that
00733      * libcurl is allowed to have.
00734      */
00735     data->set.maxconnects = va_arg(param, long);
00736     break;
00737   case CURLOPT_FORBID_REUSE:
00738     /*
00739      * When this transfer is done, it must not be left to be reused by a
00740      * subsequent transfer but shall be closed immediately.
00741      */
00742     data->set.reuse_forbid = (0 != va_arg(param, long)) ? TRUE : FALSE;
00743     break;
00744   case CURLOPT_FRESH_CONNECT:
00745     /*
00746      * This transfer shall not use a previously cached connection but
00747      * should be made with a fresh new connect!
00748      */
00749     data->set.reuse_fresh = (0 != va_arg(param, long)) ? TRUE : FALSE;
00750     break;
00751   case CURLOPT_VERBOSE:
00752     /*
00753      * Verbose means infof() calls that give a lot of information about
00754      * the connection and transfer procedures as well as internal choices.
00755      */
00756     data->set.verbose = (0 != va_arg(param, long)) ? TRUE : FALSE;
00757     break;
00758   case CURLOPT_HEADER:
00759     /*
00760      * Set to include the header in the general data output stream.
00761      */
00762     data->set.include_header = (0 != va_arg(param, long)) ? TRUE : FALSE;
00763     break;
00764   case CURLOPT_NOPROGRESS:
00765     /*
00766      * Shut off the internal supported progress meter
00767      */
00768     data->set.hide_progress = (0 != va_arg(param, long)) ? TRUE : FALSE;
00769     if(data->set.hide_progress)
00770       data->progress.flags |= PGRS_HIDE;
00771     else
00772       data->progress.flags &= ~PGRS_HIDE;
00773     break;
00774   case CURLOPT_NOBODY:
00775     /*
00776      * Do not include the body part in the output data stream.
00777      */
00778     data->set.opt_no_body = (0 != va_arg(param, long)) ? TRUE : FALSE;
00779     break;
00780   case CURLOPT_FAILONERROR:
00781     /*
00782      * Don't output the >=400 error code HTML-page, but instead only
00783      * return error.
00784      */
00785     data->set.http_fail_on_error = (0 != va_arg(param, long)) ? TRUE : FALSE;
00786     break;
00787   case CURLOPT_KEEP_SENDING_ON_ERROR:
00788     data->set.http_keep_sending_on_error = (0 != va_arg(param, long)) ?
00789                                            TRUE : FALSE;
00790     break;
00791   case CURLOPT_UPLOAD:
00792   case CURLOPT_PUT:
00793     /*
00794      * We want to sent data to the remote host. If this is HTTP, that equals
00795      * using the PUT request.
00796      */
00797     data->set.upload = (0 != va_arg(param, long)) ? TRUE : FALSE;
00798     if(data->set.upload) {
00799       /* If this is HTTP, PUT is what's needed to "upload" */
00800       data->set.httpreq = HTTPREQ_PUT;
00801       data->set.opt_no_body = FALSE; /* this is implied */
00802     }
00803     else
00804       /* In HTTP, the opposite of upload is GET (unless NOBODY is true as
00805          then this can be changed to HEAD later on) */
00806       data->set.httpreq = HTTPREQ_GET;
00807     break;
00808   case CURLOPT_FILETIME:
00809     /*
00810      * Try to get the file time of the remote document. The time will
00811      * later (possibly) become available using curl_easy_getinfo().
00812      */
00813     data->set.get_filetime = (0 != va_arg(param, long)) ? TRUE : FALSE;
00814     break;
00815   case CURLOPT_FTP_CREATE_MISSING_DIRS:
00816     /*
00817      * An FTP option that modifies an upload to create missing directories on
00818      * the server.
00819      */
00820     switch(va_arg(param, long)) {
00821     case 0:
00822       data->set.ftp_create_missing_dirs = 0;
00823       break;
00824     case 1:
00825       data->set.ftp_create_missing_dirs = 1;
00826       break;
00827     case 2:
00828       data->set.ftp_create_missing_dirs = 2;
00829       break;
00830     default:
00831       /* reserve other values for future use */
00832       result = CURLE_UNKNOWN_OPTION;
00833       break;
00834     }
00835     break;
00836   case CURLOPT_SERVER_RESPONSE_TIMEOUT:
00837     /*
00838      * Option that specifies how quickly an server response must be obtained
00839      * before it is considered failure. For pingpong protocols.
00840      */
00841     data->set.server_response_timeout = va_arg(param, long) * 1000;
00842     break;
00843   case CURLOPT_TFTP_NO_OPTIONS:
00844     /*
00845      * Option that prevents libcurl from sending TFTP option requests to the
00846      * server.
00847      */
00848     data->set.tftp_no_options = va_arg(param, long) != 0;
00849     break;
00850   case CURLOPT_TFTP_BLKSIZE:
00851     /*
00852      * TFTP option that specifies the block size to use for data transmission.
00853      */
00854     data->set.tftp_blksize = va_arg(param, long);
00855     break;
00856   case CURLOPT_DIRLISTONLY:
00857     /*
00858      * An option that changes the command to one that asks for a list
00859      * only, no file info details.
00860      */
00861     data->set.ftp_list_only = (0 != va_arg(param, long)) ? TRUE : FALSE;
00862     break;
00863   case CURLOPT_APPEND:
00864     /*
00865      * We want to upload and append to an existing file.
00866      */
00867     data->set.ftp_append = (0 != va_arg(param, long)) ? TRUE : FALSE;
00868     break;
00869   case CURLOPT_FTP_FILEMETHOD:
00870     /*
00871      * How do access files over FTP.
00872      */
00873     data->set.ftp_filemethod = (curl_ftpfile)va_arg(param, long);
00874     break;
00875   case CURLOPT_NETRC:
00876     /*
00877      * Parse the $HOME/.netrc file
00878      */
00879     data->set.use_netrc = (enum CURL_NETRC_OPTION)va_arg(param, long);
00880     break;
00881   case CURLOPT_NETRC_FILE:
00882     /*
00883      * Use this file instead of the $HOME/.netrc file
00884      */
00885     result = setstropt(&data->set.str[STRING_NETRC_FILE],
00886                        va_arg(param, char *));
00887     break;
00888   case CURLOPT_TRANSFERTEXT:
00889     /*
00890      * This option was previously named 'FTPASCII'. Renamed to work with
00891      * more protocols than merely FTP.
00892      *
00893      * Transfer using ASCII (instead of BINARY).
00894      */
00895     data->set.prefer_ascii = (0 != va_arg(param, long)) ? TRUE : FALSE;
00896     break;
00897   case CURLOPT_TIMECONDITION:
00898     /*
00899      * Set HTTP time condition. This must be one of the defines in the
00900      * curl/curl.h header file.
00901      */
00902     data->set.timecondition = (curl_TimeCond)va_arg(param, long);
00903     break;
00904   case CURLOPT_TIMEVALUE:
00905     /*
00906      * This is the value to compare with the remote document with the
00907      * method set with CURLOPT_TIMECONDITION
00908      */
00909     data->set.timevalue = (time_t)va_arg(param, long);
00910     break;
00911   case CURLOPT_SSLVERSION:
00912     /*
00913      * Set explicit SSL version to try to connect with, as some SSL
00914      * implementations are lame.
00915      */
00916 #ifdef USE_SSL
00917     data->set.ssl.primary.version = va_arg(param, long);
00918 #else
00919     result = CURLE_UNKNOWN_OPTION;
00920 #endif
00921     break;
00922   case CURLOPT_PROXY_SSLVERSION:
00923     /*
00924      * Set explicit SSL version to try to connect with for proxy, as some SSL
00925      * implementations are lame.
00926      */
00927 #ifdef USE_SSL
00928     data->set.proxy_ssl.primary.version = va_arg(param, long);
00929 #else
00930     result = CURLE_UNKNOWN_OPTION;
00931 #endif
00932     break;
00933 
00934 #ifndef CURL_DISABLE_HTTP
00935   case CURLOPT_AUTOREFERER:
00936     /*
00937      * Switch on automatic referer that gets set if curl follows locations.
00938      */
00939     data->set.http_auto_referer = (0 != va_arg(param, long)) ? TRUE : FALSE;
00940     break;
00941 
00942   case CURLOPT_ACCEPT_ENCODING:
00943     /*
00944      * String to use at the value of Accept-Encoding header.
00945      *
00946      * If the encoding is set to "" we use an Accept-Encoding header that
00947      * encompasses all the encodings we support.
00948      * If the encoding is set to NULL we don't send an Accept-Encoding header
00949      * and ignore an received Content-Encoding header.
00950      *
00951      */
00952     argptr = va_arg(param, char *);
00953     result = setstropt(&data->set.str[STRING_ENCODING],
00954                        (argptr && !*argptr)?
00955                        ALL_CONTENT_ENCODINGS: argptr);
00956     break;
00957 
00958   case CURLOPT_TRANSFER_ENCODING:
00959     data->set.http_transfer_encoding = (0 != va_arg(param, long)) ?
00960                                        TRUE : FALSE;
00961     break;
00962 
00963   case CURLOPT_FOLLOWLOCATION:
00964     /*
00965      * Follow Location: header hints on a HTTP-server.
00966      */
00967     data->set.http_follow_location = (0 != va_arg(param, long)) ? TRUE : FALSE;
00968     break;
00969 
00970   case CURLOPT_UNRESTRICTED_AUTH:
00971     /*
00972      * Send authentication (user+password) when following locations, even when
00973      * hostname changed.
00974      */
00975     data->set.http_disable_hostname_check_before_authentication =
00976       (0 != va_arg(param, long)) ? TRUE : FALSE;
00977     break;
00978 
00979   case CURLOPT_MAXREDIRS:
00980     /*
00981      * The maximum amount of hops you allow curl to follow Location:
00982      * headers. This should mostly be used to detect never-ending loops.
00983      */
00984     data->set.maxredirs = va_arg(param, long);
00985     break;
00986 
00987   case CURLOPT_POSTREDIR:
00988   {
00989     /*
00990      * Set the behaviour of POST when redirecting
00991      * CURL_REDIR_GET_ALL - POST is changed to GET after 301 and 302
00992      * CURL_REDIR_POST_301 - POST is kept as POST after 301
00993      * CURL_REDIR_POST_302 - POST is kept as POST after 302
00994      * CURL_REDIR_POST_303 - POST is kept as POST after 303
00995      * CURL_REDIR_POST_ALL - POST is kept as POST after 301, 302 and 303
00996      * other - POST is kept as POST after 301 and 302
00997      */
00998     int postRedir = curlx_sltosi(va_arg(param, long));
00999     data->set.keep_post = postRedir & CURL_REDIR_POST_ALL;
01000   }
01001   break;
01002 
01003   case CURLOPT_POST:
01004     /* Does this option serve a purpose anymore? Yes it does, when
01005        CURLOPT_POSTFIELDS isn't used and the POST data is read off the
01006        callback! */
01007     if(va_arg(param, long)) {
01008       data->set.httpreq = HTTPREQ_POST;
01009       data->set.opt_no_body = FALSE; /* this is implied */
01010     }
01011     else
01012       data->set.httpreq = HTTPREQ_GET;
01013     break;
01014 
01015   case CURLOPT_COPYPOSTFIELDS:
01016     /*
01017      * A string with POST data. Makes curl HTTP POST. Even if it is NULL.
01018      * If needed, CURLOPT_POSTFIELDSIZE must have been set prior to
01019      *  CURLOPT_COPYPOSTFIELDS and not altered later.
01020      */
01021     argptr = va_arg(param, char *);
01022 
01023     if(!argptr || data->set.postfieldsize == -1)
01024       result = setstropt(&data->set.str[STRING_COPYPOSTFIELDS], argptr);
01025     else {
01026       /*
01027        *  Check that requested length does not overflow the size_t type.
01028        */
01029 
01030       if((data->set.postfieldsize < 0) ||
01031          ((sizeof(curl_off_t) != sizeof(size_t)) &&
01032           (data->set.postfieldsize > (curl_off_t)((size_t)-1))))
01033         result = CURLE_OUT_OF_MEMORY;
01034       else {
01035         char *p;
01036 
01037         (void) setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL);
01038 
01039         /* Allocate even when size == 0. This satisfies the need of possible
01040            later address compare to detect the COPYPOSTFIELDS mode, and
01041            to mark that postfields is used rather than read function or
01042            form data.
01043         */
01044         p = malloc((size_t)(data->set.postfieldsize?
01045                             data->set.postfieldsize:1));
01046 
01047         if(!p)
01048           result = CURLE_OUT_OF_MEMORY;
01049         else {
01050           if(data->set.postfieldsize)
01051             memcpy(p, argptr, (size_t)data->set.postfieldsize);
01052 
01053           data->set.str[STRING_COPYPOSTFIELDS] = p;
01054         }
01055       }
01056     }
01057 
01058     data->set.postfields = data->set.str[STRING_COPYPOSTFIELDS];
01059     data->set.httpreq = HTTPREQ_POST;
01060     break;
01061 
01062   case CURLOPT_POSTFIELDS:
01063     /*
01064      * Like above, but use static data instead of copying it.
01065      */
01066     data->set.postfields = va_arg(param, void *);
01067     /* Release old copied data. */
01068     (void) setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL);
01069     data->set.httpreq = HTTPREQ_POST;
01070     break;
01071 
01072   case CURLOPT_POSTFIELDSIZE:
01073     /*
01074      * The size of the POSTFIELD data to prevent libcurl to do strlen() to
01075      * figure it out. Enables binary posts.
01076      */
01077     bigsize = va_arg(param, long);
01078 
01079     if(data->set.postfieldsize < bigsize &&
01080        data->set.postfields == data->set.str[STRING_COPYPOSTFIELDS]) {
01081       /* Previous CURLOPT_COPYPOSTFIELDS is no longer valid. */
01082       (void) setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL);
01083       data->set.postfields = NULL;
01084     }
01085 
01086     data->set.postfieldsize = bigsize;
01087     break;
01088 
01089   case CURLOPT_POSTFIELDSIZE_LARGE:
01090     /*
01091      * The size of the POSTFIELD data to prevent libcurl to do strlen() to
01092      * figure it out. Enables binary posts.
01093      */
01094     bigsize = va_arg(param, curl_off_t);
01095 
01096     if(data->set.postfieldsize < bigsize &&
01097        data->set.postfields == data->set.str[STRING_COPYPOSTFIELDS]) {
01098       /* Previous CURLOPT_COPYPOSTFIELDS is no longer valid. */
01099       (void) setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL);
01100       data->set.postfields = NULL;
01101     }
01102 
01103     data->set.postfieldsize = bigsize;
01104     break;
01105 
01106   case CURLOPT_HTTPPOST:
01107     /*
01108      * Set to make us do HTTP POST
01109      */
01110     data->set.httppost = va_arg(param, struct curl_httppost *);
01111     data->set.httpreq = HTTPREQ_POST_FORM;
01112     data->set.opt_no_body = FALSE; /* this is implied */
01113     break;
01114 
01115   case CURLOPT_REFERER:
01116     /*
01117      * String to set in the HTTP Referer: field.
01118      */
01119     if(data->change.referer_alloc) {
01120       Curl_safefree(data->change.referer);
01121       data->change.referer_alloc = FALSE;
01122     }
01123     result = setstropt(&data->set.str[STRING_SET_REFERER],
01124                        va_arg(param, char *));
01125     data->change.referer = data->set.str[STRING_SET_REFERER];
01126     break;
01127 
01128   case CURLOPT_USERAGENT:
01129     /*
01130      * String to use in the HTTP User-Agent field
01131      */
01132     result = setstropt(&data->set.str[STRING_USERAGENT],
01133                        va_arg(param, char *));
01134     break;
01135 
01136   case CURLOPT_HTTPHEADER:
01137     /*
01138      * Set a list with HTTP headers to use (or replace internals with)
01139      */
01140     data->set.headers = va_arg(param, struct curl_slist *);
01141     break;
01142 
01143   case CURLOPT_PROXYHEADER:
01144     /*
01145      * Set a list with proxy headers to use (or replace internals with)
01146      *
01147      * Since CURLOPT_HTTPHEADER was the only way to set HTTP headers for a
01148      * long time we remain doing it this way until CURLOPT_PROXYHEADER is
01149      * used. As soon as this option has been used, if set to anything but
01150      * NULL, custom headers for proxies are only picked from this list.
01151      *
01152      * Set this option to NULL to restore the previous behavior.
01153      */
01154     data->set.proxyheaders = va_arg(param, struct curl_slist *);
01155     break;
01156 
01157   case CURLOPT_HEADEROPT:
01158     /*
01159      * Set header option.
01160      */
01161     arg = va_arg(param, long);
01162     data->set.sep_headers = (arg & CURLHEADER_SEPARATE)? TRUE: FALSE;
01163     break;
01164 
01165   case CURLOPT_HTTP200ALIASES:
01166     /*
01167      * Set a list of aliases for HTTP 200 in response header
01168      */
01169     data->set.http200aliases = va_arg(param, struct curl_slist *);
01170     break;
01171 
01172 #if !defined(CURL_DISABLE_COOKIES)
01173   case CURLOPT_COOKIE:
01174     /*
01175      * Cookie string to send to the remote server in the request.
01176      */
01177     result = setstropt(&data->set.str[STRING_COOKIE],
01178                        va_arg(param, char *));
01179     break;
01180 
01181   case CURLOPT_COOKIEFILE:
01182     /*
01183      * Set cookie file to read and parse. Can be used multiple times.
01184      */
01185     argptr = (char *)va_arg(param, void *);
01186     if(argptr) {
01187       struct curl_slist *cl;
01188       /* append the cookie file name to the list of file names, and deal with
01189          them later */
01190       cl = curl_slist_append(data->change.cookielist, argptr);
01191       if(!cl) {
01192         curl_slist_free_all(data->change.cookielist);
01193         data->change.cookielist = NULL;
01194         return CURLE_OUT_OF_MEMORY;
01195       }
01196       data->change.cookielist = cl; /* store the list for later use */
01197     }
01198     break;
01199 
01200   case CURLOPT_COOKIEJAR:
01201     /*
01202      * Set cookie file name to dump all cookies to when we're done.
01203      */
01204   {
01205     struct CookieInfo *newcookies;
01206     result = setstropt(&data->set.str[STRING_COOKIEJAR],
01207                        va_arg(param, char *));
01208 
01209     /*
01210      * Activate the cookie parser. This may or may not already
01211      * have been made.
01212      */
01213     newcookies = Curl_cookie_init(data, NULL, data->cookies,
01214                                   data->set.cookiesession);
01215     if(!newcookies)
01216       result = CURLE_OUT_OF_MEMORY;
01217     data->cookies = newcookies;
01218   }
01219     break;
01220 
01221   case CURLOPT_COOKIESESSION:
01222     /*
01223      * Set this option to TRUE to start a new "cookie session". It will
01224      * prevent the forthcoming read-cookies-from-file actions to accept
01225      * cookies that are marked as being session cookies, as they belong to a
01226      * previous session.
01227      *
01228      * In the original Netscape cookie spec, "session cookies" are cookies
01229      * with no expire date set. RFC2109 describes the same action if no
01230      * 'Max-Age' is set and RFC2965 includes the RFC2109 description and adds
01231      * a 'Discard' action that can enforce the discard even for cookies that
01232      * have a Max-Age.
01233      *
01234      * We run mostly with the original cookie spec, as hardly anyone implements
01235      * anything else.
01236      */
01237     data->set.cookiesession = (0 != va_arg(param, long)) ? TRUE : FALSE;
01238     break;
01239 
01240   case CURLOPT_COOKIELIST:
01241     argptr = va_arg(param, char *);
01242 
01243     if(argptr == NULL)
01244       break;
01245 
01246     if(strcasecompare(argptr, "ALL")) {
01247       /* clear all cookies */
01248       Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
01249       Curl_cookie_clearall(data->cookies);
01250       Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
01251     }
01252     else if(strcasecompare(argptr, "SESS")) {
01253       /* clear session cookies */
01254       Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
01255       Curl_cookie_clearsess(data->cookies);
01256       Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
01257     }
01258     else if(strcasecompare(argptr, "FLUSH")) {
01259       /* flush cookies to file, takes care of the locking */
01260       Curl_flush_cookies(data, 0);
01261     }
01262     else if(strcasecompare(argptr, "RELOAD")) {
01263       /* reload cookies from file */
01264       Curl_cookie_loadfiles(data);
01265       break;
01266     }
01267     else {
01268       if(!data->cookies)
01269         /* if cookie engine was not running, activate it */
01270         data->cookies = Curl_cookie_init(data, NULL, NULL, TRUE);
01271 
01272       argptr = strdup(argptr);
01273       if(!argptr || !data->cookies) {
01274         result = CURLE_OUT_OF_MEMORY;
01275         free(argptr);
01276       }
01277       else {
01278         Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
01279 
01280         if(checkprefix("Set-Cookie:", argptr))
01281           /* HTTP Header format line */
01282           Curl_cookie_add(data, data->cookies, TRUE, argptr + 11, NULL, NULL);
01283 
01284         else
01285           /* Netscape format line */
01286           Curl_cookie_add(data, data->cookies, FALSE, argptr, NULL, NULL);
01287 
01288         Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
01289         free(argptr);
01290       }
01291     }
01292 
01293     break;
01294 #endif /* CURL_DISABLE_COOKIES */
01295 
01296   case CURLOPT_HTTPGET:
01297     /*
01298      * Set to force us do HTTP GET
01299      */
01300     if(va_arg(param, long)) {
01301       data->set.httpreq = HTTPREQ_GET;
01302       data->set.upload = FALSE; /* switch off upload */
01303       data->set.opt_no_body = FALSE; /* this is implied */
01304     }
01305     break;
01306 
01307   case CURLOPT_HTTP_VERSION:
01308     /*
01309      * This sets a requested HTTP version to be used. The value is one of
01310      * the listed enums in curl/curl.h.
01311      */
01312     arg = va_arg(param, long);
01313 #ifndef USE_NGHTTP2
01314     if(arg >= CURL_HTTP_VERSION_2)
01315       return CURLE_UNSUPPORTED_PROTOCOL;
01316 #endif
01317     data->set.httpversion = arg;
01318     break;
01319 
01320   case CURLOPT_HTTPAUTH:
01321     /*
01322      * Set HTTP Authentication type BITMASK.
01323      */
01324   {
01325     int bitcheck;
01326     bool authbits;
01327     unsigned long auth = va_arg(param, unsigned long);
01328 
01329     if(auth == CURLAUTH_NONE) {
01330       data->set.httpauth = auth;
01331       break;
01332     }
01333 
01334     /* the DIGEST_IE bit is only used to set a special marker, for all the
01335        rest we need to handle it as normal DIGEST */
01336     data->state.authhost.iestyle = (auth & CURLAUTH_DIGEST_IE) ? TRUE : FALSE;
01337 
01338     if(auth & CURLAUTH_DIGEST_IE) {
01339       auth |= CURLAUTH_DIGEST; /* set standard digest bit */
01340       auth &= ~CURLAUTH_DIGEST_IE; /* unset ie digest bit */
01341     }
01342 
01343     /* switch off bits we can't support */
01344 #ifndef USE_NTLM
01345     auth &= ~CURLAUTH_NTLM;    /* no NTLM support */
01346     auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */
01347 #elif !defined(NTLM_WB_ENABLED)
01348     auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */
01349 #endif
01350 #ifndef USE_SPNEGO
01351     auth &= ~CURLAUTH_NEGOTIATE; /* no Negotiate (SPNEGO) auth without
01352                                     GSS-API or SSPI */
01353 #endif
01354 
01355     /* check if any auth bit lower than CURLAUTH_ONLY is still set */
01356     bitcheck = 0;
01357     authbits = FALSE;
01358     while(bitcheck < 31) {
01359       if(auth & (1UL << bitcheck++)) {
01360         authbits = TRUE;
01361         break;
01362       }
01363     }
01364     if(!authbits)
01365       return CURLE_NOT_BUILT_IN; /* no supported types left! */
01366 
01367     data->set.httpauth = auth;
01368   }
01369   break;
01370 
01371   case CURLOPT_EXPECT_100_TIMEOUT_MS:
01372     /*
01373      * Time to wait for a response to a HTTP request containing an
01374      * Expect: 100-continue header before sending the data anyway.
01375      */
01376     data->set.expect_100_timeout = va_arg(param, long);
01377     break;
01378 
01379 #endif   /* CURL_DISABLE_HTTP */
01380 
01381   case CURLOPT_CUSTOMREQUEST:
01382     /*
01383      * Set a custom string to use as request
01384      */
01385     result = setstropt(&data->set.str[STRING_CUSTOMREQUEST],
01386                        va_arg(param, char *));
01387 
01388     /* we don't set
01389        data->set.httpreq = HTTPREQ_CUSTOM;
01390        here, we continue as if we were using the already set type
01391        and this just changes the actual request keyword */
01392     break;
01393 
01394 #ifndef CURL_DISABLE_PROXY
01395   case CURLOPT_HTTPPROXYTUNNEL:
01396     /*
01397      * Tunnel operations through the proxy instead of normal proxy use
01398      */
01399     data->set.tunnel_thru_httpproxy = (0 != va_arg(param, long)) ?
01400                                       TRUE : FALSE;
01401     break;
01402 
01403   case CURLOPT_PROXYPORT:
01404     /*
01405      * Explicitly set HTTP proxy port number.
01406      */
01407     data->set.proxyport = va_arg(param, long);
01408     break;
01409 
01410   case CURLOPT_PROXYAUTH:
01411     /*
01412      * Set HTTP Authentication type BITMASK.
01413      */
01414   {
01415     int bitcheck;
01416     bool authbits;
01417     unsigned long auth = va_arg(param, unsigned long);
01418 
01419     if(auth == CURLAUTH_NONE) {
01420       data->set.proxyauth = auth;
01421       break;
01422     }
01423 
01424     /* the DIGEST_IE bit is only used to set a special marker, for all the
01425        rest we need to handle it as normal DIGEST */
01426     data->state.authproxy.iestyle = (auth & CURLAUTH_DIGEST_IE) ? TRUE : FALSE;
01427 
01428     if(auth & CURLAUTH_DIGEST_IE) {
01429       auth |= CURLAUTH_DIGEST; /* set standard digest bit */
01430       auth &= ~CURLAUTH_DIGEST_IE; /* unset ie digest bit */
01431     }
01432     /* switch off bits we can't support */
01433 #ifndef USE_NTLM
01434     auth &= ~CURLAUTH_NTLM;    /* no NTLM support */
01435     auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */
01436 #elif !defined(NTLM_WB_ENABLED)
01437     auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */
01438 #endif
01439 #ifndef USE_SPNEGO
01440     auth &= ~CURLAUTH_NEGOTIATE; /* no Negotiate (SPNEGO) auth without
01441                                     GSS-API or SSPI */
01442 #endif
01443 
01444     /* check if any auth bit lower than CURLAUTH_ONLY is still set */
01445     bitcheck = 0;
01446     authbits = FALSE;
01447     while(bitcheck < 31) {
01448       if(auth & (1UL << bitcheck++)) {
01449         authbits = TRUE;
01450         break;
01451       }
01452     }
01453     if(!authbits)
01454       return CURLE_NOT_BUILT_IN; /* no supported types left! */
01455 
01456     data->set.proxyauth = auth;
01457   }
01458   break;
01459 
01460   case CURLOPT_PROXY:
01461     /*
01462      * Set proxy server:port to use as proxy.
01463      *
01464      * If the proxy is set to "" (and CURLOPT_SOCKS_PROXY is set to "" or NULL)
01465      * we explicitly say that we don't want to use a proxy
01466      * (even though there might be environment variables saying so).
01467      *
01468      * Setting it to NULL, means no proxy but allows the environment variables
01469      * to decide for us (if CURLOPT_SOCKS_PROXY setting it to NULL).
01470      */
01471     result = setstropt(&data->set.str[STRING_PROXY],
01472                        va_arg(param, char *));
01473     break;
01474 
01475   case CURLOPT_PRE_PROXY:
01476     /*
01477      * Set proxy server:port to use as SOCKS proxy.
01478      *
01479      * If the proxy is set to "" or NULL we explicitly say that we don't want
01480      * to use the socks proxy.
01481      */
01482     result = setstropt(&data->set.str[STRING_PRE_PROXY],
01483                        va_arg(param, char *));
01484     break;
01485 
01486   case CURLOPT_PROXYTYPE:
01487     /*
01488      * Set proxy type. HTTP/HTTP_1_0/SOCKS4/SOCKS4a/SOCKS5/SOCKS5_HOSTNAME
01489      */
01490     data->set.proxytype = (curl_proxytype)va_arg(param, long);
01491     break;
01492 
01493   case CURLOPT_PROXY_TRANSFER_MODE:
01494     /*
01495      * set transfer mode (;type=<a|i>) when doing FTP via an HTTP proxy
01496      */
01497     switch(va_arg(param, long)) {
01498     case 0:
01499       data->set.proxy_transfer_mode = FALSE;
01500       break;
01501     case 1:
01502       data->set.proxy_transfer_mode = TRUE;
01503       break;
01504     default:
01505       /* reserve other values for future use */
01506       result = CURLE_UNKNOWN_OPTION;
01507       break;
01508     }
01509     break;
01510 #endif   /* CURL_DISABLE_PROXY */
01511 
01512 #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
01513   case CURLOPT_SOCKS5_GSSAPI_NEC:
01514     /*
01515      * Set flag for NEC SOCK5 support
01516      */
01517     data->set.socks5_gssapi_nec = (0 != va_arg(param, long)) ? TRUE : FALSE;
01518     break;
01519 
01520   case CURLOPT_SOCKS5_GSSAPI_SERVICE:
01521   case CURLOPT_PROXY_SERVICE_NAME:
01522     /*
01523      * Set proxy authentication service name for Kerberos 5 and SPNEGO
01524      */
01525     result = setstropt(&data->set.str[STRING_PROXY_SERVICE_NAME],
01526                        va_arg(param, char *));
01527     break;
01528 #endif
01529 
01530 #if !defined(CURL_DISABLE_CRYPTO_AUTH) || defined(USE_KERBEROS5) || \
01531     defined(USE_SPNEGO)
01532   case CURLOPT_SERVICE_NAME:
01533     /*
01534      * Set authentication service name for DIGEST-MD5, Kerberos 5 and SPNEGO
01535      */
01536     result = setstropt(&data->set.str[STRING_SERVICE_NAME],
01537                        va_arg(param, char *));
01538     break;
01539 
01540 #endif
01541 
01542   case CURLOPT_HEADERDATA:
01543     /*
01544      * Custom pointer to pass the header write callback function
01545      */
01546     data->set.writeheader = (void *)va_arg(param, void *);
01547     break;
01548   case CURLOPT_ERRORBUFFER:
01549     /*
01550      * Error buffer provided by the caller to get the human readable
01551      * error string in.
01552      */
01553     data->set.errorbuffer = va_arg(param, char *);
01554     break;
01555   case CURLOPT_WRITEDATA:
01556     /*
01557      * FILE pointer to write to. Or possibly
01558      * used as argument to the write callback.
01559      */
01560     data->set.out = va_arg(param, void *);
01561     break;
01562   case CURLOPT_FTPPORT:
01563     /*
01564      * Use FTP PORT, this also specifies which IP address to use
01565      */
01566     result = setstropt(&data->set.str[STRING_FTPPORT],
01567                        va_arg(param, char *));
01568     data->set.ftp_use_port = (data->set.str[STRING_FTPPORT]) ? TRUE : FALSE;
01569     break;
01570 
01571   case CURLOPT_FTP_USE_EPRT:
01572     data->set.ftp_use_eprt = (0 != va_arg(param, long)) ? TRUE : FALSE;
01573     break;
01574 
01575   case CURLOPT_FTP_USE_EPSV:
01576     data->set.ftp_use_epsv = (0 != va_arg(param, long)) ? TRUE : FALSE;
01577     break;
01578 
01579   case CURLOPT_FTP_USE_PRET:
01580     data->set.ftp_use_pret = (0 != va_arg(param, long)) ? TRUE : FALSE;
01581     break;
01582 
01583   case CURLOPT_FTP_SSL_CCC:
01584     data->set.ftp_ccc = (curl_ftpccc)va_arg(param, long);
01585     break;
01586 
01587   case CURLOPT_FTP_SKIP_PASV_IP:
01588     /*
01589      * Enable or disable FTP_SKIP_PASV_IP, which will disable/enable the
01590      * bypass of the IP address in PASV responses.
01591      */
01592     data->set.ftp_skip_ip = (0 != va_arg(param, long)) ? TRUE : FALSE;
01593     break;
01594 
01595   case CURLOPT_READDATA:
01596     /*
01597      * FILE pointer to read the file to be uploaded from. Or possibly
01598      * used as argument to the read callback.
01599      */
01600     data->set.in_set = va_arg(param, void *);
01601     break;
01602   case CURLOPT_INFILESIZE:
01603     /*
01604      * If known, this should inform curl about the file size of the
01605      * to-be-uploaded file.
01606      */
01607     data->set.filesize = va_arg(param, long);
01608     break;
01609   case CURLOPT_INFILESIZE_LARGE:
01610     /*
01611      * If known, this should inform curl about the file size of the
01612      * to-be-uploaded file.
01613      */
01614     data->set.filesize = va_arg(param, curl_off_t);
01615     break;
01616   case CURLOPT_LOW_SPEED_LIMIT:
01617     /*
01618      * The low speed limit that if transfers are below this for
01619      * CURLOPT_LOW_SPEED_TIME, the transfer is aborted.
01620      */
01621     data->set.low_speed_limit=va_arg(param, long);
01622     break;
01623   case CURLOPT_MAX_SEND_SPEED_LARGE:
01624     /*
01625      * When transfer uploads are faster then CURLOPT_MAX_SEND_SPEED_LARGE
01626      * bytes per second the transfer is throttled..
01627      */
01628     data->set.max_send_speed=va_arg(param, curl_off_t);
01629     break;
01630   case CURLOPT_MAX_RECV_SPEED_LARGE:
01631     /*
01632      * When receiving data faster than CURLOPT_MAX_RECV_SPEED_LARGE bytes per
01633      * second the transfer is throttled..
01634      */
01635     data->set.max_recv_speed=va_arg(param, curl_off_t);
01636     break;
01637   case CURLOPT_LOW_SPEED_TIME:
01638     /*
01639      * The low speed time that if transfers are below the set
01640      * CURLOPT_LOW_SPEED_LIMIT during this time, the transfer is aborted.
01641      */
01642     data->set.low_speed_time=va_arg(param, long);
01643     break;
01644   case CURLOPT_URL:
01645     /*
01646      * The URL to fetch.
01647      */
01648     if(data->change.url_alloc) {
01649       /* the already set URL is allocated, free it first! */
01650       Curl_safefree(data->change.url);
01651       data->change.url_alloc = FALSE;
01652     }
01653     result = setstropt(&data->set.str[STRING_SET_URL],
01654                        va_arg(param, char *));
01655     data->change.url = data->set.str[STRING_SET_URL];
01656     break;
01657   case CURLOPT_PORT:
01658     /*
01659      * The port number to use when getting the URL
01660      */
01661     data->set.use_port = va_arg(param, long);
01662     break;
01663   case CURLOPT_TIMEOUT:
01664     /*
01665      * The maximum time you allow curl to use for a single transfer
01666      * operation.
01667      */
01668     data->set.timeout = va_arg(param, long) * 1000L;
01669     break;
01670 
01671   case CURLOPT_TIMEOUT_MS:
01672     data->set.timeout = va_arg(param, long);
01673     break;
01674 
01675   case CURLOPT_CONNECTTIMEOUT:
01676     /*
01677      * The maximum time you allow curl to use to connect.
01678      */
01679     data->set.connecttimeout = va_arg(param, long) * 1000L;
01680     break;
01681 
01682   case CURLOPT_CONNECTTIMEOUT_MS:
01683     data->set.connecttimeout = va_arg(param, long);
01684     break;
01685 
01686   case CURLOPT_ACCEPTTIMEOUT_MS:
01687     /*
01688      * The maximum time you allow curl to wait for server connect
01689      */
01690     data->set.accepttimeout = va_arg(param, long);
01691     break;
01692 
01693   case CURLOPT_USERPWD:
01694     /*
01695      * user:password to use in the operation
01696      */
01697     result = setstropt_userpwd(va_arg(param, char *),
01698                                &data->set.str[STRING_USERNAME],
01699                                &data->set.str[STRING_PASSWORD]);
01700     break;
01701 
01702   case CURLOPT_USERNAME:
01703     /*
01704      * authentication user name to use in the operation
01705      */
01706     result = setstropt(&data->set.str[STRING_USERNAME],
01707                        va_arg(param, char *));
01708     break;
01709 
01710   case CURLOPT_PASSWORD:
01711     /*
01712      * authentication password to use in the operation
01713      */
01714     result = setstropt(&data->set.str[STRING_PASSWORD],
01715                        va_arg(param, char *));
01716     break;
01717 
01718   case CURLOPT_LOGIN_OPTIONS:
01719     /*
01720      * authentication options to use in the operation
01721      */
01722     result = setstropt(&data->set.str[STRING_OPTIONS],
01723                        va_arg(param, char *));
01724     break;
01725 
01726   case CURLOPT_XOAUTH2_BEARER:
01727     /*
01728      * OAuth 2.0 bearer token to use in the operation
01729      */
01730     result = setstropt(&data->set.str[STRING_BEARER],
01731                        va_arg(param, char *));
01732     break;
01733 
01734   case CURLOPT_POSTQUOTE:
01735     /*
01736      * List of RAW FTP commands to use after a transfer
01737      */
01738     data->set.postquote = va_arg(param, struct curl_slist *);
01739     break;
01740   case CURLOPT_PREQUOTE:
01741     /*
01742      * List of RAW FTP commands to use prior to RETR (Wesley Laxton)
01743      */
01744     data->set.prequote = va_arg(param, struct curl_slist *);
01745     break;
01746   case CURLOPT_QUOTE:
01747     /*
01748      * List of RAW FTP commands to use before a transfer
01749      */
01750     data->set.quote = va_arg(param, struct curl_slist *);
01751     break;
01752   case CURLOPT_RESOLVE:
01753     /*
01754      * List of NAME:[address] names to populate the DNS cache with
01755      * Prefix the NAME with dash (-) to _remove_ the name from the cache.
01756      *
01757      * Names added with this API will remain in the cache until explicitly
01758      * removed or the handle is cleaned up.
01759      *
01760      * This API can remove any name from the DNS cache, but only entries
01761      * that aren't actually in use right now will be pruned immediately.
01762      */
01763     data->set.resolve = va_arg(param, struct curl_slist *);
01764     data->change.resolve = data->set.resolve;
01765     break;
01766   case CURLOPT_PROGRESSFUNCTION:
01767     /*
01768      * Progress callback function
01769      */
01770     data->set.fprogress = va_arg(param, curl_progress_callback);
01771     if(data->set.fprogress)
01772       data->progress.callback = TRUE; /* no longer internal */
01773     else
01774       data->progress.callback = FALSE; /* NULL enforces internal */
01775     break;
01776 
01777   case CURLOPT_XFERINFOFUNCTION:
01778     /*
01779      * Transfer info callback function
01780      */
01781     data->set.fxferinfo = va_arg(param, curl_xferinfo_callback);
01782     if(data->set.fxferinfo)
01783       data->progress.callback = TRUE; /* no longer internal */
01784     else
01785       data->progress.callback = FALSE; /* NULL enforces internal */
01786 
01787     break;
01788 
01789   case CURLOPT_PROGRESSDATA:
01790     /*
01791      * Custom client data to pass to the progress callback
01792      */
01793     data->set.progress_client = va_arg(param, void *);
01794     break;
01795 
01796 #ifndef CURL_DISABLE_PROXY
01797   case CURLOPT_PROXYUSERPWD:
01798     /*
01799      * user:password needed to use the proxy
01800      */
01801     result = setstropt_userpwd(va_arg(param, char *),
01802                                &data->set.str[STRING_PROXYUSERNAME],
01803                                &data->set.str[STRING_PROXYPASSWORD]);
01804     break;
01805   case CURLOPT_PROXYUSERNAME:
01806     /*
01807      * authentication user name to use in the operation
01808      */
01809     result = setstropt(&data->set.str[STRING_PROXYUSERNAME],
01810                        va_arg(param, char *));
01811     break;
01812   case CURLOPT_PROXYPASSWORD:
01813     /*
01814      * authentication password to use in the operation
01815      */
01816     result = setstropt(&data->set.str[STRING_PROXYPASSWORD],
01817                        va_arg(param, char *));
01818     break;
01819   case CURLOPT_NOPROXY:
01820     /*
01821      * proxy exception list
01822      */
01823     result = setstropt(&data->set.str[STRING_NOPROXY],
01824                        va_arg(param, char *));
01825     break;
01826 #endif
01827 
01828   case CURLOPT_RANGE:
01829     /*
01830      * What range of the file you want to transfer
01831      */
01832     result = setstropt(&data->set.str[STRING_SET_RANGE],
01833                        va_arg(param, char *));
01834     break;
01835   case CURLOPT_RESUME_FROM:
01836     /*
01837      * Resume transfer at the give file position
01838      */
01839     data->set.set_resume_from = va_arg(param, long);
01840     break;
01841   case CURLOPT_RESUME_FROM_LARGE:
01842     /*
01843      * Resume transfer at the give file position
01844      */
01845     data->set.set_resume_from = va_arg(param, curl_off_t);
01846     break;
01847   case CURLOPT_DEBUGFUNCTION:
01848     /*
01849      * stderr write callback.
01850      */
01851     data->set.fdebug = va_arg(param, curl_debug_callback);
01852     /*
01853      * if the callback provided is NULL, it'll use the default callback
01854      */
01855     break;
01856   case CURLOPT_DEBUGDATA:
01857     /*
01858      * Set to a void * that should receive all error writes. This
01859      * defaults to CURLOPT_STDERR for normal operations.
01860      */
01861     data->set.debugdata = va_arg(param, void *);
01862     break;
01863   case CURLOPT_STDERR:
01864     /*
01865      * Set to a FILE * that should receive all error writes. This
01866      * defaults to stderr for normal operations.
01867      */
01868     data->set.err = va_arg(param, FILE *);
01869     if(!data->set.err)
01870       data->set.err = stderr;
01871     break;
01872   case CURLOPT_HEADERFUNCTION:
01873     /*
01874      * Set header write callback
01875      */
01876     data->set.fwrite_header = va_arg(param, curl_write_callback);
01877     break;
01878   case CURLOPT_WRITEFUNCTION:
01879     /*
01880      * Set data write callback
01881      */
01882     data->set.fwrite_func = va_arg(param, curl_write_callback);
01883     if(!data->set.fwrite_func) {
01884       data->set.is_fwrite_set = 0;
01885       /* When set to NULL, reset to our internal default function */
01886       data->set.fwrite_func = (curl_write_callback)fwrite;
01887     }
01888     else
01889       data->set.is_fwrite_set = 1;
01890     break;
01891   case CURLOPT_READFUNCTION:
01892     /*
01893      * Read data callback
01894      */
01895     data->set.fread_func_set = va_arg(param, curl_read_callback);
01896     if(!data->set.fread_func_set) {
01897       data->set.is_fread_set = 0;
01898       /* When set to NULL, reset to our internal default function */
01899       data->set.fread_func_set = (curl_read_callback)fread;
01900     }
01901     else
01902       data->set.is_fread_set = 1;
01903     break;
01904   case CURLOPT_SEEKFUNCTION:
01905     /*
01906      * Seek callback. Might be NULL.
01907      */
01908     data->set.seek_func = va_arg(param, curl_seek_callback);
01909     break;
01910   case CURLOPT_SEEKDATA:
01911     /*
01912      * Seek control callback. Might be NULL.
01913      */
01914     data->set.seek_client = va_arg(param, void *);
01915     break;
01916   case CURLOPT_CONV_FROM_NETWORK_FUNCTION:
01917     /*
01918      * "Convert from network encoding" callback
01919      */
01920     data->set.convfromnetwork = va_arg(param, curl_conv_callback);
01921     break;
01922   case CURLOPT_CONV_TO_NETWORK_FUNCTION:
01923     /*
01924      * "Convert to network encoding" callback
01925      */
01926     data->set.convtonetwork = va_arg(param, curl_conv_callback);
01927     break;
01928   case CURLOPT_CONV_FROM_UTF8_FUNCTION:
01929     /*
01930      * "Convert from UTF-8 encoding" callback
01931      */
01932     data->set.convfromutf8 = va_arg(param, curl_conv_callback);
01933     break;
01934   case CURLOPT_IOCTLFUNCTION:
01935     /*
01936      * I/O control callback. Might be NULL.
01937      */
01938     data->set.ioctl_func = va_arg(param, curl_ioctl_callback);
01939     break;
01940   case CURLOPT_IOCTLDATA:
01941     /*
01942      * I/O control data pointer. Might be NULL.
01943      */
01944     data->set.ioctl_client = va_arg(param, void *);
01945     break;
01946   case CURLOPT_SSLCERT:
01947     /*
01948      * String that holds file name of the SSL certificate to use
01949      */
01950     result = setstropt(&data->set.str[STRING_CERT_ORIG],
01951                        va_arg(param, char *));
01952     break;
01953   case CURLOPT_PROXY_SSLCERT:
01954     /*
01955      * String that holds file name of the SSL certificate to use for proxy
01956      */
01957     result = setstropt(&data->set.str[STRING_CERT_PROXY],
01958                        va_arg(param, char *));
01959     break;
01960   case CURLOPT_SSLCERTTYPE:
01961     /*
01962      * String that holds file type of the SSL certificate to use
01963      */
01964     result = setstropt(&data->set.str[STRING_CERT_TYPE_ORIG],
01965                        va_arg(param, char *));
01966     break;
01967   case CURLOPT_PROXY_SSLCERTTYPE:
01968     /*
01969      * String that holds file type of the SSL certificate to use for proxy
01970      */
01971     result = setstropt(&data->set.str[STRING_CERT_TYPE_PROXY],
01972                        va_arg(param, char *));
01973     break;
01974   case CURLOPT_SSLKEY:
01975     /*
01976      * String that holds file name of the SSL key to use
01977      */
01978     result = setstropt(&data->set.str[STRING_KEY_ORIG],
01979                        va_arg(param, char *));
01980     break;
01981   case CURLOPT_PROXY_SSLKEY:
01982     /*
01983      * String that holds file name of the SSL key to use for proxy
01984      */
01985     result = setstropt(&data->set.str[STRING_KEY_PROXY],
01986                        va_arg(param, char *));
01987     break;
01988   case CURLOPT_SSLKEYTYPE:
01989     /*
01990      * String that holds file type of the SSL key to use
01991      */
01992     result = setstropt(&data->set.str[STRING_KEY_TYPE_ORIG],
01993                        va_arg(param, char *));
01994     break;
01995   case CURLOPT_PROXY_SSLKEYTYPE:
01996     /*
01997      * String that holds file type of the SSL key to use for proxy
01998      */
01999     result = setstropt(&data->set.str[STRING_KEY_TYPE_PROXY],
02000                        va_arg(param, char *));
02001     break;
02002   case CURLOPT_KEYPASSWD:
02003     /*
02004      * String that holds the SSL or SSH private key password.
02005      */
02006     result = setstropt(&data->set.str[STRING_KEY_PASSWD_ORIG],
02007                        va_arg(param, char *));
02008     break;
02009   case CURLOPT_PROXY_KEYPASSWD:
02010     /*
02011      * String that holds the SSL private key password for proxy.
02012      */
02013     result = setstropt(&data->set.str[STRING_KEY_PASSWD_PROXY],
02014                        va_arg(param, char *));
02015     break;
02016   case CURLOPT_SSLENGINE:
02017     /*
02018      * String that holds the SSL crypto engine.
02019      */
02020     argptr = va_arg(param, char *);
02021     if(argptr && argptr[0])
02022       result = Curl_ssl_set_engine(data, argptr);
02023     break;
02024 
02025   case CURLOPT_SSLENGINE_DEFAULT:
02026     /*
02027      * flag to set engine as default.
02028      */
02029     result = Curl_ssl_set_engine_default(data);
02030     break;
02031   case CURLOPT_CRLF:
02032     /*
02033      * Kludgy option to enable CRLF conversions. Subject for removal.
02034      */
02035     data->set.crlf = (0 != va_arg(param, long)) ? TRUE : FALSE;
02036     break;
02037 
02038   case CURLOPT_INTERFACE:
02039     /*
02040      * Set what interface or address/hostname to bind the socket to when
02041      * performing an operation and thus what from-IP your connection will use.
02042      */
02043     result = setstropt(&data->set.str[STRING_DEVICE],
02044                        va_arg(param, char *));
02045     break;
02046   case CURLOPT_LOCALPORT:
02047     /*
02048      * Set what local port to bind the socket to when performing an operation.
02049      */
02050     data->set.localport = curlx_sltous(va_arg(param, long));
02051     break;
02052   case CURLOPT_LOCALPORTRANGE:
02053     /*
02054      * Set number of local ports to try, starting with CURLOPT_LOCALPORT.
02055      */
02056     data->set.localportrange = curlx_sltosi(va_arg(param, long));
02057     break;
02058   case CURLOPT_KRBLEVEL:
02059     /*
02060      * A string that defines the kerberos security level.
02061      */
02062     result = setstropt(&data->set.str[STRING_KRB_LEVEL],
02063                        va_arg(param, char *));
02064     data->set.krb = (data->set.str[STRING_KRB_LEVEL]) ? TRUE : FALSE;
02065     break;
02066   case CURLOPT_GSSAPI_DELEGATION:
02067     /*
02068      * GSS-API credential delegation
02069      */
02070     data->set.gssapi_delegation = va_arg(param, long);
02071     break;
02072   case CURLOPT_SSL_VERIFYPEER:
02073     /*
02074      * Enable peer SSL verifying.
02075      */
02076     data->set.ssl.primary.verifypeer = (0 != va_arg(param, long)) ?
02077                                        TRUE : FALSE;
02078     break;
02079   case CURLOPT_PROXY_SSL_VERIFYPEER:
02080     /*
02081      * Enable peer SSL verifying for proxy.
02082      */
02083     data->set.proxy_ssl.primary.verifypeer =
02084       (0 != va_arg(param, long))?TRUE:FALSE;
02085     break;
02086   case CURLOPT_SSL_VERIFYHOST:
02087     /*
02088      * Enable verification of the host name in the peer certificate
02089      */
02090     arg = va_arg(param, long);
02091 
02092     /* Obviously people are not reading documentation and too many thought
02093        this argument took a boolean when it wasn't and misused it. We thus ban
02094        1 as a sensible input and we warn about its use. Then we only have the
02095        2 action internally stored as TRUE. */
02096 
02097     if(1 == arg) {
02098       failf(data, "CURLOPT_SSL_VERIFYHOST no longer supports 1 as value!");
02099       return CURLE_BAD_FUNCTION_ARGUMENT;
02100     }
02101 
02102     data->set.ssl.primary.verifyhost = (0 != arg) ? TRUE : FALSE;
02103     break;
02104   case CURLOPT_PROXY_SSL_VERIFYHOST:
02105     /*
02106      * Enable verification of the host name in the peer certificate for proxy
02107      */
02108     arg = va_arg(param, long);
02109 
02110     /* Obviously people are not reading documentation and too many thought
02111        this argument took a boolean when it wasn't and misused it. We thus ban
02112        1 as a sensible input and we warn about its use. Then we only have the
02113        2 action internally stored as TRUE. */
02114 
02115     if(1 == arg) {
02116       failf(data, "CURLOPT_SSL_VERIFYHOST no longer supports 1 as value!");
02117       return CURLE_BAD_FUNCTION_ARGUMENT;
02118     }
02119 
02120     data->set.proxy_ssl.primary.verifyhost = (0 != arg)?TRUE:FALSE;
02121     break;
02122   case CURLOPT_SSL_VERIFYSTATUS:
02123     /*
02124      * Enable certificate status verifying.
02125      */
02126     if(!Curl_ssl_cert_status_request()) {
02127       result = CURLE_NOT_BUILT_IN;
02128       break;
02129     }
02130 
02131     data->set.ssl.primary.verifystatus = (0 != va_arg(param, long)) ?
02132                                          TRUE : FALSE;
02133     break;
02134   case CURLOPT_SSL_CTX_FUNCTION:
02135 #ifdef have_curlssl_ssl_ctx
02136     /*
02137      * Set a SSL_CTX callback
02138      */
02139     data->set.ssl.fsslctx = va_arg(param, curl_ssl_ctx_callback);
02140 #else
02141     result = CURLE_NOT_BUILT_IN;
02142 #endif
02143     break;
02144   case CURLOPT_SSL_CTX_DATA:
02145 #ifdef have_curlssl_ssl_ctx
02146     /*
02147      * Set a SSL_CTX callback parameter pointer
02148      */
02149     data->set.ssl.fsslctxp = va_arg(param, void *);
02150 #else
02151     result = CURLE_NOT_BUILT_IN;
02152 #endif
02153     break;
02154   case CURLOPT_SSL_FALSESTART:
02155     /*
02156      * Enable TLS false start.
02157      */
02158     if(!Curl_ssl_false_start()) {
02159       result = CURLE_NOT_BUILT_IN;
02160       break;
02161     }
02162 
02163     data->set.ssl.falsestart = (0 != va_arg(param, long)) ? TRUE : FALSE;
02164     break;
02165   case CURLOPT_CERTINFO:
02166 #ifdef have_curlssl_certinfo
02167     data->set.ssl.certinfo = (0 != va_arg(param, long)) ? TRUE : FALSE;
02168 #else
02169     result = CURLE_NOT_BUILT_IN;
02170 #endif
02171     break;
02172   case CURLOPT_PINNEDPUBLICKEY:
02173 #ifdef have_curlssl_pinnedpubkey /* only by supported backends */
02174     /*
02175      * Set pinned public key for SSL connection.
02176      * Specify file name of the public key in DER format.
02177      */
02178     result = setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG],
02179                        va_arg(param, char *));
02180 #else
02181     result = CURLE_NOT_BUILT_IN;
02182 #endif
02183     break;
02184   case CURLOPT_PROXY_PINNEDPUBLICKEY:
02185 #ifdef have_curlssl_pinnedpubkey /* only by supported backends */
02186     /*
02187      * Set pinned public key for SSL connection.
02188      * Specify file name of the public key in DER format.
02189      */
02190     result = setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY],
02191                        va_arg(param, char *));
02192 #else
02193     result = CURLE_NOT_BUILT_IN;
02194 #endif
02195     break;
02196   case CURLOPT_CAINFO:
02197     /*
02198      * Set CA info for SSL connection. Specify file name of the CA certificate
02199      */
02200     result = setstropt(&data->set.str[STRING_SSL_CAFILE_ORIG],
02201                        va_arg(param, char *));
02202     break;
02203   case CURLOPT_PROXY_CAINFO:
02204     /*
02205      * Set CA info SSL connection for proxy. Specify file name of the
02206      * CA certificate
02207      */
02208     result = setstropt(&data->set.str[STRING_SSL_CAFILE_PROXY],
02209                        va_arg(param, char *));
02210     break;
02211   case CURLOPT_CAPATH:
02212 #ifdef have_curlssl_ca_path /* not supported by all backends */
02213     /*
02214      * Set CA path info for SSL connection. Specify directory name of the CA
02215      * certificates which have been prepared using openssl c_rehash utility.
02216      */
02217     /* This does not work on windows. */
02218     result = setstropt(&data->set.str[STRING_SSL_CAPATH_ORIG],
02219                        va_arg(param, char *));
02220     break;
02221   case CURLOPT_PROXY_CAPATH:
02222     /*
02223      * Set CA path info for SSL connection proxy. Specify directory name of the
02224      * CA certificates which have been prepared using openssl c_rehash utility.
02225      */
02226     /* This does not work on windows. */
02227     result = setstropt(&data->set.str[STRING_SSL_CAPATH_PROXY],
02228                        va_arg(param, char *));
02229 #else
02230     result = CURLE_NOT_BUILT_IN;
02231 #endif
02232     break;
02233   case CURLOPT_CRLFILE:
02234     /*
02235      * Set CRL file info for SSL connection. Specify file name of the CRL
02236      * to check certificates revocation
02237      */
02238     result = setstropt(&data->set.str[STRING_SSL_CRLFILE_ORIG],
02239                        va_arg(param, char *));
02240     break;
02241   case CURLOPT_PROXY_CRLFILE:
02242     /*
02243      * Set CRL file info for SSL connection for proxy. Specify file name of the
02244      * CRL to check certificates revocation
02245      */
02246     result = setstropt(&data->set.str[STRING_SSL_CRLFILE_PROXY],
02247                        va_arg(param, char *));
02248     break;
02249   case CURLOPT_ISSUERCERT:
02250     /*
02251      * Set Issuer certificate file
02252      * to check certificates issuer
02253      */
02254     result = setstropt(&data->set.str[STRING_SSL_ISSUERCERT_ORIG],
02255                        va_arg(param, char *));
02256     break;
02257   case CURLOPT_TELNETOPTIONS:
02258     /*
02259      * Set a linked list of telnet options
02260      */
02261     data->set.telnet_options = va_arg(param, struct curl_slist *);
02262     break;
02263 
02264   case CURLOPT_BUFFERSIZE:
02265     /*
02266      * The application kindly asks for a differently sized receive buffer.
02267      * If it seems reasonable, we'll use it.
02268      */
02269     data->set.buffer_size = va_arg(param, long);
02270 
02271     if((data->set.buffer_size> (BUFSIZE -1)) ||
02272        (data->set.buffer_size < 1))
02273       data->set.buffer_size = 0; /* huge internal default */
02274 
02275     break;
02276 
02277   case CURLOPT_NOSIGNAL:
02278     /*
02279      * The application asks not to set any signal() or alarm() handlers,
02280      * even when using a timeout.
02281      */
02282     data->set.no_signal = (0 != va_arg(param, long)) ? TRUE : FALSE;
02283     break;
02284 
02285   case CURLOPT_SHARE:
02286   {
02287     struct Curl_share *set;
02288     set = va_arg(param, struct Curl_share *);
02289 
02290     /* disconnect from old share, if any */
02291     if(data->share) {
02292       Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
02293 
02294       if(data->dns.hostcachetype == HCACHE_SHARED) {
02295         data->dns.hostcache = NULL;
02296         data->dns.hostcachetype = HCACHE_NONE;
02297       }
02298 
02299 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
02300       if(data->share->cookies == data->cookies)
02301         data->cookies = NULL;
02302 #endif
02303 
02304       if(data->share->sslsession == data->state.session)
02305         data->state.session = NULL;
02306 
02307       data->share->dirty--;
02308 
02309       Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
02310       data->share = NULL;
02311     }
02312 
02313     /* use new share if it set */
02314     data->share = set;
02315     if(data->share) {
02316 
02317       Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
02318 
02319       data->share->dirty++;
02320 
02321       if(data->share->specifier & (1<< CURL_LOCK_DATA_DNS)) {
02322         /* use shared host cache */
02323         data->dns.hostcache = &data->share->hostcache;
02324         data->dns.hostcachetype = HCACHE_SHARED;
02325       }
02326 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
02327       if(data->share->cookies) {
02328         /* use shared cookie list, first free own one if any */
02329         Curl_cookie_cleanup(data->cookies);
02330         /* enable cookies since we now use a share that uses cookies! */
02331         data->cookies = data->share->cookies;
02332       }
02333 #endif   /* CURL_DISABLE_HTTP */
02334       if(data->share->sslsession) {
02335         data->set.general_ssl.max_ssl_sessions = data->share->max_ssl_sessions;
02336         data->state.session = data->share->sslsession;
02337       }
02338       Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
02339 
02340     }
02341     /* check for host cache not needed,
02342      * it will be done by curl_easy_perform */
02343   }
02344   break;
02345 
02346   case CURLOPT_PRIVATE:
02347     /*
02348      * Set private data pointer.
02349      */
02350     data->set.private_data = va_arg(param, void *);
02351     break;
02352 
02353   case CURLOPT_MAXFILESIZE:
02354     /*
02355      * Set the maximum size of a file to download.
02356      */
02357     data->set.max_filesize = va_arg(param, long);
02358     break;
02359 
02360 #ifdef USE_SSL
02361   case CURLOPT_USE_SSL:
02362     /*
02363      * Make transfers attempt to use SSL/TLS.
02364      */
02365     data->set.use_ssl = (curl_usessl)va_arg(param, long);
02366     break;
02367 
02368   case CURLOPT_SSL_OPTIONS:
02369     arg = va_arg(param, long);
02370     data->set.ssl.enable_beast = arg&CURLSSLOPT_ALLOW_BEAST?TRUE:FALSE;
02371     data->set.ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE);
02372     break;
02373 
02374   case CURLOPT_PROXY_SSL_OPTIONS:
02375     arg = va_arg(param, long);
02376     data->set.proxy_ssl.enable_beast = arg&CURLSSLOPT_ALLOW_BEAST?TRUE:FALSE;
02377     data->set.proxy_ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE);
02378     break;
02379 
02380 #endif
02381   case CURLOPT_FTPSSLAUTH:
02382     /*
02383      * Set a specific auth for FTP-SSL transfers.
02384      */
02385     data->set.ftpsslauth = (curl_ftpauth)va_arg(param, long);
02386     break;
02387 
02388   case CURLOPT_IPRESOLVE:
02389     data->set.ipver = va_arg(param, long);
02390     break;
02391 
02392   case CURLOPT_MAXFILESIZE_LARGE:
02393     /*
02394      * Set the maximum size of a file to download.
02395      */
02396     data->set.max_filesize = va_arg(param, curl_off_t);
02397     break;
02398 
02399   case CURLOPT_TCP_NODELAY:
02400     /*
02401      * Enable or disable TCP_NODELAY, which will disable/enable the Nagle
02402      * algorithm
02403      */
02404     data->set.tcp_nodelay = (0 != va_arg(param, long)) ? TRUE : FALSE;
02405     break;
02406 
02407   case CURLOPT_FTP_ACCOUNT:
02408     result = setstropt(&data->set.str[STRING_FTP_ACCOUNT],
02409                        va_arg(param, char *));
02410     break;
02411 
02412   case CURLOPT_IGNORE_CONTENT_LENGTH:
02413     data->set.ignorecl = (0 != va_arg(param, long)) ? TRUE : FALSE;
02414     break;
02415 
02416   case CURLOPT_CONNECT_ONLY:
02417     /*
02418      * No data transfer, set up connection and let application use the socket
02419      */
02420     data->set.connect_only = (0 != va_arg(param, long)) ? TRUE : FALSE;
02421     break;
02422 
02423   case CURLOPT_FTP_ALTERNATIVE_TO_USER:
02424     result = setstropt(&data->set.str[STRING_FTP_ALTERNATIVE_TO_USER],
02425                        va_arg(param, char *));
02426     break;
02427 
02428   case CURLOPT_SOCKOPTFUNCTION:
02429     /*
02430      * socket callback function: called after socket() but before connect()
02431      */
02432     data->set.fsockopt = va_arg(param, curl_sockopt_callback);
02433     break;
02434 
02435   case CURLOPT_SOCKOPTDATA:
02436     /*
02437      * socket callback data pointer. Might be NULL.
02438      */
02439     data->set.sockopt_client = va_arg(param, void *);
02440     break;
02441 
02442   case CURLOPT_OPENSOCKETFUNCTION:
02443     /*
02444      * open/create socket callback function: called instead of socket(),
02445      * before connect()
02446      */
02447     data->set.fopensocket = va_arg(param, curl_opensocket_callback);
02448     break;
02449 
02450   case CURLOPT_OPENSOCKETDATA:
02451     /*
02452      * socket callback data pointer. Might be NULL.
02453      */
02454     data->set.opensocket_client = va_arg(param, void *);
02455     break;
02456 
02457   case CURLOPT_CLOSESOCKETFUNCTION:
02458     /*
02459      * close socket callback function: called instead of close()
02460      * when shutting down a connection
02461      */
02462     data->set.fclosesocket = va_arg(param, curl_closesocket_callback);
02463     break;
02464 
02465   case CURLOPT_CLOSESOCKETDATA:
02466     /*
02467      * socket callback data pointer. Might be NULL.
02468      */
02469     data->set.closesocket_client = va_arg(param, void *);
02470     break;
02471 
02472   case CURLOPT_SSL_SESSIONID_CACHE:
02473     data->set.general_ssl.sessionid = (0 != va_arg(param, long)) ?
02474                                       TRUE : FALSE;
02475     break;
02476 
02477 #ifdef USE_LIBSSH2
02478     /* we only include SSH options if explicitly built to support SSH */
02479   case CURLOPT_SSH_AUTH_TYPES:
02480     data->set.ssh_auth_types = va_arg(param, long);
02481     break;
02482 
02483   case CURLOPT_SSH_PUBLIC_KEYFILE:
02484     /*
02485      * Use this file instead of the $HOME/.ssh/id_dsa.pub file
02486      */
02487     result = setstropt(&data->set.str[STRING_SSH_PUBLIC_KEY],
02488                        va_arg(param, char *));
02489     break;
02490 
02491   case CURLOPT_SSH_PRIVATE_KEYFILE:
02492     /*
02493      * Use this file instead of the $HOME/.ssh/id_dsa file
02494      */
02495     result = setstropt(&data->set.str[STRING_SSH_PRIVATE_KEY],
02496                        va_arg(param, char *));
02497     break;
02498   case CURLOPT_SSH_HOST_PUBLIC_KEY_MD5:
02499     /*
02500      * Option to allow for the MD5 of the host public key to be checked
02501      * for validation purposes.
02502      */
02503     result = setstropt(&data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5],
02504                        va_arg(param, char *));
02505     break;
02506 #ifdef HAVE_LIBSSH2_KNOWNHOST_API
02507   case CURLOPT_SSH_KNOWNHOSTS:
02508     /*
02509      * Store the file name to read known hosts from.
02510      */
02511     result = setstropt(&data->set.str[STRING_SSH_KNOWNHOSTS],
02512                        va_arg(param, char *));
02513     break;
02514 
02515   case CURLOPT_SSH_KEYFUNCTION:
02516     /* setting to NULL is fine since the ssh.c functions themselves will
02517        then rever to use the internal default */
02518     data->set.ssh_keyfunc = va_arg(param, curl_sshkeycallback);
02519     break;
02520 
02521   case CURLOPT_SSH_KEYDATA:
02522     /*
02523      * Custom client data to pass to the SSH keyfunc callback
02524      */
02525     data->set.ssh_keyfunc_userp = va_arg(param, void *);
02526     break;
02527 #endif /* HAVE_LIBSSH2_KNOWNHOST_API */
02528 
02529 #endif /* USE_LIBSSH2 */
02530 
02531   case CURLOPT_HTTP_TRANSFER_DECODING:
02532     /*
02533      * disable libcurl transfer encoding is used
02534      */
02535     data->set.http_te_skip = (0 == va_arg(param, long)) ? TRUE : FALSE;
02536     break;
02537 
02538   case CURLOPT_HTTP_CONTENT_DECODING:
02539     /*
02540      * raw data passed to the application when content encoding is used
02541      */
02542     data->set.http_ce_skip = (0 == va_arg(param, long)) ? TRUE : FALSE;
02543     break;
02544 
02545   case CURLOPT_NEW_FILE_PERMS:
02546     /*
02547      * Uses these permissions instead of 0644
02548      */
02549     data->set.new_file_perms = va_arg(param, long);
02550     break;
02551 
02552   case CURLOPT_NEW_DIRECTORY_PERMS:
02553     /*
02554      * Uses these permissions instead of 0755
02555      */
02556     data->set.new_directory_perms = va_arg(param, long);
02557     break;
02558 
02559   case CURLOPT_ADDRESS_SCOPE:
02560     /*
02561      * We always get longs when passed plain numericals, but for this value we
02562      * know that an unsigned int will always hold the value so we blindly
02563      * typecast to this type
02564      */
02565     data->set.scope_id = curlx_sltoui(va_arg(param, long));
02566     break;
02567 
02568   case CURLOPT_PROTOCOLS:
02569     /* set the bitmask for the protocols that are allowed to be used for the
02570        transfer, which thus helps the app which takes URLs from users or other
02571        external inputs and want to restrict what protocol(s) to deal
02572        with. Defaults to CURLPROTO_ALL. */
02573     data->set.allowed_protocols = va_arg(param, long);
02574     break;
02575 
02576   case CURLOPT_REDIR_PROTOCOLS:
02577     /* set the bitmask for the protocols that libcurl is allowed to follow to,
02578        as a subset of the CURLOPT_PROTOCOLS ones. That means the protocol needs
02579        to be set in both bitmasks to be allowed to get redirected to. Defaults
02580        to all protocols except FILE and SCP. */
02581     data->set.redir_protocols = va_arg(param, long);
02582     break;
02583 
02584   case CURLOPT_DEFAULT_PROTOCOL:
02585     /* Set the protocol to use when the URL doesn't include any protocol */
02586     result = setstropt(&data->set.str[STRING_DEFAULT_PROTOCOL],
02587                        va_arg(param, char *));
02588     break;
02589 
02590   case CURLOPT_MAIL_FROM:
02591     /* Set the SMTP mail originator */
02592     result = setstropt(&data->set.str[STRING_MAIL_FROM],
02593                        va_arg(param, char *));
02594     break;
02595 
02596   case CURLOPT_MAIL_AUTH:
02597     /* Set the SMTP auth originator */
02598     result = setstropt(&data->set.str[STRING_MAIL_AUTH],
02599                        va_arg(param, char *));
02600     break;
02601 
02602   case CURLOPT_MAIL_RCPT:
02603     /* Set the list of mail recipients */
02604     data->set.mail_rcpt = va_arg(param, struct curl_slist *);
02605     break;
02606 
02607   case CURLOPT_SASL_IR:
02608     /* Enable/disable SASL initial response */
02609     data->set.sasl_ir = (0 != va_arg(param, long)) ? TRUE : FALSE;
02610     break;
02611 
02612   case CURLOPT_RTSP_REQUEST:
02613     {
02614       /*
02615        * Set the RTSP request method (OPTIONS, SETUP, PLAY, etc...)
02616        * Would this be better if the RTSPREQ_* were just moved into here?
02617        */
02618       long curl_rtspreq = va_arg(param, long);
02619       Curl_RtspReq rtspreq = RTSPREQ_NONE;
02620       switch(curl_rtspreq) {
02621         case CURL_RTSPREQ_OPTIONS:
02622           rtspreq = RTSPREQ_OPTIONS;
02623           break;
02624 
02625         case CURL_RTSPREQ_DESCRIBE:
02626           rtspreq = RTSPREQ_DESCRIBE;
02627           break;
02628 
02629         case CURL_RTSPREQ_ANNOUNCE:
02630           rtspreq = RTSPREQ_ANNOUNCE;
02631           break;
02632 
02633         case CURL_RTSPREQ_SETUP:
02634           rtspreq = RTSPREQ_SETUP;
02635           break;
02636 
02637         case CURL_RTSPREQ_PLAY:
02638           rtspreq = RTSPREQ_PLAY;
02639           break;
02640 
02641         case CURL_RTSPREQ_PAUSE:
02642           rtspreq = RTSPREQ_PAUSE;
02643           break;
02644 
02645         case CURL_RTSPREQ_TEARDOWN:
02646           rtspreq = RTSPREQ_TEARDOWN;
02647           break;
02648 
02649         case CURL_RTSPREQ_GET_PARAMETER:
02650           rtspreq = RTSPREQ_GET_PARAMETER;
02651           break;
02652 
02653         case CURL_RTSPREQ_SET_PARAMETER:
02654           rtspreq = RTSPREQ_SET_PARAMETER;
02655           break;
02656 
02657         case CURL_RTSPREQ_RECORD:
02658           rtspreq = RTSPREQ_RECORD;
02659           break;
02660 
02661         case CURL_RTSPREQ_RECEIVE:
02662           rtspreq = RTSPREQ_RECEIVE;
02663           break;
02664         default:
02665           rtspreq = RTSPREQ_NONE;
02666       }
02667 
02668       data->set.rtspreq = rtspreq;
02669     break;
02670     }
02671 
02672 
02673   case CURLOPT_RTSP_SESSION_ID:
02674     /*
02675      * Set the RTSP Session ID manually. Useful if the application is
02676      * resuming a previously established RTSP session
02677      */
02678     result = setstropt(&data->set.str[STRING_RTSP_SESSION_ID],
02679                        va_arg(param, char *));
02680     break;
02681 
02682   case CURLOPT_RTSP_STREAM_URI:
02683     /*
02684      * Set the Stream URI for the RTSP request. Unless the request is
02685      * for generic server options, the application will need to set this.
02686      */
02687     result = setstropt(&data->set.str[STRING_RTSP_STREAM_URI],
02688                        va_arg(param, char *));
02689     break;
02690 
02691   case CURLOPT_RTSP_TRANSPORT:
02692     /*
02693      * The content of the Transport: header for the RTSP request
02694      */
02695     result = setstropt(&data->set.str[STRING_RTSP_TRANSPORT],
02696                        va_arg(param, char *));
02697     break;
02698 
02699   case CURLOPT_RTSP_CLIENT_CSEQ:
02700     /*
02701      * Set the CSEQ number to issue for the next RTSP request. Useful if the
02702      * application is resuming a previously broken connection. The CSEQ
02703      * will increment from this new number henceforth.
02704      */
02705     data->state.rtsp_next_client_CSeq = va_arg(param, long);
02706     break;
02707 
02708   case CURLOPT_RTSP_SERVER_CSEQ:
02709     /* Same as the above, but for server-initiated requests */
02710     data->state.rtsp_next_client_CSeq = va_arg(param, long);
02711     break;
02712 
02713   case CURLOPT_INTERLEAVEDATA:
02714     data->set.rtp_out = va_arg(param, void *);
02715     break;
02716   case CURLOPT_INTERLEAVEFUNCTION:
02717     /* Set the user defined RTP write function */
02718     data->set.fwrite_rtp = va_arg(param, curl_write_callback);
02719     break;
02720 
02721   case CURLOPT_WILDCARDMATCH:
02722     data->set.wildcardmatch = (0 != va_arg(param, long)) ? TRUE : FALSE;
02723     break;
02724   case CURLOPT_CHUNK_BGN_FUNCTION:
02725     data->set.chunk_bgn = va_arg(param, curl_chunk_bgn_callback);
02726     break;
02727   case CURLOPT_CHUNK_END_FUNCTION:
02728     data->set.chunk_end = va_arg(param, curl_chunk_end_callback);
02729     break;
02730   case CURLOPT_FNMATCH_FUNCTION:
02731     data->set.fnmatch = va_arg(param, curl_fnmatch_callback);
02732     break;
02733   case CURLOPT_CHUNK_DATA:
02734     data->wildcard.customptr = va_arg(param, void *);
02735     break;
02736   case CURLOPT_FNMATCH_DATA:
02737     data->set.fnmatch_data = va_arg(param, void *);
02738     break;
02739 #ifdef USE_TLS_SRP
02740   case CURLOPT_TLSAUTH_USERNAME:
02741     result = setstropt(&data->set.str[STRING_TLSAUTH_USERNAME_ORIG],
02742                        va_arg(param, char *));
02743     if(data->set.str[STRING_TLSAUTH_USERNAME_ORIG] && !data->set.ssl.authtype)
02744       data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
02745     break;
02746   case CURLOPT_PROXY_TLSAUTH_USERNAME:
02747     result = setstropt(&data->set.str[STRING_TLSAUTH_USERNAME_PROXY],
02748                        va_arg(param, char *));
02749     if(data->set.str[STRING_TLSAUTH_USERNAME_PROXY] &&
02750        !data->set.proxy_ssl.authtype)
02751       data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
02752     break;
02753   case CURLOPT_TLSAUTH_PASSWORD:
02754     result = setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD_ORIG],
02755                        va_arg(param, char *));
02756     if(data->set.str[STRING_TLSAUTH_USERNAME_ORIG] && !data->set.ssl.authtype)
02757       data->set.ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
02758     break;
02759   case CURLOPT_PROXY_TLSAUTH_PASSWORD:
02760     result = setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD_PROXY],
02761                        va_arg(param, char *));
02762     if(data->set.str[STRING_TLSAUTH_USERNAME_PROXY] &&
02763        !data->set.proxy_ssl.authtype)
02764       data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
02765     break;
02766   case CURLOPT_TLSAUTH_TYPE:
02767     if(strncasecompare((char *)va_arg(param, char *), "SRP", strlen("SRP")))
02768       data->set.ssl.authtype = CURL_TLSAUTH_SRP;
02769     else
02770       data->set.ssl.authtype = CURL_TLSAUTH_NONE;
02771     break;
02772   case CURLOPT_PROXY_TLSAUTH_TYPE:
02773     if(strncasecompare((char *)va_arg(param, char *), "SRP", strlen("SRP")))
02774       data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP;
02775     else
02776       data->set.proxy_ssl.authtype = CURL_TLSAUTH_NONE;
02777     break;
02778 #endif
02779   case CURLOPT_DNS_SERVERS:
02780     result = Curl_set_dns_servers(data, va_arg(param, char *));
02781     break;
02782   case CURLOPT_DNS_INTERFACE:
02783     result = Curl_set_dns_interface(data, va_arg(param, char *));
02784     break;
02785   case CURLOPT_DNS_LOCAL_IP4:
02786     result = Curl_set_dns_local_ip4(data, va_arg(param, char *));
02787     break;
02788   case CURLOPT_DNS_LOCAL_IP6:
02789     result = Curl_set_dns_local_ip6(data, va_arg(param, char *));
02790     break;
02791 
02792   case CURLOPT_TCP_KEEPALIVE:
02793     data->set.tcp_keepalive = (0 != va_arg(param, long)) ? TRUE : FALSE;
02794     break;
02795   case CURLOPT_TCP_KEEPIDLE:
02796     data->set.tcp_keepidle = va_arg(param, long);
02797     break;
02798   case CURLOPT_TCP_KEEPINTVL:
02799     data->set.tcp_keepintvl = va_arg(param, long);
02800     break;
02801   case CURLOPT_TCP_FASTOPEN:
02802 #if defined(CONNECT_DATA_IDEMPOTENT) || defined(MSG_FASTOPEN)
02803     data->set.tcp_fastopen = (0 != va_arg(param, long))?TRUE:FALSE;
02804 #else
02805     result = CURLE_NOT_BUILT_IN;
02806 #endif
02807     break;
02808   case CURLOPT_SSL_ENABLE_NPN:
02809     data->set.ssl_enable_npn = (0 != va_arg(param, long)) ? TRUE : FALSE;
02810     break;
02811   case CURLOPT_SSL_ENABLE_ALPN:
02812     data->set.ssl_enable_alpn = (0 != va_arg(param, long)) ? TRUE : FALSE;
02813     break;
02814 
02815 #ifdef USE_UNIX_SOCKETS
02816   case CURLOPT_UNIX_SOCKET_PATH:
02817     result = setstropt(&data->set.str[STRING_UNIX_SOCKET_PATH],
02818                        va_arg(param, char *));
02819     break;
02820 #endif
02821 
02822   case CURLOPT_PATH_AS_IS:
02823     data->set.path_as_is = (0 != va_arg(param, long)) ? TRUE : FALSE;
02824     break;
02825   case CURLOPT_PIPEWAIT:
02826     data->set.pipewait = (0 != va_arg(param, long)) ? TRUE : FALSE;
02827     break;
02828   case CURLOPT_STREAM_WEIGHT:
02829 #ifndef USE_NGHTTP2
02830     return CURLE_NOT_BUILT_IN;
02831 #else
02832     arg = va_arg(param, long);
02833     if((arg>=1) && (arg <= 256))
02834       data->set.stream_weight = (int)arg;
02835     break;
02836 #endif
02837   case CURLOPT_STREAM_DEPENDS:
02838   case CURLOPT_STREAM_DEPENDS_E:
02839   {
02840 #ifndef USE_NGHTTP2
02841     return CURLE_NOT_BUILT_IN;
02842 #else
02843     struct Curl_easy *dep = va_arg(param, struct Curl_easy *);
02844     if(!dep || GOOD_EASY_HANDLE(dep)) {
02845       if(data->set.stream_depends_on) {
02846         Curl_http2_remove_child(data->set.stream_depends_on, data);
02847       }
02848       Curl_http2_add_child(dep, data, (option == CURLOPT_STREAM_DEPENDS_E));
02849     }
02850     break;
02851 #endif
02852   }
02853   case CURLOPT_CONNECT_TO:
02854     data->set.connect_to = va_arg(param, struct curl_slist *);
02855     break;
02856   default:
02857     /* unknown tag and its companion, just ignore: */
02858     result = CURLE_UNKNOWN_OPTION;
02859     break;
02860   }
02861 
02862   return result;
02863 }
02864 
02865 #ifdef USE_RECV_BEFORE_SEND_WORKAROUND
02866 static void conn_reset_postponed_data(struct connectdata *conn, int num)
02867 {
02868   struct postponed_data * const psnd = &(conn->postponed[num]);
02869   if(psnd->buffer) {
02870     DEBUGASSERT(psnd->allocated_size > 0);
02871     DEBUGASSERT(psnd->recv_size <= psnd->allocated_size);
02872     DEBUGASSERT(psnd->recv_size ?
02873                 (psnd->recv_processed < psnd->recv_size) :
02874                 (psnd->recv_processed == 0));
02875     DEBUGASSERT(psnd->bindsock != CURL_SOCKET_BAD);
02876     free(psnd->buffer);
02877     psnd->buffer = NULL;
02878     psnd->allocated_size = 0;
02879     psnd->recv_size = 0;
02880     psnd->recv_processed = 0;
02881 #ifdef DEBUGBUILD
02882     psnd->bindsock = CURL_SOCKET_BAD; /* used only for DEBUGASSERT */
02883 #endif /* DEBUGBUILD */
02884   }
02885   else {
02886     DEBUGASSERT(psnd->allocated_size == 0);
02887     DEBUGASSERT(psnd->recv_size == 0);
02888     DEBUGASSERT(psnd->recv_processed == 0);
02889     DEBUGASSERT(psnd->bindsock == CURL_SOCKET_BAD);
02890   }
02891 }
02892 
02893 static void conn_reset_all_postponed_data(struct connectdata *conn)
02894 {
02895   conn_reset_postponed_data(conn, 0);
02896   conn_reset_postponed_data(conn, 1);
02897 }
02898 #else  /* ! USE_RECV_BEFORE_SEND_WORKAROUND */
02899 /* Use "do-nothing" macros instead of functions when workaround not used */
02900 #define conn_reset_postponed_data(c,n) do {} WHILE_FALSE
02901 #define conn_reset_all_postponed_data(c) do {} WHILE_FALSE
02902 #endif /* ! USE_RECV_BEFORE_SEND_WORKAROUND */
02903 
02904 static void conn_free(struct connectdata *conn)
02905 {
02906   if(!conn)
02907     return;
02908 
02909   /* possible left-overs from the async name resolvers */
02910   Curl_resolver_cancel(conn);
02911 
02912   /* close the SSL stuff before we close any sockets since they will/may
02913      write to the sockets */
02914   Curl_ssl_close(conn, FIRSTSOCKET);
02915   Curl_ssl_close(conn, SECONDARYSOCKET);
02916 
02917   /* close possibly still open sockets */
02918   if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET])
02919     Curl_closesocket(conn, conn->sock[SECONDARYSOCKET]);
02920   if(CURL_SOCKET_BAD != conn->sock[FIRSTSOCKET])
02921     Curl_closesocket(conn, conn->sock[FIRSTSOCKET]);
02922   if(CURL_SOCKET_BAD != conn->tempsock[0])
02923     Curl_closesocket(conn, conn->tempsock[0]);
02924   if(CURL_SOCKET_BAD != conn->tempsock[1])
02925     Curl_closesocket(conn, conn->tempsock[1]);
02926 
02927 #if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \
02928     defined(NTLM_WB_ENABLED)
02929   Curl_ntlm_wb_cleanup(conn);
02930 #endif
02931 
02932   Curl_safefree(conn->user);
02933   Curl_safefree(conn->passwd);
02934   Curl_safefree(conn->oauth_bearer);
02935   Curl_safefree(conn->options);
02936   Curl_safefree(conn->http_proxy.user);
02937   Curl_safefree(conn->socks_proxy.user);
02938   Curl_safefree(conn->http_proxy.passwd);
02939   Curl_safefree(conn->socks_proxy.passwd);
02940   Curl_safefree(conn->allocptr.proxyuserpwd);
02941   Curl_safefree(conn->allocptr.uagent);
02942   Curl_safefree(conn->allocptr.userpwd);
02943   Curl_safefree(conn->allocptr.accept_encoding);
02944   Curl_safefree(conn->allocptr.te);
02945   Curl_safefree(conn->allocptr.rangeline);
02946   Curl_safefree(conn->allocptr.ref);
02947   Curl_safefree(conn->allocptr.host);
02948   Curl_safefree(conn->allocptr.cookiehost);
02949   Curl_safefree(conn->allocptr.rtsp_transport);
02950   Curl_safefree(conn->trailer);
02951   Curl_safefree(conn->host.rawalloc); /* host name buffer */
02952   Curl_safefree(conn->conn_to_host.rawalloc); /* host name buffer */
02953   Curl_safefree(conn->secondaryhostname);
02954   Curl_safefree(conn->http_proxy.host.rawalloc); /* http proxy name buffer */
02955   Curl_safefree(conn->socks_proxy.host.rawalloc); /* socks proxy name buffer */
02956   Curl_safefree(conn->master_buffer);
02957 
02958   conn_reset_all_postponed_data(conn);
02959 
02960   Curl_llist_destroy(conn->send_pipe, NULL);
02961   Curl_llist_destroy(conn->recv_pipe, NULL);
02962 
02963   conn->send_pipe = NULL;
02964   conn->recv_pipe = NULL;
02965 
02966   Curl_safefree(conn->localdev);
02967   Curl_free_primary_ssl_config(&conn->ssl_config);
02968   Curl_free_primary_ssl_config(&conn->proxy_ssl_config);
02969 
02970 #ifdef USE_UNIX_SOCKETS
02971   Curl_safefree(conn->unix_domain_socket);
02972 #endif
02973 
02974   free(conn); /* free all the connection oriented data */
02975 }
02976 
02977 /*
02978  * Disconnects the given connection. Note the connection may not be the
02979  * primary connection, like when freeing room in the connection cache or
02980  * killing of a dead old connection.
02981  *
02982  * This function MUST NOT reset state in the Curl_easy struct if that
02983  * isn't strictly bound to the life-time of *this* particular connection.
02984  *
02985  */
02986 
02987 CURLcode Curl_disconnect(struct connectdata *conn, bool dead_connection)
02988 {
02989   struct Curl_easy *data;
02990   if(!conn)
02991     return CURLE_OK; /* this is closed and fine already */
02992   data = conn->data;
02993 
02994   if(!data) {
02995     DEBUGF(fprintf(stderr, "DISCONNECT without easy handle, ignoring\n"));
02996     return CURLE_OK;
02997   }
02998 
02999   /*
03000    * If this connection isn't marked to force-close, leave it open if there
03001    * are other users of it
03002    */
03003   if(!conn->bits.close &&
03004      (conn->send_pipe->size + conn->recv_pipe->size)) {
03005     DEBUGF(infof(data, "Curl_disconnect, usecounter: %d\n",
03006                  conn->send_pipe->size + conn->recv_pipe->size));
03007     return CURLE_OK;
03008   }
03009 
03010   if(conn->dns_entry != NULL) {
03011     Curl_resolv_unlock(data, conn->dns_entry);
03012     conn->dns_entry = NULL;
03013   }
03014 
03015   Curl_hostcache_prune(data); /* kill old DNS cache entries */
03016 
03017 #if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM)
03018   /* Cleanup NTLM connection-related data */
03019   Curl_http_ntlm_cleanup(conn);
03020 #endif
03021 
03022   if(conn->handler->disconnect)
03023     /* This is set if protocol-specific cleanups should be made */
03024     conn->handler->disconnect(conn, dead_connection);
03025 
03026     /* unlink ourselves! */
03027   infof(data, "Closing connection %ld\n", conn->connection_id);
03028   Curl_conncache_remove_conn(data->state.conn_cache, conn);
03029 
03030   free_fixed_hostname(&conn->host);
03031   free_fixed_hostname(&conn->conn_to_host);
03032   free_fixed_hostname(&conn->proxy);
03033   free_fixed_hostname(&conn->http_proxy.host);
03034   free_fixed_hostname(&conn->socks_proxy.host);
03035 
03036   Curl_ssl_close(conn, FIRSTSOCKET);
03037 
03038   /* Indicate to all handles on the pipe that we're dead */
03039   if(Curl_pipeline_wanted(data->multi, CURLPIPE_ANY)) {
03040     signalPipeClose(conn->send_pipe, TRUE);
03041     signalPipeClose(conn->recv_pipe, TRUE);
03042   }
03043 
03044   conn_free(conn);
03045 
03046   return CURLE_OK;
03047 }
03048 
03049 /*
03050  * This function should return TRUE if the socket is to be assumed to
03051  * be dead. Most commonly this happens when the server has closed the
03052  * connection due to inactivity.
03053  */
03054 static bool SocketIsDead(curl_socket_t sock)
03055 {
03056   int sval;
03057   bool ret_val = TRUE;
03058 
03059   sval = SOCKET_READABLE(sock, 0);
03060   if(sval == 0)
03061     /* timeout */
03062     ret_val = FALSE;
03063 
03064   return ret_val;
03065 }
03066 
03067 /*
03068  * IsPipeliningPossible() returns TRUE if the options set would allow
03069  * pipelining/multiplexing and the connection is using a HTTP protocol.
03070  */
03071 static bool IsPipeliningPossible(const struct Curl_easy *handle,
03072                                  const struct connectdata *conn)
03073 {
03074   /* If a HTTP protocol and pipelining is enabled */
03075   if((conn->handler->protocol & PROTO_FAMILY_HTTP) &&
03076      (!conn->bits.protoconnstart || !conn->bits.close)) {
03077 
03078     if(Curl_pipeline_wanted(handle->multi, CURLPIPE_HTTP1) &&
03079        (handle->set.httpversion != CURL_HTTP_VERSION_1_0) &&
03080        (handle->set.httpreq == HTTPREQ_GET ||
03081         handle->set.httpreq == HTTPREQ_HEAD))
03082       /* didn't ask for HTTP/1.0 and a GET or HEAD */
03083       return TRUE;
03084 
03085     if(Curl_pipeline_wanted(handle->multi, CURLPIPE_MULTIPLEX) &&
03086        (handle->set.httpversion >= CURL_HTTP_VERSION_2))
03087       /* allows HTTP/2 */
03088       return TRUE;
03089   }
03090   return FALSE;
03091 }
03092 
03093 int Curl_removeHandleFromPipeline(struct Curl_easy *handle,
03094                                   struct curl_llist *pipeline)
03095 {
03096   if(pipeline) {
03097     struct curl_llist_element *curr;
03098 
03099     curr = pipeline->head;
03100     while(curr) {
03101       if(curr->ptr == handle) {
03102         Curl_llist_remove(pipeline, curr, NULL);
03103         return 1; /* we removed a handle */
03104       }
03105       curr = curr->next;
03106     }
03107   }
03108 
03109   return 0;
03110 }
03111 
03112 #if 0 /* this code is saved here as it is useful for debugging purposes */
03113 static void Curl_printPipeline(struct curl_llist *pipeline)
03114 {
03115   struct curl_llist_element *curr;
03116 
03117   curr = pipeline->head;
03118   while(curr) {
03119     struct Curl_easy *data = (struct Curl_easy *) curr->ptr;
03120     infof(data, "Handle in pipeline: %s\n", data->state.path);
03121     curr = curr->next;
03122   }
03123 }
03124 #endif
03125 
03126 static struct Curl_easy* gethandleathead(struct curl_llist *pipeline)
03127 {
03128   struct curl_llist_element *curr = pipeline->head;
03129   if(curr) {
03130     return (struct Curl_easy *) curr->ptr;
03131   }
03132 
03133   return NULL;
03134 }
03135 
03136 /* remove the specified connection from all (possible) pipelines and related
03137    queues */
03138 void Curl_getoff_all_pipelines(struct Curl_easy *data,
03139                                struct connectdata *conn)
03140 {
03141   bool recv_head = (conn->readchannel_inuse &&
03142                     Curl_recvpipe_head(data, conn));
03143   bool send_head = (conn->writechannel_inuse &&
03144                     Curl_sendpipe_head(data, conn));
03145 
03146   if(Curl_removeHandleFromPipeline(data, conn->recv_pipe) && recv_head)
03147     Curl_pipeline_leave_read(conn);
03148   if(Curl_removeHandleFromPipeline(data, conn->send_pipe) && send_head)
03149     Curl_pipeline_leave_write(conn);
03150 }
03151 
03152 static void signalPipeClose(struct curl_llist *pipeline, bool pipe_broke)
03153 {
03154   struct curl_llist_element *curr;
03155 
03156   if(!pipeline)
03157     return;
03158 
03159   curr = pipeline->head;
03160   while(curr) {
03161     struct curl_llist_element *next = curr->next;
03162     struct Curl_easy *data = (struct Curl_easy *) curr->ptr;
03163 
03164 #ifdef DEBUGBUILD /* debug-only code */
03165     if(data->magic != CURLEASY_MAGIC_NUMBER) {
03166       /* MAJOR BADNESS */
03167       infof(data, "signalPipeClose() found BAAD easy handle\n");
03168     }
03169 #endif
03170 
03171     if(pipe_broke)
03172       data->state.pipe_broke = TRUE;
03173     Curl_multi_handlePipeBreak(data);
03174     Curl_llist_remove(pipeline, curr, NULL);
03175     curr = next;
03176   }
03177 }
03178 
03179 /*
03180  * This function finds the connection in the connection
03181  * cache that has been unused for the longest time.
03182  *
03183  * Returns the pointer to the oldest idle connection, or NULL if none was
03184  * found.
03185  */
03186 struct connectdata *
03187 Curl_oldest_idle_connection(struct Curl_easy *data)
03188 {
03189   struct conncache *bc = data->state.conn_cache;
03190   struct curl_hash_iterator iter;
03191   struct curl_llist_element *curr;
03192   struct curl_hash_element *he;
03193   time_t highscore=-1;
03194   time_t score;
03195   struct timeval now;
03196   struct connectdata *conn_candidate = NULL;
03197   struct connectbundle *bundle;
03198 
03199   now = Curl_tvnow();
03200 
03201   Curl_hash_start_iterate(&bc->hash, &iter);
03202 
03203   he = Curl_hash_next_element(&iter);
03204   while(he) {
03205     struct connectdata *conn;
03206 
03207     bundle = he->ptr;
03208 
03209     curr = bundle->conn_list->head;
03210     while(curr) {
03211       conn = curr->ptr;
03212 
03213       if(!conn->inuse) {
03214         /* Set higher score for the age passed since the connection was used */
03215         score = Curl_tvdiff(now, conn->now);
03216 
03217         if(score > highscore) {
03218           highscore = score;
03219           conn_candidate = conn;
03220         }
03221       }
03222       curr = curr->next;
03223     }
03224 
03225     he = Curl_hash_next_element(&iter);
03226   }
03227 
03228   return conn_candidate;
03229 }
03230 
03231 static bool
03232 proxy_info_matches(const struct proxy_info* data,
03233                    const struct proxy_info* needle)
03234 {
03235   if((data->proxytype == needle->proxytype) &&
03236      (data->port == needle->port) &&
03237      Curl_safe_strcasecompare(data->host.name, needle->host.name) &&
03238      Curl_safe_strcasecompare(data->user, needle->user) &&
03239      Curl_safe_strcasecompare(data->passwd, needle->passwd))
03240     return TRUE;
03241 
03242   return FALSE;
03243 }
03244 
03245 
03246 /*
03247  * This function finds the connection in the connection
03248  * bundle that has been unused for the longest time.
03249  *
03250  * Returns the pointer to the oldest idle connection, or NULL if none was
03251  * found.
03252  */
03253 static struct connectdata *
03254 find_oldest_idle_connection_in_bundle(struct Curl_easy *data,
03255                                       struct connectbundle *bundle)
03256 {
03257   struct curl_llist_element *curr;
03258   time_t highscore=-1;
03259   time_t score;
03260   struct timeval now;
03261   struct connectdata *conn_candidate = NULL;
03262   struct connectdata *conn;
03263 
03264   (void)data;
03265 
03266   now = Curl_tvnow();
03267 
03268   curr = bundle->conn_list->head;
03269   while(curr) {
03270     conn = curr->ptr;
03271 
03272     if(!conn->inuse) {
03273       /* Set higher score for the age passed since the connection was used */
03274       score = Curl_tvdiff(now, conn->now);
03275 
03276       if(score > highscore) {
03277         highscore = score;
03278         conn_candidate = conn;
03279       }
03280     }
03281     curr = curr->next;
03282   }
03283 
03284   return conn_candidate;
03285 }
03286 
03287 /*
03288  * This function checks if given connection is dead and disconnects if so.
03289  * (That also removes it from the connection cache.)
03290  *
03291  * Returns TRUE if the connection actually was dead and disconnected.
03292  */
03293 static bool disconnect_if_dead(struct connectdata *conn,
03294                                struct Curl_easy *data)
03295 {
03296   size_t pipeLen = conn->send_pipe->size + conn->recv_pipe->size;
03297   if(!pipeLen && !conn->inuse) {
03298     /* The check for a dead socket makes sense only if there are no
03299        handles in pipeline and the connection isn't already marked in
03300        use */
03301     bool dead;
03302     if(conn->handler->protocol & CURLPROTO_RTSP)
03303       /* RTSP is a special case due to RTP interleaving */
03304       dead = Curl_rtsp_connisdead(conn);
03305     else
03306       dead = SocketIsDead(conn->sock[FIRSTSOCKET]);
03307 
03308     if(dead) {
03309       conn->data = data;
03310       infof(data, "Connection %ld seems to be dead!\n", conn->connection_id);
03311 
03312       /* disconnect resources */
03313       Curl_disconnect(conn, /* dead_connection */TRUE);
03314       return TRUE;
03315     }
03316   }
03317   return FALSE;
03318 }
03319 
03320 /*
03321  * Wrapper to use disconnect_if_dead() function in Curl_conncache_foreach()
03322  *
03323  * Returns always 0.
03324  */
03325 static int call_disconnect_if_dead(struct connectdata *conn,
03326                                       void *param)
03327 {
03328   struct Curl_easy* data = (struct Curl_easy*)param;
03329   disconnect_if_dead(conn, data);
03330   return 0; /* continue iteration */
03331 }
03332 
03333 /*
03334  * This function scans the connection cache for half-open/dead connections,
03335  * closes and removes them.
03336  * The cleanup is done at most once per second.
03337  */
03338 static void prune_dead_connections(struct Curl_easy *data)
03339 {
03340   struct timeval now = Curl_tvnow();
03341   time_t elapsed = Curl_tvdiff(now, data->state.conn_cache->last_cleanup);
03342 
03343   if(elapsed >= 1000L) {
03344     Curl_conncache_foreach(data->state.conn_cache, data,
03345                            call_disconnect_if_dead);
03346     data->state.conn_cache->last_cleanup = now;
03347   }
03348 }
03349 
03350 
03351 static size_t max_pipeline_length(struct Curl_multi *multi)
03352 {
03353   return multi ? multi->max_pipeline_length : 0;
03354 }
03355 
03356 
03357 /*
03358  * Given one filled in connection struct (named needle), this function should
03359  * detect if there already is one that has all the significant details
03360  * exactly the same and thus should be used instead.
03361  *
03362  * If there is a match, this function returns TRUE - and has marked the
03363  * connection as 'in-use'. It must later be called with ConnectionDone() to
03364  * return back to 'idle' (unused) state.
03365  *
03366  * The force_reuse flag is set if the connection must be used, even if
03367  * the pipelining strategy wants to open a new connection instead of reusing.
03368  */
03369 static bool
03370 ConnectionExists(struct Curl_easy *data,
03371                  struct connectdata *needle,
03372                  struct connectdata **usethis,
03373                  bool *force_reuse,
03374                  bool *waitpipe)
03375 {
03376   struct connectdata *check;
03377   struct connectdata *chosen = 0;
03378   bool foundPendingCandidate = FALSE;
03379   bool canPipeline = IsPipeliningPossible(data, needle);
03380   struct connectbundle *bundle;
03381 
03382 #ifdef USE_NTLM
03383   bool wantNTLMhttp = ((data->state.authhost.want &
03384                       (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) &&
03385                       (needle->handler->protocol & PROTO_FAMILY_HTTP));
03386   bool wantProxyNTLMhttp = (needle->bits.proxy_user_passwd &&
03387                            ((data->state.authproxy.want &
03388                            (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) &&
03389                            (needle->handler->protocol & PROTO_FAMILY_HTTP)));
03390 #endif
03391 
03392   *force_reuse = FALSE;
03393   *waitpipe = FALSE;
03394 
03395   /* We can't pipe if the site is blacklisted */
03396   if(canPipeline && Curl_pipeline_site_blacklisted(data, needle)) {
03397     canPipeline = FALSE;
03398   }
03399 
03400   /* Look up the bundle with all the connections to this
03401      particular host */
03402   bundle = Curl_conncache_find_bundle(needle, data->state.conn_cache);
03403   if(bundle) {
03404     /* Max pipe length is zero (unlimited) for multiplexed connections */
03405     size_t max_pipe_len = (bundle->multiuse != BUNDLE_MULTIPLEX)?
03406       max_pipeline_length(data->multi):0;
03407     size_t best_pipe_len = max_pipe_len;
03408     struct curl_llist_element *curr;
03409     const char *hostname;
03410 
03411     if(needle->bits.conn_to_host)
03412       hostname = needle->conn_to_host.name;
03413     else
03414       hostname = needle->host.name;
03415 
03416     infof(data, "Found bundle for host %s: %p [%s]\n",
03417           hostname, (void *)bundle,
03418           (bundle->multiuse== BUNDLE_PIPELINING?
03419            "can pipeline":
03420            (bundle->multiuse== BUNDLE_MULTIPLEX?
03421             "can multiplex":"serially")));
03422 
03423     /* We can't pipe if we don't know anything about the server */
03424     if(canPipeline) {
03425       if(bundle->multiuse <= BUNDLE_UNKNOWN) {
03426         if((bundle->multiuse == BUNDLE_UNKNOWN) && data->set.pipewait) {
03427           infof(data, "Server doesn't support multi-use yet, wait\n");
03428           *waitpipe = TRUE;
03429           return FALSE; /* no re-use */
03430         }
03431 
03432         infof(data, "Server doesn't support multi-use (yet)\n");
03433         canPipeline = FALSE;
03434       }
03435       if((bundle->multiuse == BUNDLE_PIPELINING) &&
03436          !Curl_pipeline_wanted(data->multi, CURLPIPE_HTTP1)) {
03437         /* not asked for, switch off */
03438         infof(data, "Could pipeline, but not asked to!\n");
03439         canPipeline = FALSE;
03440       }
03441       else if((bundle->multiuse == BUNDLE_MULTIPLEX) &&
03442               !Curl_pipeline_wanted(data->multi, CURLPIPE_MULTIPLEX)) {
03443         infof(data, "Could multiplex, but not asked to!\n");
03444         canPipeline = FALSE;
03445       }
03446     }
03447 
03448     curr = bundle->conn_list->head;
03449     while(curr) {
03450       bool match = FALSE;
03451       size_t pipeLen;
03452 
03453       /*
03454        * Note that if we use a HTTP proxy in normal mode (no tunneling), we
03455        * check connections to that proxy and not to the actual remote server.
03456        */
03457       check = curr->ptr;
03458       curr = curr->next;
03459 
03460       if(disconnect_if_dead(check, data))
03461         continue;
03462 
03463       pipeLen = check->send_pipe->size + check->recv_pipe->size;
03464 
03465       if(canPipeline) {
03466         if(check->bits.protoconnstart && check->bits.close)
03467           continue;
03468 
03469         if(!check->bits.multiplex) {
03470           /* If not multiplexing, make sure the pipe has only GET requests */
03471           struct Curl_easy* sh = gethandleathead(check->send_pipe);
03472           struct Curl_easy* rh = gethandleathead(check->recv_pipe);
03473           if(sh) {
03474             if(!IsPipeliningPossible(sh, check))
03475               continue;
03476           }
03477           else if(rh) {
03478             if(!IsPipeliningPossible(rh, check))
03479               continue;
03480           }
03481         }
03482       }
03483       else {
03484         if(pipeLen > 0) {
03485           /* can only happen within multi handles, and means that another easy
03486              handle is using this connection */
03487           continue;
03488         }
03489 
03490         if(Curl_resolver_asynch()) {
03491           /* ip_addr_str[0] is NUL only if the resolving of the name hasn't
03492              completed yet and until then we don't re-use this connection */
03493           if(!check->ip_addr_str[0]) {
03494             infof(data,
03495                   "Connection #%ld is still name resolving, can't reuse\n",
03496                   check->connection_id);
03497             continue;
03498           }
03499         }
03500 
03501         if((check->sock[FIRSTSOCKET] == CURL_SOCKET_BAD) ||
03502            check->bits.close) {
03503           if(!check->bits.close)
03504             foundPendingCandidate = TRUE;
03505           /* Don't pick a connection that hasn't connected yet or that is going
03506              to get closed. */
03507           infof(data, "Connection #%ld isn't open enough, can't reuse\n",
03508                 check->connection_id);
03509 #ifdef DEBUGBUILD
03510           if(check->recv_pipe->size > 0) {
03511             infof(data,
03512                   "BAD! Unconnected #%ld has a non-empty recv pipeline!\n",
03513                   check->connection_id);
03514           }
03515 #endif
03516           continue;
03517         }
03518       }
03519 
03520 #ifdef USE_UNIX_SOCKETS
03521       if(needle->unix_domain_socket) {
03522         if(!check->unix_domain_socket)
03523           continue;
03524         if(strcmp(needle->unix_domain_socket, check->unix_domain_socket))
03525           continue;
03526       }
03527       else if(check->unix_domain_socket)
03528         continue;
03529 #endif
03530 
03531       if((needle->handler->flags&PROTOPT_SSL) !=
03532          (check->handler->flags&PROTOPT_SSL))
03533         /* don't do mixed SSL and non-SSL connections */
03534         if(get_protocol_family(check->handler->protocol) !=
03535            needle->handler->protocol || !check->tls_upgraded)
03536           /* except protocols that have been upgraded via TLS */
03537           continue;
03538 
03539       if(needle->bits.httpproxy != check->bits.httpproxy ||
03540          needle->bits.socksproxy != check->bits.socksproxy)
03541         continue;
03542 
03543       if(needle->bits.socksproxy && !proxy_info_matches(&needle->socks_proxy,
03544                                                         &check->socks_proxy))
03545         continue;
03546 
03547       if(needle->bits.conn_to_host != check->bits.conn_to_host)
03548         /* don't mix connections that use the "connect to host" feature and
03549          * connections that don't use this feature */
03550         continue;
03551 
03552       if(needle->bits.conn_to_port != check->bits.conn_to_port)
03553         /* don't mix connections that use the "connect to port" feature and
03554          * connections that don't use this feature */
03555         continue;
03556 
03557       if(needle->bits.httpproxy) {
03558         if(!proxy_info_matches(&needle->http_proxy, &check->http_proxy))
03559           continue;
03560 
03561         if(needle->bits.tunnel_proxy != check->bits.tunnel_proxy)
03562           continue;
03563 
03564         if(needle->http_proxy.proxytype == CURLPROXY_HTTPS) {
03565           /* use https proxy */
03566           if(needle->handler->flags&PROTOPT_SSL) {
03567             /* use double layer ssl */
03568             if(!Curl_ssl_config_matches(&needle->proxy_ssl_config,
03569                                         &check->proxy_ssl_config))
03570               continue;
03571             if(check->proxy_ssl[FIRSTSOCKET].state != ssl_connection_complete)
03572               continue;
03573           }
03574           else {
03575             if(!Curl_ssl_config_matches(&needle->ssl_config,
03576                                         &check->ssl_config))
03577               continue;
03578             if(check->ssl[FIRSTSOCKET].state != ssl_connection_complete)
03579               continue;
03580           }
03581         }
03582       }
03583 
03584       if(!canPipeline && check->inuse)
03585         /* this request can't be pipelined but the checked connection is
03586            already in use so we skip it */
03587         continue;
03588 
03589       if(needle->localdev || needle->localport) {
03590         /* If we are bound to a specific local end (IP+port), we must not
03591            re-use a random other one, although if we didn't ask for a
03592            particular one we can reuse one that was bound.
03593 
03594            This comparison is a bit rough and too strict. Since the input
03595            parameters can be specified in numerous ways and still end up the
03596            same it would take a lot of processing to make it really accurate.
03597            Instead, this matching will assume that re-uses of bound connections
03598            will most likely also re-use the exact same binding parameters and
03599            missing out a few edge cases shouldn't hurt anyone very much.
03600         */
03601         if((check->localport != needle->localport) ||
03602            (check->localportrange != needle->localportrange) ||
03603            (needle->localdev &&
03604             (!check->localdev || strcmp(check->localdev, needle->localdev))))
03605           continue;
03606       }
03607 
03608       if(!(needle->handler->flags & PROTOPT_CREDSPERREQUEST)) {
03609         /* This protocol requires credentials per connection,
03610            so verify that we're using the same name and password as well */
03611         if(strcmp(needle->user, check->user) ||
03612            strcmp(needle->passwd, check->passwd)) {
03613           /* one of them was different */
03614           continue;
03615         }
03616       }
03617 
03618       if(!needle->bits.httpproxy || (needle->handler->flags&PROTOPT_SSL) ||
03619          needle->bits.tunnel_proxy) {
03620         /* The requested connection does not use a HTTP proxy or it uses SSL or
03621            it is a non-SSL protocol tunneled or it is a non-SSL protocol which
03622            is allowed to be upgraded via TLS */
03623 
03624         if((strcasecompare(needle->handler->scheme, check->handler->scheme) ||
03625             (get_protocol_family(check->handler->protocol) ==
03626              needle->handler->protocol && check->tls_upgraded)) &&
03627            (!needle->bits.conn_to_host || strcasecompare(
03628             needle->conn_to_host.name, check->conn_to_host.name)) &&
03629            (!needle->bits.conn_to_port ||
03630              needle->conn_to_port == check->conn_to_port) &&
03631            strcasecompare(needle->host.name, check->host.name) &&
03632            needle->remote_port == check->remote_port) {
03633           /* The schemes match or the the protocol family is the same and the
03634              previous connection was TLS upgraded, and the hostname and host
03635              port match */
03636           if(needle->handler->flags & PROTOPT_SSL) {
03637             /* This is a SSL connection so verify that we're using the same
03638                SSL options as well */
03639             if(!Curl_ssl_config_matches(&needle->ssl_config,
03640                                         &check->ssl_config)) {
03641               DEBUGF(infof(data,
03642                            "Connection #%ld has different SSL parameters, "
03643                            "can't reuse\n",
03644                            check->connection_id));
03645               continue;
03646             }
03647             else if(check->ssl[FIRSTSOCKET].state != ssl_connection_complete) {
03648               foundPendingCandidate = TRUE;
03649               DEBUGF(infof(data,
03650                            "Connection #%ld has not started SSL connect, "
03651                            "can't reuse\n",
03652                            check->connection_id));
03653               continue;
03654             }
03655           }
03656           match = TRUE;
03657         }
03658       }
03659       else {
03660         /* The requested connection is using the same HTTP proxy in normal
03661            mode (no tunneling) */
03662         match = TRUE;
03663       }
03664 
03665       if(match) {
03666 #if defined(USE_NTLM)
03667         /* If we are looking for an HTTP+NTLM connection, check if this is
03668            already authenticating with the right credentials. If not, keep
03669            looking so that we can reuse NTLM connections if
03670            possible. (Especially we must not reuse the same connection if
03671            partway through a handshake!) */
03672         if(wantNTLMhttp) {
03673           if(strcmp(needle->user, check->user) ||
03674              strcmp(needle->passwd, check->passwd))
03675             continue;
03676         }
03677         else if(check->ntlm.state != NTLMSTATE_NONE) {
03678           /* Connection is using NTLM auth but we don't want NTLM */
03679           continue;
03680         }
03681 
03682         /* Same for Proxy NTLM authentication */
03683         if(wantProxyNTLMhttp) {
03684           /* Both check->http_proxy.user and check->http_proxy.passwd can be
03685            * NULL */
03686           if(!check->http_proxy.user || !check->http_proxy.passwd)
03687             continue;
03688 
03689           if(strcmp(needle->http_proxy.user, check->http_proxy.user) ||
03690              strcmp(needle->http_proxy.passwd, check->http_proxy.passwd))
03691             continue;
03692         }
03693         else if(check->proxyntlm.state != NTLMSTATE_NONE) {
03694           /* Proxy connection is using NTLM auth but we don't want NTLM */
03695           continue;
03696         }
03697 
03698         if(wantNTLMhttp || wantProxyNTLMhttp) {
03699           /* Credentials are already checked, we can use this connection */
03700           chosen = check;
03701 
03702           if((wantNTLMhttp &&
03703              (check->ntlm.state != NTLMSTATE_NONE)) ||
03704               (wantProxyNTLMhttp &&
03705                (check->proxyntlm.state != NTLMSTATE_NONE))) {
03706             /* We must use this connection, no other */
03707             *force_reuse = TRUE;
03708             break;
03709           }
03710 
03711           /* Continue look up for a better connection */
03712           continue;
03713         }
03714 #endif
03715         if(canPipeline) {
03716           /* We can pipeline if we want to. Let's continue looking for
03717              the optimal connection to use, i.e the shortest pipe that is not
03718              blacklisted. */
03719 
03720           if(pipeLen == 0) {
03721             /* We have the optimal connection. Let's stop looking. */
03722             chosen = check;
03723             break;
03724           }
03725 
03726           /* We can't use the connection if the pipe is full */
03727           if(max_pipe_len && (pipeLen >= max_pipe_len)) {
03728             infof(data, "Pipe is full, skip (%zu)\n", pipeLen);
03729             continue;
03730           }
03731 #ifdef USE_NGHTTP2
03732           /* If multiplexed, make sure we don't go over concurrency limit */
03733           if(check->bits.multiplex) {
03734             /* Multiplexed connections can only be HTTP/2 for now */
03735             struct http_conn *httpc = &check->proto.httpc;
03736             if(pipeLen >= httpc->settings.max_concurrent_streams) {
03737               infof(data, "MAX_CONCURRENT_STREAMS reached, skip (%zu)\n",
03738                     pipeLen);
03739               continue;
03740             }
03741           }
03742 #endif
03743           /* We can't use the connection if the pipe is penalized */
03744           if(Curl_pipeline_penalized(data, check)) {
03745             infof(data, "Penalized, skip\n");
03746             continue;
03747           }
03748 
03749           if(max_pipe_len) {
03750             if(pipeLen < best_pipe_len) {
03751               /* This connection has a shorter pipe so far. We'll pick this
03752                  and continue searching */
03753               chosen = check;
03754               best_pipe_len = pipeLen;
03755               continue;
03756             }
03757           }
03758           else {
03759             /* When not pipelining (== multiplexed), we have a match here! */
03760             chosen = check;
03761             infof(data, "Multiplexed connection found!\n");
03762             break;
03763           }
03764         }
03765         else {
03766           /* We have found a connection. Let's stop searching. */
03767           chosen = check;
03768           break;
03769         }
03770       }
03771     }
03772   }
03773 
03774   if(chosen) {
03775     *usethis = chosen;
03776     return TRUE; /* yes, we found one to use! */
03777   }
03778 
03779   if(foundPendingCandidate && data->set.pipewait) {
03780     infof(data,
03781           "Found pending candidate for reuse and CURLOPT_PIPEWAIT is set\n");
03782     *waitpipe = TRUE;
03783   }
03784 
03785   return FALSE; /* no matching connecting exists */
03786 }
03787 
03788 /* after a TCP connection to the proxy has been verified, this function does
03789    the next magic step.
03790 
03791    Note: this function's sub-functions call failf()
03792 
03793 */
03794 CURLcode Curl_connected_proxy(struct connectdata *conn, int sockindex)
03795 {
03796   CURLcode result = CURLE_OK;
03797 
03798   if(conn->bits.socksproxy) {
03799 #ifndef CURL_DISABLE_PROXY
03800     const char * const host = conn->bits.conn_to_host ?
03801                               conn->conn_to_host.name :
03802                               conn->bits.httpproxy ?
03803                               conn->http_proxy.host.name :
03804                               sockindex == SECONDARYSOCKET ?
03805                               conn->secondaryhostname : conn->host.name;
03806     const int port = conn->bits.conn_to_port ? conn->conn_to_port :
03807                      conn->bits.httpproxy ?
03808                      (int)conn->http_proxy.port :
03809                      sockindex == SECONDARYSOCKET ?
03810                       conn->secondary_port : conn->remote_port;
03811     conn->bits.socksproxy_connecting = TRUE;
03812     switch(conn->socks_proxy.proxytype) {
03813     case CURLPROXY_SOCKS5:
03814     case CURLPROXY_SOCKS5_HOSTNAME:
03815       result = Curl_SOCKS5(conn->socks_proxy.user, conn->socks_proxy.passwd,
03816                          host, port, sockindex, conn);
03817       break;
03818 
03819     case CURLPROXY_SOCKS4:
03820     case CURLPROXY_SOCKS4A:
03821       result = Curl_SOCKS4(conn->socks_proxy.user, host, port, sockindex,
03822                            conn);
03823       break;
03824 
03825     default:
03826       failf(conn->data, "unknown proxytype option given");
03827       result = CURLE_COULDNT_CONNECT;
03828     } /* switch proxytype */
03829     conn->bits.socksproxy_connecting = FALSE;
03830 #else
03831   (void)sockindex;
03832 #endif /* CURL_DISABLE_PROXY */
03833   }
03834 
03835   return result;
03836 }
03837 
03838 /*
03839  * verboseconnect() displays verbose information after a connect
03840  */
03841 #ifndef CURL_DISABLE_VERBOSE_STRINGS
03842 void Curl_verboseconnect(struct connectdata *conn)
03843 {
03844   if(conn->data->set.verbose)
03845     infof(conn->data, "Connected to %s (%s) port %ld (#%ld)\n",
03846           conn->bits.socksproxy ? conn->socks_proxy.host.dispname :
03847           conn->bits.httpproxy ? conn->http_proxy.host.dispname :
03848                              conn->host.dispname,
03849           conn->ip_addr_str, conn->port, conn->connection_id);
03850 }
03851 #endif
03852 
03853 int Curl_protocol_getsock(struct connectdata *conn,
03854                           curl_socket_t *socks,
03855                           int numsocks)
03856 {
03857   if(conn->handler->proto_getsock)
03858     return conn->handler->proto_getsock(conn, socks, numsocks);
03859   return GETSOCK_BLANK;
03860 }
03861 
03862 int Curl_doing_getsock(struct connectdata *conn,
03863                        curl_socket_t *socks,
03864                        int numsocks)
03865 {
03866   if(conn && conn->handler->doing_getsock)
03867     return conn->handler->doing_getsock(conn, socks, numsocks);
03868   return GETSOCK_BLANK;
03869 }
03870 
03871 /*
03872  * We are doing protocol-specific connecting and this is being called over and
03873  * over from the multi interface until the connection phase is done on
03874  * protocol layer.
03875  */
03876 
03877 CURLcode Curl_protocol_connecting(struct connectdata *conn,
03878                                   bool *done)
03879 {
03880   CURLcode result=CURLE_OK;
03881 
03882   if(conn && conn->handler->connecting) {
03883     *done = FALSE;
03884     result = conn->handler->connecting(conn, done);
03885   }
03886   else
03887     *done = TRUE;
03888 
03889   return result;
03890 }
03891 
03892 /*
03893  * We are DOING this is being called over and over from the multi interface
03894  * until the DOING phase is done on protocol layer.
03895  */
03896 
03897 CURLcode Curl_protocol_doing(struct connectdata *conn, bool *done)
03898 {
03899   CURLcode result=CURLE_OK;
03900 
03901   if(conn && conn->handler->doing) {
03902     *done = FALSE;
03903     result = conn->handler->doing(conn, done);
03904   }
03905   else
03906     *done = TRUE;
03907 
03908   return result;
03909 }
03910 
03911 /*
03912  * We have discovered that the TCP connection has been successful, we can now
03913  * proceed with some action.
03914  *
03915  */
03916 CURLcode Curl_protocol_connect(struct connectdata *conn,
03917                                bool *protocol_done)
03918 {
03919   CURLcode result=CURLE_OK;
03920 
03921   *protocol_done = FALSE;
03922 
03923   if(conn->bits.tcpconnect[FIRSTSOCKET] && conn->bits.protoconnstart) {
03924     /* We already are connected, get back. This may happen when the connect
03925        worked fine in the first call, like when we connect to a local server
03926        or proxy. Note that we don't know if the protocol is actually done.
03927 
03928        Unless this protocol doesn't have any protocol-connect callback, as
03929        then we know we're done. */
03930     if(!conn->handler->connecting)
03931       *protocol_done = TRUE;
03932 
03933     return CURLE_OK;
03934   }
03935 
03936   if(!conn->bits.protoconnstart) {
03937 
03938     result = Curl_proxy_connect(conn, FIRSTSOCKET);
03939     if(result)
03940       return result;
03941 
03942     if(CONNECT_FIRSTSOCKET_PROXY_SSL())
03943       /* wait for HTTPS proxy SSL initialization to complete */
03944       return CURLE_OK;
03945 
03946     if(conn->bits.tunnel_proxy && conn->bits.httpproxy &&
03947        (conn->tunnel_state[FIRSTSOCKET] != TUNNEL_COMPLETE))
03948       /* when using an HTTP tunnel proxy, await complete tunnel establishment
03949          before proceeding further. Return CURLE_OK so we'll be called again */
03950       return CURLE_OK;
03951 
03952     if(conn->handler->connect_it) {
03953       /* is there a protocol-specific connect() procedure? */
03954 
03955       /* Call the protocol-specific connect function */
03956       result = conn->handler->connect_it(conn, protocol_done);
03957     }
03958     else
03959       *protocol_done = TRUE;
03960 
03961     /* it has started, possibly even completed but that knowledge isn't stored
03962        in this bit! */
03963     if(!result)
03964       conn->bits.protoconnstart = TRUE;
03965   }
03966 
03967   return result; /* pass back status */
03968 }
03969 
03970 /*
03971  * Helpers for IDNA convertions.
03972  */
03973 static bool is_ASCII_name(const char *hostname)
03974 {
03975   const unsigned char *ch = (const unsigned char *)hostname;
03976 
03977   while(*ch) {
03978     if(*ch++ & 0x80)
03979       return FALSE;
03980   }
03981   return TRUE;
03982 }
03983 
03984 /*
03985  * Perform any necessary IDN conversion of hostname
03986  */
03987 static void fix_hostname(struct connectdata *conn, struct hostname *host)
03988 {
03989   size_t len;
03990   struct Curl_easy *data = conn->data;
03991 
03992 #ifndef USE_LIBIDN2
03993   (void)data;
03994   (void)conn;
03995 #elif defined(CURL_DISABLE_VERBOSE_STRINGS)
03996   (void)conn;
03997 #endif
03998 
03999   /* set the name we use to display the host name */
04000   host->dispname = host->name;
04001 
04002   len = strlen(host->name);
04003   if(len && (host->name[len-1] == '.'))
04004     /* strip off a single trailing dot if present, primarily for SNI but
04005        there's no use for it */
04006     host->name[len-1]=0;
04007 
04008   /* Check name for non-ASCII and convert hostname to ACE form if we can */
04009   if(!is_ASCII_name(host->name)) {
04010 #ifdef USE_LIBIDN2
04011     if(idn2_check_version(IDN2_VERSION)) {
04012       char *ace_hostname = NULL;
04013       int rc = idn2_lookup_ul((const char *)host->name, &ace_hostname, 0);
04014       if(rc == IDN2_OK) {
04015         host->encalloc = (char *)ace_hostname;
04016         /* change the name pointer to point to the encoded hostname */
04017         host->name = host->encalloc;
04018       }
04019       else
04020         infof(data, "Failed to convert %s to ACE; %s\n", host->name,
04021               idn2_strerror(rc));
04022     }
04023 #elif defined(USE_WIN32_IDN)
04024     char *ace_hostname = NULL;
04025 
04026     if(curl_win32_idn_to_ascii(host->name, &ace_hostname)) {
04027       host->encalloc = ace_hostname;
04028       /* change the name pointer to point to the encoded hostname */
04029       host->name = host->encalloc;
04030     }
04031     else
04032       infof(data, "Failed to convert %s to ACE;\n", host->name);
04033 #else
04034     infof(data, "IDN support not present, can't parse Unicode domains\n");
04035 #endif
04036   }
04037 }
04038 
04039 /*
04040  * Frees data allocated by fix_hostname()
04041  */
04042 static void free_fixed_hostname(struct hostname *host)
04043 {
04044 #if defined(USE_LIBIDN2)
04045   if(host->encalloc) {
04046     idn2_free(host->encalloc); /* must be freed with idn2_free() since this was
04047                                  allocated by libidn */
04048     host->encalloc = NULL;
04049   }
04050 #elif defined(USE_WIN32_IDN)
04051   free(host->encalloc); /* must be freed withidn_free() since this was
04052                            allocated by curl_win32_idn_to_ascii */
04053   host->encalloc = NULL;
04054 #else
04055   (void)host;
04056 #endif
04057 }
04058 
04059 static void llist_dtor(void *user, void *element)
04060 {
04061   (void)user;
04062   (void)element;
04063   /* Do nothing */
04064 }
04065 
04066 /*
04067  * Allocate and initialize a new connectdata object.
04068  */
04069 static struct connectdata *allocate_conn(struct Curl_easy *data)
04070 {
04071   struct connectdata *conn = calloc(1, sizeof(struct connectdata));
04072   if(!conn)
04073     return NULL;
04074 
04075   conn->handler = &Curl_handler_dummy;  /* Be sure we have a handler defined
04076                                            already from start to avoid NULL
04077                                            situations and checks */
04078 
04079   /* and we setup a few fields in case we end up actually using this struct */
04080 
04081   conn->sock[FIRSTSOCKET] = CURL_SOCKET_BAD;     /* no file descriptor */
04082   conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD; /* no file descriptor */
04083   conn->tempsock[0] = CURL_SOCKET_BAD; /* no file descriptor */
04084   conn->tempsock[1] = CURL_SOCKET_BAD; /* no file descriptor */
04085   conn->connection_id = -1;    /* no ID */
04086   conn->port = -1; /* unknown at this point */
04087   conn->remote_port = -1; /* unknown */
04088 #if defined(USE_RECV_BEFORE_SEND_WORKAROUND) && defined(DEBUGBUILD)
04089   conn->postponed[0].bindsock = CURL_SOCKET_BAD; /* no file descriptor */
04090   conn->postponed[1].bindsock = CURL_SOCKET_BAD; /* no file descriptor */
04091 #endif /* USE_RECV_BEFORE_SEND_WORKAROUND && DEBUGBUILD */
04092 
04093   /* Default protocol-independent behavior doesn't support persistent
04094      connections, so we set this to force-close. Protocols that support
04095      this need to set this to FALSE in their "curl_do" functions. */
04096   connclose(conn, "Default to force-close");
04097 
04098   /* Store creation time to help future close decision making */
04099   conn->created = Curl_tvnow();
04100 
04101   conn->data = data; /* Setup the association between this connection
04102                         and the Curl_easy */
04103 
04104   conn->http_proxy.proxytype = data->set.proxytype;
04105   conn->socks_proxy.proxytype = CURLPROXY_SOCKS4;
04106 
04107 #ifdef CURL_DISABLE_PROXY
04108 
04109   conn->bits.proxy = FALSE;
04110   conn->bits.httpproxy = FALSE;
04111   conn->bits.socksproxy = FALSE;
04112   conn->bits.proxy_user_passwd = FALSE;
04113   conn->bits.tunnel_proxy = FALSE;
04114 
04115 #else /* CURL_DISABLE_PROXY */
04116 
04117   /* note that these two proxy bits are now just on what looks to be
04118      requested, they may be altered down the road */
04119   conn->bits.proxy = (data->set.str[STRING_PROXY] &&
04120                       *data->set.str[STRING_PROXY]) ? TRUE : FALSE;
04121   conn->bits.httpproxy = (conn->bits.proxy &&
04122                           (conn->http_proxy.proxytype == CURLPROXY_HTTP ||
04123                            conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0 ||
04124                            conn->http_proxy.proxytype == CURLPROXY_HTTPS)) ?
04125                            TRUE : FALSE;
04126   conn->bits.socksproxy = (conn->bits.proxy &&
04127                            !conn->bits.httpproxy) ? TRUE : FALSE;
04128 
04129   if(data->set.str[STRING_PRE_PROXY] && *data->set.str[STRING_PRE_PROXY]) {
04130     conn->bits.proxy = TRUE;
04131     conn->bits.socksproxy = TRUE;
04132   }
04133 
04134   conn->bits.proxy_user_passwd =
04135     (data->set.str[STRING_PROXYUSERNAME]) ? TRUE : FALSE;
04136   conn->bits.tunnel_proxy = data->set.tunnel_thru_httpproxy;
04137 
04138 #endif /* CURL_DISABLE_PROXY */
04139 
04140   conn->bits.user_passwd = (data->set.str[STRING_USERNAME]) ? TRUE : FALSE;
04141   conn->bits.ftp_use_epsv = data->set.ftp_use_epsv;
04142   conn->bits.ftp_use_eprt = data->set.ftp_use_eprt;
04143 
04144   conn->ssl_config.verifypeer = data->set.ssl.primary.verifypeer;
04145   conn->ssl_config.verifyhost = data->set.ssl.primary.verifyhost;
04146   conn->proxy_ssl_config.verifypeer = data->set.proxy_ssl.primary.verifypeer;
04147   conn->proxy_ssl_config.verifyhost = data->set.proxy_ssl.primary.verifyhost;
04148 
04149   conn->ip_version = data->set.ipver;
04150 
04151 #if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \
04152     defined(NTLM_WB_ENABLED)
04153   conn->ntlm_auth_hlpr_socket = CURL_SOCKET_BAD;
04154   conn->ntlm_auth_hlpr_pid = 0;
04155   conn->challenge_header = NULL;
04156   conn->response_header = NULL;
04157 #endif
04158 
04159   if(Curl_pipeline_wanted(data->multi, CURLPIPE_HTTP1) &&
04160      !conn->master_buffer) {
04161     /* Allocate master_buffer to be used for HTTP/1 pipelining */
04162     conn->master_buffer = calloc(BUFSIZE, sizeof(char));
04163     if(!conn->master_buffer)
04164       goto error;
04165   }
04166 
04167   /* Initialize the pipeline lists */
04168   conn->send_pipe = Curl_llist_alloc((curl_llist_dtor) llist_dtor);
04169   conn->recv_pipe = Curl_llist_alloc((curl_llist_dtor) llist_dtor);
04170   if(!conn->send_pipe || !conn->recv_pipe)
04171     goto error;
04172 
04173 #ifdef HAVE_GSSAPI
04174   conn->data_prot = PROT_CLEAR;
04175 #endif
04176 
04177   /* Store the local bind parameters that will be used for this connection */
04178   if(data->set.str[STRING_DEVICE]) {
04179     conn->localdev = strdup(data->set.str[STRING_DEVICE]);
04180     if(!conn->localdev)
04181       goto error;
04182   }
04183   conn->localportrange = data->set.localportrange;
04184   conn->localport = data->set.localport;
04185 
04186   /* the close socket stuff needs to be copied to the connection struct as
04187      it may live on without (this specific) Curl_easy */
04188   conn->fclosesocket = data->set.fclosesocket;
04189   conn->closesocket_client = data->set.closesocket_client;
04190 
04191   return conn;
04192   error:
04193 
04194   Curl_llist_destroy(conn->send_pipe, NULL);
04195   Curl_llist_destroy(conn->recv_pipe, NULL);
04196 
04197   conn->send_pipe = NULL;
04198   conn->recv_pipe = NULL;
04199 
04200   free(conn->master_buffer);
04201   free(conn->localdev);
04202   free(conn);
04203   return NULL;
04204 }
04205 
04206 static CURLcode findprotocol(struct Curl_easy *data,
04207                              struct connectdata *conn,
04208                              const char *protostr)
04209 {
04210   const struct Curl_handler * const *pp;
04211   const struct Curl_handler *p;
04212 
04213   /* Scan protocol handler table and match against 'protostr' to set a few
04214      variables based on the URL. Now that the handler may be changed later
04215      when the protocol specific setup function is called. */
04216   for(pp = protocols; (p = *pp) != NULL; pp++) {
04217     if(strcasecompare(p->scheme, protostr)) {
04218       /* Protocol found in table. Check if allowed */
04219       if(!(data->set.allowed_protocols & p->protocol))
04220         /* nope, get out */
04221         break;
04222 
04223       /* it is allowed for "normal" request, now do an extra check if this is
04224          the result of a redirect */
04225       if(data->state.this_is_a_follow &&
04226          !(data->set.redir_protocols & p->protocol))
04227         /* nope, get out */
04228         break;
04229 
04230       /* Perform setup complement if some. */
04231       conn->handler = conn->given = p;
04232 
04233       /* 'port' and 'remote_port' are set in setup_connection_internals() */
04234       return CURLE_OK;
04235     }
04236   }
04237 
04238 
04239   /* The protocol was not found in the table, but we don't have to assign it
04240      to anything since it is already assigned to a dummy-struct in the
04241      create_conn() function when the connectdata struct is allocated. */
04242   failf(data, "Protocol \"%s\" not supported or disabled in " LIBCURL_NAME,
04243         protostr);
04244 
04245   return CURLE_UNSUPPORTED_PROTOCOL;
04246 }
04247 
04248 /*
04249  * Parse URL and fill in the relevant members of the connection struct.
04250  */
04251 static CURLcode parseurlandfillconn(struct Curl_easy *data,
04252                                     struct connectdata *conn,
04253                                     bool *prot_missing,
04254                                     char **userp, char **passwdp,
04255                                     char **optionsp)
04256 {
04257   char *at;
04258   char *fragment;
04259   char *path = data->state.path;
04260   char *query;
04261   int rc;
04262   char protobuf[16] = "";
04263   const char *protop = "";
04264   CURLcode result;
04265   bool rebuild_url = FALSE;
04266 
04267   *prot_missing = FALSE;
04268 
04269   /* We might pass the entire URL into the request so we need to make sure
04270    * there are no bad characters in there.*/
04271   if(strpbrk(data->change.url, "\r\n")) {
04272     failf(data, "Illegal characters found in URL");
04273     return CURLE_URL_MALFORMAT;
04274   }
04275 
04276   /*************************************************************
04277    * Parse the URL.
04278    *
04279    * We need to parse the url even when using the proxy, because we will need
04280    * the hostname and port in case we are trying to SSL connect through the
04281    * proxy -- and we don't know if we will need to use SSL until we parse the
04282    * url ...
04283    ************************************************************/
04284   if((2 == sscanf(data->change.url, "%15[^:]:%[^\n]",
04285                   protobuf, path)) &&
04286      strcasecompare(protobuf, "file")) {
04287     if(path[0] == '/' && path[1] == '/') {
04288       /* Allow omitted hostname (e.g. file:/<path>).  This is not strictly
04289        * speaking a valid file: URL by RFC 1738, but treating file:/<path> as
04290        * file://localhost/<path> is similar to how other schemes treat missing
04291        * hostnames.  See RFC 1808. */
04292 
04293       /* This cannot be done with strcpy() in a portable manner, since the
04294          memory areas overlap! */
04295       memmove(path, path + 2, strlen(path + 2)+1);
04296     }
04297     /*
04298      * we deal with file://<host>/<path> differently since it supports no
04299      * hostname other than "localhost" and "127.0.0.1", which is unique among
04300      * the URL protocols specified in RFC 1738
04301      */
04302     if(path[0] != '/') {
04303       /* the URL includes a host name, it must match "localhost" or
04304          "127.0.0.1" to be valid */
04305       char *ptr;
04306       if(!checkprefix("localhost/", path) &&
04307          !checkprefix("127.0.0.1/", path)) {
04308         failf(data, "Valid host name with slash missing in URL");
04309         return CURLE_URL_MALFORMAT;
04310       }
04311       ptr = &path[9]; /* now points to the slash after the host */
04312 
04313       /* there was a host name and slash present
04314 
04315          RFC1738 (section 3.1, page 5) says:
04316 
04317          The rest of the locator consists of data specific to the scheme,
04318          and is known as the "url-path". It supplies the details of how the
04319          specified resource can be accessed. Note that the "/" between the
04320          host (or port) and the url-path is NOT part of the url-path.
04321 
04322          As most agents use file://localhost/foo to get '/foo' although the
04323          slash preceding foo is a separator and not a slash for the path,
04324          a URL as file://localhost//foo must be valid as well, to refer to
04325          the same file with an absolute path.
04326       */
04327 
04328       if('/' == ptr[1])
04329         /* if there was two slashes, we skip the first one as that is then
04330            used truly as a separator */
04331         ptr++;
04332 
04333       /* This cannot be made with strcpy, as the memory chunks overlap! */
04334       memmove(path, ptr, strlen(ptr)+1);
04335     }
04336 
04337     protop = "file"; /* protocol string */
04338   }
04339   else {
04340     /* clear path */
04341     char slashbuf[4];
04342     path[0]=0;
04343 
04344     rc = sscanf(data->change.url,
04345                 "%15[^\n:]:%3[/]%[^\n/?#]%[^\n]",
04346                 protobuf, slashbuf, conn->host.name, path);
04347     if(2 == rc) {
04348       failf(data, "Bad URL");
04349       return CURLE_URL_MALFORMAT;
04350     }
04351     if(3 > rc) {
04352 
04353       /*
04354        * The URL was badly formatted, let's try the browser-style _without_
04355        * protocol specified like 'http://'.
04356        */
04357       rc = sscanf(data->change.url, "%[^\n/?#]%[^\n]", conn->host.name, path);
04358       if(1 > rc) {
04359         /*
04360          * We couldn't even get this format.
04361          * djgpp 2.04 has a sscanf() bug where 'conn->host.name' is
04362          * assigned, but the return value is EOF!
04363          */
04364 #if defined(__DJGPP__) && (DJGPP_MINOR == 4)
04365         if(!(rc == -1 && *conn->host.name))
04366 #endif
04367         {
04368           failf(data, "<url> malformed");
04369           return CURLE_URL_MALFORMAT;
04370         }
04371       }
04372 
04373       /*
04374        * Since there was no protocol part specified in the URL use the
04375        * user-specified default protocol. If we weren't given a default make a
04376        * guess by matching some protocols against the host's outermost
04377        * sub-domain name. Finally if there was no match use HTTP.
04378        */
04379 
04380       protop = data->set.str[STRING_DEFAULT_PROTOCOL];
04381       if(!protop) {
04382         /* Note: if you add a new protocol, please update the list in
04383          * lib/version.c too! */
04384         if(checkprefix("FTP.", conn->host.name))
04385           protop = "ftp";
04386         else if(checkprefix("DICT.", conn->host.name))
04387           protop = "DICT";
04388         else if(checkprefix("LDAP.", conn->host.name))
04389           protop = "LDAP";
04390         else if(checkprefix("IMAP.", conn->host.name))
04391           protop = "IMAP";
04392         else if(checkprefix("SMTP.", conn->host.name))
04393           protop = "smtp";
04394         else if(checkprefix("POP3.", conn->host.name))
04395           protop = "pop3";
04396         else
04397           protop = "http";
04398       }
04399 
04400       *prot_missing = TRUE; /* not given in URL */
04401     }
04402     else {
04403       size_t s = strlen(slashbuf);
04404       protop = protobuf;
04405       if(s != 2) {
04406         infof(data, "Unwillingly accepted illegal URL using %d slash%s!\n",
04407               s, s>1?"es":"");
04408 
04409         if(data->change.url_alloc)
04410           free(data->change.url);
04411         /* repair the URL to use two slashes */
04412         data->change.url = aprintf("%s://%s%s",
04413                                    protobuf, conn->host.name, path);
04414         if(!data->change.url)
04415           return CURLE_OUT_OF_MEMORY;
04416         data->change.url_alloc = TRUE;
04417       }
04418     }
04419   }
04420 
04421   /* We search for '?' in the host name (but only on the right side of a
04422    * @-letter to allow ?-letters in username and password) to handle things
04423    * like http://example.com?param= (notice the missing '/').
04424    */
04425   at = strchr(conn->host.name, '@');
04426   if(at)
04427     query = strchr(at+1, '?');
04428   else
04429     query = strchr(conn->host.name, '?');
04430 
04431   if(query) {
04432     /* We must insert a slash before the '?'-letter in the URL. If the URL had
04433        a slash after the '?', that is where the path currently begins and the
04434        '?string' is still part of the host name.
04435 
04436        We must move the trailing part from the host name and put it first in
04437        the path. And have it all prefixed with a slash.
04438     */
04439 
04440     size_t hostlen = strlen(query);
04441     size_t pathlen = strlen(path);
04442 
04443     /* move the existing path plus the zero byte forward, to make room for
04444        the host-name part */
04445     memmove(path+hostlen+1, path, pathlen+1);
04446 
04447      /* now copy the trailing host part in front of the existing path */
04448     memcpy(path+1, query, hostlen);
04449 
04450     path[0]='/'; /* prepend the missing slash */
04451     rebuild_url = TRUE;
04452 
04453     *query=0; /* now cut off the hostname at the ? */
04454   }
04455   else if(!path[0]) {
04456     /* if there's no path set, use a single slash */
04457     strcpy(path, "/");
04458     rebuild_url = TRUE;
04459   }
04460 
04461   /* If the URL is malformatted (missing a '/' after hostname before path) we
04462    * insert a slash here. The only letters except '/' that can start a path is
04463    * '?' and '#' - as controlled by the two sscanf() patterns above.
04464    */
04465   if(path[0] != '/') {
04466     /* We need this function to deal with overlapping memory areas. We know
04467        that the memory area 'path' points to is 'urllen' bytes big and that
04468        is bigger than the path. Use +1 to move the zero byte too. */
04469     memmove(&path[1], path, strlen(path)+1);
04470     path[0] = '/';
04471     rebuild_url = TRUE;
04472   }
04473   else if(!data->set.path_as_is) {
04474     /* sanitise paths and remove ../ and ./ sequences according to RFC3986 */
04475     char *newp = Curl_dedotdotify(path);
04476     if(!newp)
04477       return CURLE_OUT_OF_MEMORY;
04478 
04479     if(strcmp(newp, path)) {
04480       rebuild_url = TRUE;
04481       free(data->state.pathbuffer);
04482       data->state.pathbuffer = newp;
04483       data->state.path = newp;
04484       path = newp;
04485     }
04486     else
04487       free(newp);
04488   }
04489 
04490   /*
04491    * "rebuild_url" means that one or more URL components have been modified so
04492    * we need to generate an updated full version.  We need the corrected URL
04493    * when communicating over HTTP proxy and we don't know at this point if
04494    * we're using a proxy or not.
04495    */
04496   if(rebuild_url) {
04497     char *reurl;
04498 
04499     size_t plen = strlen(path); /* new path, should be 1 byte longer than
04500                                    the original */
04501     size_t urllen = strlen(data->change.url); /* original URL length */
04502 
04503     size_t prefixlen = strlen(conn->host.name);
04504 
04505     if(!*prot_missing)
04506       prefixlen += strlen(protop) + strlen("://");
04507 
04508     reurl = malloc(urllen + 2); /* 2 for zerobyte + slash */
04509     if(!reurl)
04510       return CURLE_OUT_OF_MEMORY;
04511 
04512     /* copy the prefix */
04513     memcpy(reurl, data->change.url, prefixlen);
04514 
04515     /* append the trailing piece + zerobyte */
04516     memcpy(&reurl[prefixlen], path, plen + 1);
04517 
04518     /* possible free the old one */
04519     if(data->change.url_alloc) {
04520       Curl_safefree(data->change.url);
04521       data->change.url_alloc = FALSE;
04522     }
04523 
04524     infof(data, "Rebuilt URL to: %s\n", reurl);
04525 
04526     data->change.url = reurl;
04527     data->change.url_alloc = TRUE; /* free this later */
04528   }
04529 
04530   /*
04531    * Parse the login details from the URL and strip them out of
04532    * the host name
04533    */
04534   result = parse_url_login(data, conn, userp, passwdp, optionsp);
04535   if(result)
04536     return result;
04537 
04538   if(conn->host.name[0] == '[') {
04539     /* This looks like an IPv6 address literal.  See if there is an address
04540        scope if there is no location header */
04541     char *percent = strchr(conn->host.name, '%');
04542     if(percent) {
04543       unsigned int identifier_offset = 3;
04544       char *endp;
04545       unsigned long scope;
04546       if(strncmp("%25", percent, 3) != 0) {
04547         infof(data,
04548               "Please URL encode %% as %%25, see RFC 6874.\n");
04549         identifier_offset = 1;
04550       }
04551       scope = strtoul(percent + identifier_offset, &endp, 10);
04552       if(*endp == ']') {
04553         /* The address scope was well formed.  Knock it out of the
04554            hostname. */
04555         memmove(percent, endp, strlen(endp)+1);
04556         conn->scope_id = (unsigned int)scope;
04557       }
04558       else {
04559         /* Zone identifier is not numeric */
04560 #if defined(HAVE_NET_IF_H) && defined(IFNAMSIZ) && defined(HAVE_IF_NAMETOINDEX)
04561         char ifname[IFNAMSIZ + 2];
04562         char *square_bracket;
04563         unsigned int scopeidx = 0;
04564         strncpy(ifname, percent + identifier_offset, IFNAMSIZ + 2);
04565         /* Ensure nullbyte termination */
04566         ifname[IFNAMSIZ + 1] = '\0';
04567         square_bracket = strchr(ifname, ']');
04568         if(square_bracket) {
04569           /* Remove ']' */
04570           *square_bracket = '\0';
04571           scopeidx = if_nametoindex(ifname);
04572           if(scopeidx == 0) {
04573             infof(data, "Invalid network interface: %s; %s\n", ifname,
04574                   strerror(errno));
04575           }
04576         }
04577         if(scopeidx > 0) {
04578           char *p = percent + identifier_offset + strlen(ifname);
04579 
04580           /* Remove zone identifier from hostname */
04581           memmove(percent, p, strlen(p) + 1);
04582           conn->scope_id = scopeidx;
04583         }
04584         else
04585 #endif /* HAVE_NET_IF_H && IFNAMSIZ */
04586           infof(data, "Invalid IPv6 address format\n");
04587       }
04588     }
04589   }
04590 
04591   if(data->set.scope_id)
04592     /* Override any scope that was set above.  */
04593     conn->scope_id = data->set.scope_id;
04594 
04595   /* Remove the fragment part of the path. Per RFC 2396, this is always the
04596      last part of the URI. We are looking for the first '#' so that we deal
04597      gracefully with non conformant URI such as http://example.com#foo#bar. */
04598   fragment = strchr(path, '#');
04599   if(fragment) {
04600     *fragment = 0;
04601 
04602     /* we know the path part ended with a fragment, so we know the full URL
04603        string does too and we need to cut it off from there so it isn't used
04604        over proxy */
04605     fragment = strchr(data->change.url, '#');
04606     if(fragment)
04607       *fragment = 0;
04608   }
04609 
04610   /*
04611    * So if the URL was A://B/C#D,
04612    *   protop is A
04613    *   conn->host.name is B
04614    *   data->state.path is /C
04615    */
04616 
04617   return findprotocol(data, conn, protop);
04618 }
04619 
04620 /*
04621  * If we're doing a resumed transfer, we need to setup our stuff
04622  * properly.
04623  */
04624 static CURLcode setup_range(struct Curl_easy *data)
04625 {
04626   struct UrlState *s = &data->state;
04627   s->resume_from = data->set.set_resume_from;
04628   if(s->resume_from || data->set.str[STRING_SET_RANGE]) {
04629     if(s->rangestringalloc)
04630       free(s->range);
04631 
04632     if(s->resume_from)
04633       s->range = aprintf("%" CURL_FORMAT_CURL_OFF_TU "-", s->resume_from);
04634     else
04635       s->range = strdup(data->set.str[STRING_SET_RANGE]);
04636 
04637     s->rangestringalloc = (s->range) ? TRUE : FALSE;
04638 
04639     if(!s->range)
04640       return CURLE_OUT_OF_MEMORY;
04641 
04642     /* tell ourselves to fetch this range */
04643     s->use_range = TRUE;        /* enable range download */
04644   }
04645   else
04646     s->use_range = FALSE; /* disable range download */
04647 
04648   return CURLE_OK;
04649 }
04650 
04651 
04652 /*
04653  * setup_connection_internals() -
04654  *
04655  * Setup connection internals specific to the requested protocol in the
04656  * Curl_easy. This is inited and setup before the connection is made but
04657  * is about the particular protocol that is to be used.
04658  *
04659  * This MUST get called after proxy magic has been figured out.
04660  */
04661 static CURLcode setup_connection_internals(struct connectdata *conn)
04662 {
04663   const struct Curl_handler * p;
04664   CURLcode result;
04665   struct Curl_easy *data = conn->data;
04666 
04667   /* in some case in the multi state-machine, we go back to the CONNECT state
04668      and then a second (or third or...) call to this function will be made
04669      without doing a DISCONNECT or DONE in between (since the connection is
04670      yet in place) and therefore this function needs to first make sure
04671      there's no lingering previous data allocated. */
04672   Curl_free_request_state(data);
04673 
04674   memset(&data->req, 0, sizeof(struct SingleRequest));
04675   data->req.maxdownload = -1;
04676 
04677   conn->socktype = SOCK_STREAM; /* most of them are TCP streams */
04678 
04679   /* Perform setup complement if some. */
04680   p = conn->handler;
04681 
04682   if(p->setup_connection) {
04683     result = (*p->setup_connection)(conn);
04684 
04685     if(result)
04686       return result;
04687 
04688     p = conn->handler;              /* May have changed. */
04689   }
04690 
04691   if(conn->port < 0)
04692     /* we check for -1 here since if proxy was detected already, this
04693        was very likely already set to the proxy port */
04694     conn->port = p->defport;
04695 
04696   return CURLE_OK;
04697 }
04698 
04699 /*
04700  * Curl_free_request_state() should free temp data that was allocated in the
04701  * Curl_easy for this single request.
04702  */
04703 
04704 void Curl_free_request_state(struct Curl_easy *data)
04705 {
04706   Curl_safefree(data->req.protop);
04707   Curl_safefree(data->req.newurl);
04708 }
04709 
04710 
04711 #ifndef CURL_DISABLE_PROXY
04712 /****************************************************************
04713 * Checks if the host is in the noproxy list. returns true if it matches
04714 * and therefore the proxy should NOT be used.
04715 ****************************************************************/
04716 static bool check_noproxy(const char *name, const char *no_proxy)
04717 {
04718   /* no_proxy=domain1.dom,host.domain2.dom
04719    *   (a comma-separated list of hosts which should
04720    *   not be proxied, or an asterisk to override
04721    *   all proxy variables)
04722    */
04723   size_t tok_start;
04724   size_t tok_end;
04725   const char *separator = ", ";
04726   size_t no_proxy_len;
04727   size_t namelen;
04728   char *endptr;
04729 
04730   if(no_proxy && no_proxy[0]) {
04731     if(strcasecompare("*", no_proxy)) {
04732       return TRUE;
04733     }
04734 
04735     /* NO_PROXY was specified and it wasn't just an asterisk */
04736 
04737     no_proxy_len = strlen(no_proxy);
04738     endptr = strchr(name, ':');
04739     if(endptr)
04740       namelen = endptr - name;
04741     else
04742       namelen = strlen(name);
04743 
04744     for(tok_start = 0; tok_start < no_proxy_len; tok_start = tok_end + 1) {
04745       while(tok_start < no_proxy_len &&
04746             strchr(separator, no_proxy[tok_start]) != NULL) {
04747         /* Look for the beginning of the token. */
04748         ++tok_start;
04749       }
04750 
04751       if(tok_start == no_proxy_len)
04752         break; /* It was all trailing separator chars, no more tokens. */
04753 
04754       for(tok_end = tok_start; tok_end < no_proxy_len &&
04755             strchr(separator, no_proxy[tok_end]) == NULL; ++tok_end)
04756         /* Look for the end of the token. */
04757         ;
04758 
04759       /* To match previous behaviour, where it was necessary to specify
04760        * ".local.com" to prevent matching "notlocal.com", we will leave
04761        * the '.' off.
04762        */
04763       if(no_proxy[tok_start] == '.')
04764         ++tok_start;
04765 
04766       if((tok_end - tok_start) <= namelen) {
04767         /* Match the last part of the name to the domain we are checking. */
04768         const char *checkn = name + namelen - (tok_end - tok_start);
04769         if(strncasecompare(no_proxy + tok_start, checkn,
04770                            tok_end - tok_start)) {
04771           if((tok_end - tok_start) == namelen || *(checkn - 1) == '.') {
04772             /* We either have an exact match, or the previous character is a .
04773              * so it is within the same domain, so no proxy for this host.
04774              */
04775             return TRUE;
04776           }
04777         }
04778       } /* if((tok_end - tok_start) <= namelen) */
04779     } /* for(tok_start = 0; tok_start < no_proxy_len;
04780          tok_start = tok_end + 1) */
04781   } /* NO_PROXY was specified and it wasn't just an asterisk */
04782 
04783   return FALSE;
04784 }
04785 
04786 /****************************************************************
04787 * Detect what (if any) proxy to use. Remember that this selects a host
04788 * name and is not limited to HTTP proxies only.
04789 * The returned pointer must be freed by the caller (unless NULL)
04790 ****************************************************************/
04791 static char *detect_proxy(struct connectdata *conn)
04792 {
04793   char *proxy = NULL;
04794 
04795 #ifndef CURL_DISABLE_HTTP
04796   /* If proxy was not specified, we check for default proxy environment
04797    * variables, to enable i.e Lynx compliance:
04798    *
04799    * http_proxy=http://some.server.dom:port/
04800    * https_proxy=http://some.server.dom:port/
04801    * ftp_proxy=http://some.server.dom:port/
04802    * no_proxy=domain1.dom,host.domain2.dom
04803    *   (a comma-separated list of hosts which should
04804    *   not be proxied, or an asterisk to override
04805    *   all proxy variables)
04806    * all_proxy=http://some.server.dom:port/
04807    *   (seems to exist for the CERN www lib. Probably
04808    *   the first to check for.)
04809    *
04810    * For compatibility, the all-uppercase versions of these variables are
04811    * checked if the lowercase versions don't exist.
04812    */
04813   char *no_proxy=NULL;
04814   char proxy_env[128];
04815 
04816   no_proxy=curl_getenv("no_proxy");
04817   if(!no_proxy)
04818     no_proxy=curl_getenv("NO_PROXY");
04819 
04820   if(!check_noproxy(conn->host.name, no_proxy)) {
04821     /* It was not listed as without proxy */
04822     const char *protop = conn->handler->scheme;
04823     char *envp = proxy_env;
04824     char *prox;
04825 
04826     /* Now, build <protocol>_proxy and check for such a one to use */
04827     while(*protop)
04828       *envp++ = (char)tolower((int)*protop++);
04829 
04830     /* append _proxy */
04831     strcpy(envp, "_proxy");
04832 
04833     /* read the protocol proxy: */
04834     prox=curl_getenv(proxy_env);
04835 
04836     /*
04837      * We don't try the uppercase version of HTTP_PROXY because of
04838      * security reasons:
04839      *
04840      * When curl is used in a webserver application
04841      * environment (cgi or php), this environment variable can
04842      * be controlled by the web server user by setting the
04843      * http header 'Proxy:' to some value.
04844      *
04845      * This can cause 'internal' http/ftp requests to be
04846      * arbitrarily redirected by any external attacker.
04847      */
04848     if(!prox && !strcasecompare("http_proxy", proxy_env)) {
04849       /* There was no lowercase variable, try the uppercase version: */
04850       Curl_strntoupper(proxy_env, proxy_env, sizeof(proxy_env));
04851       prox=curl_getenv(proxy_env);
04852     }
04853 
04854     if(prox)
04855       proxy = prox; /* use this */
04856     else {
04857       proxy = curl_getenv("all_proxy"); /* default proxy to use */
04858       if(!proxy)
04859         proxy=curl_getenv("ALL_PROXY");
04860     }
04861   } /* if(!check_noproxy(conn->host.name, no_proxy)) - it wasn't specified
04862        non-proxy */
04863   free(no_proxy);
04864 
04865 #else /* !CURL_DISABLE_HTTP */
04866 
04867   (void)conn;
04868 #endif /* CURL_DISABLE_HTTP */
04869 
04870   return proxy;
04871 }
04872 
04873 /*
04874  * If this is supposed to use a proxy, we need to figure out the proxy
04875  * host name, so that we can re-use an existing connection
04876  * that may exist registered to the same proxy host.
04877  */
04878 static CURLcode parse_proxy(struct Curl_easy *data,
04879                             struct connectdata *conn, char *proxy,
04880                             curl_proxytype proxytype)
04881 {
04882   char *prox_portno;
04883   char *endofprot;
04884 
04885   /* We use 'proxyptr' to point to the proxy name from now on... */
04886   char *proxyptr;
04887   char *portptr;
04888   char *atsign;
04889   long port = -1;
04890   char *proxyuser = NULL;
04891   char *proxypasswd = NULL;
04892   bool sockstype;
04893 
04894   /* We do the proxy host string parsing here. We want the host name and the
04895    * port name. Accept a protocol:// prefix
04896    */
04897 
04898   /* Parse the protocol part if present */
04899   endofprot = strstr(proxy, "://");
04900   if(endofprot) {
04901     proxyptr = endofprot+3;
04902     if(checkprefix("https", proxy))
04903       proxytype = CURLPROXY_HTTPS;
04904     else if(checkprefix("socks5h", proxy))
04905       proxytype = CURLPROXY_SOCKS5_HOSTNAME;
04906     else if(checkprefix("socks5", proxy))
04907       proxytype = CURLPROXY_SOCKS5;
04908     else if(checkprefix("socks4a", proxy))
04909       proxytype = CURLPROXY_SOCKS4A;
04910     else if(checkprefix("socks4", proxy) || checkprefix("socks", proxy))
04911       proxytype = CURLPROXY_SOCKS4;
04912     else if(checkprefix("http:", proxy))
04913       ; /* leave it as HTTP or HTTP/1.0 */
04914     else {
04915       /* Any other xxx:// reject! */
04916       failf(data, "Unsupported proxy scheme for \'%s\'", proxy);
04917       return CURLE_COULDNT_CONNECT;
04918     }
04919   }
04920   else
04921     proxyptr = proxy; /* No xxx:// head: It's a HTTP proxy */
04922 
04923 #ifndef HTTPS_PROXY_SUPPORT
04924   if(proxytype == CURLPROXY_HTTPS) {
04925     failf(data, "Unsupported proxy \'%s\'"
04926                 ", libcurl is built without the HTTPS-proxy support.", proxy);
04927     return CURLE_NOT_BUILT_IN;
04928   }
04929 #endif
04930 
04931   sockstype = proxytype == CURLPROXY_SOCKS5_HOSTNAME ||
04932               proxytype == CURLPROXY_SOCKS5 ||
04933               proxytype == CURLPROXY_SOCKS4A ||
04934               proxytype == CURLPROXY_SOCKS4;
04935 
04936   /* Is there a username and password given in this proxy url? */
04937   atsign = strchr(proxyptr, '@');
04938   if(atsign) {
04939     CURLcode result =
04940       parse_login_details(proxyptr, atsign - proxyptr,
04941                               &proxyuser, &proxypasswd, NULL);
04942     if(result)
04943       return result;
04944     proxyptr = atsign + 1;
04945   }
04946 
04947   /* start scanning for port number at this point */
04948   portptr = proxyptr;
04949 
04950   /* detect and extract RFC6874-style IPv6-addresses */
04951   if(*proxyptr == '[') {
04952     char *ptr = ++proxyptr; /* advance beyond the initial bracket */
04953     while(*ptr && (ISXDIGIT(*ptr) || (*ptr == ':') || (*ptr == '.')))
04954       ptr++;
04955     if(*ptr == '%') {
04956       /* There might be a zone identifier */
04957       if(strncmp("%25", ptr, 3))
04958         infof(data, "Please URL encode %% as %%25, see RFC 6874.\n");
04959       ptr++;
04960       /* Allow unreserved characters as defined in RFC 3986 */
04961       while(*ptr && (ISALPHA(*ptr) || ISXDIGIT(*ptr) || (*ptr == '-') ||
04962                      (*ptr == '.') || (*ptr == '_') || (*ptr == '~')))
04963         ptr++;
04964     }
04965     if(*ptr == ']')
04966       /* yeps, it ended nicely with a bracket as well */
04967       *ptr++ = 0;
04968     else
04969       infof(data, "Invalid IPv6 address format\n");
04970     portptr = ptr;
04971     /* Note that if this didn't end with a bracket, we still advanced the
04972      * proxyptr first, but I can't see anything wrong with that as no host
04973      * name nor a numeric can legally start with a bracket.
04974      */
04975   }
04976 
04977   /* Get port number off proxy.server.com:1080 */
04978   prox_portno = strchr(portptr, ':');
04979   if(prox_portno) {
04980     char *endp = NULL;
04981 
04982     *prox_portno = 0x0; /* cut off number from host name */
04983     prox_portno ++;
04984     /* now set the local port number */
04985     port = strtol(prox_portno, &endp, 10);
04986     if((endp && *endp && (*endp != '/') && (*endp != ' ')) ||
04987        (port < 0) || (port > 65535)) {
04988       /* meant to detect for example invalid IPv6 numerical addresses without
04989          brackets: "2a00:fac0:a000::7:13". Accept a trailing slash only
04990          because we then allow "URL style" with the number followed by a
04991          slash, used in curl test cases already. Space is also an acceptable
04992          terminating symbol. */
04993       infof(data, "No valid port number in proxy string (%s)\n",
04994             prox_portno);
04995     }
04996     else
04997       conn->port = port;
04998   }
04999   else {
05000     if(proxyptr[0]=='/')
05001       /* If the first character in the proxy string is a slash, fail
05002          immediately. The following code will otherwise clear the string which
05003          will lead to code running as if no proxy was set! */
05004       return CURLE_COULDNT_RESOLVE_PROXY;
05005 
05006     /* without a port number after the host name, some people seem to use
05007        a slash so we strip everything from the first slash */
05008     atsign = strchr(proxyptr, '/');
05009     if(atsign)
05010       *atsign = '\0'; /* cut off path part from host name */
05011 
05012     if(data->set.proxyport)
05013       /* None given in the proxy string, then get the default one if it is
05014          given */
05015       port = data->set.proxyport;
05016     else {
05017       if(proxytype == CURLPROXY_HTTPS)
05018         port = CURL_DEFAULT_HTTPS_PROXY_PORT;
05019       else
05020         port = CURL_DEFAULT_PROXY_PORT;
05021     }
05022   }
05023 
05024   if(*proxyptr) {
05025     struct proxy_info *proxyinfo =
05026       sockstype ? &conn->socks_proxy : &conn->http_proxy;
05027     proxyinfo->proxytype = proxytype;
05028 
05029     if(proxyuser) {
05030       /* found user and password, rip them out.  note that we are unescaping
05031          them, as there is otherwise no way to have a username or password
05032          with reserved characters like ':' in them. */
05033       Curl_safefree(proxyinfo->user);
05034       proxyinfo->user = curl_easy_unescape(data, proxyuser, 0, NULL);
05035 
05036       if(!proxyinfo->user)
05037         return CURLE_OUT_OF_MEMORY;
05038 
05039       Curl_safefree(proxyinfo->passwd);
05040       if(proxypasswd && strlen(proxypasswd) < MAX_CURL_PASSWORD_LENGTH)
05041         proxyinfo->passwd = curl_easy_unescape(data, proxypasswd, 0, NULL);
05042       else
05043         proxyinfo->passwd = strdup("");
05044 
05045       if(!proxyinfo->passwd)
05046         return CURLE_OUT_OF_MEMORY;
05047 
05048       conn->bits.proxy_user_passwd = TRUE; /* enable it */
05049     }
05050 
05051     if(port >= 0) {
05052       proxyinfo->port = port;
05053       if(conn->port < 0 || sockstype || !conn->socks_proxy.host.rawalloc)
05054         conn->port = port;
05055     }
05056 
05057     /* now, clone the cleaned proxy host name */
05058     Curl_safefree(proxyinfo->host.rawalloc);
05059     proxyinfo->host.rawalloc = strdup(proxyptr);
05060     proxyinfo->host.name = proxyinfo->host.rawalloc;
05061 
05062     if(!proxyinfo->host.rawalloc)
05063       return CURLE_OUT_OF_MEMORY;
05064   }
05065 
05066   Curl_safefree(proxyuser);
05067   Curl_safefree(proxypasswd);
05068 
05069   return CURLE_OK;
05070 }
05071 
05072 /*
05073  * Extract the user and password from the authentication string
05074  */
05075 static CURLcode parse_proxy_auth(struct Curl_easy *data,
05076                                  struct connectdata *conn)
05077 {
05078   char proxyuser[MAX_CURL_USER_LENGTH]="";
05079   char proxypasswd[MAX_CURL_PASSWORD_LENGTH]="";
05080   CURLcode result;
05081 
05082   if(data->set.str[STRING_PROXYUSERNAME] != NULL) {
05083     strncpy(proxyuser, data->set.str[STRING_PROXYUSERNAME],
05084             MAX_CURL_USER_LENGTH);
05085     proxyuser[MAX_CURL_USER_LENGTH-1] = '\0';   /*To be on safe side*/
05086   }
05087   if(data->set.str[STRING_PROXYPASSWORD] != NULL) {
05088     strncpy(proxypasswd, data->set.str[STRING_PROXYPASSWORD],
05089             MAX_CURL_PASSWORD_LENGTH);
05090     proxypasswd[MAX_CURL_PASSWORD_LENGTH-1] = '\0'; /*To be on safe side*/
05091   }
05092 
05093   result = Curl_urldecode(data, proxyuser, 0, &conn->http_proxy.user, NULL,
05094                           FALSE);
05095   if(!result)
05096     result = Curl_urldecode(data, proxypasswd, 0, &conn->http_proxy.passwd,
05097                             NULL, FALSE);
05098   return result;
05099 }
05100 #endif /* CURL_DISABLE_PROXY */
05101 
05102 /*
05103  * parse_url_login()
05104  *
05105  * Parse the login details (user name, password and options) from the URL and
05106  * strip them out of the host name
05107  *
05108  * Inputs: data->set.use_netrc (CURLOPT_NETRC)
05109  *         conn->host.name
05110  *
05111  * Outputs: (almost :- all currently undefined)
05112  *          conn->bits.user_passwd  - non-zero if non-default passwords exist
05113  *          user                    - non-zero length if defined
05114  *          passwd                  - non-zero length if defined
05115  *          options                 - non-zero length if defined
05116  *          conn->host.name         - remove user name and password
05117  */
05118 static CURLcode parse_url_login(struct Curl_easy *data,
05119                                 struct connectdata *conn,
05120                                 char **user, char **passwd, char **options)
05121 {
05122   CURLcode result = CURLE_OK;
05123   char *userp = NULL;
05124   char *passwdp = NULL;
05125   char *optionsp = NULL;
05126 
05127   /* At this point, we're hoping all the other special cases have
05128    * been taken care of, so conn->host.name is at most
05129    *    [user[:password][;options]]@]hostname
05130    *
05131    * We need somewhere to put the embedded details, so do that first.
05132    */
05133 
05134   char *ptr = strchr(conn->host.name, '@');
05135   char *login = conn->host.name;
05136 
05137   DEBUGASSERT(!**user);
05138   DEBUGASSERT(!**passwd);
05139   DEBUGASSERT(!**options);
05140 
05141   if(!ptr)
05142     goto out;
05143 
05144   /* We will now try to extract the
05145    * possible login information in a string like:
05146    * ftp://user:password@ftp.my.site:8021/README */
05147   conn->host.name = ++ptr;
05148 
05149   /* So the hostname is sane.  Only bother interpreting the
05150    * results if we could care.  It could still be wasted
05151    * work because it might be overtaken by the programmatically
05152    * set user/passwd, but doing that first adds more cases here :-(
05153    */
05154 
05155   if(data->set.use_netrc == CURL_NETRC_REQUIRED)
05156     goto out;
05157 
05158   /* We could use the login information in the URL so extract it */
05159   result = parse_login_details(login, ptr - login - 1,
05160                                &userp, &passwdp, &optionsp);
05161   if(result)
05162     goto out;
05163 
05164   if(userp) {
05165     char *newname;
05166 
05167     /* We have a user in the URL */
05168     conn->bits.userpwd_in_url = TRUE;
05169     conn->bits.user_passwd = TRUE; /* enable user+password */
05170 
05171     /* Decode the user */
05172     result = Curl_urldecode(data, userp, 0, &newname, NULL, FALSE);
05173     if(result) {
05174       goto out;
05175     }
05176 
05177     free(*user);
05178     *user = newname;
05179   }
05180 
05181   if(passwdp) {
05182     /* We have a password in the URL so decode it */
05183     char *newpasswd;
05184     result = Curl_urldecode(data, passwdp, 0, &newpasswd, NULL, FALSE);
05185     if(result) {
05186       goto out;
05187     }
05188 
05189     free(*passwd);
05190     *passwd = newpasswd;
05191   }
05192 
05193   if(optionsp) {
05194     /* We have an options list in the URL so decode it */
05195     char *newoptions;
05196     result = Curl_urldecode(data, optionsp, 0, &newoptions, NULL, FALSE);
05197     if(result) {
05198       goto out;
05199     }
05200 
05201     free(*options);
05202     *options = newoptions;
05203   }
05204 
05205 
05206   out:
05207 
05208   free(userp);
05209   free(passwdp);
05210   free(optionsp);
05211 
05212   return result;
05213 }
05214 
05215 /*
05216  * parse_login_details()
05217  *
05218  * This is used to parse a login string for user name, password and options in
05219  * the following formats:
05220  *
05221  *   user
05222  *   user:password
05223  *   user:password;options
05224  *   user;options
05225  *   user;options:password
05226  *   :password
05227  *   :password;options
05228  *   ;options
05229  *   ;options:password
05230  *
05231  * Parameters:
05232  *
05233  * login    [in]     - The login string.
05234  * len      [in]     - The length of the login string.
05235  * userp    [in/out] - The address where a pointer to newly allocated memory
05236  *                     holding the user will be stored upon completion.
05237  * passdwp  [in/out] - The address where a pointer to newly allocated memory
05238  *                     holding the password will be stored upon completion.
05239  * optionsp [in/out] - The address where a pointer to newly allocated memory
05240  *                     holding the options will be stored upon completion.
05241  *
05242  * Returns CURLE_OK on success.
05243  */
05244 static CURLcode parse_login_details(const char *login, const size_t len,
05245                                     char **userp, char **passwdp,
05246                                     char **optionsp)
05247 {
05248   CURLcode result = CURLE_OK;
05249   char *ubuf = NULL;
05250   char *pbuf = NULL;
05251   char *obuf = NULL;
05252   const char *psep = NULL;
05253   const char *osep = NULL;
05254   size_t ulen;
05255   size_t plen;
05256   size_t olen;
05257 
05258   /* Attempt to find the password separator */
05259   if(passwdp) {
05260     psep = strchr(login, ':');
05261 
05262     /* Within the constraint of the login string */
05263     if(psep >= login + len)
05264       psep = NULL;
05265   }
05266 
05267   /* Attempt to find the options separator */
05268   if(optionsp) {
05269     osep = strchr(login, ';');
05270 
05271     /* Within the constraint of the login string */
05272     if(osep >= login + len)
05273       osep = NULL;
05274   }
05275 
05276   /* Calculate the portion lengths */
05277   ulen = (psep ?
05278           (size_t)(osep && psep > osep ? osep - login : psep - login) :
05279           (osep ? (size_t)(osep - login) : len));
05280   plen = (psep ?
05281           (osep && osep > psep ? (size_t)(osep - psep) :
05282                                  (size_t)(login + len - psep)) - 1 : 0);
05283   olen = (osep ?
05284           (psep && psep > osep ? (size_t)(psep - osep) :
05285                                  (size_t)(login + len - osep)) - 1 : 0);
05286 
05287   /* Allocate the user portion buffer */
05288   if(userp && ulen) {
05289     ubuf = malloc(ulen + 1);
05290     if(!ubuf)
05291       result = CURLE_OUT_OF_MEMORY;
05292   }
05293 
05294   /* Allocate the password portion buffer */
05295   if(!result && passwdp && plen) {
05296     pbuf = malloc(plen + 1);
05297     if(!pbuf) {
05298       free(ubuf);
05299       result = CURLE_OUT_OF_MEMORY;
05300     }
05301   }
05302 
05303   /* Allocate the options portion buffer */
05304   if(!result && optionsp && olen) {
05305     obuf = malloc(olen + 1);
05306     if(!obuf) {
05307       free(pbuf);
05308       free(ubuf);
05309       result = CURLE_OUT_OF_MEMORY;
05310     }
05311   }
05312 
05313   if(!result) {
05314     /* Store the user portion if necessary */
05315     if(ubuf) {
05316       memcpy(ubuf, login, ulen);
05317       ubuf[ulen] = '\0';
05318       Curl_safefree(*userp);
05319       *userp = ubuf;
05320     }
05321 
05322     /* Store the password portion if necessary */
05323     if(pbuf) {
05324       memcpy(pbuf, psep + 1, plen);
05325       pbuf[plen] = '\0';
05326       Curl_safefree(*passwdp);
05327       *passwdp = pbuf;
05328     }
05329 
05330     /* Store the options portion if necessary */
05331     if(obuf) {
05332       memcpy(obuf, osep + 1, olen);
05333       obuf[olen] = '\0';
05334       Curl_safefree(*optionsp);
05335       *optionsp = obuf;
05336     }
05337   }
05338 
05339   return result;
05340 }
05341 
05342 /*************************************************************
05343  * Figure out the remote port number and fix it in the URL
05344  *
05345  * No matter if we use a proxy or not, we have to figure out the remote
05346  * port number of various reasons.
05347  *
05348  * To be able to detect port number flawlessly, we must not confuse them
05349  * IPv6-specified addresses in the [0::1] style. (RFC2732)
05350  *
05351  * The conn->host.name is currently [user:passwd@]host[:port] where host
05352  * could be a hostname, IPv4 address or IPv6 address.
05353  *
05354  * The port number embedded in the URL is replaced, if necessary.
05355  *************************************************************/
05356 static CURLcode parse_remote_port(struct Curl_easy *data,
05357                                   struct connectdata *conn)
05358 {
05359   char *portptr;
05360   char endbracket;
05361 
05362   /* Note that at this point, the IPv6 address cannot contain any scope
05363      suffix as that has already been removed in the parseurlandfillconn()
05364      function */
05365   if((1 == sscanf(conn->host.name, "[%*45[0123456789abcdefABCDEF:.]%c",
05366                   &endbracket)) &&
05367      (']' == endbracket)) {
05368     /* this is a RFC2732-style specified IP-address */
05369     conn->bits.ipv6_ip = TRUE;
05370 
05371     conn->host.name++; /* skip over the starting bracket */
05372     portptr = strchr(conn->host.name, ']');
05373     if(portptr) {
05374       *portptr++ = '\0'; /* zero terminate, killing the bracket */
05375       if(':' != *portptr)
05376         portptr = NULL; /* no port number available */
05377     }
05378   }
05379   else {
05380 #ifdef ENABLE_IPV6
05381     struct in6_addr in6;
05382     if(Curl_inet_pton(AF_INET6, conn->host.name, &in6) > 0) {
05383       /* This is a numerical IPv6 address, meaning this is a wrongly formatted
05384          URL */
05385       failf(data, "IPv6 numerical address used in URL without brackets");
05386       return CURLE_URL_MALFORMAT;
05387     }
05388 #endif
05389 
05390     portptr = strrchr(conn->host.name, ':');
05391   }
05392 
05393   if(data->set.use_port && data->state.allow_port) {
05394     /* if set, we use this and ignore the port possibly given in the URL */
05395     conn->remote_port = (unsigned short)data->set.use_port;
05396     if(portptr)
05397       *portptr = '\0'; /* cut off the name there anyway - if there was a port
05398                       number - since the port number is to be ignored! */
05399     if(conn->bits.httpproxy) {
05400       /* we need to create new URL with the new port number */
05401       char *url;
05402       char type[12]="";
05403 
05404       if(conn->bits.type_set)
05405         snprintf(type, sizeof(type), ";type=%c",
05406                  data->set.prefer_ascii?'A':
05407                  (data->set.ftp_list_only?'D':'I'));
05408 
05409       /*
05410        * This synthesized URL isn't always right--suffixes like ;type=A are
05411        * stripped off. It would be better to work directly from the original
05412        * URL and simply replace the port part of it.
05413        */
05414       url = aprintf("%s://%s%s%s:%hu%s%s%s", conn->given->scheme,
05415                     conn->bits.ipv6_ip?"[":"", conn->host.name,
05416                     conn->bits.ipv6_ip?"]":"", conn->remote_port,
05417                     data->state.slash_removed?"/":"", data->state.path,
05418                     type);
05419       if(!url)
05420         return CURLE_OUT_OF_MEMORY;
05421 
05422       if(data->change.url_alloc) {
05423         Curl_safefree(data->change.url);
05424         data->change.url_alloc = FALSE;
05425       }
05426 
05427       data->change.url = url;
05428       data->change.url_alloc = TRUE;
05429     }
05430   }
05431   else if(portptr) {
05432     /* no CURLOPT_PORT given, extract the one from the URL */
05433 
05434     char *rest;
05435     long port;
05436 
05437     port=strtol(portptr+1, &rest, 10);  /* Port number must be decimal */
05438 
05439     if((port < 0) || (port > 0xffff)) {
05440       /* Single unix standard says port numbers are 16 bits long */
05441       failf(data, "Port number out of range");
05442       return CURLE_URL_MALFORMAT;
05443     }
05444 
05445     else if(rest != &portptr[1]) {
05446       *portptr = '\0'; /* cut off the name there */
05447       conn->remote_port = curlx_ultous(port);
05448     }
05449     else {
05450       if(rest[0]) {
05451         failf(data, "Illegal port number");
05452         return CURLE_URL_MALFORMAT;
05453       }
05454       /* Browser behavior adaptation. If there's a colon with no digits after,
05455          just cut off the name there which makes us ignore the colon and just
05456          use the default port. Firefox and Chrome both do that. */
05457       *portptr = '\0';
05458     }
05459   }
05460 
05461   /* only if remote_port was not already parsed off the URL we use the
05462      default port number */
05463   if(conn->remote_port < 0)
05464     conn->remote_port = (unsigned short)conn->given->defport;
05465 
05466   return CURLE_OK;
05467 }
05468 
05469 /*
05470  * Override the login details from the URL with that in the CURLOPT_USERPWD
05471  * option or a .netrc file, if applicable.
05472  */
05473 static CURLcode override_login(struct Curl_easy *data,
05474                                struct connectdata *conn,
05475                                char **userp, char **passwdp, char **optionsp)
05476 {
05477   if(data->set.str[STRING_USERNAME]) {
05478     free(*userp);
05479     *userp = strdup(data->set.str[STRING_USERNAME]);
05480     if(!*userp)
05481       return CURLE_OUT_OF_MEMORY;
05482   }
05483 
05484   if(data->set.str[STRING_PASSWORD]) {
05485     free(*passwdp);
05486     *passwdp = strdup(data->set.str[STRING_PASSWORD]);
05487     if(!*passwdp)
05488       return CURLE_OUT_OF_MEMORY;
05489   }
05490 
05491   if(data->set.str[STRING_OPTIONS]) {
05492     free(*optionsp);
05493     *optionsp = strdup(data->set.str[STRING_OPTIONS]);
05494     if(!*optionsp)
05495       return CURLE_OUT_OF_MEMORY;
05496   }
05497 
05498   conn->bits.netrc = FALSE;
05499   if(data->set.use_netrc != CURL_NETRC_IGNORED) {
05500     int ret = Curl_parsenetrc(conn->host.name,
05501                               userp, passwdp,
05502                               data->set.str[STRING_NETRC_FILE]);
05503     if(ret > 0) {
05504       infof(data, "Couldn't find host %s in the "
05505             DOT_CHAR "netrc file; using defaults\n",
05506             conn->host.name);
05507     }
05508     else if(ret < 0) {
05509       return CURLE_OUT_OF_MEMORY;
05510     }
05511     else {
05512       /* set bits.netrc TRUE to remember that we got the name from a .netrc
05513          file, so that it is safe to use even if we followed a Location: to a
05514          different host or similar. */
05515       conn->bits.netrc = TRUE;
05516 
05517       conn->bits.user_passwd = TRUE; /* enable user+password */
05518     }
05519   }
05520 
05521   return CURLE_OK;
05522 }
05523 
05524 /*
05525  * Set the login details so they're available in the connection
05526  */
05527 static CURLcode set_login(struct connectdata *conn,
05528                           const char *user, const char *passwd,
05529                           const char *options)
05530 {
05531   CURLcode result = CURLE_OK;
05532 
05533   /* If our protocol needs a password and we have none, use the defaults */
05534   if((conn->handler->flags & PROTOPT_NEEDSPWD) && !conn->bits.user_passwd) {
05535     /* Store the default user */
05536     conn->user = strdup(CURL_DEFAULT_USER);
05537 
05538     /* Store the default password */
05539     if(conn->user)
05540       conn->passwd = strdup(CURL_DEFAULT_PASSWORD);
05541     else
05542       conn->passwd = NULL;
05543 
05544     /* This is the default password, so DON'T set conn->bits.user_passwd */
05545   }
05546   else {
05547     /* Store the user, zero-length if not set */
05548     conn->user = strdup(user);
05549 
05550     /* Store the password (only if user is present), zero-length if not set */
05551     if(conn->user)
05552       conn->passwd = strdup(passwd);
05553     else
05554       conn->passwd = NULL;
05555   }
05556 
05557   if(!conn->user || !conn->passwd)
05558     result = CURLE_OUT_OF_MEMORY;
05559 
05560   /* Store the options, null if not set */
05561   if(!result && options[0]) {
05562     conn->options = strdup(options);
05563 
05564     if(!conn->options)
05565       result = CURLE_OUT_OF_MEMORY;
05566   }
05567 
05568   return result;
05569 }
05570 
05571 /*
05572  * Parses a "host:port" string to connect to.
05573  * The hostname and the port may be empty; in this case, NULL is returned for
05574  * the hostname and -1 for the port.
05575  */
05576 static CURLcode parse_connect_to_host_port(struct Curl_easy *data,
05577                                            const char *host,
05578                                            char **hostname_result,
05579                                            int *port_result)
05580 {
05581   char *host_dup;
05582   char *hostptr;
05583   char *host_portno;
05584   char *portptr;
05585   int port = -1;
05586 
05587   *hostname_result = NULL;
05588   *port_result = -1;
05589 
05590   if(!host || !*host)
05591     return CURLE_OK;
05592 
05593   host_dup = strdup(host);
05594   if(!host_dup)
05595     return CURLE_OUT_OF_MEMORY;
05596 
05597   hostptr = host_dup;
05598 
05599   /* start scanning for port number at this point */
05600   portptr = hostptr;
05601 
05602   /* detect and extract RFC6874-style IPv6-addresses */
05603   if(*hostptr == '[') {
05604     char *ptr = ++hostptr; /* advance beyond the initial bracket */
05605     while(*ptr && (ISXDIGIT(*ptr) || (*ptr == ':') || (*ptr == '.')))
05606       ptr++;
05607     if(*ptr == '%') {
05608       /* There might be a zone identifier */
05609       if(strncmp("%25", ptr, 3))
05610         infof(data, "Please URL encode %% as %%25, see RFC 6874.\n");
05611       ptr++;
05612       /* Allow unreserved characters as defined in RFC 3986 */
05613       while(*ptr && (ISALPHA(*ptr) || ISXDIGIT(*ptr) || (*ptr == '-') ||
05614                      (*ptr == '.') || (*ptr == '_') || (*ptr == '~')))
05615         ptr++;
05616     }
05617     if(*ptr == ']')
05618       /* yeps, it ended nicely with a bracket as well */
05619       *ptr++ = '\0';
05620     else
05621       infof(data, "Invalid IPv6 address format\n");
05622     portptr = ptr;
05623     /* Note that if this didn't end with a bracket, we still advanced the
05624      * hostptr first, but I can't see anything wrong with that as no host
05625      * name nor a numeric can legally start with a bracket.
05626      */
05627   }
05628 
05629   /* Get port number off server.com:1080 */
05630   host_portno = strchr(portptr, ':');
05631   if(host_portno) {
05632     char *endp = NULL;
05633     *host_portno = '\0'; /* cut off number from host name */
05634     host_portno++;
05635     if(*host_portno) {
05636       long portparse = strtol(host_portno, &endp, 10);
05637       if((endp && *endp) || (portparse < 0) || (portparse > 65535)) {
05638         infof(data, "No valid port number in connect to host string (%s)\n",
05639               host_portno);
05640         hostptr = NULL;
05641         port = -1;
05642       }
05643       else
05644         port = (int)portparse; /* we know it will fit */
05645     }
05646   }
05647 
05648   /* now, clone the cleaned host name */
05649   if(hostptr) {
05650     *hostname_result = strdup(hostptr);
05651     if(!*hostname_result) {
05652       free(host_dup);
05653       return CURLE_OUT_OF_MEMORY;
05654     }
05655   }
05656 
05657   *port_result = port;
05658 
05659   free(host_dup);
05660   return CURLE_OK;
05661 }
05662 
05663 /*
05664  * Parses one "connect to" string in the form:
05665  * "HOST:PORT:CONNECT-TO-HOST:CONNECT-TO-PORT".
05666  */
05667 static CURLcode parse_connect_to_string(struct Curl_easy *data,
05668                                         struct connectdata *conn,
05669                                         const char *conn_to_host,
05670                                         char **host_result,
05671                                         int *port_result)
05672 {
05673   CURLcode result = CURLE_OK;
05674   const char *ptr = conn_to_host;
05675   int host_match = FALSE;
05676   int port_match = FALSE;
05677 
05678   *host_result = NULL;
05679   *port_result = -1;
05680 
05681   if(*ptr == ':') {
05682     /* an empty hostname always matches */
05683     host_match = TRUE;
05684     ptr++;
05685   }
05686   else {
05687     /* check whether the URL's hostname matches */
05688     size_t hostname_to_match_len;
05689     char *hostname_to_match = aprintf("%s%s%s",
05690                                       conn->bits.ipv6_ip ? "[" : "",
05691                                       conn->host.name,
05692                                       conn->bits.ipv6_ip ? "]" : "");
05693     if(!hostname_to_match)
05694       return CURLE_OUT_OF_MEMORY;
05695     hostname_to_match_len = strlen(hostname_to_match);
05696     host_match = strncasecompare(ptr, hostname_to_match,
05697                                  hostname_to_match_len);
05698     free(hostname_to_match);
05699     ptr += hostname_to_match_len;
05700 
05701     host_match = host_match && *ptr == ':';
05702     ptr++;
05703   }
05704 
05705   if(host_match) {
05706     if(*ptr == ':') {
05707       /* an empty port always matches */
05708       port_match = TRUE;
05709       ptr++;
05710     }
05711     else {
05712       /* check whether the URL's port matches */
05713       char *ptr_next = strchr(ptr, ':');
05714       if(ptr_next) {
05715         char *endp = NULL;
05716         long port_to_match = strtol(ptr, &endp, 10);
05717         if((endp == ptr_next) && (port_to_match == conn->remote_port)) {
05718           port_match = TRUE;
05719           ptr = ptr_next + 1;
05720         }
05721       }
05722     }
05723   }
05724 
05725   if(host_match && port_match) {
05726     /* parse the hostname and port to connect to */
05727     result = parse_connect_to_host_port(data, ptr, host_result, port_result);
05728   }
05729 
05730   return result;
05731 }
05732 
05733 /*
05734  * Processes all strings in the "connect to" slist, and uses the "connect
05735  * to host" and "connect to port" of the first string that matches.
05736  */
05737 static CURLcode parse_connect_to_slist(struct Curl_easy *data,
05738                                        struct connectdata *conn,
05739                                        struct curl_slist *conn_to_host)
05740 {
05741   CURLcode result = CURLE_OK;
05742   char *host = NULL;
05743   int port = -1;
05744 
05745   while(conn_to_host && !host && port == -1) {
05746     result = parse_connect_to_string(data, conn, conn_to_host->data,
05747                                      &host, &port);
05748     if(result)
05749       return result;
05750 
05751     if(host && *host) {
05752       bool ipv6host;
05753       conn->conn_to_host.rawalloc = host;
05754       conn->conn_to_host.name = host;
05755       conn->bits.conn_to_host = TRUE;
05756 
05757       ipv6host = strchr(host, ':') != NULL;
05758       infof(data, "Connecting to hostname: %s%s%s\n",
05759             ipv6host ? "[" : "", host, ipv6host ? "]" : "");
05760     }
05761     else {
05762       /* no "connect to host" */
05763       conn->bits.conn_to_host = FALSE;
05764       Curl_safefree(host);
05765     }
05766 
05767     if(port >= 0) {
05768       conn->conn_to_port = port;
05769       conn->bits.conn_to_port = TRUE;
05770       infof(data, "Connecting to port: %d\n", port);
05771     }
05772     else {
05773       /* no "connect to port" */
05774       conn->bits.conn_to_port = FALSE;
05775       port = -1;
05776     }
05777 
05778     conn_to_host = conn_to_host->next;
05779   }
05780 
05781   return result;
05782 }
05783 
05784 /*************************************************************
05785  * Resolve the address of the server or proxy
05786  *************************************************************/
05787 static CURLcode resolve_server(struct Curl_easy *data,
05788                                struct connectdata *conn,
05789                                bool *async)
05790 {
05791   CURLcode result=CURLE_OK;
05792   time_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
05793 
05794   /*************************************************************
05795    * Resolve the name of the server or proxy
05796    *************************************************************/
05797   if(conn->bits.reuse)
05798     /* We're reusing the connection - no need to resolve anything, and
05799        fix_hostname() was called already in create_conn() for the re-use
05800        case. */
05801     *async = FALSE;
05802 
05803   else {
05804     /* this is a fresh connect */
05805     int rc;
05806     struct Curl_dns_entry *hostaddr;
05807 
05808 #ifdef USE_UNIX_SOCKETS
05809     if(conn->unix_domain_socket) {
05810       /* Unix domain sockets are local. The host gets ignored, just use the
05811        * specified domain socket address. Do not cache "DNS entries". There is
05812        * no DNS involved and we already have the filesystem path available */
05813       const char *path = conn->unix_domain_socket;
05814 
05815       hostaddr = calloc(1, sizeof(struct Curl_dns_entry));
05816       if(!hostaddr)
05817         result = CURLE_OUT_OF_MEMORY;
05818       else {
05819         int longpath=0;
05820         hostaddr->addr = Curl_unix2addr(path, &longpath);
05821         if(hostaddr->addr)
05822           hostaddr->inuse++;
05823         else {
05824           /* Long paths are not supported for now */
05825           if(longpath) {
05826             failf(data, "Unix socket path too long: '%s'", path);
05827             result = CURLE_COULDNT_RESOLVE_HOST;
05828           }
05829           else
05830             result = CURLE_OUT_OF_MEMORY;
05831           free(hostaddr);
05832           hostaddr = NULL;
05833         }
05834       }
05835     }
05836     else
05837 #endif
05838     if(!conn->bits.proxy) {
05839       struct hostname *connhost;
05840       if(conn->bits.conn_to_host)
05841         connhost = &conn->conn_to_host;
05842       else
05843         connhost = &conn->host;
05844 
05845       /* If not connecting via a proxy, extract the port from the URL, if it is
05846        * there, thus overriding any defaults that might have been set above. */
05847       if(conn->bits.conn_to_port)
05848         conn->port = conn->conn_to_port;
05849       else
05850         conn->port = conn->remote_port; /* it is the same port */
05851 
05852       /* Resolve target host right on */
05853       rc = Curl_resolv_timeout(conn, connhost->name, (int)conn->port,
05854                                &hostaddr, timeout_ms);
05855       if(rc == CURLRESOLV_PENDING)
05856         *async = TRUE;
05857 
05858       else if(rc == CURLRESOLV_TIMEDOUT)
05859         result = CURLE_OPERATION_TIMEDOUT;
05860 
05861       else if(!hostaddr) {
05862         failf(data, "Couldn't resolve host '%s'", connhost->dispname);
05863         result =  CURLE_COULDNT_RESOLVE_HOST;
05864         /* don't return yet, we need to clean up the timeout first */
05865       }
05866     }
05867     else {
05868       /* This is a proxy that hasn't been resolved yet. */
05869 
05870       struct hostname * const host = conn->bits.socksproxy ?
05871         &conn->socks_proxy.host : &conn->http_proxy.host;
05872 
05873       /* resolve proxy */
05874       rc = Curl_resolv_timeout(conn, host->name, (int)conn->port,
05875                                &hostaddr, timeout_ms);
05876 
05877       if(rc == CURLRESOLV_PENDING)
05878         *async = TRUE;
05879 
05880       else if(rc == CURLRESOLV_TIMEDOUT)
05881         result = CURLE_OPERATION_TIMEDOUT;
05882 
05883       else if(!hostaddr) {
05884         failf(data, "Couldn't resolve proxy '%s'", host->dispname);
05885         result = CURLE_COULDNT_RESOLVE_PROXY;
05886         /* don't return yet, we need to clean up the timeout first */
05887       }
05888     }
05889     DEBUGASSERT(conn->dns_entry == NULL);
05890     conn->dns_entry = hostaddr;
05891   }
05892 
05893   return result;
05894 }
05895 
05896 /*
05897  * Cleanup the connection just allocated before we can move along and use the
05898  * previously existing one.  All relevant data is copied over and old_conn is
05899  * ready for freeing once this function returns.
05900  */
05901 static void reuse_conn(struct connectdata *old_conn,
05902                        struct connectdata *conn)
05903 {
05904   free_fixed_hostname(&old_conn->http_proxy.host);
05905   free_fixed_hostname(&old_conn->socks_proxy.host);
05906   free_fixed_hostname(&old_conn->proxy);
05907 
05908   free(old_conn->http_proxy.host.rawalloc);
05909   free(old_conn->socks_proxy.host.rawalloc);
05910   free(old_conn->proxy.rawalloc);
05911 
05912   /* free the SSL config struct from this connection struct as this was
05913      allocated in vain and is targeted for destruction */
05914   Curl_free_primary_ssl_config(&old_conn->ssl_config);
05915   Curl_free_primary_ssl_config(&old_conn->proxy_ssl_config);
05916 
05917   conn->data = old_conn->data;
05918 
05919   /* get the user+password information from the old_conn struct since it may
05920    * be new for this request even when we re-use an existing connection */
05921   conn->bits.user_passwd = old_conn->bits.user_passwd;
05922   if(conn->bits.user_passwd) {
05923     /* use the new user name and password though */
05924     Curl_safefree(conn->user);
05925     Curl_safefree(conn->passwd);
05926     conn->user = old_conn->user;
05927     conn->passwd = old_conn->passwd;
05928     old_conn->user = NULL;
05929     old_conn->passwd = NULL;
05930   }
05931 
05932   conn->bits.proxy_user_passwd = old_conn->bits.proxy_user_passwd;
05933   if(conn->bits.proxy_user_passwd) {
05934     /* use the new proxy user name and proxy password though */
05935     Curl_safefree(conn->http_proxy.user);
05936     Curl_safefree(conn->socks_proxy.user);
05937     Curl_safefree(conn->http_proxy.passwd);
05938     Curl_safefree(conn->socks_proxy.passwd);
05939     conn->http_proxy.user = old_conn->http_proxy.user;
05940     conn->socks_proxy.user = old_conn->socks_proxy.user;
05941     conn->http_proxy.passwd = old_conn->http_proxy.passwd;
05942     conn->socks_proxy.passwd = old_conn->socks_proxy.passwd;
05943     old_conn->http_proxy.user = NULL;
05944     old_conn->socks_proxy.user = NULL;
05945     old_conn->http_proxy.passwd = NULL;
05946     old_conn->socks_proxy.passwd = NULL;
05947   }
05948 
05949   /* host can change, when doing keepalive with a proxy or if the case is
05950      different this time etc */
05951   free_fixed_hostname(&conn->host);
05952   free_fixed_hostname(&conn->conn_to_host);
05953   Curl_safefree(conn->host.rawalloc);
05954   Curl_safefree(conn->conn_to_host.rawalloc);
05955   conn->host=old_conn->host;
05956   conn->bits.conn_to_host = old_conn->bits.conn_to_host;
05957   conn->conn_to_host = old_conn->conn_to_host;
05958   conn->bits.conn_to_port = old_conn->bits.conn_to_port;
05959   conn->conn_to_port = old_conn->conn_to_port;
05960 
05961   /* persist connection info in session handle */
05962   Curl_persistconninfo(conn);
05963 
05964   conn_reset_all_postponed_data(old_conn); /* free buffers */
05965   conn_reset_all_postponed_data(conn);     /* reset unprocessed data */
05966 
05967   /* re-use init */
05968   conn->bits.reuse = TRUE; /* yes, we're re-using here */
05969 
05970   Curl_safefree(old_conn->user);
05971   Curl_safefree(old_conn->passwd);
05972   Curl_safefree(old_conn->http_proxy.user);
05973   Curl_safefree(old_conn->socks_proxy.user);
05974   Curl_safefree(old_conn->http_proxy.passwd);
05975   Curl_safefree(old_conn->socks_proxy.passwd);
05976   Curl_safefree(old_conn->localdev);
05977 
05978   Curl_llist_destroy(old_conn->send_pipe, NULL);
05979   Curl_llist_destroy(old_conn->recv_pipe, NULL);
05980 
05981   old_conn->send_pipe = NULL;
05982   old_conn->recv_pipe = NULL;
05983 
05984   Curl_safefree(old_conn->master_buffer);
05985 
05986 #ifdef USE_UNIX_SOCKETS
05987   Curl_safefree(old_conn->unix_domain_socket);
05988 #endif
05989 }
05990 
06007 static CURLcode create_conn(struct Curl_easy *data,
06008                             struct connectdata **in_connect,
06009                             bool *async)
06010 {
06011   CURLcode result = CURLE_OK;
06012   struct connectdata *conn;
06013   struct connectdata *conn_temp = NULL;
06014   size_t urllen;
06015   char *user = NULL;
06016   char *passwd = NULL;
06017   char *options = NULL;
06018   bool reuse;
06019   char *proxy = NULL;
06020   char *socksproxy = NULL;
06021   bool prot_missing = FALSE;
06022   bool connections_available = TRUE;
06023   bool force_reuse = FALSE;
06024   bool waitpipe = FALSE;
06025   size_t max_host_connections = Curl_multi_max_host_connections(data->multi);
06026   size_t max_total_connections = Curl_multi_max_total_connections(data->multi);
06027 
06028   *async = FALSE;
06029 
06030   /*************************************************************
06031    * Check input data
06032    *************************************************************/
06033 
06034   if(!data->change.url) {
06035     result = CURLE_URL_MALFORMAT;
06036     goto out;
06037   }
06038 
06039   /* First, split up the current URL in parts so that we can use the
06040      parts for checking against the already present connections. In order
06041      to not have to modify everything at once, we allocate a temporary
06042      connection data struct and fill in for comparison purposes. */
06043   conn = allocate_conn(data);
06044 
06045   if(!conn) {
06046     result = CURLE_OUT_OF_MEMORY;
06047     goto out;
06048   }
06049 
06050   /* We must set the return variable as soon as possible, so that our
06051      parent can cleanup any possible allocs we may have done before
06052      any failure */
06053   *in_connect = conn;
06054 
06055   /* This initing continues below, see the comment "Continue connectdata
06056    * initialization here" */
06057 
06058   /***********************************************************
06059    * We need to allocate memory to store the path in. We get the size of the
06060    * full URL to be sure, and we need to make it at least 256 bytes since
06061    * other parts of the code will rely on this fact
06062    ***********************************************************/
06063 #define LEAST_PATH_ALLOC 256
06064   urllen=strlen(data->change.url);
06065   if(urllen < LEAST_PATH_ALLOC)
06066     urllen=LEAST_PATH_ALLOC;
06067 
06068   /*
06069    * We malloc() the buffers below urllen+2 to make room for 2 possibilities:
06070    * 1 - an extra terminating zero
06071    * 2 - an extra slash (in case a syntax like "www.host.com?moo" is used)
06072    */
06073 
06074   Curl_safefree(data->state.pathbuffer);
06075   data->state.path = NULL;
06076 
06077   data->state.pathbuffer = malloc(urllen+2);
06078   if(NULL == data->state.pathbuffer) {
06079     result = CURLE_OUT_OF_MEMORY; /* really bad error */
06080     goto out;
06081   }
06082   data->state.path = data->state.pathbuffer;
06083 
06084   conn->host.rawalloc = malloc(urllen+2);
06085   if(NULL == conn->host.rawalloc) {
06086     Curl_safefree(data->state.pathbuffer);
06087     data->state.path = NULL;
06088     result = CURLE_OUT_OF_MEMORY;
06089     goto out;
06090   }
06091 
06092   conn->host.name = conn->host.rawalloc;
06093   conn->host.name[0] = 0;
06094 
06095   user = strdup("");
06096   passwd = strdup("");
06097   options = strdup("");
06098   if(!user || !passwd || !options) {
06099     result = CURLE_OUT_OF_MEMORY;
06100     goto out;
06101   }
06102 
06103   result = parseurlandfillconn(data, conn, &prot_missing, &user, &passwd,
06104                                &options);
06105   if(result)
06106     goto out;
06107 
06108   /*************************************************************
06109    * No protocol part in URL was used, add it!
06110    *************************************************************/
06111   if(prot_missing) {
06112     /* We're guessing prefixes here and if we're told to use a proxy or if
06113        we're gonna follow a Location: later or... then we need the protocol
06114        part added so that we have a valid URL. */
06115     char *reurl;
06116     char *ch_lower;
06117 
06118     reurl = aprintf("%s://%s", conn->handler->scheme, data->change.url);
06119 
06120     if(!reurl) {
06121       result = CURLE_OUT_OF_MEMORY;
06122       goto out;
06123     }
06124 
06125     /* Change protocol prefix to lower-case */
06126     for(ch_lower = reurl; *ch_lower != ':'; ch_lower++)
06127       *ch_lower = (char)TOLOWER(*ch_lower);
06128 
06129     if(data->change.url_alloc) {
06130       Curl_safefree(data->change.url);
06131       data->change.url_alloc = FALSE;
06132     }
06133 
06134     data->change.url = reurl;
06135     data->change.url_alloc = TRUE; /* free this later */
06136   }
06137 
06138   /*************************************************************
06139    * If the protocol can't handle url query strings, then cut
06140    * off the unhandable part
06141    *************************************************************/
06142   if((conn->given->flags&PROTOPT_NOURLQUERY)) {
06143     char *path_q_sep = strchr(conn->data->state.path, '?');
06144     if(path_q_sep) {
06145       /* according to rfc3986, allow the query (?foo=bar)
06146          also on protocols that can't handle it.
06147 
06148          cut the string-part after '?'
06149       */
06150 
06151       /* terminate the string */
06152       path_q_sep[0] = 0;
06153     }
06154   }
06155 
06156   if(data->set.str[STRING_BEARER]) {
06157     conn->oauth_bearer = strdup(data->set.str[STRING_BEARER]);
06158     if(!conn->oauth_bearer) {
06159       result = CURLE_OUT_OF_MEMORY;
06160       goto out;
06161     }
06162   }
06163 
06164 #ifndef CURL_DISABLE_PROXY
06165   /*************************************************************
06166    * Extract the user and password from the authentication string
06167    *************************************************************/
06168   if(conn->bits.proxy_user_passwd) {
06169     result = parse_proxy_auth(data, conn);
06170     if(result)
06171       goto out;
06172   }
06173 
06174   /*************************************************************
06175    * Detect what (if any) proxy to use
06176    *************************************************************/
06177   if(data->set.str[STRING_PROXY]) {
06178     proxy = strdup(data->set.str[STRING_PROXY]);
06179     /* if global proxy is set, this is it */
06180     if(NULL == proxy) {
06181       failf(data, "memory shortage");
06182       result = CURLE_OUT_OF_MEMORY;
06183       goto out;
06184     }
06185   }
06186 
06187   if(data->set.str[STRING_PRE_PROXY]) {
06188     socksproxy = strdup(data->set.str[STRING_PRE_PROXY]);
06189     /* if global socks proxy is set, this is it */
06190     if(NULL == socksproxy) {
06191       failf(data, "memory shortage");
06192       result = CURLE_OUT_OF_MEMORY;
06193       goto out;
06194     }
06195   }
06196 
06197   if(data->set.str[STRING_NOPROXY] &&
06198      check_noproxy(conn->host.name, data->set.str[STRING_NOPROXY])) {
06199     Curl_safefree(proxy);
06200     Curl_safefree(socksproxy);
06201   }
06202   else if(!proxy && !socksproxy)
06203     proxy = detect_proxy(conn);
06204 
06205 #ifdef USE_UNIX_SOCKETS
06206   if(data->set.str[STRING_UNIX_SOCKET_PATH]) {
06207     if(proxy) {
06208       free(proxy); /* Unix domain sockets cannot be proxied, so disable it */
06209       proxy = NULL;
06210     }
06211     conn->unix_domain_socket = strdup(data->set.str[STRING_UNIX_SOCKET_PATH]);
06212     if(conn->unix_domain_socket == NULL) {
06213       result = CURLE_OUT_OF_MEMORY;
06214       goto out;
06215     }
06216   }
06217 #endif
06218 
06219   if(proxy && (!*proxy || (conn->handler->flags & PROTOPT_NONETWORK))) {
06220     free(proxy);  /* Don't bother with an empty proxy string or if the
06221                      protocol doesn't work with network */
06222     proxy = NULL;
06223   }
06224   if(socksproxy && (!*socksproxy ||
06225                     (conn->handler->flags & PROTOPT_NONETWORK))) {
06226     free(socksproxy);  /* Don't bother with an empty socks proxy string or if
06227                           the protocol doesn't work with network */
06228     socksproxy = NULL;
06229   }
06230 
06231   /***********************************************************************
06232    * If this is supposed to use a proxy, we need to figure out the proxy host
06233    * name, proxy type and port number, so that we can re-use an existing
06234    * connection that may exist registered to the same proxy host.
06235    ***********************************************************************/
06236   if(proxy || socksproxy) {
06237     if(proxy) {
06238       result = parse_proxy(data, conn, proxy, conn->http_proxy.proxytype);
06239       Curl_safefree(proxy); /* parse_proxy copies the proxy string */
06240       if(result)
06241         goto out;
06242     }
06243 
06244     if(socksproxy) {
06245       result = parse_proxy(data, conn, socksproxy,
06246                            conn->socks_proxy.proxytype);
06247       /* parse_proxy copies the socks proxy string */
06248       Curl_safefree(socksproxy);
06249       if(result)
06250         goto out;
06251     }
06252 
06253     if(conn->http_proxy.host.rawalloc) {
06254 #ifdef CURL_DISABLE_HTTP
06255       /* asking for a HTTP proxy is a bit funny when HTTP is disabled... */
06256       result = CURLE_UNSUPPORTED_PROTOCOL;
06257       goto out;
06258 #else
06259       /* force this connection's protocol to become HTTP if not already
06260          compatible - if it isn't tunneling through */
06261       if(!(conn->handler->protocol & PROTO_FAMILY_HTTP) &&
06262          !conn->bits.tunnel_proxy)
06263         conn->handler = &Curl_handler_http;
06264 
06265       conn->bits.httpproxy = TRUE;
06266 #endif
06267     }
06268     else {
06269       conn->bits.httpproxy = FALSE; /* not a HTTP proxy */
06270       conn->bits.tunnel_proxy = FALSE; /* no tunneling if not HTTP */
06271     }
06272 
06273     if(conn->socks_proxy.host.rawalloc) {
06274       if(!conn->http_proxy.host.rawalloc) {
06275         /* once a socks proxy */
06276         if(!conn->socks_proxy.user) {
06277           conn->socks_proxy.user = conn->http_proxy.user;
06278           conn->http_proxy.user = NULL;
06279           Curl_safefree(conn->socks_proxy.passwd);
06280           conn->socks_proxy.passwd = conn->http_proxy.passwd;
06281           conn->http_proxy.passwd = NULL;
06282         }
06283       }
06284       conn->bits.socksproxy = TRUE;
06285     }
06286     else
06287       conn->bits.socksproxy = FALSE; /* not a socks proxy */
06288   }
06289   else {
06290     conn->bits.socksproxy = FALSE;
06291     conn->bits.httpproxy = FALSE;
06292   }
06293   conn->bits.proxy = conn->bits.httpproxy || conn->bits.socksproxy;
06294 
06295   if(!conn->bits.proxy) {
06296     /* we aren't using the proxy after all... */
06297     conn->bits.proxy = FALSE;
06298     conn->bits.httpproxy = FALSE;
06299     conn->bits.socksproxy = FALSE;
06300     conn->bits.proxy_user_passwd = FALSE;
06301     conn->bits.tunnel_proxy = FALSE;
06302   }
06303 
06304 #endif /* CURL_DISABLE_PROXY */
06305 
06306   /*************************************************************
06307    * If the protocol is using SSL and HTTP proxy is used, we set
06308    * the tunnel_proxy bit.
06309    *************************************************************/
06310   if((conn->given->flags&PROTOPT_SSL) && conn->bits.httpproxy)
06311     conn->bits.tunnel_proxy = TRUE;
06312 
06313   /*************************************************************
06314    * Figure out the remote port number and fix it in the URL
06315    *************************************************************/
06316   result = parse_remote_port(data, conn);
06317   if(result)
06318     goto out;
06319 
06320   /* Check for overridden login details and set them accordingly so they
06321      they are known when protocol->setup_connection is called! */
06322   result = override_login(data, conn, &user, &passwd, &options);
06323   if(result)
06324     goto out;
06325   result = set_login(conn, user, passwd, options);
06326   if(result)
06327     goto out;
06328 
06329   /*************************************************************
06330    * Process the "connect to" linked list of hostname/port mappings.
06331    * Do this after the remote port number has been fixed in the URL.
06332    *************************************************************/
06333   result = parse_connect_to_slist(data, conn, data->set.connect_to);
06334   if(result)
06335     goto out;
06336 
06337   /*************************************************************
06338    * IDN-fix the hostnames
06339    *************************************************************/
06340   fix_hostname(conn, &conn->host);
06341   if(conn->bits.conn_to_host)
06342     fix_hostname(conn, &conn->conn_to_host);
06343   if(conn->proxy.name && *conn->proxy.name)
06344     fix_hostname(conn, &conn->proxy);
06345 
06346   /*************************************************************
06347    * Check whether the host and the "connect to host" are equal.
06348    * Do this after the hostnames have been IDN-fixed .
06349    *************************************************************/
06350   if(conn->bits.conn_to_host &&
06351      strcasecompare(conn->conn_to_host.name, conn->host.name)) {
06352     conn->bits.conn_to_host = FALSE;
06353   }
06354 
06355   /*************************************************************
06356    * Check whether the port and the "connect to port" are equal.
06357    * Do this after the remote port number has been fixed in the URL.
06358    *************************************************************/
06359   if(conn->bits.conn_to_port && conn->conn_to_port == conn->remote_port) {
06360     conn->bits.conn_to_port = FALSE;
06361   }
06362 
06363   /*************************************************************
06364    * If the "connect to" feature is used with an HTTP proxy,
06365    * we set the tunnel_proxy bit.
06366    *************************************************************/
06367   if((conn->bits.conn_to_host || conn->bits.conn_to_port) &&
06368       conn->bits.httpproxy)
06369     conn->bits.tunnel_proxy = TRUE;
06370 
06371   /*************************************************************
06372    * Setup internals depending on protocol. Needs to be done after
06373    * we figured out what/if proxy to use.
06374    *************************************************************/
06375   result = setup_connection_internals(conn);
06376   if(result)
06377     goto out;
06378 
06379   conn->recv[FIRSTSOCKET] = Curl_recv_plain;
06380   conn->send[FIRSTSOCKET] = Curl_send_plain;
06381   conn->recv[SECONDARYSOCKET] = Curl_recv_plain;
06382   conn->send[SECONDARYSOCKET] = Curl_send_plain;
06383 
06384   conn->bits.tcp_fastopen = data->set.tcp_fastopen;
06385 
06386   /***********************************************************************
06387    * file: is a special case in that it doesn't need a network connection
06388    ***********************************************************************/
06389 #ifndef CURL_DISABLE_FILE
06390   if(conn->handler->flags & PROTOPT_NONETWORK) {
06391     bool done;
06392     /* this is supposed to be the connect function so we better at least check
06393        that the file is present here! */
06394     DEBUGASSERT(conn->handler->connect_it);
06395     result = conn->handler->connect_it(conn, &done);
06396 
06397     /* Setup a "faked" transfer that'll do nothing */
06398     if(!result) {
06399       conn->data = data;
06400       conn->bits.tcpconnect[FIRSTSOCKET] = TRUE; /* we are "connected */
06401 
06402       Curl_conncache_add_conn(data->state.conn_cache, conn);
06403 
06404       /*
06405        * Setup whatever necessary for a resumed transfer
06406        */
06407       result = setup_range(data);
06408       if(result) {
06409         DEBUGASSERT(conn->handler->done);
06410         /* we ignore the return code for the protocol-specific DONE */
06411         (void)conn->handler->done(conn, result, FALSE);
06412         goto out;
06413       }
06414 
06415       Curl_setup_transfer(conn, -1, -1, FALSE, NULL, /* no download */
06416                           -1, NULL); /* no upload */
06417     }
06418 
06419     /* since we skip do_init() */
06420     Curl_init_do(data, conn);
06421 
06422     goto out;
06423   }
06424 #endif
06425 
06426   /* Get a cloned copy of the SSL config situation stored in the
06427      connection struct. But to get this going nicely, we must first make
06428      sure that the strings in the master copy are pointing to the correct
06429      strings in the session handle strings array!
06430 
06431      Keep in mind that the pointers in the master copy are pointing to strings
06432      that will be freed as part of the Curl_easy struct, but all cloned
06433      copies will be separately allocated.
06434   */
06435   data->set.ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH_ORIG];
06436   data->set.proxy_ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH_PROXY];
06437   data->set.ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE_ORIG];
06438   data->set.proxy_ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE_PROXY];
06439   data->set.ssl.primary.random_file = data->set.str[STRING_SSL_RANDOM_FILE];
06440   data->set.proxy_ssl.primary.random_file =
06441     data->set.str[STRING_SSL_RANDOM_FILE];
06442   data->set.ssl.primary.egdsocket = data->set.str[STRING_SSL_EGDSOCKET];
06443   data->set.proxy_ssl.primary.egdsocket = data->set.str[STRING_SSL_EGDSOCKET];
06444   data->set.ssl.primary.cipher_list =
06445     data->set.str[STRING_SSL_CIPHER_LIST_ORIG];
06446   data->set.proxy_ssl.primary.cipher_list =
06447     data->set.str[STRING_SSL_CIPHER_LIST_PROXY];
06448 
06449   data->set.ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE_ORIG];
06450   data->set.proxy_ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE_PROXY];
06451   data->set.ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT_ORIG];
06452   data->set.proxy_ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT_PROXY];
06453   data->set.ssl.cert = data->set.str[STRING_CERT_ORIG];
06454   data->set.proxy_ssl.cert = data->set.str[STRING_CERT_PROXY];
06455   data->set.ssl.cert_type = data->set.str[STRING_CERT_TYPE_ORIG];
06456   data->set.proxy_ssl.cert_type = data->set.str[STRING_CERT_TYPE_PROXY];
06457   data->set.ssl.key = data->set.str[STRING_KEY_ORIG];
06458   data->set.proxy_ssl.key = data->set.str[STRING_KEY_PROXY];
06459   data->set.ssl.key_type = data->set.str[STRING_KEY_TYPE_ORIG];
06460   data->set.proxy_ssl.key_type = data->set.str[STRING_KEY_TYPE_PROXY];
06461   data->set.ssl.key_passwd = data->set.str[STRING_KEY_PASSWD_ORIG];
06462   data->set.proxy_ssl.key_passwd = data->set.str[STRING_KEY_PASSWD_PROXY];
06463   data->set.ssl.primary.clientcert = data->set.str[STRING_CERT_ORIG];
06464   data->set.proxy_ssl.primary.clientcert = data->set.str[STRING_CERT_PROXY];
06465 #ifdef USE_TLS_SRP
06466   data->set.ssl.username = data->set.str[STRING_TLSAUTH_USERNAME_ORIG];
06467   data->set.proxy_ssl.username = data->set.str[STRING_TLSAUTH_USERNAME_PROXY];
06468   data->set.ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD_ORIG];
06469   data->set.proxy_ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD_PROXY];
06470 #endif
06471 
06472   if(!Curl_clone_primary_ssl_config(&data->set.ssl.primary,
06473      &conn->ssl_config)) {
06474     result = CURLE_OUT_OF_MEMORY;
06475     goto out;
06476   }
06477 
06478   if(!Curl_clone_primary_ssl_config(&data->set.proxy_ssl.primary,
06479                                     &conn->proxy_ssl_config)) {
06480     result = CURLE_OUT_OF_MEMORY;
06481     goto out;
06482   }
06483 
06484   prune_dead_connections(data);
06485 
06486   /*************************************************************
06487    * Check the current list of connections to see if we can
06488    * re-use an already existing one or if we have to create a
06489    * new one.
06490    *************************************************************/
06491 
06492   /* reuse_fresh is TRUE if we are told to use a new connection by force, but
06493      we only acknowledge this option if this is not a re-used connection
06494      already (which happens due to follow-location or during a HTTP
06495      authentication phase). */
06496   if(data->set.reuse_fresh && !data->state.this_is_a_follow)
06497     reuse = FALSE;
06498   else
06499     reuse = ConnectionExists(data, conn, &conn_temp, &force_reuse, &waitpipe);
06500 
06501   /* If we found a reusable connection, we may still want to
06502      open a new connection if we are pipelining. */
06503   if(reuse && !force_reuse && IsPipeliningPossible(data, conn_temp)) {
06504     size_t pipelen = conn_temp->send_pipe->size + conn_temp->recv_pipe->size;
06505     if(pipelen > 0) {
06506       infof(data, "Found connection %ld, with requests in the pipe (%zu)\n",
06507             conn_temp->connection_id, pipelen);
06508 
06509       if(conn_temp->bundle->num_connections < max_host_connections &&
06510          data->state.conn_cache->num_connections < max_total_connections) {
06511         /* We want a new connection anyway */
06512         reuse = FALSE;
06513 
06514         infof(data, "We can reuse, but we want a new connection anyway\n");
06515       }
06516     }
06517   }
06518 
06519   if(reuse) {
06520     /*
06521      * We already have a connection for this, we got the former connection
06522      * in the conn_temp variable and thus we need to cleanup the one we
06523      * just allocated before we can move along and use the previously
06524      * existing one.
06525      */
06526     conn_temp->inuse = TRUE; /* mark this as being in use so that no other
06527                                 handle in a multi stack may nick it */
06528     reuse_conn(conn, conn_temp);
06529     free(conn);          /* we don't need this anymore */
06530     conn = conn_temp;
06531     *in_connect = conn;
06532 
06533     infof(data, "Re-using existing connection! (#%ld) with %s %s\n",
06534           conn->connection_id,
06535           conn->bits.proxy?"proxy":"host",
06536           conn->socks_proxy.host.name ? conn->socks_proxy.host.dispname :
06537           conn->http_proxy.host.name ? conn->http_proxy.host.dispname :
06538                                        conn->host.dispname);
06539   }
06540   else {
06541     /* We have decided that we want a new connection. However, we may not
06542        be able to do that if we have reached the limit of how many
06543        connections we are allowed to open. */
06544     struct connectbundle *bundle = NULL;
06545 
06546     if(conn->handler->flags & PROTOPT_ALPN_NPN) {
06547       /* The protocol wants it, so set the bits if enabled in the easy handle
06548          (default) */
06549       if(data->set.ssl_enable_alpn)
06550         conn->bits.tls_enable_alpn = TRUE;
06551       if(data->set.ssl_enable_npn)
06552         conn->bits.tls_enable_npn = TRUE;
06553     }
06554 
06555     if(waitpipe)
06556       /* There is a connection that *might* become usable for pipelining
06557          "soon", and we wait for that */
06558       connections_available = FALSE;
06559     else
06560       bundle = Curl_conncache_find_bundle(conn, data->state.conn_cache);
06561 
06562     if(max_host_connections > 0 && bundle &&
06563        (bundle->num_connections >= max_host_connections)) {
06564       struct connectdata *conn_candidate;
06565 
06566       /* The bundle is full. Let's see if we can kill a connection. */
06567       conn_candidate = find_oldest_idle_connection_in_bundle(data, bundle);
06568 
06569       if(conn_candidate) {
06570         /* Set the connection's owner correctly, then kill it */
06571         conn_candidate->data = data;
06572         (void)Curl_disconnect(conn_candidate, /* dead_connection */ FALSE);
06573       }
06574       else {
06575         infof(data, "No more connections allowed to host: %d\n",
06576               max_host_connections);
06577         connections_available = FALSE;
06578       }
06579     }
06580 
06581     if(connections_available &&
06582        (max_total_connections > 0) &&
06583        (data->state.conn_cache->num_connections >= max_total_connections)) {
06584       struct connectdata *conn_candidate;
06585 
06586       /* The cache is full. Let's see if we can kill a connection. */
06587       conn_candidate = Curl_oldest_idle_connection(data);
06588 
06589       if(conn_candidate) {
06590         /* Set the connection's owner correctly, then kill it */
06591         conn_candidate->data = data;
06592         (void)Curl_disconnect(conn_candidate, /* dead_connection */ FALSE);
06593       }
06594       else {
06595         infof(data, "No connections available in cache\n");
06596         connections_available = FALSE;
06597       }
06598     }
06599 
06600     if(!connections_available) {
06601       infof(data, "No connections available.\n");
06602 
06603       conn_free(conn);
06604       *in_connect = NULL;
06605 
06606       result = CURLE_NO_CONNECTION_AVAILABLE;
06607       goto out;
06608     }
06609     else {
06610       /*
06611        * This is a brand new connection, so let's store it in the connection
06612        * cache of ours!
06613        */
06614       Curl_conncache_add_conn(data->state.conn_cache, conn);
06615     }
06616 
06617 #if defined(USE_NTLM)
06618     /* If NTLM is requested in a part of this connection, make sure we don't
06619        assume the state is fine as this is a fresh connection and NTLM is
06620        connection based. */
06621     if((data->state.authhost.picked & (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) &&
06622        data->state.authhost.done) {
06623       infof(data, "NTLM picked AND auth done set, clear picked!\n");
06624       data->state.authhost.picked = CURLAUTH_NONE;
06625       data->state.authhost.done = FALSE;
06626     }
06627 
06628     if((data->state.authproxy.picked & (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) &&
06629        data->state.authproxy.done) {
06630       infof(data, "NTLM-proxy picked AND auth done set, clear picked!\n");
06631       data->state.authproxy.picked = CURLAUTH_NONE;
06632       data->state.authproxy.done = FALSE;
06633     }
06634 #endif
06635   }
06636 
06637   /* Mark the connection as used */
06638   conn->inuse = TRUE;
06639 
06640   /* Setup and init stuff before DO starts, in preparing for the transfer. */
06641   Curl_init_do(data, conn);
06642 
06643   /*
06644    * Setup whatever necessary for a resumed transfer
06645    */
06646   result = setup_range(data);
06647   if(result)
06648     goto out;
06649 
06650   /* Continue connectdata initialization here. */
06651 
06652   /*
06653    * Inherit the proper values from the urldata struct AFTER we have arranged
06654    * the persistent connection stuff
06655    */
06656   conn->seek_func = data->set.seek_func;
06657   conn->seek_client = data->set.seek_client;
06658 
06659   /*************************************************************
06660    * Resolve the address of the server or proxy
06661    *************************************************************/
06662   result = resolve_server(data, conn, async);
06663 
06664   out:
06665 
06666   free(options);
06667   free(passwd);
06668   free(user);
06669   free(socksproxy);
06670   free(proxy);
06671   return result;
06672 }
06673 
06674 /* Curl_setup_conn() is called after the name resolve initiated in
06675  * create_conn() is all done.
06676  *
06677  * Curl_setup_conn() also handles reused connections
06678  *
06679  * conn->data MUST already have been setup fine (in create_conn)
06680  */
06681 
06682 CURLcode Curl_setup_conn(struct connectdata *conn,
06683                          bool *protocol_done)
06684 {
06685   CURLcode result = CURLE_OK;
06686   struct Curl_easy *data = conn->data;
06687 
06688   Curl_pgrsTime(data, TIMER_NAMELOOKUP);
06689 
06690   if(conn->handler->flags & PROTOPT_NONETWORK) {
06691     /* nothing to setup when not using a network */
06692     *protocol_done = TRUE;
06693     return result;
06694   }
06695   *protocol_done = FALSE; /* default to not done */
06696 
06697   /* set proxy_connect_closed to false unconditionally already here since it
06698      is used strictly to provide extra information to a parent function in the
06699      case of proxy CONNECT failures and we must make sure we don't have it
06700      lingering set from a previous invoke */
06701   conn->bits.proxy_connect_closed = FALSE;
06702 
06703   /*
06704    * Set user-agent. Used for HTTP, but since we can attempt to tunnel
06705    * basically anything through a http proxy we can't limit this based on
06706    * protocol.
06707    */
06708   if(data->set.str[STRING_USERAGENT]) {
06709     Curl_safefree(conn->allocptr.uagent);
06710     conn->allocptr.uagent =
06711       aprintf("User-Agent: %s\r\n", data->set.str[STRING_USERAGENT]);
06712     if(!conn->allocptr.uagent)
06713       return CURLE_OUT_OF_MEMORY;
06714   }
06715 
06716   data->req.headerbytecount = 0;
06717 
06718 #ifdef CURL_DO_LINEEND_CONV
06719   data->state.crlf_conversions = 0; /* reset CRLF conversion counter */
06720 #endif /* CURL_DO_LINEEND_CONV */
06721 
06722   /* set start time here for timeout purposes in the connect procedure, it
06723      is later set again for the progress meter purpose */
06724   conn->now = Curl_tvnow();
06725 
06726   if(CURL_SOCKET_BAD == conn->sock[FIRSTSOCKET]) {
06727     conn->bits.tcpconnect[FIRSTSOCKET] = FALSE;
06728     result = Curl_connecthost(conn, conn->dns_entry);
06729     if(result)
06730       return result;
06731   }
06732   else {
06733     Curl_pgrsTime(data, TIMER_CONNECT);    /* we're connected already */
06734     Curl_pgrsTime(data, TIMER_APPCONNECT); /* we're connected already */
06735     conn->bits.tcpconnect[FIRSTSOCKET] = TRUE;
06736     *protocol_done = TRUE;
06737     Curl_updateconninfo(conn, conn->sock[FIRSTSOCKET]);
06738     Curl_verboseconnect(conn);
06739   }
06740 
06741   conn->now = Curl_tvnow(); /* time this *after* the connect is done, we
06742                                set this here perhaps a second time */
06743 
06744 #ifdef __EMX__
06745   /*
06746    * This check is quite a hack. We're calling _fsetmode to fix the problem
06747    * with fwrite converting newline characters (you get mangled text files,
06748    * and corrupted binary files when you download to stdout and redirect it to
06749    * a file).
06750    */
06751 
06752   if((data->set.out)->_handle == NULL) {
06753     _fsetmode(stdout, "b");
06754   }
06755 #endif
06756 
06757   return result;
06758 }
06759 
06760 CURLcode Curl_connect(struct Curl_easy *data,
06761                       struct connectdata **in_connect,
06762                       bool *asyncp,
06763                       bool *protocol_done)
06764 {
06765   CURLcode result;
06766 
06767   *asyncp = FALSE; /* assume synchronous resolves by default */
06768 
06769   /* call the stuff that needs to be called */
06770   result = create_conn(data, in_connect, asyncp);
06771 
06772   if(!result) {
06773     /* no error */
06774     if((*in_connect)->send_pipe->size || (*in_connect)->recv_pipe->size)
06775       /* pipelining */
06776       *protocol_done = TRUE;
06777     else if(!*asyncp) {
06778       /* DNS resolution is done: that's either because this is a reused
06779          connection, in which case DNS was unnecessary, or because DNS
06780          really did finish already (synch resolver/fast async resolve) */
06781       result = Curl_setup_conn(*in_connect, protocol_done);
06782     }
06783   }
06784 
06785   if(result == CURLE_NO_CONNECTION_AVAILABLE) {
06786     *in_connect = NULL;
06787     return result;
06788   }
06789 
06790   if(result && *in_connect) {
06791     /* We're not allowed to return failure with memory left allocated
06792        in the connectdata struct, free those here */
06793     Curl_disconnect(*in_connect, FALSE); /* close the connection */
06794     *in_connect = NULL;           /* return a NULL */
06795   }
06796 
06797   return result;
06798 }
06799 
06800 /*
06801  * Curl_init_do() inits the readwrite session. This is inited each time (in
06802  * the DO function before the protocol-specific DO functions are invoked) for
06803  * a transfer, sometimes multiple times on the same Curl_easy. Make sure
06804  * nothing in here depends on stuff that are setup dynamically for the
06805  * transfer.
06806  *
06807  * Allow this function to get called with 'conn' set to NULL.
06808  */
06809 
06810 CURLcode Curl_init_do(struct Curl_easy *data, struct connectdata *conn)
06811 {
06812   struct SingleRequest *k = &data->req;
06813 
06814   if(conn)
06815     conn->bits.do_more = FALSE; /* by default there's no curl_do_more() to
06816                                  * use */
06817 
06818   data->state.done = FALSE; /* *_done() is not called yet */
06819   data->state.expect100header = FALSE;
06820 
06821   if(data->set.opt_no_body)
06822     /* in HTTP lingo, no body means using the HEAD request... */
06823     data->set.httpreq = HTTPREQ_HEAD;
06824   else if(HTTPREQ_HEAD == data->set.httpreq)
06825     /* ... but if unset there really is no perfect method that is the
06826        "opposite" of HEAD but in reality most people probably think GET
06827        then. The important thing is that we can't let it remain HEAD if the
06828        opt_no_body is set FALSE since then we'll behave wrong when getting
06829        HTTP. */
06830     data->set.httpreq = HTTPREQ_GET;
06831 
06832   k->start = Curl_tvnow(); /* start time */
06833   k->now = k->start;   /* current time is now */
06834   k->header = TRUE; /* assume header */
06835 
06836   k->bytecount = 0;
06837 
06838   k->buf = data->state.buffer;
06839   k->uploadbuf = data->state.uploadbuffer;
06840   k->hbufp = data->state.headerbuff;
06841   k->ignorebody=FALSE;
06842 
06843   Curl_speedinit(data);
06844 
06845   Curl_pgrsSetUploadCounter(data, 0);
06846   Curl_pgrsSetDownloadCounter(data, 0);
06847 
06848   return CURLE_OK;
06849 }
06850 
06851 /*
06852 * get_protocol_family()
06853 *
06854 * This is used to return the protocol family for a given protocol.
06855 *
06856 * Parameters:
06857 *
06858 * protocol  [in]  - A single bit protocol identifier such as HTTP or HTTPS.
06859 *
06860 * Returns the family as a single bit protocol identifier.
06861 */
06862 
06863 unsigned int get_protocol_family(unsigned int protocol)
06864 {
06865   unsigned int family;
06866 
06867   switch(protocol) {
06868   case CURLPROTO_HTTP:
06869   case CURLPROTO_HTTPS:
06870     family = CURLPROTO_HTTP;
06871     break;
06872 
06873   case CURLPROTO_FTP:
06874   case CURLPROTO_FTPS:
06875     family = CURLPROTO_FTP;
06876     break;
06877 
06878   case CURLPROTO_SCP:
06879     family = CURLPROTO_SCP;
06880     break;
06881 
06882   case CURLPROTO_SFTP:
06883     family = CURLPROTO_SFTP;
06884     break;
06885 
06886   case CURLPROTO_TELNET:
06887     family = CURLPROTO_TELNET;
06888     break;
06889 
06890   case CURLPROTO_LDAP:
06891   case CURLPROTO_LDAPS:
06892     family = CURLPROTO_LDAP;
06893     break;
06894 
06895   case CURLPROTO_DICT:
06896     family = CURLPROTO_DICT;
06897     break;
06898 
06899   case CURLPROTO_FILE:
06900     family = CURLPROTO_FILE;
06901     break;
06902 
06903   case CURLPROTO_TFTP:
06904     family = CURLPROTO_TFTP;
06905     break;
06906 
06907   case CURLPROTO_IMAP:
06908   case CURLPROTO_IMAPS:
06909     family = CURLPROTO_IMAP;
06910     break;
06911 
06912   case CURLPROTO_POP3:
06913   case CURLPROTO_POP3S:
06914     family = CURLPROTO_POP3;
06915     break;
06916 
06917   case CURLPROTO_SMTP:
06918   case CURLPROTO_SMTPS:
06919       family = CURLPROTO_SMTP;
06920       break;
06921 
06922   case CURLPROTO_RTSP:
06923     family = CURLPROTO_RTSP;
06924     break;
06925 
06926   case CURLPROTO_RTMP:
06927   case CURLPROTO_RTMPS:
06928     family = CURLPROTO_RTMP;
06929     break;
06930 
06931   case CURLPROTO_RTMPT:
06932   case CURLPROTO_RTMPTS:
06933     family = CURLPROTO_RTMPT;
06934     break;
06935 
06936   case CURLPROTO_RTMPE:
06937     family = CURLPROTO_RTMPE;
06938     break;
06939 
06940   case CURLPROTO_RTMPTE:
06941     family = CURLPROTO_RTMPTE;
06942     break;
06943 
06944   case CURLPROTO_GOPHER:
06945     family = CURLPROTO_GOPHER;
06946     break;
06947 
06948   case CURLPROTO_SMB:
06949   case CURLPROTO_SMBS:
06950     family = CURLPROTO_SMB;
06951     break;
06952 
06953   default:
06954       family = 0;
06955       break;
06956   }
06957 
06958   return family;
06959 }


rc_visard_driver
Author(s): Heiko Hirschmueller , Christian Emmerich , Felix Ruess
autogenerated on Thu Jun 6 2019 20:43:07