File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / curl / lib / url.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Jun 3 10:01:15 2020 UTC (4 years ago) by misho
Branches: curl, MAIN
CVS tags: v7_70_0p4, HEAD
curl

    1: /***************************************************************************
    2:  *                                  _   _ ____  _
    3:  *  Project                     ___| | | |  _ \| |
    4:  *                             / __| | | | |_) | |
    5:  *                            | (__| |_| |  _ <| |___
    6:  *                             \___|\___/|_| \_\_____|
    7:  *
    8:  * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
    9:  *
   10:  * This software is licensed as described in the file COPYING, which
   11:  * you should have received as part of this distribution. The terms
   12:  * are also available at https://curl.haxx.se/docs/copyright.html.
   13:  *
   14:  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
   15:  * copies of the Software, and permit persons to whom the Software is
   16:  * furnished to do so, under the terms of the COPYING file.
   17:  *
   18:  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
   19:  * KIND, either express or implied.
   20:  *
   21:  ***************************************************************************/
   22: 
   23: #include "curl_setup.h"
   24: 
   25: #ifdef HAVE_NETINET_IN_H
   26: #include <netinet/in.h>
   27: #endif
   28: #ifdef HAVE_NETDB_H
   29: #include <netdb.h>
   30: #endif
   31: #ifdef HAVE_ARPA_INET_H
   32: #include <arpa/inet.h>
   33: #endif
   34: #ifdef HAVE_NET_IF_H
   35: #include <net/if.h>
   36: #endif
   37: #ifdef HAVE_IPHLPAPI_H
   38: #include <Iphlpapi.h>
   39: #endif
   40: #ifdef HAVE_SYS_IOCTL_H
   41: #include <sys/ioctl.h>
   42: #endif
   43: #ifdef HAVE_SYS_PARAM_H
   44: #include <sys/param.h>
   45: #endif
   46: 
   47: #ifdef __VMS
   48: #include <in.h>
   49: #include <inet.h>
   50: #endif
   51: 
   52: #ifdef HAVE_SYS_UN_H
   53: #include <sys/un.h>
   54: #endif
   55: 
   56: #ifndef HAVE_SOCKET
   57: #error "We can't compile without socket() support!"
   58: #endif
   59: 
   60: #include <limits.h>
   61: 
   62: #ifdef USE_LIBIDN2
   63: #include <idn2.h>
   64: 
   65: #elif defined(USE_WIN32_IDN)
   66: /* prototype for curl_win32_idn_to_ascii() */
   67: bool curl_win32_idn_to_ascii(const char *in, char **out);
   68: #endif  /* USE_LIBIDN2 */
   69: 
   70: #include "urldata.h"
   71: #include "netrc.h"
   72: 
   73: #include "formdata.h"
   74: #include "mime.h"
   75: #include "vtls/vtls.h"
   76: #include "hostip.h"
   77: #include "transfer.h"
   78: #include "sendf.h"
   79: #include "progress.h"
   80: #include "cookie.h"
   81: #include "strcase.h"
   82: #include "strerror.h"
   83: #include "escape.h"
   84: #include "strtok.h"
   85: #include "share.h"
   86: #include "content_encoding.h"
   87: #include "http_digest.h"
   88: #include "http_negotiate.h"
   89: #include "select.h"
   90: #include "multiif.h"
   91: #include "easyif.h"
   92: #include "speedcheck.h"
   93: #include "warnless.h"
   94: #include "non-ascii.h"
   95: #include "inet_pton.h"
   96: #include "getinfo.h"
   97: #include "urlapi-int.h"
   98: #include "system_win32.h"
   99: 
  100: /* And now for the protocols */
  101: #include "ftp.h"
  102: #include "dict.h"
  103: #include "telnet.h"
  104: #include "tftp.h"
  105: #include "http.h"
  106: #include "http2.h"
  107: #include "file.h"
  108: #include "curl_ldap.h"
  109: #include "vssh/ssh.h"
  110: #include "imap.h"
  111: #include "url.h"
  112: #include "connect.h"
  113: #include "inet_ntop.h"
  114: #include "http_ntlm.h"
  115: #include "curl_rtmp.h"
  116: #include "gopher.h"
  117: #include "mqtt.h"
  118: #include "http_proxy.h"
  119: #include "conncache.h"
  120: #include "multihandle.h"
  121: #include "dotdot.h"
  122: #include "strdup.h"
  123: #include "setopt.h"
  124: #include "altsvc.h"
  125: 
  126: /* The last 3 #include files should be in this order */
  127: #include "curl_printf.h"
  128: #include "curl_memory.h"
  129: #include "memdebug.h"
  130: 
  131: static void conn_free(struct connectdata *conn);
  132: static unsigned int get_protocol_family(unsigned int protocol);
  133: 
  134: /* Some parts of the code (e.g. chunked encoding) assume this buffer has at
  135:  * more than just a few bytes to play with. Don't let it become too small or
  136:  * bad things will happen.
  137:  */
  138: #if READBUFFER_SIZE < READBUFFER_MIN
  139: # error READBUFFER_SIZE is too small
  140: #endif
  141: 
  142: 
  143: /*
  144:  * Protocol table.
  145:  */
  146: 
  147: static const struct Curl_handler * const protocols[] = {
  148: 
  149: #ifndef CURL_DISABLE_HTTP
  150:   &Curl_handler_http,
  151: #endif
  152: 
  153: #if defined(USE_SSL) && !defined(CURL_DISABLE_HTTP)
  154:   &Curl_handler_https,
  155: #endif
  156: 
  157: #ifndef CURL_DISABLE_FTP
  158:   &Curl_handler_ftp,
  159: #endif
  160: 
  161: #if defined(USE_SSL) && !defined(CURL_DISABLE_FTP)
  162:   &Curl_handler_ftps,
  163: #endif
  164: 
  165: #ifndef CURL_DISABLE_TELNET
  166:   &Curl_handler_telnet,
  167: #endif
  168: 
  169: #ifndef CURL_DISABLE_DICT
  170:   &Curl_handler_dict,
  171: #endif
  172: 
  173: #ifndef CURL_DISABLE_LDAP
  174:   &Curl_handler_ldap,
  175: #if !defined(CURL_DISABLE_LDAPS) && \
  176:     ((defined(USE_OPENLDAP) && defined(USE_SSL)) || \
  177:      (!defined(USE_OPENLDAP) && defined(HAVE_LDAP_SSL)))
  178:   &Curl_handler_ldaps,
  179: #endif
  180: #endif
  181: 
  182: #ifndef CURL_DISABLE_FILE
  183:   &Curl_handler_file,
  184: #endif
  185: 
  186: #ifndef CURL_DISABLE_TFTP
  187:   &Curl_handler_tftp,
  188: #endif
  189: 
  190: #if defined(USE_SSH) && !defined(USE_WOLFSSH)
  191:   &Curl_handler_scp,
  192: #endif
  193: 
  194: #if defined(USE_SSH)
  195:   &Curl_handler_sftp,
  196: #endif
  197: 
  198: #ifndef CURL_DISABLE_IMAP
  199:   &Curl_handler_imap,
  200: #ifdef USE_SSL
  201:   &Curl_handler_imaps,
  202: #endif
  203: #endif
  204: 
  205: #ifndef CURL_DISABLE_POP3
  206:   &Curl_handler_pop3,
  207: #ifdef USE_SSL
  208:   &Curl_handler_pop3s,
  209: #endif
  210: #endif
  211: 
  212: #if !defined(CURL_DISABLE_SMB) && defined(USE_NTLM) && \
  213:    (CURL_SIZEOF_CURL_OFF_T > 4) && \
  214:    (!defined(USE_WINDOWS_SSPI) || defined(USE_WIN32_CRYPTO))
  215:   &Curl_handler_smb,
  216: #ifdef USE_SSL
  217:   &Curl_handler_smbs,
  218: #endif
  219: #endif
  220: 
  221: #ifndef CURL_DISABLE_SMTP
  222:   &Curl_handler_smtp,
  223: #ifdef USE_SSL
  224:   &Curl_handler_smtps,
  225: #endif
  226: #endif
  227: 
  228: #ifndef CURL_DISABLE_RTSP
  229:   &Curl_handler_rtsp,
  230: #endif
  231: 
  232: #ifndef CURL_DISABLE_GOPHER
  233:   &Curl_handler_gopher,
  234: #endif
  235: 
  236: #ifdef CURL_ENABLE_MQTT
  237:   &Curl_handler_mqtt,
  238: #endif
  239: 
  240: #ifdef USE_LIBRTMP
  241:   &Curl_handler_rtmp,
  242:   &Curl_handler_rtmpt,
  243:   &Curl_handler_rtmpe,
  244:   &Curl_handler_rtmpte,
  245:   &Curl_handler_rtmps,
  246:   &Curl_handler_rtmpts,
  247: #endif
  248: 
  249:   (struct Curl_handler *) NULL
  250: };
  251: 
  252: /*
  253:  * Dummy handler for undefined protocol schemes.
  254:  */
  255: 
  256: static const struct Curl_handler Curl_handler_dummy = {
  257:   "<no protocol>",                      /* scheme */
  258:   ZERO_NULL,                            /* setup_connection */
  259:   ZERO_NULL,                            /* do_it */
  260:   ZERO_NULL,                            /* done */
  261:   ZERO_NULL,                            /* do_more */
  262:   ZERO_NULL,                            /* connect_it */
  263:   ZERO_NULL,                            /* connecting */
  264:   ZERO_NULL,                            /* doing */
  265:   ZERO_NULL,                            /* proto_getsock */
  266:   ZERO_NULL,                            /* doing_getsock */
  267:   ZERO_NULL,                            /* domore_getsock */
  268:   ZERO_NULL,                            /* perform_getsock */
  269:   ZERO_NULL,                            /* disconnect */
  270:   ZERO_NULL,                            /* readwrite */
  271:   ZERO_NULL,                            /* connection_check */
  272:   0,                                    /* defport */
  273:   0,                                    /* protocol */
  274:   PROTOPT_NONE                          /* flags */
  275: };
  276: 
  277: void Curl_freeset(struct Curl_easy *data)
  278: {
  279:   /* Free all dynamic strings stored in the data->set substructure. */
  280:   enum dupstring i;
  281:   for(i = (enum dupstring)0; i < STRING_LAST; i++) {
  282:     Curl_safefree(data->set.str[i]);
  283:   }
  284: 
  285:   if(data->change.referer_alloc) {
  286:     Curl_safefree(data->change.referer);
  287:     data->change.referer_alloc = FALSE;
  288:   }
  289:   data->change.referer = NULL;
  290:   if(data->change.url_alloc) {
  291:     Curl_safefree(data->change.url);
  292:     data->change.url_alloc = FALSE;
  293:   }
  294:   data->change.url = NULL;
  295: 
  296:   Curl_mime_cleanpart(&data->set.mimepost);
  297: }
  298: 
  299: /* free the URL pieces */
  300: static void up_free(struct Curl_easy *data)
  301: {
  302:   struct urlpieces *up = &data->state.up;
  303:   Curl_safefree(up->scheme);
  304:   Curl_safefree(up->hostname);
  305:   Curl_safefree(up->port);
  306:   Curl_safefree(up->user);
  307:   Curl_safefree(up->password);
  308:   Curl_safefree(up->options);
  309:   Curl_safefree(up->path);
  310:   Curl_safefree(up->query);
  311:   curl_url_cleanup(data->state.uh);
  312:   data->state.uh = NULL;
  313: }
  314: 
  315: /*
  316:  * This is the internal function curl_easy_cleanup() calls. This should
  317:  * cleanup and free all resources associated with this sessionhandle.
  318:  *
  319:  * NOTE: if we ever add something that attempts to write to a socket or
  320:  * similar here, we must ignore SIGPIPE first. It is currently only done
  321:  * when curl_easy_perform() is invoked.
  322:  */
  323: 
  324: CURLcode Curl_close(struct Curl_easy **datap)
  325: {
  326:   struct Curl_multi *m;
  327:   struct Curl_easy *data;
  328: 
  329:   if(!datap || !*datap)
  330:     return CURLE_OK;
  331: 
  332:   data = *datap;
  333:   *datap = NULL;
  334: 
  335:   Curl_expire_clear(data); /* shut off timers */
  336: 
  337:   m = data->multi;
  338:   if(m)
  339:     /* This handle is still part of a multi handle, take care of this first
  340:        and detach this handle from there. */
  341:     curl_multi_remove_handle(data->multi, data);
  342: 
  343:   if(data->multi_easy) {
  344:     /* when curl_easy_perform() is used, it creates its own multi handle to
  345:        use and this is the one */
  346:     curl_multi_cleanup(data->multi_easy);
  347:     data->multi_easy = NULL;
  348:   }
  349: 
  350:   /* Destroy the timeout list that is held in the easy handle. It is
  351:      /normally/ done by curl_multi_remove_handle() but this is "just in
  352:      case" */
  353:   Curl_llist_destroy(&data->state.timeoutlist, NULL);
  354: 
  355:   data->magic = 0; /* force a clear AFTER the possibly enforced removal from
  356:                       the multi handle, since that function uses the magic
  357:                       field! */
  358: 
  359:   if(data->state.rangestringalloc)
  360:     free(data->state.range);
  361: 
  362:   /* freed here just in case DONE wasn't called */
  363:   Curl_free_request_state(data);
  364: 
  365:   /* Close down all open SSL info and sessions */
  366:   Curl_ssl_close_all(data);
  367:   Curl_safefree(data->state.first_host);
  368:   Curl_safefree(data->state.scratch);
  369:   Curl_ssl_free_certinfo(data);
  370: 
  371:   /* Cleanup possible redirect junk */
  372:   free(data->req.newurl);
  373:   data->req.newurl = NULL;
  374: 
  375:   if(data->change.referer_alloc) {
  376:     Curl_safefree(data->change.referer);
  377:     data->change.referer_alloc = FALSE;
  378:   }
  379:   data->change.referer = NULL;
  380: 
  381:   up_free(data);
  382:   Curl_safefree(data->state.buffer);
  383:   Curl_safefree(data->state.headerbuff);
  384:   Curl_safefree(data->state.ulbuf);
  385:   Curl_flush_cookies(data, TRUE);
  386: #ifdef USE_ALTSVC
  387:   Curl_altsvc_save(data, data->asi, data->set.str[STRING_ALTSVC]);
  388:   Curl_altsvc_cleanup(data->asi);
  389:   data->asi = NULL;
  390: #endif
  391: #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_CRYPTO_AUTH)
  392:   Curl_http_auth_cleanup_digest(data);
  393: #endif
  394:   Curl_safefree(data->info.contenttype);
  395:   Curl_safefree(data->info.wouldredirect);
  396: 
  397:   /* this destroys the channel and we cannot use it anymore after this */
  398:   Curl_resolver_cleanup(data->state.resolver);
  399: 
  400:   Curl_http2_cleanup_dependencies(data);
  401:   Curl_convert_close(data);
  402: 
  403:   /* No longer a dirty share, if it exists */
  404:   if(data->share) {
  405:     Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
  406:     data->share->dirty--;
  407:     Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
  408:   }
  409: 
  410: #ifndef CURL_DISABLE_DOH
  411:   free(data->req.doh.probe[0].serverdoh.memory);
  412:   free(data->req.doh.probe[1].serverdoh.memory);
  413:   curl_slist_free_all(data->req.doh.headers);
  414: #endif
  415: 
  416:   /* destruct wildcard structures if it is needed */
  417:   Curl_wildcard_dtor(&data->wildcard);
  418:   Curl_freeset(data);
  419:   free(data);
  420:   return CURLE_OK;
  421: }
  422: 
  423: /*
  424:  * Initialize the UserDefined fields within a Curl_easy.
  425:  * This may be safely called on a new or existing Curl_easy.
  426:  */
  427: CURLcode Curl_init_userdefined(struct Curl_easy *data)
  428: {
  429:   struct UserDefined *set = &data->set;
  430:   CURLcode result = CURLE_OK;
  431: 
  432:   set->out = stdout; /* default output to stdout */
  433:   set->in_set = stdin;  /* default input from stdin */
  434:   set->err  = stderr;  /* default stderr to stderr */
  435: 
  436:   /* use fwrite as default function to store output */
  437:   set->fwrite_func = (curl_write_callback)fwrite;
  438: 
  439:   /* use fread as default function to read input */
  440:   set->fread_func_set = (curl_read_callback)fread;
  441:   set->is_fread_set = 0;
  442:   set->is_fwrite_set = 0;
  443: 
  444:   set->seek_func = ZERO_NULL;
  445:   set->seek_client = ZERO_NULL;
  446: 
  447:   /* conversion callbacks for non-ASCII hosts */
  448:   set->convfromnetwork = ZERO_NULL;
  449:   set->convtonetwork   = ZERO_NULL;
  450:   set->convfromutf8    = ZERO_NULL;
  451: 
  452:   set->filesize = -1;        /* we don't know the size */
  453:   set->postfieldsize = -1;   /* unknown size */
  454:   set->maxredirs = -1;       /* allow any amount by default */
  455: 
  456:   set->httpreq = HTTPREQ_GET; /* Default HTTP request */
  457:   set->rtspreq = RTSPREQ_OPTIONS; /* Default RTSP request */
  458: #ifndef CURL_DISABLE_FTP
  459:   set->ftp_use_epsv = TRUE;   /* FTP defaults to EPSV operations */
  460:   set->ftp_use_eprt = TRUE;   /* FTP defaults to EPRT operations */
  461:   set->ftp_use_pret = FALSE;  /* mainly useful for drftpd servers */
  462:   set->ftp_filemethod = FTPFILE_MULTICWD;
  463: #endif
  464:   set->dns_cache_timeout = 60; /* Timeout every 60 seconds by default */
  465: 
  466:   /* Set the default size of the SSL session ID cache */
  467:   set->general_ssl.max_ssl_sessions = 5;
  468: 
  469:   set->proxyport = 0;
  470:   set->proxytype = CURLPROXY_HTTP; /* defaults to HTTP proxy */
  471:   set->httpauth = CURLAUTH_BASIC;  /* defaults to basic */
  472:   set->proxyauth = CURLAUTH_BASIC; /* defaults to basic */
  473: 
  474:   /* SOCKS5 proxy auth defaults to username/password + GSS-API */
  475:   set->socks5auth = CURLAUTH_BASIC | CURLAUTH_GSSAPI;
  476: 
  477:   /* make libcurl quiet by default: */
  478:   set->hide_progress = TRUE;  /* CURLOPT_NOPROGRESS changes these */
  479: 
  480:   Curl_mime_initpart(&set->mimepost, data);
  481: 
  482:   /*
  483:    * libcurl 7.10 introduced SSL verification *by default*! This needs to be
  484:    * switched off unless wanted.
  485:    */
  486:   set->ssl.primary.verifypeer = TRUE;
  487:   set->ssl.primary.verifyhost = TRUE;
  488: #ifdef USE_TLS_SRP
  489:   set->ssl.authtype = CURL_TLSAUTH_NONE;
  490: #endif
  491:   set->ssh_auth_types = CURLSSH_AUTH_DEFAULT; /* defaults to any auth
  492:                                                       type */
  493:   set->ssl.primary.sessionid = TRUE; /* session ID caching enabled by
  494:                                         default */
  495:   set->proxy_ssl = set->ssl;
  496: 
  497:   set->new_file_perms = 0644;    /* Default permissions */
  498:   set->new_directory_perms = 0755; /* Default permissions */
  499: 
  500:   /* for the *protocols fields we don't use the CURLPROTO_ALL convenience
  501:      define since we internally only use the lower 16 bits for the passed
  502:      in bitmask to not conflict with the private bits */
  503:   set->allowed_protocols = CURLPROTO_ALL;
  504:   set->redir_protocols = CURLPROTO_HTTP | CURLPROTO_HTTPS | CURLPROTO_FTP |
  505:                          CURLPROTO_FTPS;
  506: 
  507: #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
  508:   /*
  509:    * disallow unprotected protection negotiation NEC reference implementation
  510:    * seem not to follow rfc1961 section 4.3/4.4
  511:    */
  512:   set->socks5_gssapi_nec = FALSE;
  513: #endif
  514: 
  515:   /* Set the default CA cert bundle/path detected/specified at build time.
  516:    *
  517:    * If Schannel is the selected SSL backend then these locations are
  518:    * ignored. We allow setting CA location for schannel only when explicitly
  519:    * specified by the user via CURLOPT_CAINFO / --cacert.
  520:    */
  521:   if(Curl_ssl_backend() != CURLSSLBACKEND_SCHANNEL) {
  522: #if defined(CURL_CA_BUNDLE)
  523:     result = Curl_setstropt(&set->str[STRING_SSL_CAFILE_ORIG], CURL_CA_BUNDLE);
  524:     if(result)
  525:       return result;
  526: 
  527:     result = Curl_setstropt(&set->str[STRING_SSL_CAFILE_PROXY],
  528:                             CURL_CA_BUNDLE);
  529:     if(result)
  530:       return result;
  531: #endif
  532: #if defined(CURL_CA_PATH)
  533:     result = Curl_setstropt(&set->str[STRING_SSL_CAPATH_ORIG], CURL_CA_PATH);
  534:     if(result)
  535:       return result;
  536: 
  537:     result = Curl_setstropt(&set->str[STRING_SSL_CAPATH_PROXY], CURL_CA_PATH);
  538:     if(result)
  539:       return result;
  540: #endif
  541:   }
  542: 
  543:   set->wildcard_enabled = FALSE;
  544:   set->chunk_bgn      = ZERO_NULL;
  545:   set->chunk_end      = ZERO_NULL;
  546:   set->tcp_keepalive = FALSE;
  547:   set->tcp_keepintvl = 60;
  548:   set->tcp_keepidle = 60;
  549:   set->tcp_fastopen = FALSE;
  550:   set->tcp_nodelay = TRUE;
  551:   set->ssl_enable_npn = TRUE;
  552:   set->ssl_enable_alpn = TRUE;
  553:   set->expect_100_timeout = 1000L; /* Wait for a second by default. */
  554:   set->sep_headers = TRUE; /* separated header lists by default */
  555:   set->buffer_size = READBUFFER_SIZE;
  556:   set->upload_buffer_size = UPLOADBUFFER_DEFAULT;
  557:   set->happy_eyeballs_timeout = CURL_HET_DEFAULT;
  558:   set->fnmatch = ZERO_NULL;
  559:   set->upkeep_interval_ms = CURL_UPKEEP_INTERVAL_DEFAULT;
  560:   set->maxconnects = DEFAULT_CONNCACHE_SIZE; /* for easy handles */
  561:   set->maxage_conn = 118;
  562:   set->http09_allowed = FALSE;
  563:   set->httpversion =
  564: #ifdef USE_NGHTTP2
  565:     CURL_HTTP_VERSION_2TLS
  566: #else
  567:     CURL_HTTP_VERSION_1_1
  568: #endif
  569:     ;
  570: #if defined(__FreeBSD_version)
  571:   /* different handling of signals and threads */
  572:   set->no_signal = TRUE;
  573: #endif
  574:   Curl_http2_init_userset(set);
  575:   return result;
  576: }
  577: 
  578: /**
  579:  * Curl_open()
  580:  *
  581:  * @param curl is a pointer to a sessionhandle pointer that gets set by this
  582:  * function.
  583:  * @return CURLcode
  584:  */
  585: 
  586: CURLcode Curl_open(struct Curl_easy **curl)
  587: {
  588:   CURLcode result;
  589:   struct Curl_easy *data;
  590: 
  591:   /* Very simple start-up: alloc the struct, init it with zeroes and return */
  592:   data = calloc(1, sizeof(struct Curl_easy));
  593:   if(!data) {
  594:     /* this is a very serious error */
  595:     DEBUGF(fprintf(stderr, "Error: calloc of Curl_easy failed\n"));
  596:     return CURLE_OUT_OF_MEMORY;
  597:   }
  598: 
  599:   data->magic = CURLEASY_MAGIC_NUMBER;
  600: 
  601:   result = Curl_resolver_init(data, &data->state.resolver);
  602:   if(result) {
  603:     DEBUGF(fprintf(stderr, "Error: resolver_init failed\n"));
  604:     free(data);
  605:     return result;
  606:   }
  607: 
  608:   /* We do some initial setup here, all those fields that can't be just 0 */
  609: 
  610:   data->state.buffer = malloc(READBUFFER_SIZE + 1);
  611:   if(!data->state.buffer) {
  612:     DEBUGF(fprintf(stderr, "Error: malloc of buffer failed\n"));
  613:     result = CURLE_OUT_OF_MEMORY;
  614:   }
  615:   else {
  616:     data->state.headerbuff = malloc(HEADERSIZE);
  617:     if(!data->state.headerbuff) {
  618:       DEBUGF(fprintf(stderr, "Error: malloc of headerbuff failed\n"));
  619:       result = CURLE_OUT_OF_MEMORY;
  620:     }
  621:     else {
  622:       result = Curl_init_userdefined(data);
  623: 
  624:       data->state.headersize = HEADERSIZE;
  625:       Curl_convert_init(data);
  626:       Curl_initinfo(data);
  627: 
  628:       /* most recent connection is not yet defined */
  629:       data->state.lastconnect = NULL;
  630: 
  631:       data->progress.flags |= PGRS_HIDE;
  632:       data->state.current_speed = -1; /* init to negative == impossible */
  633:     }
  634:   }
  635: 
  636:   if(result) {
  637:     Curl_resolver_cleanup(data->state.resolver);
  638:     free(data->state.buffer);
  639:     free(data->state.headerbuff);
  640:     Curl_freeset(data);
  641:     free(data);
  642:     data = NULL;
  643:   }
  644:   else
  645:     *curl = data;
  646: 
  647:   return result;
  648: }
  649: 
  650: #ifdef USE_RECV_BEFORE_SEND_WORKAROUND
  651: static void conn_reset_postponed_data(struct connectdata *conn, int num)
  652: {
  653:   struct postponed_data * const psnd = &(conn->postponed[num]);
  654:   if(psnd->buffer) {
  655:     DEBUGASSERT(psnd->allocated_size > 0);
  656:     DEBUGASSERT(psnd->recv_size <= psnd->allocated_size);
  657:     DEBUGASSERT(psnd->recv_size ?
  658:                 (psnd->recv_processed < psnd->recv_size) :
  659:                 (psnd->recv_processed == 0));
  660:     DEBUGASSERT(psnd->bindsock != CURL_SOCKET_BAD);
  661:     free(psnd->buffer);
  662:     psnd->buffer = NULL;
  663:     psnd->allocated_size = 0;
  664:     psnd->recv_size = 0;
  665:     psnd->recv_processed = 0;
  666: #ifdef DEBUGBUILD
  667:     psnd->bindsock = CURL_SOCKET_BAD; /* used only for DEBUGASSERT */
  668: #endif /* DEBUGBUILD */
  669:   }
  670:   else {
  671:     DEBUGASSERT(psnd->allocated_size == 0);
  672:     DEBUGASSERT(psnd->recv_size == 0);
  673:     DEBUGASSERT(psnd->recv_processed == 0);
  674:     DEBUGASSERT(psnd->bindsock == CURL_SOCKET_BAD);
  675:   }
  676: }
  677: 
  678: static void conn_reset_all_postponed_data(struct connectdata *conn)
  679: {
  680:   conn_reset_postponed_data(conn, 0);
  681:   conn_reset_postponed_data(conn, 1);
  682: }
  683: #else  /* ! USE_RECV_BEFORE_SEND_WORKAROUND */
  684: /* Use "do-nothing" macro instead of function when workaround not used */
  685: #define conn_reset_all_postponed_data(c) do {} while(0)
  686: #endif /* ! USE_RECV_BEFORE_SEND_WORKAROUND */
  687: 
  688: 
  689: static void conn_shutdown(struct connectdata *conn)
  690: {
  691:   if(!conn)
  692:     return;
  693: 
  694:   infof(conn->data, "Closing connection %ld\n", conn->connection_id);
  695:   DEBUGASSERT(conn->data);
  696: 
  697:   /* possible left-overs from the async name resolvers */
  698:   Curl_resolver_cancel(conn);
  699: 
  700:   /* close the SSL stuff before we close any sockets since they will/may
  701:      write to the sockets */
  702:   Curl_ssl_close(conn, FIRSTSOCKET);
  703:   Curl_ssl_close(conn, SECONDARYSOCKET);
  704: 
  705:   /* close possibly still open sockets */
  706:   if(CURL_SOCKET_BAD != conn->sock[SECONDARYSOCKET])
  707:     Curl_closesocket(conn, conn->sock[SECONDARYSOCKET]);
  708:   if(CURL_SOCKET_BAD != conn->sock[FIRSTSOCKET])
  709:     Curl_closesocket(conn, conn->sock[FIRSTSOCKET]);
  710:   if(CURL_SOCKET_BAD != conn->tempsock[0])
  711:     Curl_closesocket(conn, conn->tempsock[0]);
  712:   if(CURL_SOCKET_BAD != conn->tempsock[1])
  713:     Curl_closesocket(conn, conn->tempsock[1]);
  714: 
  715:   /* unlink ourselves. this should be called last since other shutdown
  716:      procedures need a valid conn->data and this may clear it. */
  717:   Curl_conncache_remove_conn(conn->data, conn, TRUE);
  718: }
  719: 
  720: static void conn_free(struct connectdata *conn)
  721: {
  722:   if(!conn)
  723:     return;
  724: 
  725:   Curl_free_idnconverted_hostname(&conn->host);
  726:   Curl_free_idnconverted_hostname(&conn->conn_to_host);
  727:   Curl_free_idnconverted_hostname(&conn->http_proxy.host);
  728:   Curl_free_idnconverted_hostname(&conn->socks_proxy.host);
  729: 
  730:   Curl_safefree(conn->user);
  731:   Curl_safefree(conn->passwd);
  732:   Curl_safefree(conn->sasl_authzid);
  733:   Curl_safefree(conn->options);
  734:   Curl_safefree(conn->http_proxy.user);
  735:   Curl_safefree(conn->socks_proxy.user);
  736:   Curl_safefree(conn->http_proxy.passwd);
  737:   Curl_safefree(conn->socks_proxy.passwd);
  738:   Curl_safefree(conn->allocptr.proxyuserpwd);
  739:   Curl_safefree(conn->allocptr.uagent);
  740:   Curl_safefree(conn->allocptr.userpwd);
  741:   Curl_safefree(conn->allocptr.accept_encoding);
  742:   Curl_safefree(conn->allocptr.te);
  743:   Curl_safefree(conn->allocptr.rangeline);
  744:   Curl_safefree(conn->allocptr.ref);
  745:   Curl_safefree(conn->allocptr.host);
  746:   Curl_safefree(conn->allocptr.cookiehost);
  747:   Curl_safefree(conn->allocptr.rtsp_transport);
  748:   Curl_safefree(conn->trailer);
  749:   Curl_safefree(conn->host.rawalloc); /* host name buffer */
  750:   Curl_safefree(conn->conn_to_host.rawalloc); /* host name buffer */
  751:   Curl_safefree(conn->hostname_resolve);
  752:   Curl_safefree(conn->secondaryhostname);
  753:   Curl_safefree(conn->http_proxy.host.rawalloc); /* http proxy name buffer */
  754:   Curl_safefree(conn->socks_proxy.host.rawalloc); /* socks proxy name buffer */
  755:   Curl_safefree(conn->connect_state);
  756: 
  757:   conn_reset_all_postponed_data(conn);
  758:   Curl_llist_destroy(&conn->easyq, NULL);
  759:   Curl_safefree(conn->localdev);
  760:   Curl_free_primary_ssl_config(&conn->ssl_config);
  761:   Curl_free_primary_ssl_config(&conn->proxy_ssl_config);
  762: 
  763: #ifdef USE_UNIX_SOCKETS
  764:   Curl_safefree(conn->unix_domain_socket);
  765: #endif
  766: 
  767: #ifdef USE_SSL
  768:   Curl_safefree(conn->ssl_extra);
  769: #endif
  770:   free(conn); /* free all the connection oriented data */
  771: }
  772: 
  773: /*
  774:  * Disconnects the given connection. Note the connection may not be the
  775:  * primary connection, like when freeing room in the connection cache or
  776:  * killing of a dead old connection.
  777:  *
  778:  * A connection needs an easy handle when closing down. We support this passed
  779:  * in separately since the connection to get closed here is often already
  780:  * disassociated from an easy handle.
  781:  *
  782:  * This function MUST NOT reset state in the Curl_easy struct if that
  783:  * isn't strictly bound to the life-time of *this* particular connection.
  784:  *
  785:  */
  786: 
  787: CURLcode Curl_disconnect(struct Curl_easy *data,
  788:                          struct connectdata *conn, bool dead_connection)
  789: {
  790:   if(!conn)
  791:     return CURLE_OK; /* this is closed and fine already */
  792: 
  793:   if(!data) {
  794:     DEBUGF(infof(data, "DISCONNECT without easy handle, ignoring\n"));
  795:     return CURLE_OK;
  796:   }
  797: 
  798:   /*
  799:    * If this connection isn't marked to force-close, leave it open if there
  800:    * are other users of it
  801:    */
  802:   if(CONN_INUSE(conn) && !dead_connection) {
  803:     DEBUGF(infof(data, "Curl_disconnect when inuse: %zu\n", CONN_INUSE(conn)));
  804:     return CURLE_OK;
  805:   }
  806: 
  807:   if(conn->dns_entry != NULL) {
  808:     Curl_resolv_unlock(data, conn->dns_entry);
  809:     conn->dns_entry = NULL;
  810:   }
  811: 
  812:   Curl_hostcache_prune(data); /* kill old DNS cache entries */
  813: 
  814: #if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM)
  815:   /* Cleanup NTLM connection-related data */
  816:   Curl_http_auth_cleanup_ntlm(conn);
  817: #endif
  818: #if !defined(CURL_DISABLE_HTTP) && defined(USE_SPNEGO)
  819:   /* Cleanup NEGOTIATE connection-related data */
  820:   Curl_http_auth_cleanup_negotiate(conn);
  821: #endif
  822: 
  823:   /* the protocol specific disconnect handler and conn_shutdown need a transfer
  824:      for the connection! */
  825:   conn->data = data;
  826: 
  827:   if(conn->bits.connect_only)
  828:     /* treat the connection as dead in CONNECT_ONLY situations */
  829:     dead_connection = TRUE;
  830: 
  831:   if(conn->handler->disconnect)
  832:     /* This is set if protocol-specific cleanups should be made */
  833:     conn->handler->disconnect(conn, dead_connection);
  834: 
  835:   conn_shutdown(conn);
  836:   conn_free(conn);
  837:   return CURLE_OK;
  838: }
  839: 
  840: /*
  841:  * This function should return TRUE if the socket is to be assumed to
  842:  * be dead. Most commonly this happens when the server has closed the
  843:  * connection due to inactivity.
  844:  */
  845: static bool SocketIsDead(curl_socket_t sock)
  846: {
  847:   int sval;
  848:   bool ret_val = TRUE;
  849: 
  850:   sval = SOCKET_READABLE(sock, 0);
  851:   if(sval == 0)
  852:     /* timeout */
  853:     ret_val = FALSE;
  854: 
  855:   return ret_val;
  856: }
  857: 
  858: /*
  859:  * IsMultiplexingPossible()
  860:  *
  861:  * Return a bitmask with the available multiplexing options for the given
  862:  * requested connection.
  863:  */
  864: static int IsMultiplexingPossible(const struct Curl_easy *handle,
  865:                                   const struct connectdata *conn)
  866: {
  867:   int avail = 0;
  868: 
  869:   /* If a HTTP protocol and multiplexing is enabled */
  870:   if((conn->handler->protocol & PROTO_FAMILY_HTTP) &&
  871:      (!conn->bits.protoconnstart || !conn->bits.close)) {
  872: 
  873:     if(Curl_multiplex_wanted(handle->multi) &&
  874:        (handle->set.httpversion >= CURL_HTTP_VERSION_2))
  875:       /* allows HTTP/2 */
  876:       avail |= CURLPIPE_MULTIPLEX;
  877:   }
  878:   return avail;
  879: }
  880: 
  881: #ifndef CURL_DISABLE_PROXY
  882: static bool
  883: proxy_info_matches(const struct proxy_info* data,
  884:                    const struct proxy_info* needle)
  885: {
  886:   if((data->proxytype == needle->proxytype) &&
  887:      (data->port == needle->port) &&
  888:      Curl_safe_strcasecompare(data->host.name, needle->host.name))
  889:     return TRUE;
  890: 
  891:   return FALSE;
  892: }
  893: 
  894: static bool
  895: socks_proxy_info_matches(const struct proxy_info* data,
  896:                          const struct proxy_info* needle)
  897: {
  898:   if(!proxy_info_matches(data, needle))
  899:     return FALSE;
  900: 
  901:   /* the user information is case-sensitive
  902:      or at least it is not defined as case-insensitive
  903:      see https://tools.ietf.org/html/rfc3986#section-3.2.1 */
  904:   if((data->user == NULL) != (needle->user == NULL))
  905:     return FALSE;
  906:   /* curl_strequal does a case insentive comparison, so do not use it here! */
  907:   if(data->user &&
  908:      needle->user &&
  909:      strcmp(data->user, needle->user) != 0)
  910:     return FALSE;
  911:   if((data->passwd == NULL) != (needle->passwd == NULL))
  912:     return FALSE;
  913:   /* curl_strequal does a case insentive comparison, so do not use it here! */
  914:   if(data->passwd &&
  915:      needle->passwd &&
  916:      strcmp(data->passwd, needle->passwd) != 0)
  917:     return FALSE;
  918:   return TRUE;
  919: }
  920: #else
  921: /* disabled, won't get called */
  922: #define proxy_info_matches(x,y) FALSE
  923: #define socks_proxy_info_matches(x,y) FALSE
  924: #endif
  925: 
  926: /* A connection has to have been idle for a shorter time than 'maxage_conn' to
  927:    be subject for reuse. The success rate is just too low after this. */
  928: 
  929: static bool conn_maxage(struct Curl_easy *data,
  930:                         struct connectdata *conn,
  931:                         struct curltime now)
  932: {
  933:   if(!conn->data) {
  934:     timediff_t idletime = Curl_timediff(now, conn->lastused);
  935:     idletime /= 1000; /* integer seconds is fine */
  936: 
  937:     if(idletime > data->set.maxage_conn) {
  938:       infof(data, "Too old connection (%ld seconds), disconnect it\n",
  939:             idletime);
  940:       return TRUE;
  941:     }
  942:   }
  943:   return FALSE;
  944: }
  945: 
  946: /*
  947:  * This function checks if the given connection is dead and extracts it from
  948:  * the connection cache if so.
  949:  *
  950:  * When this is called as a Curl_conncache_foreach() callback, the connection
  951:  * cache lock is held!
  952:  *
  953:  * Returns TRUE if the connection was dead and extracted.
  954:  */
  955: static bool extract_if_dead(struct connectdata *conn,
  956:                             struct Curl_easy *data)
  957: {
  958:   if(!CONN_INUSE(conn) && !conn->data) {
  959:     /* The check for a dead socket makes sense only if the connection isn't in
  960:        use */
  961:     bool dead;
  962:     struct curltime now = Curl_now();
  963:     if(conn_maxage(data, conn, now)) {
  964:       dead = TRUE;
  965:     }
  966:     else if(conn->handler->connection_check) {
  967:       /* The protocol has a special method for checking the state of the
  968:          connection. Use it to check if the connection is dead. */
  969:       unsigned int state;
  970:       struct Curl_easy *olddata = conn->data;
  971:       conn->data = data; /* use this transfer for now */
  972:       state = conn->handler->connection_check(conn, CONNCHECK_ISDEAD);
  973:       conn->data = olddata;
  974:       dead = (state & CONNRESULT_DEAD);
  975:     }
  976:     else {
  977:       /* Use the general method for determining the death of a connection */
  978:       dead = SocketIsDead(conn->sock[FIRSTSOCKET]);
  979:     }
  980: 
  981:     if(dead) {
  982:       infof(data, "Connection %ld seems to be dead!\n", conn->connection_id);
  983:       Curl_conncache_remove_conn(data, conn, FALSE);
  984:       return TRUE;
  985:     }
  986:   }
  987:   return FALSE;
  988: }
  989: 
  990: struct prunedead {
  991:   struct Curl_easy *data;
  992:   struct connectdata *extracted;
  993: };
  994: 
  995: /*
  996:  * Wrapper to use extract_if_dead() function in Curl_conncache_foreach()
  997:  *
  998:  */
  999: static int call_extract_if_dead(struct connectdata *conn, void *param)
 1000: {
 1001:   struct prunedead *p = (struct prunedead *)param;
 1002:   if(extract_if_dead(conn, p->data)) {
 1003:     /* stop the iteration here, pass back the connection that was extracted */
 1004:     p->extracted = conn;
 1005:     return 1;
 1006:   }
 1007:   return 0; /* continue iteration */
 1008: }
 1009: 
 1010: /*
 1011:  * This function scans the connection cache for half-open/dead connections,
 1012:  * closes and removes them.
 1013:  * The cleanup is done at most once per second.
 1014:  */
 1015: static void prune_dead_connections(struct Curl_easy *data)
 1016: {
 1017:   struct curltime now = Curl_now();
 1018:   timediff_t elapsed =
 1019:     Curl_timediff(now, data->state.conn_cache->last_cleanup);
 1020: 
 1021:   if(elapsed >= 1000L) {
 1022:     struct prunedead prune;
 1023:     prune.data = data;
 1024:     prune.extracted = NULL;
 1025:     while(Curl_conncache_foreach(data, data->state.conn_cache, &prune,
 1026:                                  call_extract_if_dead)) {
 1027:       /* disconnect it */
 1028:       (void)Curl_disconnect(data, prune.extracted, /* dead_connection */TRUE);
 1029:     }
 1030:     data->state.conn_cache->last_cleanup = now;
 1031:   }
 1032: }
 1033: 
 1034: /*
 1035:  * Given one filled in connection struct (named needle), this function should
 1036:  * detect if there already is one that has all the significant details
 1037:  * exactly the same and thus should be used instead.
 1038:  *
 1039:  * If there is a match, this function returns TRUE - and has marked the
 1040:  * connection as 'in-use'. It must later be called with ConnectionDone() to
 1041:  * return back to 'idle' (unused) state.
 1042:  *
 1043:  * The force_reuse flag is set if the connection must be used.
 1044:  */
 1045: static bool
 1046: ConnectionExists(struct Curl_easy *data,
 1047:                  struct connectdata *needle,
 1048:                  struct connectdata **usethis,
 1049:                  bool *force_reuse,
 1050:                  bool *waitpipe)
 1051: {
 1052:   struct connectdata *check;
 1053:   struct connectdata *chosen = 0;
 1054:   bool foundPendingCandidate = FALSE;
 1055:   bool canmultiplex = IsMultiplexingPossible(data, needle);
 1056:   struct connectbundle *bundle;
 1057:   const char *hostbundle;
 1058: 
 1059: #ifdef USE_NTLM
 1060:   bool wantNTLMhttp = ((data->state.authhost.want &
 1061:                       (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) &&
 1062:                       (needle->handler->protocol & PROTO_FAMILY_HTTP));
 1063:   bool wantProxyNTLMhttp = (needle->bits.proxy_user_passwd &&
 1064:                            ((data->state.authproxy.want &
 1065:                            (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) &&
 1066:                            (needle->handler->protocol & PROTO_FAMILY_HTTP)));
 1067: #endif
 1068: 
 1069:   *force_reuse = FALSE;
 1070:   *waitpipe = FALSE;
 1071: 
 1072:   /* Look up the bundle with all the connections to this particular host.
 1073:      Locks the connection cache, beware of early returns! */
 1074:   bundle = Curl_conncache_find_bundle(needle, data->state.conn_cache,
 1075:                                       &hostbundle);
 1076:   if(bundle) {
 1077:     /* Max pipe length is zero (unlimited) for multiplexed connections */
 1078:     struct curl_llist_element *curr;
 1079: 
 1080:     infof(data, "Found bundle for host %s: %p [%s]\n",
 1081:           hostbundle, (void *)bundle, (bundle->multiuse == BUNDLE_MULTIPLEX ?
 1082:                                        "can multiplex" : "serially"));
 1083: 
 1084:     /* We can't multiplex if we don't know anything about the server */
 1085:     if(canmultiplex) {
 1086:       if(bundle->multiuse == BUNDLE_UNKNOWN) {
 1087:         if(data->set.pipewait) {
 1088:           infof(data, "Server doesn't support multiplex yet, wait\n");
 1089:           *waitpipe = TRUE;
 1090:           Curl_conncache_unlock(data);
 1091:           return FALSE; /* no re-use */
 1092:         }
 1093: 
 1094:         infof(data, "Server doesn't support multiplex (yet)\n");
 1095:         canmultiplex = FALSE;
 1096:       }
 1097:       if((bundle->multiuse == BUNDLE_MULTIPLEX) &&
 1098:          !Curl_multiplex_wanted(data->multi)) {
 1099:         infof(data, "Could multiplex, but not asked to!\n");
 1100:         canmultiplex = FALSE;
 1101:       }
 1102:       if(bundle->multiuse == BUNDLE_NO_MULTIUSE) {
 1103:         infof(data, "Can not multiplex, even if we wanted to!\n");
 1104:         canmultiplex = FALSE;
 1105:       }
 1106:     }
 1107: 
 1108:     curr = bundle->conn_list.head;
 1109:     while(curr) {
 1110:       bool match = FALSE;
 1111:       size_t multiplexed = 0;
 1112: 
 1113:       /*
 1114:        * Note that if we use a HTTP proxy in normal mode (no tunneling), we
 1115:        * check connections to that proxy and not to the actual remote server.
 1116:        */
 1117:       check = curr->ptr;
 1118:       curr = curr->next;
 1119: 
 1120:       if(check->bits.connect_only || check->bits.close)
 1121:         /* connect-only or to-be-closed connections will not be reused */
 1122:         continue;
 1123: 
 1124:       if(bundle->multiuse == BUNDLE_MULTIPLEX)
 1125:         multiplexed = CONN_INUSE(check);
 1126: 
 1127:       if(canmultiplex) {
 1128:         ;
 1129:       }
 1130:       else {
 1131:         if(multiplexed) {
 1132:           /* can only happen within multi handles, and means that another easy
 1133:              handle is using this connection */
 1134:           continue;
 1135:         }
 1136: 
 1137:         if(Curl_resolver_asynch()) {
 1138:           /* ip_addr_str[0] is NUL only if the resolving of the name hasn't
 1139:              completed yet and until then we don't re-use this connection */
 1140:           if(!check->ip_addr_str[0]) {
 1141:             infof(data,
 1142:                   "Connection #%ld is still name resolving, can't reuse\n",
 1143:                   check->connection_id);
 1144:             continue;
 1145:           }
 1146:         }
 1147: 
 1148:         if(check->sock[FIRSTSOCKET] == CURL_SOCKET_BAD) {
 1149:           foundPendingCandidate = TRUE;
 1150:           /* Don't pick a connection that hasn't connected yet */
 1151:           infof(data, "Connection #%ld isn't open enough, can't reuse\n",
 1152:                 check->connection_id);
 1153:           continue;
 1154:         }
 1155:       }
 1156: 
 1157: #ifdef USE_UNIX_SOCKETS
 1158:       if(needle->unix_domain_socket) {
 1159:         if(!check->unix_domain_socket)
 1160:           continue;
 1161:         if(strcmp(needle->unix_domain_socket, check->unix_domain_socket))
 1162:           continue;
 1163:         if(needle->abstract_unix_socket != check->abstract_unix_socket)
 1164:           continue;
 1165:       }
 1166:       else if(check->unix_domain_socket)
 1167:         continue;
 1168: #endif
 1169: 
 1170:       if((needle->handler->flags&PROTOPT_SSL) !=
 1171:          (check->handler->flags&PROTOPT_SSL))
 1172:         /* don't do mixed SSL and non-SSL connections */
 1173:         if(get_protocol_family(check->handler->protocol) !=
 1174:            needle->handler->protocol || !check->tls_upgraded)
 1175:           /* except protocols that have been upgraded via TLS */
 1176:           continue;
 1177: 
 1178:       if(needle->bits.httpproxy != check->bits.httpproxy ||
 1179:          needle->bits.socksproxy != check->bits.socksproxy)
 1180:         continue;
 1181: 
 1182:       if(needle->bits.socksproxy &&
 1183:         !socks_proxy_info_matches(&needle->socks_proxy,
 1184:                                   &check->socks_proxy))
 1185:         continue;
 1186: 
 1187:       if(needle->bits.conn_to_host != check->bits.conn_to_host)
 1188:         /* don't mix connections that use the "connect to host" feature and
 1189:          * connections that don't use this feature */
 1190:         continue;
 1191: 
 1192:       if(needle->bits.conn_to_port != check->bits.conn_to_port)
 1193:         /* don't mix connections that use the "connect to port" feature and
 1194:          * connections that don't use this feature */
 1195:         continue;
 1196: 
 1197:       if(needle->bits.httpproxy) {
 1198:         if(!proxy_info_matches(&needle->http_proxy, &check->http_proxy))
 1199:           continue;
 1200: 
 1201:         if(needle->bits.tunnel_proxy != check->bits.tunnel_proxy)
 1202:           continue;
 1203: 
 1204:         if(needle->http_proxy.proxytype == CURLPROXY_HTTPS) {
 1205:           /* use https proxy */
 1206:           if(needle->handler->flags&PROTOPT_SSL) {
 1207:             /* use double layer ssl */
 1208:             if(!Curl_ssl_config_matches(&needle->proxy_ssl_config,
 1209:                                         &check->proxy_ssl_config))
 1210:               continue;
 1211:             if(check->proxy_ssl[FIRSTSOCKET].state != ssl_connection_complete)
 1212:               continue;
 1213:           }
 1214:           else {
 1215:             if(!Curl_ssl_config_matches(&needle->ssl_config,
 1216:                                         &check->ssl_config))
 1217:               continue;
 1218:             if(check->ssl[FIRSTSOCKET].state != ssl_connection_complete)
 1219:               continue;
 1220:           }
 1221:         }
 1222:       }
 1223: 
 1224:       DEBUGASSERT(!check->data || GOOD_EASY_HANDLE(check->data));
 1225: 
 1226:       if(!canmultiplex && check->data)
 1227:         /* this request can't be multiplexed but the checked connection is
 1228:            already in use so we skip it */
 1229:         continue;
 1230: 
 1231:       if(check->data && (check->data->multi != needle->data->multi))
 1232:         /* this could be subject for multiplex use, but only if they belong to
 1233:          * the same multi handle */
 1234:         continue;
 1235: 
 1236:       if(needle->localdev || needle->localport) {
 1237:         /* If we are bound to a specific local end (IP+port), we must not
 1238:            re-use a random other one, although if we didn't ask for a
 1239:            particular one we can reuse one that was bound.
 1240: 
 1241:            This comparison is a bit rough and too strict. Since the input
 1242:            parameters can be specified in numerous ways and still end up the
 1243:            same it would take a lot of processing to make it really accurate.
 1244:            Instead, this matching will assume that re-uses of bound connections
 1245:            will most likely also re-use the exact same binding parameters and
 1246:            missing out a few edge cases shouldn't hurt anyone very much.
 1247:         */
 1248:         if((check->localport != needle->localport) ||
 1249:            (check->localportrange != needle->localportrange) ||
 1250:            (needle->localdev &&
 1251:             (!check->localdev || strcmp(check->localdev, needle->localdev))))
 1252:           continue;
 1253:       }
 1254: 
 1255:       if(!(needle->handler->flags & PROTOPT_CREDSPERREQUEST)) {
 1256:         /* This protocol requires credentials per connection,
 1257:            so verify that we're using the same name and password as well */
 1258:         if(strcmp(needle->user, check->user) ||
 1259:            strcmp(needle->passwd, check->passwd)) {
 1260:           /* one of them was different */
 1261:           continue;
 1262:         }
 1263:       }
 1264: 
 1265:       if(!needle->bits.httpproxy || (needle->handler->flags&PROTOPT_SSL) ||
 1266:          needle->bits.tunnel_proxy) {
 1267:         /* The requested connection does not use a HTTP proxy or it uses SSL or
 1268:            it is a non-SSL protocol tunneled or it is a non-SSL protocol which
 1269:            is allowed to be upgraded via TLS */
 1270: 
 1271:         if((strcasecompare(needle->handler->scheme, check->handler->scheme) ||
 1272:             (get_protocol_family(check->handler->protocol) ==
 1273:              needle->handler->protocol && check->tls_upgraded)) &&
 1274:            (!needle->bits.conn_to_host || strcasecompare(
 1275:             needle->conn_to_host.name, check->conn_to_host.name)) &&
 1276:            (!needle->bits.conn_to_port ||
 1277:              needle->conn_to_port == check->conn_to_port) &&
 1278:            strcasecompare(needle->host.name, check->host.name) &&
 1279:            needle->remote_port == check->remote_port) {
 1280:           /* The schemes match or the protocol family is the same and the
 1281:              previous connection was TLS upgraded, and the hostname and host
 1282:              port match */
 1283:           if(needle->handler->flags & PROTOPT_SSL) {
 1284:             /* This is a SSL connection so verify that we're using the same
 1285:                SSL options as well */
 1286:             if(!Curl_ssl_config_matches(&needle->ssl_config,
 1287:                                         &check->ssl_config)) {
 1288:               DEBUGF(infof(data,
 1289:                            "Connection #%ld has different SSL parameters, "
 1290:                            "can't reuse\n",
 1291:                            check->connection_id));
 1292:               continue;
 1293:             }
 1294:             if(check->ssl[FIRSTSOCKET].state != ssl_connection_complete) {
 1295:               foundPendingCandidate = TRUE;
 1296:               DEBUGF(infof(data,
 1297:                            "Connection #%ld has not started SSL connect, "
 1298:                            "can't reuse\n",
 1299:                            check->connection_id));
 1300:               continue;
 1301:             }
 1302:           }
 1303:           match = TRUE;
 1304:         }
 1305:       }
 1306:       else {
 1307:         /* The requested connection is using the same HTTP proxy in normal
 1308:            mode (no tunneling) */
 1309:         match = TRUE;
 1310:       }
 1311: 
 1312:       if(match) {
 1313: #if defined(USE_NTLM)
 1314:         /* If we are looking for an HTTP+NTLM connection, check if this is
 1315:            already authenticating with the right credentials. If not, keep
 1316:            looking so that we can reuse NTLM connections if
 1317:            possible. (Especially we must not reuse the same connection if
 1318:            partway through a handshake!) */
 1319:         if(wantNTLMhttp) {
 1320:           if(strcmp(needle->user, check->user) ||
 1321:              strcmp(needle->passwd, check->passwd)) {
 1322: 
 1323:             /* we prefer a credential match, but this is at least a connection
 1324:                that can be reused and "upgraded" to NTLM */
 1325:             if(check->http_ntlm_state == NTLMSTATE_NONE)
 1326:               chosen = check;
 1327:             continue;
 1328:           }
 1329:         }
 1330:         else if(check->http_ntlm_state != NTLMSTATE_NONE) {
 1331:           /* Connection is using NTLM auth but we don't want NTLM */
 1332:           continue;
 1333:         }
 1334: 
 1335:         /* Same for Proxy NTLM authentication */
 1336:         if(wantProxyNTLMhttp) {
 1337:           /* Both check->http_proxy.user and check->http_proxy.passwd can be
 1338:            * NULL */
 1339:           if(!check->http_proxy.user || !check->http_proxy.passwd)
 1340:             continue;
 1341: 
 1342:           if(strcmp(needle->http_proxy.user, check->http_proxy.user) ||
 1343:              strcmp(needle->http_proxy.passwd, check->http_proxy.passwd))
 1344:             continue;
 1345:         }
 1346:         else if(check->proxy_ntlm_state != NTLMSTATE_NONE) {
 1347:           /* Proxy connection is using NTLM auth but we don't want NTLM */
 1348:           continue;
 1349:         }
 1350: 
 1351:         if(wantNTLMhttp || wantProxyNTLMhttp) {
 1352:           /* Credentials are already checked, we can use this connection */
 1353:           chosen = check;
 1354: 
 1355:           if((wantNTLMhttp &&
 1356:              (check->http_ntlm_state != NTLMSTATE_NONE)) ||
 1357:               (wantProxyNTLMhttp &&
 1358:                (check->proxy_ntlm_state != NTLMSTATE_NONE))) {
 1359:             /* We must use this connection, no other */
 1360:             *force_reuse = TRUE;
 1361:             break;
 1362:           }
 1363: 
 1364:           /* Continue look up for a better connection */
 1365:           continue;
 1366:         }
 1367: #endif
 1368:         if(canmultiplex) {
 1369:           /* We can multiplex if we want to. Let's continue looking for
 1370:              the optimal connection to use. */
 1371: 
 1372:           if(!multiplexed) {
 1373:             /* We have the optimal connection. Let's stop looking. */
 1374:             chosen = check;
 1375:             break;
 1376:           }
 1377: 
 1378: #ifdef USE_NGHTTP2
 1379:           /* If multiplexed, make sure we don't go over concurrency limit */
 1380:           if(check->bits.multiplex) {
 1381:             /* Multiplexed connections can only be HTTP/2 for now */
 1382:             struct http_conn *httpc = &check->proto.httpc;
 1383:             if(multiplexed >= httpc->settings.max_concurrent_streams) {
 1384:               infof(data, "MAX_CONCURRENT_STREAMS reached, skip (%zu)\n",
 1385:                     multiplexed);
 1386:               continue;
 1387:             }
 1388:             else if(multiplexed >=
 1389:                     Curl_multi_max_concurrent_streams(needle->data->multi)) {
 1390:               infof(data, "client side MAX_CONCURRENT_STREAMS reached"
 1391:                     ", skip (%zu)\n",
 1392:                     multiplexed);
 1393:               continue;
 1394:             }
 1395:           }
 1396: #endif
 1397:           /* When not multiplexed, we have a match here! */
 1398:           chosen = check;
 1399:           infof(data, "Multiplexed connection found!\n");
 1400:           break;
 1401:         }
 1402:         else {
 1403:           /* We have found a connection. Let's stop searching. */
 1404:           chosen = check;
 1405:           break;
 1406:         }
 1407:       }
 1408:     }
 1409:   }
 1410: 
 1411:   if(chosen) {
 1412:     /* mark it as used before releasing the lock */
 1413:     chosen->data = data; /* own it! */
 1414:     Curl_conncache_unlock(data);
 1415:     *usethis = chosen;
 1416:     return TRUE; /* yes, we found one to use! */
 1417:   }
 1418:   Curl_conncache_unlock(data);
 1419: 
 1420:   if(foundPendingCandidate && data->set.pipewait) {
 1421:     infof(data,
 1422:           "Found pending candidate for reuse and CURLOPT_PIPEWAIT is set\n");
 1423:     *waitpipe = TRUE;
 1424:   }
 1425: 
 1426:   return FALSE; /* no matching connecting exists */
 1427: }
 1428: 
 1429: /*
 1430:  * verboseconnect() displays verbose information after a connect
 1431:  */
 1432: #ifndef CURL_DISABLE_VERBOSE_STRINGS
 1433: void Curl_verboseconnect(struct connectdata *conn)
 1434: {
 1435:   if(conn->data->set.verbose)
 1436:     infof(conn->data, "Connected to %s (%s) port %ld (#%ld)\n",
 1437:           conn->bits.socksproxy ? conn->socks_proxy.host.dispname :
 1438:           conn->bits.httpproxy ? conn->http_proxy.host.dispname :
 1439:           conn->bits.conn_to_host ? conn->conn_to_host.dispname :
 1440:           conn->host.dispname,
 1441:           conn->ip_addr_str, conn->port, conn->connection_id);
 1442: }
 1443: #endif
 1444: 
 1445: /*
 1446:  * Helpers for IDNA conversions.
 1447:  */
 1448: bool Curl_is_ASCII_name(const char *hostname)
 1449: {
 1450:   /* get an UNSIGNED local version of the pointer */
 1451:   const unsigned char *ch = (const unsigned char *)hostname;
 1452: 
 1453:   if(!hostname) /* bad input, consider it ASCII! */
 1454:     return TRUE;
 1455: 
 1456:   while(*ch) {
 1457:     if(*ch++ & 0x80)
 1458:       return FALSE;
 1459:   }
 1460:   return TRUE;
 1461: }
 1462: 
 1463: /*
 1464:  * Strip single trailing dot in the hostname,
 1465:  * primarily for SNI and http host header.
 1466:  */
 1467: static void strip_trailing_dot(struct hostname *host)
 1468: {
 1469:   size_t len;
 1470:   if(!host || !host->name)
 1471:     return;
 1472:   len = strlen(host->name);
 1473:   if(len && (host->name[len-1] == '.'))
 1474:     host->name[len-1] = 0;
 1475: }
 1476: 
 1477: /*
 1478:  * Perform any necessary IDN conversion of hostname
 1479:  */
 1480: CURLcode Curl_idnconvert_hostname(struct connectdata *conn,
 1481:                                   struct hostname *host)
 1482: {
 1483:   struct Curl_easy *data = conn->data;
 1484: 
 1485: #ifndef USE_LIBIDN2
 1486:   (void)data;
 1487:   (void)conn;
 1488: #elif defined(CURL_DISABLE_VERBOSE_STRINGS)
 1489:   (void)conn;
 1490: #endif
 1491: 
 1492:   /* set the name we use to display the host name */
 1493:   host->dispname = host->name;
 1494: 
 1495:   /* Check name for non-ASCII and convert hostname to ACE form if we can */
 1496:   if(!Curl_is_ASCII_name(host->name)) {
 1497: #ifdef USE_LIBIDN2
 1498:     if(idn2_check_version(IDN2_VERSION)) {
 1499:       char *ace_hostname = NULL;
 1500: #if IDN2_VERSION_NUMBER >= 0x00140000
 1501:       /* IDN2_NFC_INPUT: Normalize input string using normalization form C.
 1502:          IDN2_NONTRANSITIONAL: Perform Unicode TR46 non-transitional
 1503:          processing. */
 1504:       int flags = IDN2_NFC_INPUT | IDN2_NONTRANSITIONAL;
 1505: #else
 1506:       int flags = IDN2_NFC_INPUT;
 1507: #endif
 1508:       int rc = idn2_lookup_ul((const char *)host->name, &ace_hostname, flags);
 1509:       if(rc == IDN2_OK) {
 1510:         host->encalloc = (char *)ace_hostname;
 1511:         /* change the name pointer to point to the encoded hostname */
 1512:         host->name = host->encalloc;
 1513:       }
 1514:       else {
 1515:         failf(data, "Failed to convert %s to ACE; %s\n", host->name,
 1516:               idn2_strerror(rc));
 1517:         return CURLE_URL_MALFORMAT;
 1518:       }
 1519:     }
 1520: #elif defined(USE_WIN32_IDN)
 1521:     char *ace_hostname = NULL;
 1522: 
 1523:     if(curl_win32_idn_to_ascii(host->name, &ace_hostname)) {
 1524:       host->encalloc = ace_hostname;
 1525:       /* change the name pointer to point to the encoded hostname */
 1526:       host->name = host->encalloc;
 1527:     }
 1528:     else {
 1529:       char buffer[STRERROR_LEN];
 1530:       failf(data, "Failed to convert %s to ACE; %s\n", host->name,
 1531:             Curl_winapi_strerror(GetLastError(), buffer, sizeof(buffer)));
 1532:       return CURLE_URL_MALFORMAT;
 1533:     }
 1534: #else
 1535:     infof(data, "IDN support not present, can't parse Unicode domains\n");
 1536: #endif
 1537:   }
 1538:   return CURLE_OK;
 1539: }
 1540: 
 1541: /*
 1542:  * Frees data allocated by idnconvert_hostname()
 1543:  */
 1544: void Curl_free_idnconverted_hostname(struct hostname *host)
 1545: {
 1546: #if defined(USE_LIBIDN2)
 1547:   if(host->encalloc) {
 1548:     idn2_free(host->encalloc); /* must be freed with idn2_free() since this was
 1549:                                  allocated by libidn */
 1550:     host->encalloc = NULL;
 1551:   }
 1552: #elif defined(USE_WIN32_IDN)
 1553:   free(host->encalloc); /* must be freed with free() since this was
 1554:                            allocated by curl_win32_idn_to_ascii */
 1555:   host->encalloc = NULL;
 1556: #else
 1557:   (void)host;
 1558: #endif
 1559: }
 1560: 
 1561: /*
 1562:  * Allocate and initialize a new connectdata object.
 1563:  */
 1564: static struct connectdata *allocate_conn(struct Curl_easy *data)
 1565: {
 1566:   struct connectdata *conn = calloc(1, sizeof(struct connectdata));
 1567:   if(!conn)
 1568:     return NULL;
 1569: 
 1570: #ifdef USE_SSL
 1571:   /* The SSL backend-specific data (ssl_backend_data) objects are allocated as
 1572:      a separate array to ensure suitable alignment.
 1573:      Note that these backend pointers can be swapped by vtls (eg ssl backend
 1574:      data becomes proxy backend data). */
 1575:   {
 1576:     size_t sslsize = Curl_ssl->sizeof_ssl_backend_data;
 1577:     char *ssl = calloc(4, sslsize);
 1578:     if(!ssl) {
 1579:       free(conn);
 1580:       return NULL;
 1581:     }
 1582:     conn->ssl_extra = ssl;
 1583:     conn->ssl[0].backend = (void *)ssl;
 1584:     conn->ssl[1].backend = (void *)(ssl + sslsize);
 1585:     conn->proxy_ssl[0].backend = (void *)(ssl + 2 * sslsize);
 1586:     conn->proxy_ssl[1].backend = (void *)(ssl + 3 * sslsize);
 1587:   }
 1588: #endif
 1589: 
 1590:   conn->handler = &Curl_handler_dummy;  /* Be sure we have a handler defined
 1591:                                            already from start to avoid NULL
 1592:                                            situations and checks */
 1593: 
 1594:   /* and we setup a few fields in case we end up actually using this struct */
 1595: 
 1596:   conn->sock[FIRSTSOCKET] = CURL_SOCKET_BAD;     /* no file descriptor */
 1597:   conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD; /* no file descriptor */
 1598:   conn->tempsock[0] = CURL_SOCKET_BAD; /* no file descriptor */
 1599:   conn->tempsock[1] = CURL_SOCKET_BAD; /* no file descriptor */
 1600:   conn->connection_id = -1;    /* no ID */
 1601:   conn->port = -1; /* unknown at this point */
 1602:   conn->remote_port = -1; /* unknown at this point */
 1603: #if defined(USE_RECV_BEFORE_SEND_WORKAROUND) && defined(DEBUGBUILD)
 1604:   conn->postponed[0].bindsock = CURL_SOCKET_BAD; /* no file descriptor */
 1605:   conn->postponed[1].bindsock = CURL_SOCKET_BAD; /* no file descriptor */
 1606: #endif /* USE_RECV_BEFORE_SEND_WORKAROUND && DEBUGBUILD */
 1607: 
 1608:   /* Default protocol-independent behavior doesn't support persistent
 1609:      connections, so we set this to force-close. Protocols that support
 1610:      this need to set this to FALSE in their "curl_do" functions. */
 1611:   connclose(conn, "Default to force-close");
 1612: 
 1613:   /* Store creation time to help future close decision making */
 1614:   conn->created = Curl_now();
 1615: 
 1616:   /* Store current time to give a baseline to keepalive connection times. */
 1617:   conn->keepalive = Curl_now();
 1618: 
 1619:   /* Store off the configured connection upkeep time. */
 1620:   conn->upkeep_interval_ms = data->set.upkeep_interval_ms;
 1621: 
 1622:   conn->data = data; /* Setup the association between this connection
 1623:                         and the Curl_easy */
 1624: 
 1625:   conn->http_proxy.proxytype = data->set.proxytype;
 1626:   conn->socks_proxy.proxytype = CURLPROXY_SOCKS4;
 1627: 
 1628: #if !defined(CURL_DISABLE_PROXY)
 1629:   /* note that these two proxy bits are now just on what looks to be
 1630:      requested, they may be altered down the road */
 1631:   conn->bits.proxy = (data->set.str[STRING_PROXY] &&
 1632:                       *data->set.str[STRING_PROXY]) ? TRUE : FALSE;
 1633:   conn->bits.httpproxy = (conn->bits.proxy &&
 1634:                           (conn->http_proxy.proxytype == CURLPROXY_HTTP ||
 1635:                            conn->http_proxy.proxytype == CURLPROXY_HTTP_1_0 ||
 1636:                            conn->http_proxy.proxytype == CURLPROXY_HTTPS)) ?
 1637:                            TRUE : FALSE;
 1638:   conn->bits.socksproxy = (conn->bits.proxy &&
 1639:                            !conn->bits.httpproxy) ? TRUE : FALSE;
 1640: 
 1641:   if(data->set.str[STRING_PRE_PROXY] && *data->set.str[STRING_PRE_PROXY]) {
 1642:     conn->bits.proxy = TRUE;
 1643:     conn->bits.socksproxy = TRUE;
 1644:   }
 1645: 
 1646:   conn->bits.proxy_user_passwd =
 1647:     (data->set.str[STRING_PROXYUSERNAME]) ? TRUE : FALSE;
 1648:   conn->bits.tunnel_proxy = data->set.tunnel_thru_httpproxy;
 1649: #endif /* CURL_DISABLE_PROXY */
 1650: 
 1651:   conn->bits.user_passwd = (data->set.str[STRING_USERNAME]) ? TRUE : FALSE;
 1652: #ifndef CURL_DISABLE_FTP
 1653:   conn->bits.ftp_use_epsv = data->set.ftp_use_epsv;
 1654:   conn->bits.ftp_use_eprt = data->set.ftp_use_eprt;
 1655: #endif
 1656:   conn->ssl_config.verifystatus = data->set.ssl.primary.verifystatus;
 1657:   conn->ssl_config.verifypeer = data->set.ssl.primary.verifypeer;
 1658:   conn->ssl_config.verifyhost = data->set.ssl.primary.verifyhost;
 1659:   conn->proxy_ssl_config.verifystatus =
 1660:     data->set.proxy_ssl.primary.verifystatus;
 1661:   conn->proxy_ssl_config.verifypeer = data->set.proxy_ssl.primary.verifypeer;
 1662:   conn->proxy_ssl_config.verifyhost = data->set.proxy_ssl.primary.verifyhost;
 1663:   conn->ip_version = data->set.ipver;
 1664:   conn->bits.connect_only = data->set.connect_only;
 1665:   conn->transport = TRNSPRT_TCP; /* most of them are TCP streams */
 1666: 
 1667: #if !defined(CURL_DISABLE_HTTP) && defined(USE_NTLM) && \
 1668:     defined(NTLM_WB_ENABLED)
 1669:   conn->ntlm.ntlm_auth_hlpr_socket = CURL_SOCKET_BAD;
 1670:   conn->proxyntlm.ntlm_auth_hlpr_socket = CURL_SOCKET_BAD;
 1671: #endif
 1672: 
 1673:   /* Initialize the easy handle list */
 1674:   Curl_llist_init(&conn->easyq, NULL);
 1675: 
 1676: #ifdef HAVE_GSSAPI
 1677:   conn->data_prot = PROT_CLEAR;
 1678: #endif
 1679: 
 1680:   /* Store the local bind parameters that will be used for this connection */
 1681:   if(data->set.str[STRING_DEVICE]) {
 1682:     conn->localdev = strdup(data->set.str[STRING_DEVICE]);
 1683:     if(!conn->localdev)
 1684:       goto error;
 1685:   }
 1686:   conn->localportrange = data->set.localportrange;
 1687:   conn->localport = data->set.localport;
 1688: 
 1689:   /* the close socket stuff needs to be copied to the connection struct as
 1690:      it may live on without (this specific) Curl_easy */
 1691:   conn->fclosesocket = data->set.fclosesocket;
 1692:   conn->closesocket_client = data->set.closesocket_client;
 1693:   conn->lastused = Curl_now(); /* used now */
 1694: 
 1695:   return conn;
 1696:   error:
 1697: 
 1698:   Curl_llist_destroy(&conn->easyq, NULL);
 1699:   free(conn->localdev);
 1700: #ifdef USE_SSL
 1701:   free(conn->ssl_extra);
 1702: #endif
 1703:   free(conn);
 1704:   return NULL;
 1705: }
 1706: 
 1707: /* returns the handler if the given scheme is built-in */
 1708: const struct Curl_handler *Curl_builtin_scheme(const char *scheme)
 1709: {
 1710:   const struct Curl_handler * const *pp;
 1711:   const struct Curl_handler *p;
 1712:   /* Scan protocol handler table and match against 'scheme'. The handler may
 1713:      be changed later when the protocol specific setup function is called. */
 1714:   for(pp = protocols; (p = *pp) != NULL; pp++)
 1715:     if(strcasecompare(p->scheme, scheme))
 1716:       /* Protocol found in table. Check if allowed */
 1717:       return p;
 1718:   return NULL; /* not found */
 1719: }
 1720: 
 1721: 
 1722: static CURLcode findprotocol(struct Curl_easy *data,
 1723:                              struct connectdata *conn,
 1724:                              const char *protostr)
 1725: {
 1726:   const struct Curl_handler *p = Curl_builtin_scheme(protostr);
 1727: 
 1728:   if(p && /* Protocol found in table. Check if allowed */
 1729:      (data->set.allowed_protocols & p->protocol)) {
 1730: 
 1731:     /* it is allowed for "normal" request, now do an extra check if this is
 1732:        the result of a redirect */
 1733:     if(data->state.this_is_a_follow &&
 1734:        !(data->set.redir_protocols & p->protocol))
 1735:       /* nope, get out */
 1736:       ;
 1737:     else {
 1738:       /* Perform setup complement if some. */
 1739:       conn->handler = conn->given = p;
 1740: 
 1741:       /* 'port' and 'remote_port' are set in setup_connection_internals() */
 1742:       return CURLE_OK;
 1743:     }
 1744:   }
 1745: 
 1746:   /* The protocol was not found in the table, but we don't have to assign it
 1747:      to anything since it is already assigned to a dummy-struct in the
 1748:      create_conn() function when the connectdata struct is allocated. */
 1749:   failf(data, "Protocol \"%s\" not supported or disabled in " LIBCURL_NAME,
 1750:         protostr);
 1751: 
 1752:   return CURLE_UNSUPPORTED_PROTOCOL;
 1753: }
 1754: 
 1755: 
 1756: CURLcode Curl_uc_to_curlcode(CURLUcode uc)
 1757: {
 1758:   switch(uc) {
 1759:   default:
 1760:     return CURLE_URL_MALFORMAT;
 1761:   case CURLUE_UNSUPPORTED_SCHEME:
 1762:     return CURLE_UNSUPPORTED_PROTOCOL;
 1763:   case CURLUE_OUT_OF_MEMORY:
 1764:     return CURLE_OUT_OF_MEMORY;
 1765:   case CURLUE_USER_NOT_ALLOWED:
 1766:     return CURLE_LOGIN_DENIED;
 1767:   }
 1768: }
 1769: 
 1770: /*
 1771:  * If the URL was set with an IPv6 numerical address with a zone id part, set
 1772:  * the scope_id based on that!
 1773:  */
 1774: 
 1775: static void zonefrom_url(CURLU *uh, struct connectdata *conn)
 1776: {
 1777:   char *zoneid;
 1778:   CURLUcode uc;
 1779: 
 1780:   uc = curl_url_get(uh, CURLUPART_ZONEID, &zoneid, 0);
 1781: 
 1782:   if(!uc && zoneid) {
 1783:     char *endp;
 1784:     unsigned long scope = strtoul(zoneid, &endp, 10);
 1785:     if(!*endp && (scope < UINT_MAX))
 1786:       /* A plain number, use it directly as a scope id. */
 1787:       conn->scope_id = (unsigned int)scope;
 1788: #if defined(HAVE_IF_NAMETOINDEX)
 1789:     else {
 1790: #elif defined(WIN32)
 1791:     else if(Curl_if_nametoindex) {
 1792: #endif
 1793: 
 1794: #if defined(HAVE_IF_NAMETOINDEX) || defined(WIN32)
 1795:       /* Zone identifier is not numeric */
 1796:       unsigned int scopeidx = 0;
 1797: #if defined(WIN32)
 1798:       scopeidx = Curl_if_nametoindex(zoneid);
 1799: #else
 1800:       scopeidx = if_nametoindex(zoneid);
 1801: #endif
 1802:       if(!scopeidx)
 1803:         infof(conn->data, "Invalid zoneid: %s; %s\n", zoneid,
 1804:               strerror(errno));
 1805:       else
 1806:         conn->scope_id = scopeidx;
 1807:     }
 1808: #endif /* HAVE_IF_NAMETOINDEX || WIN32 */
 1809: 
 1810:     free(zoneid);
 1811:   }
 1812: }
 1813: 
 1814: /*
 1815:  * Parse URL and fill in the relevant members of the connection struct.
 1816:  */
 1817: static CURLcode parseurlandfillconn(struct Curl_easy *data,
 1818:                                     struct connectdata *conn)
 1819: {
 1820:   CURLcode result;
 1821:   CURLU *uh;
 1822:   CURLUcode uc;
 1823:   char *hostname;
 1824: 
 1825:   up_free(data); /* cleanup previous leftovers first */
 1826: 
 1827:   /* parse the URL */
 1828:   if(data->set.uh) {
 1829:     uh = data->state.uh = curl_url_dup(data->set.uh);
 1830:   }
 1831:   else {
 1832:     uh = data->state.uh = curl_url();
 1833:   }
 1834: 
 1835:   if(!uh)
 1836:     return CURLE_OUT_OF_MEMORY;
 1837: 
 1838:   if(data->set.str[STRING_DEFAULT_PROTOCOL] &&
 1839:      !Curl_is_absolute_url(data->change.url, NULL, MAX_SCHEME_LEN)) {
 1840:     char *url;
 1841:     if(data->change.url_alloc)
 1842:       free(data->change.url);
 1843:     url = aprintf("%s://%s", data->set.str[STRING_DEFAULT_PROTOCOL],
 1844:                   data->change.url);
 1845:     if(!url)
 1846:       return CURLE_OUT_OF_MEMORY;
 1847:     data->change.url = url;
 1848:     data->change.url_alloc = TRUE;
 1849:   }
 1850: 
 1851:   if(!data->set.uh) {
 1852:     char *newurl;
 1853:     uc = curl_url_set(uh, CURLUPART_URL, data->change.url,
 1854:                     CURLU_GUESS_SCHEME |
 1855:                     CURLU_NON_SUPPORT_SCHEME |
 1856:                     (data->set.disallow_username_in_url ?
 1857:                      CURLU_DISALLOW_USER : 0) |
 1858:                     (data->set.path_as_is ? CURLU_PATH_AS_IS : 0));
 1859:     if(uc) {
 1860:       DEBUGF(infof(data, "curl_url_set rejected %s\n", data->change.url));
 1861:       return Curl_uc_to_curlcode(uc);
 1862:     }
 1863: 
 1864:     /* after it was parsed, get the generated normalized version */
 1865:     uc = curl_url_get(uh, CURLUPART_URL, &newurl, 0);
 1866:     if(uc)
 1867:       return Curl_uc_to_curlcode(uc);
 1868:     if(data->change.url_alloc)
 1869:       free(data->change.url);
 1870:     data->change.url = newurl;
 1871:     data->change.url_alloc = TRUE;
 1872:   }
 1873: 
 1874:   uc = curl_url_get(uh, CURLUPART_SCHEME, &data->state.up.scheme, 0);
 1875:   if(uc)
 1876:     return Curl_uc_to_curlcode(uc);
 1877: 
 1878:   result = findprotocol(data, conn, data->state.up.scheme);
 1879:   if(result)
 1880:     return result;
 1881: 
 1882:   uc = curl_url_get(uh, CURLUPART_USER, &data->state.up.user,
 1883:                     CURLU_URLDECODE);
 1884:   if(!uc) {
 1885:     conn->user = strdup(data->state.up.user);
 1886:     if(!conn->user)
 1887:       return CURLE_OUT_OF_MEMORY;
 1888:     conn->bits.user_passwd = TRUE;
 1889:   }
 1890:   else if(uc != CURLUE_NO_USER)
 1891:     return Curl_uc_to_curlcode(uc);
 1892: 
 1893:   uc = curl_url_get(uh, CURLUPART_PASSWORD, &data->state.up.password,
 1894:                     CURLU_URLDECODE);
 1895:   if(!uc) {
 1896:     conn->passwd = strdup(data->state.up.password);
 1897:     if(!conn->passwd)
 1898:       return CURLE_OUT_OF_MEMORY;
 1899:     conn->bits.user_passwd = TRUE;
 1900:   }
 1901:   else if(uc != CURLUE_NO_PASSWORD)
 1902:     return Curl_uc_to_curlcode(uc);
 1903: 
 1904:   uc = curl_url_get(uh, CURLUPART_OPTIONS, &data->state.up.options,
 1905:                     CURLU_URLDECODE);
 1906:   if(!uc) {
 1907:     conn->options = strdup(data->state.up.options);
 1908:     if(!conn->options)
 1909:       return CURLE_OUT_OF_MEMORY;
 1910:   }
 1911:   else if(uc != CURLUE_NO_OPTIONS)
 1912:     return Curl_uc_to_curlcode(uc);
 1913: 
 1914:   uc = curl_url_get(uh, CURLUPART_HOST, &data->state.up.hostname, 0);
 1915:   if(uc) {
 1916:     if(!strcasecompare("file", data->state.up.scheme))
 1917:       return CURLE_OUT_OF_MEMORY;
 1918:   }
 1919: 
 1920:   uc = curl_url_get(uh, CURLUPART_PATH, &data->state.up.path, 0);
 1921:   if(uc)
 1922:     return Curl_uc_to_curlcode(uc);
 1923: 
 1924:   uc = curl_url_get(uh, CURLUPART_PORT, &data->state.up.port,
 1925:                     CURLU_DEFAULT_PORT);
 1926:   if(uc) {
 1927:     if(!strcasecompare("file", data->state.up.scheme))
 1928:       return CURLE_OUT_OF_MEMORY;
 1929:   }
 1930:   else {
 1931:     unsigned long port = strtoul(data->state.up.port, NULL, 10);
 1932:     conn->port = conn->remote_port = curlx_ultous(port);
 1933:   }
 1934: 
 1935:   (void)curl_url_get(uh, CURLUPART_QUERY, &data->state.up.query, 0);
 1936: 
 1937:   hostname = data->state.up.hostname;
 1938:   if(hostname && hostname[0] == '[') {
 1939:     /* This looks like an IPv6 address literal. See if there is an address
 1940:        scope. */
 1941:     size_t hlen;
 1942:     conn->bits.ipv6_ip = TRUE;
 1943:     /* cut off the brackets! */
 1944:     hostname++;
 1945:     hlen = strlen(hostname);
 1946:     hostname[hlen - 1] = 0;
 1947: 
 1948:     zonefrom_url(uh, conn);
 1949:   }
 1950: 
 1951:   /* make sure the connect struct gets its own copy of the host name */
 1952:   conn->host.rawalloc = strdup(hostname ? hostname : "");
 1953:   if(!conn->host.rawalloc)
 1954:     return CURLE_OUT_OF_MEMORY;
 1955:   conn->host.name = conn->host.rawalloc;
 1956: 
 1957:   if(data->set.scope_id)
 1958:     /* Override any scope that was set above.  */
 1959:     conn->scope_id = data->set.scope_id;
 1960: 
 1961:   return CURLE_OK;
 1962: }
 1963: 
 1964: 
 1965: /*
 1966:  * If we're doing a resumed transfer, we need to setup our stuff
 1967:  * properly.
 1968:  */
 1969: static CURLcode setup_range(struct Curl_easy *data)
 1970: {
 1971:   struct UrlState *s = &data->state;
 1972:   s->resume_from = data->set.set_resume_from;
 1973:   if(s->resume_from || data->set.str[STRING_SET_RANGE]) {
 1974:     if(s->rangestringalloc)
 1975:       free(s->range);
 1976: 
 1977:     if(s->resume_from)
 1978:       s->range = aprintf("%" CURL_FORMAT_CURL_OFF_T "-", s->resume_from);
 1979:     else
 1980:       s->range = strdup(data->set.str[STRING_SET_RANGE]);
 1981: 
 1982:     s->rangestringalloc = (s->range) ? TRUE : FALSE;
 1983: 
 1984:     if(!s->range)
 1985:       return CURLE_OUT_OF_MEMORY;
 1986: 
 1987:     /* tell ourselves to fetch this range */
 1988:     s->use_range = TRUE;        /* enable range download */
 1989:   }
 1990:   else
 1991:     s->use_range = FALSE; /* disable range download */
 1992: 
 1993:   return CURLE_OK;
 1994: }
 1995: 
 1996: 
 1997: /*
 1998:  * setup_connection_internals() -
 1999:  *
 2000:  * Setup connection internals specific to the requested protocol in the
 2001:  * Curl_easy. This is inited and setup before the connection is made but
 2002:  * is about the particular protocol that is to be used.
 2003:  *
 2004:  * This MUST get called after proxy magic has been figured out.
 2005:  */
 2006: static CURLcode setup_connection_internals(struct connectdata *conn)
 2007: {
 2008:   const struct Curl_handler * p;
 2009:   CURLcode result;
 2010: 
 2011:   /* Perform setup complement if some. */
 2012:   p = conn->handler;
 2013: 
 2014:   if(p->setup_connection) {
 2015:     result = (*p->setup_connection)(conn);
 2016: 
 2017:     if(result)
 2018:       return result;
 2019: 
 2020:     p = conn->handler;              /* May have changed. */
 2021:   }
 2022: 
 2023:   if(conn->port < 0)
 2024:     /* we check for -1 here since if proxy was detected already, this
 2025:        was very likely already set to the proxy port */
 2026:     conn->port = p->defport;
 2027: 
 2028:   return CURLE_OK;
 2029: }
 2030: 
 2031: /*
 2032:  * Curl_free_request_state() should free temp data that was allocated in the
 2033:  * Curl_easy for this single request.
 2034:  */
 2035: 
 2036: void Curl_free_request_state(struct Curl_easy *data)
 2037: {
 2038:   Curl_safefree(data->req.protop);
 2039:   Curl_safefree(data->req.newurl);
 2040: 
 2041: #ifndef CURL_DISABLE_DOH
 2042:   Curl_close(&data->req.doh.probe[0].easy);
 2043:   Curl_close(&data->req.doh.probe[1].easy);
 2044: #endif
 2045: }
 2046: 
 2047: 
 2048: #ifndef CURL_DISABLE_PROXY
 2049: /****************************************************************
 2050: * Checks if the host is in the noproxy list. returns true if it matches
 2051: * and therefore the proxy should NOT be used.
 2052: ****************************************************************/
 2053: static bool check_noproxy(const char *name, const char *no_proxy)
 2054: {
 2055:   /* no_proxy=domain1.dom,host.domain2.dom
 2056:    *   (a comma-separated list of hosts which should
 2057:    *   not be proxied, or an asterisk to override
 2058:    *   all proxy variables)
 2059:    */
 2060:   if(no_proxy && no_proxy[0]) {
 2061:     size_t tok_start;
 2062:     size_t tok_end;
 2063:     const char *separator = ", ";
 2064:     size_t no_proxy_len;
 2065:     size_t namelen;
 2066:     char *endptr;
 2067:     if(strcasecompare("*", no_proxy)) {
 2068:       return TRUE;
 2069:     }
 2070: 
 2071:     /* NO_PROXY was specified and it wasn't just an asterisk */
 2072: 
 2073:     no_proxy_len = strlen(no_proxy);
 2074:     if(name[0] == '[') {
 2075:       /* IPv6 numerical address */
 2076:       endptr = strchr(name, ']');
 2077:       if(!endptr)
 2078:         return FALSE;
 2079:       name++;
 2080:       namelen = endptr - name;
 2081:     }
 2082:     else
 2083:       namelen = strlen(name);
 2084: 
 2085:     for(tok_start = 0; tok_start < no_proxy_len; tok_start = tok_end + 1) {
 2086:       while(tok_start < no_proxy_len &&
 2087:             strchr(separator, no_proxy[tok_start]) != NULL) {
 2088:         /* Look for the beginning of the token. */
 2089:         ++tok_start;
 2090:       }
 2091: 
 2092:       if(tok_start == no_proxy_len)
 2093:         break; /* It was all trailing separator chars, no more tokens. */
 2094: 
 2095:       for(tok_end = tok_start; tok_end < no_proxy_len &&
 2096:             strchr(separator, no_proxy[tok_end]) == NULL; ++tok_end)
 2097:         /* Look for the end of the token. */
 2098:         ;
 2099: 
 2100:       /* To match previous behaviour, where it was necessary to specify
 2101:        * ".local.com" to prevent matching "notlocal.com", we will leave
 2102:        * the '.' off.
 2103:        */
 2104:       if(no_proxy[tok_start] == '.')
 2105:         ++tok_start;
 2106: 
 2107:       if((tok_end - tok_start) <= namelen) {
 2108:         /* Match the last part of the name to the domain we are checking. */
 2109:         const char *checkn = name + namelen - (tok_end - tok_start);
 2110:         if(strncasecompare(no_proxy + tok_start, checkn,
 2111:                            tok_end - tok_start)) {
 2112:           if((tok_end - tok_start) == namelen || *(checkn - 1) == '.') {
 2113:             /* We either have an exact match, or the previous character is a .
 2114:              * so it is within the same domain, so no proxy for this host.
 2115:              */
 2116:             return TRUE;
 2117:           }
 2118:         }
 2119:       } /* if((tok_end - tok_start) <= namelen) */
 2120:     } /* for(tok_start = 0; tok_start < no_proxy_len;
 2121:          tok_start = tok_end + 1) */
 2122:   } /* NO_PROXY was specified and it wasn't just an asterisk */
 2123: 
 2124:   return FALSE;
 2125: }
 2126: 
 2127: #ifndef CURL_DISABLE_HTTP
 2128: /****************************************************************
 2129: * Detect what (if any) proxy to use. Remember that this selects a host
 2130: * name and is not limited to HTTP proxies only.
 2131: * The returned pointer must be freed by the caller (unless NULL)
 2132: ****************************************************************/
 2133: static char *detect_proxy(struct connectdata *conn)
 2134: {
 2135:   char *proxy = NULL;
 2136: 
 2137:   /* If proxy was not specified, we check for default proxy environment
 2138:    * variables, to enable i.e Lynx compliance:
 2139:    *
 2140:    * http_proxy=http://some.server.dom:port/
 2141:    * https_proxy=http://some.server.dom:port/
 2142:    * ftp_proxy=http://some.server.dom:port/
 2143:    * no_proxy=domain1.dom,host.domain2.dom
 2144:    *   (a comma-separated list of hosts which should
 2145:    *   not be proxied, or an asterisk to override
 2146:    *   all proxy variables)
 2147:    * all_proxy=http://some.server.dom:port/
 2148:    *   (seems to exist for the CERN www lib. Probably
 2149:    *   the first to check for.)
 2150:    *
 2151:    * For compatibility, the all-uppercase versions of these variables are
 2152:    * checked if the lowercase versions don't exist.
 2153:    */
 2154:   char proxy_env[128];
 2155:   const char *protop = conn->handler->scheme;
 2156:   char *envp = proxy_env;
 2157:   char *prox;
 2158: 
 2159:   /* Now, build <protocol>_proxy and check for such a one to use */
 2160:   while(*protop)
 2161:     *envp++ = (char)tolower((int)*protop++);
 2162: 
 2163:   /* append _proxy */
 2164:   strcpy(envp, "_proxy");
 2165: 
 2166:   /* read the protocol proxy: */
 2167:   prox = curl_getenv(proxy_env);
 2168: 
 2169:   /*
 2170:    * We don't try the uppercase version of HTTP_PROXY because of
 2171:    * security reasons:
 2172:    *
 2173:    * When curl is used in a webserver application
 2174:    * environment (cgi or php), this environment variable can
 2175:    * be controlled by the web server user by setting the
 2176:    * http header 'Proxy:' to some value.
 2177:    *
 2178:    * This can cause 'internal' http/ftp requests to be
 2179:    * arbitrarily redirected by any external attacker.
 2180:    */
 2181:   if(!prox && !strcasecompare("http_proxy", proxy_env)) {
 2182:     /* There was no lowercase variable, try the uppercase version: */
 2183:     Curl_strntoupper(proxy_env, proxy_env, sizeof(proxy_env));
 2184:     prox = curl_getenv(proxy_env);
 2185:   }
 2186: 
 2187:   envp = proxy_env;
 2188:   if(prox) {
 2189:     proxy = prox; /* use this */
 2190:   }
 2191:   else {
 2192:     envp = (char *)"all_proxy";
 2193:     proxy = curl_getenv(envp); /* default proxy to use */
 2194:     if(!proxy) {
 2195:       envp = (char *)"ALL_PROXY";
 2196:       proxy = curl_getenv(envp);
 2197:     }
 2198:   }
 2199:   if(proxy)
 2200:     infof(conn->data, "Uses proxy env variable %s == '%s'\n", envp, proxy);
 2201: 
 2202:   return proxy;
 2203: }
 2204: #endif /* CURL_DISABLE_HTTP */
 2205: 
 2206: /*
 2207:  * If this is supposed to use a proxy, we need to figure out the proxy
 2208:  * host name, so that we can re-use an existing connection
 2209:  * that may exist registered to the same proxy host.
 2210:  */
 2211: static CURLcode parse_proxy(struct Curl_easy *data,
 2212:                             struct connectdata *conn, char *proxy,
 2213:                             curl_proxytype proxytype)
 2214: {
 2215:   char *portptr = NULL;
 2216:   long port = -1;
 2217:   char *proxyuser = NULL;
 2218:   char *proxypasswd = NULL;
 2219:   char *host;
 2220:   bool sockstype;
 2221:   CURLUcode uc;
 2222:   struct proxy_info *proxyinfo;
 2223:   CURLU *uhp = curl_url();
 2224:   CURLcode result = CURLE_OK;
 2225:   char *scheme = NULL;
 2226: 
 2227:   /* When parsing the proxy, allowing non-supported schemes since we have
 2228:      these made up ones for proxies. Guess scheme for URLs without it. */
 2229:   uc = curl_url_set(uhp, CURLUPART_URL, proxy,
 2230:                     CURLU_NON_SUPPORT_SCHEME|CURLU_GUESS_SCHEME);
 2231:   if(!uc) {
 2232:     /* parsed okay as a URL */
 2233:     uc = curl_url_get(uhp, CURLUPART_SCHEME, &scheme, 0);
 2234:     if(uc) {
 2235:       result = CURLE_OUT_OF_MEMORY;
 2236:       goto error;
 2237:     }
 2238: 
 2239:     if(strcasecompare("https", scheme))
 2240:       proxytype = CURLPROXY_HTTPS;
 2241:     else if(strcasecompare("socks5h", scheme))
 2242:       proxytype = CURLPROXY_SOCKS5_HOSTNAME;
 2243:     else if(strcasecompare("socks5", scheme))
 2244:       proxytype = CURLPROXY_SOCKS5;
 2245:     else if(strcasecompare("socks4a", scheme))
 2246:       proxytype = CURLPROXY_SOCKS4A;
 2247:     else if(strcasecompare("socks4", scheme) ||
 2248:             strcasecompare("socks", scheme))
 2249:       proxytype = CURLPROXY_SOCKS4;
 2250:     else if(strcasecompare("http", scheme))
 2251:       ; /* leave it as HTTP or HTTP/1.0 */
 2252:     else {
 2253:       /* Any other xxx:// reject! */
 2254:       failf(data, "Unsupported proxy scheme for \'%s\'", proxy);
 2255:       result = CURLE_COULDNT_CONNECT;
 2256:       goto error;
 2257:     }
 2258:   }
 2259:   else {
 2260:     failf(data, "Unsupported proxy syntax in \'%s\'", proxy);
 2261:     result = CURLE_COULDNT_RESOLVE_PROXY;
 2262:     goto error;
 2263:   }
 2264: 
 2265: #ifdef USE_SSL
 2266:   if(!(Curl_ssl->supports & SSLSUPP_HTTPS_PROXY))
 2267: #endif
 2268:     if(proxytype == CURLPROXY_HTTPS) {
 2269:       failf(data, "Unsupported proxy \'%s\', libcurl is built without the "
 2270:                   "HTTPS-proxy support.", proxy);
 2271:       result = CURLE_NOT_BUILT_IN;
 2272:       goto error;
 2273:     }
 2274: 
 2275:   sockstype =
 2276:     proxytype == CURLPROXY_SOCKS5_HOSTNAME ||
 2277:     proxytype == CURLPROXY_SOCKS5 ||
 2278:     proxytype == CURLPROXY_SOCKS4A ||
 2279:     proxytype == CURLPROXY_SOCKS4;
 2280: 
 2281:   proxyinfo = sockstype ? &conn->socks_proxy : &conn->http_proxy;
 2282:   proxyinfo->proxytype = proxytype;
 2283: 
 2284:   /* Is there a username and password given in this proxy url? */
 2285:   curl_url_get(uhp, CURLUPART_USER, &proxyuser, CURLU_URLDECODE);
 2286:   curl_url_get(uhp, CURLUPART_PASSWORD, &proxypasswd, CURLU_URLDECODE);
 2287:   if(proxyuser || proxypasswd) {
 2288:     Curl_safefree(proxyinfo->user);
 2289:     proxyinfo->user = proxyuser;
 2290:     Curl_safefree(proxyinfo->passwd);
 2291:     if(!proxypasswd) {
 2292:       proxypasswd = strdup("");
 2293:       if(!proxypasswd) {
 2294:         result = CURLE_OUT_OF_MEMORY;
 2295:         goto error;
 2296:       }
 2297:     }
 2298:     proxyinfo->passwd = proxypasswd;
 2299:     conn->bits.proxy_user_passwd = TRUE; /* enable it */
 2300:   }
 2301: 
 2302:   curl_url_get(uhp, CURLUPART_PORT, &portptr, 0);
 2303: 
 2304:   if(portptr) {
 2305:     port = strtol(portptr, NULL, 10);
 2306:     free(portptr);
 2307:   }
 2308:   else {
 2309:     if(data->set.proxyport)
 2310:       /* None given in the proxy string, then get the default one if it is
 2311:          given */
 2312:       port = data->set.proxyport;
 2313:     else {
 2314:       if(proxytype == CURLPROXY_HTTPS)
 2315:         port = CURL_DEFAULT_HTTPS_PROXY_PORT;
 2316:       else
 2317:         port = CURL_DEFAULT_PROXY_PORT;
 2318:     }
 2319:   }
 2320:   if(port >= 0) {
 2321:     proxyinfo->port = port;
 2322:     if(conn->port < 0 || sockstype || !conn->socks_proxy.host.rawalloc)
 2323:       conn->port = port;
 2324:   }
 2325: 
 2326:   /* now, clone the proxy host name */
 2327:   uc = curl_url_get(uhp, CURLUPART_HOST, &host, CURLU_URLDECODE);
 2328:   if(uc) {
 2329:     result = CURLE_OUT_OF_MEMORY;
 2330:     goto error;
 2331:   }
 2332:   Curl_safefree(proxyinfo->host.rawalloc);
 2333:   proxyinfo->host.rawalloc = host;
 2334:   if(host[0] == '[') {
 2335:     /* this is a numerical IPv6, strip off the brackets */
 2336:     size_t len = strlen(host);
 2337:     host[len-1] = 0; /* clear the trailing bracket */
 2338:     host++;
 2339:     zonefrom_url(uhp, conn);
 2340:   }
 2341:   proxyinfo->host.name = host;
 2342: 
 2343:   error:
 2344:   free(scheme);
 2345:   curl_url_cleanup(uhp);
 2346:   return result;
 2347: }
 2348: 
 2349: /*
 2350:  * Extract the user and password from the authentication string
 2351:  */
 2352: static CURLcode parse_proxy_auth(struct Curl_easy *data,
 2353:                                  struct connectdata *conn)
 2354: {
 2355:   char proxyuser[MAX_CURL_USER_LENGTH]="";
 2356:   char proxypasswd[MAX_CURL_PASSWORD_LENGTH]="";
 2357:   CURLcode result;
 2358: 
 2359:   if(data->set.str[STRING_PROXYUSERNAME] != NULL) {
 2360:     strncpy(proxyuser, data->set.str[STRING_PROXYUSERNAME],
 2361:             MAX_CURL_USER_LENGTH);
 2362:     proxyuser[MAX_CURL_USER_LENGTH-1] = '\0';   /*To be on safe side*/
 2363:   }
 2364:   if(data->set.str[STRING_PROXYPASSWORD] != NULL) {
 2365:     strncpy(proxypasswd, data->set.str[STRING_PROXYPASSWORD],
 2366:             MAX_CURL_PASSWORD_LENGTH);
 2367:     proxypasswd[MAX_CURL_PASSWORD_LENGTH-1] = '\0'; /*To be on safe side*/
 2368:   }
 2369: 
 2370:   result = Curl_urldecode(data, proxyuser, 0, &conn->http_proxy.user, NULL,
 2371:                           FALSE);
 2372:   if(!result)
 2373:     result = Curl_urldecode(data, proxypasswd, 0, &conn->http_proxy.passwd,
 2374:                             NULL, FALSE);
 2375:   return result;
 2376: }
 2377: 
 2378: /* create_conn helper to parse and init proxy values. to be called after unix
 2379:    socket init but before any proxy vars are evaluated. */
 2380: static CURLcode create_conn_helper_init_proxy(struct connectdata *conn)
 2381: {
 2382:   char *proxy = NULL;
 2383:   char *socksproxy = NULL;
 2384:   char *no_proxy = NULL;
 2385:   CURLcode result = CURLE_OK;
 2386:   struct Curl_easy *data = conn->data;
 2387: 
 2388:   /*************************************************************
 2389:    * Extract the user and password from the authentication string
 2390:    *************************************************************/
 2391:   if(conn->bits.proxy_user_passwd) {
 2392:     result = parse_proxy_auth(data, conn);
 2393:     if(result)
 2394:       goto out;
 2395:   }
 2396: 
 2397:   /*************************************************************
 2398:    * Detect what (if any) proxy to use
 2399:    *************************************************************/
 2400:   if(data->set.str[STRING_PROXY]) {
 2401:     proxy = strdup(data->set.str[STRING_PROXY]);
 2402:     /* if global proxy is set, this is it */
 2403:     if(NULL == proxy) {
 2404:       failf(data, "memory shortage");
 2405:       result = CURLE_OUT_OF_MEMORY;
 2406:       goto out;
 2407:     }
 2408:   }
 2409: 
 2410:   if(data->set.str[STRING_PRE_PROXY]) {
 2411:     socksproxy = strdup(data->set.str[STRING_PRE_PROXY]);
 2412:     /* if global socks proxy is set, this is it */
 2413:     if(NULL == socksproxy) {
 2414:       failf(data, "memory shortage");
 2415:       result = CURLE_OUT_OF_MEMORY;
 2416:       goto out;
 2417:     }
 2418:   }
 2419: 
 2420:   if(!data->set.str[STRING_NOPROXY]) {
 2421:     const char *p = "no_proxy";
 2422:     no_proxy = curl_getenv(p);
 2423:     if(!no_proxy) {
 2424:       p = "NO_PROXY";
 2425:       no_proxy = curl_getenv(p);
 2426:     }
 2427:     if(no_proxy) {
 2428:       infof(conn->data, "Uses proxy env variable %s == '%s'\n", p, no_proxy);
 2429:     }
 2430:   }
 2431: 
 2432:   if(check_noproxy(conn->host.name, data->set.str[STRING_NOPROXY] ?
 2433:       data->set.str[STRING_NOPROXY] : no_proxy)) {
 2434:     Curl_safefree(proxy);
 2435:     Curl_safefree(socksproxy);
 2436:   }
 2437: #ifndef CURL_DISABLE_HTTP
 2438:   else if(!proxy && !socksproxy)
 2439:     /* if the host is not in the noproxy list, detect proxy. */
 2440:     proxy = detect_proxy(conn);
 2441: #endif /* CURL_DISABLE_HTTP */
 2442: 
 2443:   Curl_safefree(no_proxy);
 2444: 
 2445: #ifdef USE_UNIX_SOCKETS
 2446:   /* For the time being do not mix proxy and unix domain sockets. See #1274 */
 2447:   if(proxy && conn->unix_domain_socket) {
 2448:     free(proxy);
 2449:     proxy = NULL;
 2450:   }
 2451: #endif
 2452: 
 2453:   if(proxy && (!*proxy || (conn->handler->flags & PROTOPT_NONETWORK))) {
 2454:     free(proxy);  /* Don't bother with an empty proxy string or if the
 2455:                      protocol doesn't work with network */
 2456:     proxy = NULL;
 2457:   }
 2458:   if(socksproxy && (!*socksproxy ||
 2459:                     (conn->handler->flags & PROTOPT_NONETWORK))) {
 2460:     free(socksproxy);  /* Don't bother with an empty socks proxy string or if
 2461:                           the protocol doesn't work with network */
 2462:     socksproxy = NULL;
 2463:   }
 2464: 
 2465:   /***********************************************************************
 2466:    * If this is supposed to use a proxy, we need to figure out the proxy host
 2467:    * name, proxy type and port number, so that we can re-use an existing
 2468:    * connection that may exist registered to the same proxy host.
 2469:    ***********************************************************************/
 2470:   if(proxy || socksproxy) {
 2471:     if(proxy) {
 2472:       result = parse_proxy(data, conn, proxy, conn->http_proxy.proxytype);
 2473:       Curl_safefree(proxy); /* parse_proxy copies the proxy string */
 2474:       if(result)
 2475:         goto out;
 2476:     }
 2477: 
 2478:     if(socksproxy) {
 2479:       result = parse_proxy(data, conn, socksproxy,
 2480:                            conn->socks_proxy.proxytype);
 2481:       /* parse_proxy copies the socks proxy string */
 2482:       Curl_safefree(socksproxy);
 2483:       if(result)
 2484:         goto out;
 2485:     }
 2486: 
 2487:     if(conn->http_proxy.host.rawalloc) {
 2488: #ifdef CURL_DISABLE_HTTP
 2489:       /* asking for a HTTP proxy is a bit funny when HTTP is disabled... */
 2490:       result = CURLE_UNSUPPORTED_PROTOCOL;
 2491:       goto out;
 2492: #else
 2493:       /* force this connection's protocol to become HTTP if compatible */
 2494:       if(!(conn->handler->protocol & PROTO_FAMILY_HTTP)) {
 2495:         if((conn->handler->flags & PROTOPT_PROXY_AS_HTTP) &&
 2496:            !conn->bits.tunnel_proxy)
 2497:           conn->handler = &Curl_handler_http;
 2498:         else
 2499:           /* if not converting to HTTP over the proxy, enforce tunneling */
 2500:           conn->bits.tunnel_proxy = TRUE;
 2501:       }
 2502:       conn->bits.httpproxy = TRUE;
 2503: #endif
 2504:     }
 2505:     else {
 2506:       conn->bits.httpproxy = FALSE; /* not a HTTP proxy */
 2507:       conn->bits.tunnel_proxy = FALSE; /* no tunneling if not HTTP */
 2508:     }
 2509: 
 2510:     if(conn->socks_proxy.host.rawalloc) {
 2511:       if(!conn->http_proxy.host.rawalloc) {
 2512:         /* once a socks proxy */
 2513:         if(!conn->socks_proxy.user) {
 2514:           conn->socks_proxy.user = conn->http_proxy.user;
 2515:           conn->http_proxy.user = NULL;
 2516:           Curl_safefree(conn->socks_proxy.passwd);
 2517:           conn->socks_proxy.passwd = conn->http_proxy.passwd;
 2518:           conn->http_proxy.passwd = NULL;
 2519:         }
 2520:       }
 2521:       conn->bits.socksproxy = TRUE;
 2522:     }
 2523:     else
 2524:       conn->bits.socksproxy = FALSE; /* not a socks proxy */
 2525:   }
 2526:   else {
 2527:     conn->bits.socksproxy = FALSE;
 2528:     conn->bits.httpproxy = FALSE;
 2529:   }
 2530:   conn->bits.proxy = conn->bits.httpproxy || conn->bits.socksproxy;
 2531: 
 2532:   if(!conn->bits.proxy) {
 2533:     /* we aren't using the proxy after all... */
 2534:     conn->bits.proxy = FALSE;
 2535:     conn->bits.httpproxy = FALSE;
 2536:     conn->bits.socksproxy = FALSE;
 2537:     conn->bits.proxy_user_passwd = FALSE;
 2538:     conn->bits.tunnel_proxy = FALSE;
 2539:   }
 2540: 
 2541: out:
 2542: 
 2543:   free(socksproxy);
 2544:   free(proxy);
 2545:   return result;
 2546: }
 2547: #endif /* CURL_DISABLE_PROXY */
 2548: 
 2549: /*
 2550:  * Curl_parse_login_details()
 2551:  *
 2552:  * This is used to parse a login string for user name, password and options in
 2553:  * the following formats:
 2554:  *
 2555:  *   user
 2556:  *   user:password
 2557:  *   user:password;options
 2558:  *   user;options
 2559:  *   user;options:password
 2560:  *   :password
 2561:  *   :password;options
 2562:  *   ;options
 2563:  *   ;options:password
 2564:  *
 2565:  * Parameters:
 2566:  *
 2567:  * login    [in]     - The login string.
 2568:  * len      [in]     - The length of the login string.
 2569:  * userp    [in/out] - The address where a pointer to newly allocated memory
 2570:  *                     holding the user will be stored upon completion.
 2571:  * passwdp  [in/out] - The address where a pointer to newly allocated memory
 2572:  *                     holding the password will be stored upon completion.
 2573:  * optionsp [in/out] - The address where a pointer to newly allocated memory
 2574:  *                     holding the options will be stored upon completion.
 2575:  *
 2576:  * Returns CURLE_OK on success.
 2577:  */
 2578: CURLcode Curl_parse_login_details(const char *login, const size_t len,
 2579:                                   char **userp, char **passwdp,
 2580:                                   char **optionsp)
 2581: {
 2582:   CURLcode result = CURLE_OK;
 2583:   char *ubuf = NULL;
 2584:   char *pbuf = NULL;
 2585:   char *obuf = NULL;
 2586:   const char *psep = NULL;
 2587:   const char *osep = NULL;
 2588:   size_t ulen;
 2589:   size_t plen;
 2590:   size_t olen;
 2591: 
 2592:   /* Attempt to find the password separator */
 2593:   if(passwdp) {
 2594:     psep = strchr(login, ':');
 2595: 
 2596:     /* Within the constraint of the login string */
 2597:     if(psep >= login + len)
 2598:       psep = NULL;
 2599:   }
 2600: 
 2601:   /* Attempt to find the options separator */
 2602:   if(optionsp) {
 2603:     osep = strchr(login, ';');
 2604: 
 2605:     /* Within the constraint of the login string */
 2606:     if(osep >= login + len)
 2607:       osep = NULL;
 2608:   }
 2609: 
 2610:   /* Calculate the portion lengths */
 2611:   ulen = (psep ?
 2612:           (size_t)(osep && psep > osep ? osep - login : psep - login) :
 2613:           (osep ? (size_t)(osep - login) : len));
 2614:   plen = (psep ?
 2615:           (osep && osep > psep ? (size_t)(osep - psep) :
 2616:                                  (size_t)(login + len - psep)) - 1 : 0);
 2617:   olen = (osep ?
 2618:           (psep && psep > osep ? (size_t)(psep - osep) :
 2619:                                  (size_t)(login + len - osep)) - 1 : 0);
 2620: 
 2621:   /* Allocate the user portion buffer */
 2622:   if(userp && ulen) {
 2623:     ubuf = malloc(ulen + 1);
 2624:     if(!ubuf)
 2625:       result = CURLE_OUT_OF_MEMORY;
 2626:   }
 2627: 
 2628:   /* Allocate the password portion buffer */
 2629:   if(!result && passwdp && plen) {
 2630:     pbuf = malloc(plen + 1);
 2631:     if(!pbuf) {
 2632:       free(ubuf);
 2633:       result = CURLE_OUT_OF_MEMORY;
 2634:     }
 2635:   }
 2636: 
 2637:   /* Allocate the options portion buffer */
 2638:   if(!result && optionsp && olen) {
 2639:     obuf = malloc(olen + 1);
 2640:     if(!obuf) {
 2641:       free(pbuf);
 2642:       free(ubuf);
 2643:       result = CURLE_OUT_OF_MEMORY;
 2644:     }
 2645:   }
 2646: 
 2647:   if(!result) {
 2648:     /* Store the user portion if necessary */
 2649:     if(ubuf) {
 2650:       memcpy(ubuf, login, ulen);
 2651:       ubuf[ulen] = '\0';
 2652:       Curl_safefree(*userp);
 2653:       *userp = ubuf;
 2654:     }
 2655: 
 2656:     /* Store the password portion if necessary */
 2657:     if(pbuf) {
 2658:       memcpy(pbuf, psep + 1, plen);
 2659:       pbuf[plen] = '\0';
 2660:       Curl_safefree(*passwdp);
 2661:       *passwdp = pbuf;
 2662:     }
 2663: 
 2664:     /* Store the options portion if necessary */
 2665:     if(obuf) {
 2666:       memcpy(obuf, osep + 1, olen);
 2667:       obuf[olen] = '\0';
 2668:       Curl_safefree(*optionsp);
 2669:       *optionsp = obuf;
 2670:     }
 2671:   }
 2672: 
 2673:   return result;
 2674: }
 2675: 
 2676: /*************************************************************
 2677:  * Figure out the remote port number and fix it in the URL
 2678:  *
 2679:  * No matter if we use a proxy or not, we have to figure out the remote
 2680:  * port number of various reasons.
 2681:  *
 2682:  * The port number embedded in the URL is replaced, if necessary.
 2683:  *************************************************************/
 2684: static CURLcode parse_remote_port(struct Curl_easy *data,
 2685:                                   struct connectdata *conn)
 2686: {
 2687: 
 2688:   if(data->set.use_port && data->state.allow_port) {
 2689:     /* if set, we use this instead of the port possibly given in the URL */
 2690:     char portbuf[16];
 2691:     CURLUcode uc;
 2692:     conn->remote_port = (unsigned short)data->set.use_port;
 2693:     msnprintf(portbuf, sizeof(portbuf), "%d", conn->remote_port);
 2694:     uc = curl_url_set(data->state.uh, CURLUPART_PORT, portbuf, 0);
 2695:     if(uc)
 2696:       return CURLE_OUT_OF_MEMORY;
 2697:   }
 2698: 
 2699:   return CURLE_OK;
 2700: }
 2701: 
 2702: /*
 2703:  * Override the login details from the URL with that in the CURLOPT_USERPWD
 2704:  * option or a .netrc file, if applicable.
 2705:  */
 2706: static CURLcode override_login(struct Curl_easy *data,
 2707:                                struct connectdata *conn,
 2708:                                char **userp, char **passwdp, char **optionsp)
 2709: {
 2710:   bool user_changed = FALSE;
 2711:   bool passwd_changed = FALSE;
 2712:   CURLUcode uc;
 2713: 
 2714:   if(data->set.use_netrc == CURL_NETRC_REQUIRED && conn->bits.user_passwd) {
 2715:     /* ignore user+password in the URL */
 2716:     if(*userp) {
 2717:       Curl_safefree(*userp);
 2718:       user_changed = TRUE;
 2719:     }
 2720:     if(*passwdp) {
 2721:       Curl_safefree(*passwdp);
 2722:       passwd_changed = TRUE;
 2723:     }
 2724:     conn->bits.user_passwd = FALSE; /* disable user+password */
 2725:   }
 2726: 
 2727:   if(data->set.str[STRING_USERNAME]) {
 2728:     free(*userp);
 2729:     *userp = strdup(data->set.str[STRING_USERNAME]);
 2730:     if(!*userp)
 2731:       return CURLE_OUT_OF_MEMORY;
 2732:     conn->bits.user_passwd = TRUE; /* enable user+password */
 2733:     user_changed = TRUE;
 2734:   }
 2735: 
 2736:   if(data->set.str[STRING_PASSWORD]) {
 2737:     free(*passwdp);
 2738:     *passwdp = strdup(data->set.str[STRING_PASSWORD]);
 2739:     if(!*passwdp)
 2740:       return CURLE_OUT_OF_MEMORY;
 2741:     conn->bits.user_passwd = TRUE; /* enable user+password */
 2742:     passwd_changed = TRUE;
 2743:   }
 2744: 
 2745:   if(data->set.str[STRING_OPTIONS]) {
 2746:     free(*optionsp);
 2747:     *optionsp = strdup(data->set.str[STRING_OPTIONS]);
 2748:     if(!*optionsp)
 2749:       return CURLE_OUT_OF_MEMORY;
 2750:   }
 2751: 
 2752:   conn->bits.netrc = FALSE;
 2753:   if(data->set.use_netrc != CURL_NETRC_IGNORED &&
 2754:       (!*userp || !**userp || !*passwdp || !**passwdp)) {
 2755:     bool netrc_user_changed = FALSE;
 2756:     bool netrc_passwd_changed = FALSE;
 2757:     int ret;
 2758: 
 2759:     ret = Curl_parsenetrc(conn->host.name,
 2760:                           userp, passwdp,
 2761:                           &netrc_user_changed, &netrc_passwd_changed,
 2762:                           data->set.str[STRING_NETRC_FILE]);
 2763:     if(ret > 0) {
 2764:       infof(data, "Couldn't find host %s in the .netrc file; using defaults\n",
 2765:             conn->host.name);
 2766:     }
 2767:     else if(ret < 0) {
 2768:       return CURLE_OUT_OF_MEMORY;
 2769:     }
 2770:     else {
 2771:       /* set bits.netrc TRUE to remember that we got the name from a .netrc
 2772:          file, so that it is safe to use even if we followed a Location: to a
 2773:          different host or similar. */
 2774:       conn->bits.netrc = TRUE;
 2775:       conn->bits.user_passwd = TRUE; /* enable user+password */
 2776: 
 2777:       if(netrc_user_changed) {
 2778:         user_changed = TRUE;
 2779:       }
 2780:       if(netrc_passwd_changed) {
 2781:         passwd_changed = TRUE;
 2782:       }
 2783:     }
 2784:   }
 2785: 
 2786:   /* for updated strings, we update them in the URL */
 2787:   if(user_changed) {
 2788:     uc = curl_url_set(data->state.uh, CURLUPART_USER, *userp, 0);
 2789:     if(uc)
 2790:       return Curl_uc_to_curlcode(uc);
 2791:   }
 2792:   if(passwd_changed) {
 2793:     uc = curl_url_set(data->state.uh, CURLUPART_PASSWORD, *passwdp, 0);
 2794:     if(uc)
 2795:       return Curl_uc_to_curlcode(uc);
 2796:   }
 2797:   return CURLE_OK;
 2798: }
 2799: 
 2800: /*
 2801:  * Set the login details so they're available in the connection
 2802:  */
 2803: static CURLcode set_login(struct connectdata *conn)
 2804: {
 2805:   CURLcode result = CURLE_OK;
 2806:   const char *setuser = CURL_DEFAULT_USER;
 2807:   const char *setpasswd = CURL_DEFAULT_PASSWORD;
 2808: 
 2809:   /* If our protocol needs a password and we have none, use the defaults */
 2810:   if((conn->handler->flags & PROTOPT_NEEDSPWD) && !conn->bits.user_passwd)
 2811:     ;
 2812:   else {
 2813:     setuser = "";
 2814:     setpasswd = "";
 2815:   }
 2816:   /* Store the default user */
 2817:   if(!conn->user) {
 2818:     conn->user = strdup(setuser);
 2819:     if(!conn->user)
 2820:       return CURLE_OUT_OF_MEMORY;
 2821:   }
 2822: 
 2823:   /* Store the default password */
 2824:   if(!conn->passwd) {
 2825:     conn->passwd = strdup(setpasswd);
 2826:     if(!conn->passwd)
 2827:       result = CURLE_OUT_OF_MEMORY;
 2828:   }
 2829: 
 2830:   return result;
 2831: }
 2832: 
 2833: /*
 2834:  * Parses a "host:port" string to connect to.
 2835:  * The hostname and the port may be empty; in this case, NULL is returned for
 2836:  * the hostname and -1 for the port.
 2837:  */
 2838: static CURLcode parse_connect_to_host_port(struct Curl_easy *data,
 2839:                                            const char *host,
 2840:                                            char **hostname_result,
 2841:                                            int *port_result)
 2842: {
 2843:   char *host_dup;
 2844:   char *hostptr;
 2845:   char *host_portno;
 2846:   char *portptr;
 2847:   int port = -1;
 2848: 
 2849: #if defined(CURL_DISABLE_VERBOSE_STRINGS)
 2850:   (void) data;
 2851: #endif
 2852: 
 2853:   *hostname_result = NULL;
 2854:   *port_result = -1;
 2855: 
 2856:   if(!host || !*host)
 2857:     return CURLE_OK;
 2858: 
 2859:   host_dup = strdup(host);
 2860:   if(!host_dup)
 2861:     return CURLE_OUT_OF_MEMORY;
 2862: 
 2863:   hostptr = host_dup;
 2864: 
 2865:   /* start scanning for port number at this point */
 2866:   portptr = hostptr;
 2867: 
 2868:   /* detect and extract RFC6874-style IPv6-addresses */
 2869:   if(*hostptr == '[') {
 2870: #ifdef ENABLE_IPV6
 2871:     char *ptr = ++hostptr; /* advance beyond the initial bracket */
 2872:     while(*ptr && (ISXDIGIT(*ptr) || (*ptr == ':') || (*ptr == '.')))
 2873:       ptr++;
 2874:     if(*ptr == '%') {
 2875:       /* There might be a zone identifier */
 2876:       if(strncmp("%25", ptr, 3))
 2877:         infof(data, "Please URL encode %% as %%25, see RFC 6874.\n");
 2878:       ptr++;
 2879:       /* Allow unreserved characters as defined in RFC 3986 */
 2880:       while(*ptr && (ISALPHA(*ptr) || ISXDIGIT(*ptr) || (*ptr == '-') ||
 2881:                      (*ptr == '.') || (*ptr == '_') || (*ptr == '~')))
 2882:         ptr++;
 2883:     }
 2884:     if(*ptr == ']')
 2885:       /* yeps, it ended nicely with a bracket as well */
 2886:       *ptr++ = '\0';
 2887:     else
 2888:       infof(data, "Invalid IPv6 address format\n");
 2889:     portptr = ptr;
 2890:     /* Note that if this didn't end with a bracket, we still advanced the
 2891:      * hostptr first, but I can't see anything wrong with that as no host
 2892:      * name nor a numeric can legally start with a bracket.
 2893:      */
 2894: #else
 2895:     failf(data, "Use of IPv6 in *_CONNECT_TO without IPv6 support built-in!");
 2896:     free(host_dup);
 2897:     return CURLE_NOT_BUILT_IN;
 2898: #endif
 2899:   }
 2900: 
 2901:   /* Get port number off server.com:1080 */
 2902:   host_portno = strchr(portptr, ':');
 2903:   if(host_portno) {
 2904:     char *endp = NULL;
 2905:     *host_portno = '\0'; /* cut off number from host name */
 2906:     host_portno++;
 2907:     if(*host_portno) {
 2908:       long portparse = strtol(host_portno, &endp, 10);
 2909:       if((endp && *endp) || (portparse < 0) || (portparse > 65535)) {
 2910:         infof(data, "No valid port number in connect to host string (%s)\n",
 2911:               host_portno);
 2912:         hostptr = NULL;
 2913:         port = -1;
 2914:       }
 2915:       else
 2916:         port = (int)portparse; /* we know it will fit */
 2917:     }
 2918:   }
 2919: 
 2920:   /* now, clone the cleaned host name */
 2921:   if(hostptr) {
 2922:     *hostname_result = strdup(hostptr);
 2923:     if(!*hostname_result) {
 2924:       free(host_dup);
 2925:       return CURLE_OUT_OF_MEMORY;
 2926:     }
 2927:   }
 2928: 
 2929:   *port_result = port;
 2930: 
 2931:   free(host_dup);
 2932:   return CURLE_OK;
 2933: }
 2934: 
 2935: /*
 2936:  * Parses one "connect to" string in the form:
 2937:  * "HOST:PORT:CONNECT-TO-HOST:CONNECT-TO-PORT".
 2938:  */
 2939: static CURLcode parse_connect_to_string(struct Curl_easy *data,
 2940:                                         struct connectdata *conn,
 2941:                                         const char *conn_to_host,
 2942:                                         char **host_result,
 2943:                                         int *port_result)
 2944: {
 2945:   CURLcode result = CURLE_OK;
 2946:   const char *ptr = conn_to_host;
 2947:   int host_match = FALSE;
 2948:   int port_match = FALSE;
 2949: 
 2950:   *host_result = NULL;
 2951:   *port_result = -1;
 2952: 
 2953:   if(*ptr == ':') {
 2954:     /* an empty hostname always matches */
 2955:     host_match = TRUE;
 2956:     ptr++;
 2957:   }
 2958:   else {
 2959:     /* check whether the URL's hostname matches */
 2960:     size_t hostname_to_match_len;
 2961:     char *hostname_to_match = aprintf("%s%s%s",
 2962:                                       conn->bits.ipv6_ip ? "[" : "",
 2963:                                       conn->host.name,
 2964:                                       conn->bits.ipv6_ip ? "]" : "");
 2965:     if(!hostname_to_match)
 2966:       return CURLE_OUT_OF_MEMORY;
 2967:     hostname_to_match_len = strlen(hostname_to_match);
 2968:     host_match = strncasecompare(ptr, hostname_to_match,
 2969:                                  hostname_to_match_len);
 2970:     free(hostname_to_match);
 2971:     ptr += hostname_to_match_len;
 2972: 
 2973:     host_match = host_match && *ptr == ':';
 2974:     ptr++;
 2975:   }
 2976: 
 2977:   if(host_match) {
 2978:     if(*ptr == ':') {
 2979:       /* an empty port always matches */
 2980:       port_match = TRUE;
 2981:       ptr++;
 2982:     }
 2983:     else {
 2984:       /* check whether the URL's port matches */
 2985:       char *ptr_next = strchr(ptr, ':');
 2986:       if(ptr_next) {
 2987:         char *endp = NULL;
 2988:         long port_to_match = strtol(ptr, &endp, 10);
 2989:         if((endp == ptr_next) && (port_to_match == conn->remote_port)) {
 2990:           port_match = TRUE;
 2991:           ptr = ptr_next + 1;
 2992:         }
 2993:       }
 2994:     }
 2995:   }
 2996: 
 2997:   if(host_match && port_match) {
 2998:     /* parse the hostname and port to connect to */
 2999:     result = parse_connect_to_host_port(data, ptr, host_result, port_result);
 3000:   }
 3001: 
 3002:   return result;
 3003: }
 3004: 
 3005: /*
 3006:  * Processes all strings in the "connect to" slist, and uses the "connect
 3007:  * to host" and "connect to port" of the first string that matches.
 3008:  */
 3009: static CURLcode parse_connect_to_slist(struct Curl_easy *data,
 3010:                                        struct connectdata *conn,
 3011:                                        struct curl_slist *conn_to_host)
 3012: {
 3013:   CURLcode result = CURLE_OK;
 3014:   char *host = NULL;
 3015:   int port = -1;
 3016: 
 3017:   while(conn_to_host && !host && port == -1) {
 3018:     result = parse_connect_to_string(data, conn, conn_to_host->data,
 3019:                                      &host, &port);
 3020:     if(result)
 3021:       return result;
 3022: 
 3023:     if(host && *host) {
 3024:       conn->conn_to_host.rawalloc = host;
 3025:       conn->conn_to_host.name = host;
 3026:       conn->bits.conn_to_host = TRUE;
 3027: 
 3028:       infof(data, "Connecting to hostname: %s\n", host);
 3029:     }
 3030:     else {
 3031:       /* no "connect to host" */
 3032:       conn->bits.conn_to_host = FALSE;
 3033:       Curl_safefree(host);
 3034:     }
 3035: 
 3036:     if(port >= 0) {
 3037:       conn->conn_to_port = port;
 3038:       conn->bits.conn_to_port = TRUE;
 3039:       infof(data, "Connecting to port: %d\n", port);
 3040:     }
 3041:     else {
 3042:       /* no "connect to port" */
 3043:       conn->bits.conn_to_port = FALSE;
 3044:       port = -1;
 3045:     }
 3046: 
 3047:     conn_to_host = conn_to_host->next;
 3048:   }
 3049: 
 3050: #ifdef USE_ALTSVC
 3051:   if(data->asi && !host && (port == -1) &&
 3052:      ((conn->handler->protocol == CURLPROTO_HTTPS) ||
 3053: #ifdef CURLDEBUG
 3054:       /* allow debug builds to circumvent the HTTPS restriction */
 3055:       getenv("CURL_ALTSVC_HTTP")
 3056: #else
 3057:       0
 3058: #endif
 3059:        )) {
 3060:     /* no connect_to match, try alt-svc! */
 3061:     enum alpnid srcalpnid;
 3062:     bool hit;
 3063:     struct altsvc *as;
 3064:     const int allowed_versions = ( ALPN_h1
 3065: #ifdef USE_NGHTTP2
 3066:       | ALPN_h2
 3067: #endif
 3068: #ifdef ENABLE_QUIC
 3069:       | ALPN_h3
 3070: #endif
 3071:       ) & data->asi->flags;
 3072: 
 3073:     host = conn->host.rawalloc;
 3074: #ifdef USE_NGHTTP2
 3075:     /* with h2 support, check that first */
 3076:     srcalpnid = ALPN_h2;
 3077:     hit = Curl_altsvc_lookup(data->asi,
 3078:                              srcalpnid, host, conn->remote_port, /* from */
 3079:                              &as /* to */,
 3080:                              allowed_versions);
 3081:     if(!hit)
 3082: #endif
 3083:     {
 3084:       srcalpnid = ALPN_h1;
 3085:       hit = Curl_altsvc_lookup(data->asi,
 3086:                                srcalpnid, host, conn->remote_port, /* from */
 3087:                                &as /* to */,
 3088:                                allowed_versions);
 3089:     }
 3090:     if(hit) {
 3091:       char *hostd = strdup((char *)as->dst.host);
 3092:       if(!hostd)
 3093:         return CURLE_OUT_OF_MEMORY;
 3094:       conn->conn_to_host.rawalloc = hostd;
 3095:       conn->conn_to_host.name = hostd;
 3096:       conn->bits.conn_to_host = TRUE;
 3097:       conn->conn_to_port = as->dst.port;
 3098:       conn->bits.conn_to_port = TRUE;
 3099:       conn->bits.altused = TRUE;
 3100:       infof(data, "Alt-svc connecting from [%s]%s:%d to [%s]%s:%d\n",
 3101:             Curl_alpnid2str(srcalpnid), host, conn->remote_port,
 3102:             Curl_alpnid2str(as->dst.alpnid), hostd, as->dst.port);
 3103:       if(srcalpnid != as->dst.alpnid) {
 3104:         /* protocol version switch */
 3105:         switch(as->dst.alpnid) {
 3106:         case ALPN_h1:
 3107:           conn->httpversion = 11;
 3108:           break;
 3109:         case ALPN_h2:
 3110:           conn->httpversion = 20;
 3111:           break;
 3112:         case ALPN_h3:
 3113:           conn->transport = TRNSPRT_QUIC;
 3114:           conn->httpversion = 30;
 3115:           break;
 3116:         default: /* shouldn't be possible */
 3117:           break;
 3118:         }
 3119:       }
 3120:     }
 3121:   }
 3122: #endif
 3123: 
 3124:   return result;
 3125: }
 3126: 
 3127: /*************************************************************
 3128:  * Resolve the address of the server or proxy
 3129:  *************************************************************/
 3130: static CURLcode resolve_server(struct Curl_easy *data,
 3131:                                struct connectdata *conn,
 3132:                                bool *async)
 3133: {
 3134:   CURLcode result = CURLE_OK;
 3135:   timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE);
 3136: 
 3137:   DEBUGASSERT(conn);
 3138:   DEBUGASSERT(data);
 3139:   /*************************************************************
 3140:    * Resolve the name of the server or proxy
 3141:    *************************************************************/
 3142:   if(conn->bits.reuse)
 3143:     /* We're reusing the connection - no need to resolve anything, and
 3144:        idnconvert_hostname() was called already in create_conn() for the re-use
 3145:        case. */
 3146:     *async = FALSE;
 3147: 
 3148:   else {
 3149:     /* this is a fresh connect */
 3150:     int rc;
 3151:     struct Curl_dns_entry *hostaddr;
 3152: 
 3153: #ifdef USE_UNIX_SOCKETS
 3154:     if(conn->unix_domain_socket) {
 3155:       /* Unix domain sockets are local. The host gets ignored, just use the
 3156:        * specified domain socket address. Do not cache "DNS entries". There is
 3157:        * no DNS involved and we already have the filesystem path available */
 3158:       const char *path = conn->unix_domain_socket;
 3159: 
 3160:       hostaddr = calloc(1, sizeof(struct Curl_dns_entry));
 3161:       if(!hostaddr)
 3162:         result = CURLE_OUT_OF_MEMORY;
 3163:       else {
 3164:         bool longpath = FALSE;
 3165:         hostaddr->addr = Curl_unix2addr(path, &longpath,
 3166:                                         conn->abstract_unix_socket);
 3167:         if(hostaddr->addr)
 3168:           hostaddr->inuse++;
 3169:         else {
 3170:           /* Long paths are not supported for now */
 3171:           if(longpath) {
 3172:             failf(data, "Unix socket path too long: '%s'", path);
 3173:             result = CURLE_COULDNT_RESOLVE_HOST;
 3174:           }
 3175:           else
 3176:             result = CURLE_OUT_OF_MEMORY;
 3177:           free(hostaddr);
 3178:           hostaddr = NULL;
 3179:         }
 3180:       }
 3181:     }
 3182:     else
 3183: #endif
 3184:     if(!conn->bits.proxy) {
 3185:       struct hostname *connhost;
 3186:       if(conn->bits.conn_to_host)
 3187:         connhost = &conn->conn_to_host;
 3188:       else
 3189:         connhost = &conn->host;
 3190: 
 3191:       /* If not connecting via a proxy, extract the port from the URL, if it is
 3192:        * there, thus overriding any defaults that might have been set above. */
 3193:       if(conn->bits.conn_to_port)
 3194:         conn->port = conn->conn_to_port;
 3195:       else
 3196:         conn->port = conn->remote_port;
 3197: 
 3198:       /* Resolve target host right on */
 3199:       conn->hostname_resolve = strdup(connhost->name);
 3200:       if(!conn->hostname_resolve)
 3201:         return CURLE_OUT_OF_MEMORY;
 3202:       rc = Curl_resolv_timeout(conn, conn->hostname_resolve, (int)conn->port,
 3203:                                &hostaddr, timeout_ms);
 3204:       if(rc == CURLRESOLV_PENDING)
 3205:         *async = TRUE;
 3206: 
 3207:       else if(rc == CURLRESOLV_TIMEDOUT)
 3208:         result = CURLE_OPERATION_TIMEDOUT;
 3209: 
 3210:       else if(!hostaddr) {
 3211:         failf(data, "Couldn't resolve host '%s'", connhost->dispname);
 3212:         result =  CURLE_COULDNT_RESOLVE_HOST;
 3213:         /* don't return yet, we need to clean up the timeout first */
 3214:       }
 3215:     }
 3216:     else {
 3217:       /* This is a proxy that hasn't been resolved yet. */
 3218: 
 3219:       struct hostname * const host = conn->bits.socksproxy ?
 3220:         &conn->socks_proxy.host : &conn->http_proxy.host;
 3221: 
 3222:       /* resolve proxy */
 3223:       conn->hostname_resolve = strdup(host->name);
 3224:       if(!conn->hostname_resolve)
 3225:         return CURLE_OUT_OF_MEMORY;
 3226:       rc = Curl_resolv_timeout(conn, conn->hostname_resolve, (int)conn->port,
 3227:                                &hostaddr, timeout_ms);
 3228: 
 3229:       if(rc == CURLRESOLV_PENDING)
 3230:         *async = TRUE;
 3231: 
 3232:       else if(rc == CURLRESOLV_TIMEDOUT)
 3233:         result = CURLE_OPERATION_TIMEDOUT;
 3234: 
 3235:       else if(!hostaddr) {
 3236:         failf(data, "Couldn't resolve proxy '%s'", host->dispname);
 3237:         result = CURLE_COULDNT_RESOLVE_PROXY;
 3238:         /* don't return yet, we need to clean up the timeout first */
 3239:       }
 3240:     }
 3241:     DEBUGASSERT(conn->dns_entry == NULL);
 3242:     conn->dns_entry = hostaddr;
 3243:   }
 3244: 
 3245:   return result;
 3246: }
 3247: 
 3248: /*
 3249:  * Cleanup the connection just allocated before we can move along and use the
 3250:  * previously existing one.  All relevant data is copied over and old_conn is
 3251:  * ready for freeing once this function returns.
 3252:  */
 3253: static void reuse_conn(struct connectdata *old_conn,
 3254:                        struct connectdata *conn)
 3255: {
 3256:   Curl_free_idnconverted_hostname(&old_conn->http_proxy.host);
 3257:   Curl_free_idnconverted_hostname(&old_conn->socks_proxy.host);
 3258: 
 3259:   free(old_conn->http_proxy.host.rawalloc);
 3260:   free(old_conn->socks_proxy.host.rawalloc);
 3261: 
 3262:   /* free the SSL config struct from this connection struct as this was
 3263:      allocated in vain and is targeted for destruction */
 3264:   Curl_free_primary_ssl_config(&old_conn->ssl_config);
 3265:   Curl_free_primary_ssl_config(&old_conn->proxy_ssl_config);
 3266: 
 3267:   conn->data = old_conn->data;
 3268: 
 3269:   /* get the user+password information from the old_conn struct since it may
 3270:    * be new for this request even when we re-use an existing connection */
 3271:   conn->bits.user_passwd = old_conn->bits.user_passwd;
 3272:   if(conn->bits.user_passwd) {
 3273:     /* use the new user name and password though */
 3274:     Curl_safefree(conn->user);
 3275:     Curl_safefree(conn->passwd);
 3276:     conn->user = old_conn->user;
 3277:     conn->passwd = old_conn->passwd;
 3278:     old_conn->user = NULL;
 3279:     old_conn->passwd = NULL;
 3280:   }
 3281: 
 3282:   conn->bits.proxy_user_passwd = old_conn->bits.proxy_user_passwd;
 3283:   if(conn->bits.proxy_user_passwd) {
 3284:     /* use the new proxy user name and proxy password though */
 3285:     Curl_safefree(conn->http_proxy.user);
 3286:     Curl_safefree(conn->socks_proxy.user);
 3287:     Curl_safefree(conn->http_proxy.passwd);
 3288:     Curl_safefree(conn->socks_proxy.passwd);
 3289:     conn->http_proxy.user = old_conn->http_proxy.user;
 3290:     conn->socks_proxy.user = old_conn->socks_proxy.user;
 3291:     conn->http_proxy.passwd = old_conn->http_proxy.passwd;
 3292:     conn->socks_proxy.passwd = old_conn->socks_proxy.passwd;
 3293:     old_conn->http_proxy.user = NULL;
 3294:     old_conn->socks_proxy.user = NULL;
 3295:     old_conn->http_proxy.passwd = NULL;
 3296:     old_conn->socks_proxy.passwd = NULL;
 3297:   }
 3298: 
 3299:   /* host can change, when doing keepalive with a proxy or if the case is
 3300:      different this time etc */
 3301:   Curl_free_idnconverted_hostname(&conn->host);
 3302:   Curl_free_idnconverted_hostname(&conn->conn_to_host);
 3303:   Curl_safefree(conn->host.rawalloc);
 3304:   Curl_safefree(conn->conn_to_host.rawalloc);
 3305:   conn->host = old_conn->host;
 3306:   conn->conn_to_host = old_conn->conn_to_host;
 3307:   conn->conn_to_port = old_conn->conn_to_port;
 3308:   conn->remote_port = old_conn->remote_port;
 3309:   Curl_safefree(conn->hostname_resolve);
 3310: 
 3311:   conn->hostname_resolve = old_conn->hostname_resolve;
 3312:   old_conn->hostname_resolve = NULL;
 3313: 
 3314:   /* persist connection info in session handle */
 3315:   Curl_persistconninfo(conn);
 3316: 
 3317:   conn_reset_all_postponed_data(old_conn); /* free buffers */
 3318: 
 3319:   /* re-use init */
 3320:   conn->bits.reuse = TRUE; /* yes, we're re-using here */
 3321: 
 3322:   Curl_safefree(old_conn->user);
 3323:   Curl_safefree(old_conn->passwd);
 3324:   Curl_safefree(old_conn->options);
 3325:   Curl_safefree(old_conn->http_proxy.user);
 3326:   Curl_safefree(old_conn->socks_proxy.user);
 3327:   Curl_safefree(old_conn->http_proxy.passwd);
 3328:   Curl_safefree(old_conn->socks_proxy.passwd);
 3329:   Curl_safefree(old_conn->localdev);
 3330:   Curl_llist_destroy(&old_conn->easyq, NULL);
 3331: 
 3332: #ifdef USE_UNIX_SOCKETS
 3333:   Curl_safefree(old_conn->unix_domain_socket);
 3334: #endif
 3335: }
 3336: 
 3337: /**
 3338:  * create_conn() sets up a new connectdata struct, or re-uses an already
 3339:  * existing one, and resolves host name.
 3340:  *
 3341:  * if this function returns CURLE_OK and *async is set to TRUE, the resolve
 3342:  * response will be coming asynchronously. If *async is FALSE, the name is
 3343:  * already resolved.
 3344:  *
 3345:  * @param data The sessionhandle pointer
 3346:  * @param in_connect is set to the next connection data pointer
 3347:  * @param async is set TRUE when an async DNS resolution is pending
 3348:  * @see Curl_setup_conn()
 3349:  *
 3350:  * *NOTE* this function assigns the conn->data pointer!
 3351:  */
 3352: 
 3353: static CURLcode create_conn(struct Curl_easy *data,
 3354:                             struct connectdata **in_connect,
 3355:                             bool *async)
 3356: {
 3357:   CURLcode result = CURLE_OK;
 3358:   struct connectdata *conn;
 3359:   struct connectdata *conn_temp = NULL;
 3360:   bool reuse;
 3361:   bool connections_available = TRUE;
 3362:   bool force_reuse = FALSE;
 3363:   bool waitpipe = FALSE;
 3364:   size_t max_host_connections = Curl_multi_max_host_connections(data->multi);
 3365:   size_t max_total_connections = Curl_multi_max_total_connections(data->multi);
 3366: 
 3367:   *async = FALSE;
 3368:   *in_connect = NULL;
 3369: 
 3370:   /*************************************************************
 3371:    * Check input data
 3372:    *************************************************************/
 3373:   if(!data->change.url) {
 3374:     result = CURLE_URL_MALFORMAT;
 3375:     goto out;
 3376:   }
 3377: 
 3378:   /* First, split up the current URL in parts so that we can use the
 3379:      parts for checking against the already present connections. In order
 3380:      to not have to modify everything at once, we allocate a temporary
 3381:      connection data struct and fill in for comparison purposes. */
 3382:   conn = allocate_conn(data);
 3383: 
 3384:   if(!conn) {
 3385:     result = CURLE_OUT_OF_MEMORY;
 3386:     goto out;
 3387:   }
 3388: 
 3389:   /* We must set the return variable as soon as possible, so that our
 3390:      parent can cleanup any possible allocs we may have done before
 3391:      any failure */
 3392:   *in_connect = conn;
 3393: 
 3394:   result = parseurlandfillconn(data, conn);
 3395:   if(result)
 3396:     goto out;
 3397: 
 3398:   if(data->set.str[STRING_SASL_AUTHZID]) {
 3399:     conn->sasl_authzid = strdup(data->set.str[STRING_SASL_AUTHZID]);
 3400:     if(!conn->sasl_authzid) {
 3401:       result = CURLE_OUT_OF_MEMORY;
 3402:       goto out;
 3403:     }
 3404:   }
 3405: 
 3406: #ifdef USE_UNIX_SOCKETS
 3407:   if(data->set.str[STRING_UNIX_SOCKET_PATH]) {
 3408:     conn->unix_domain_socket = strdup(data->set.str[STRING_UNIX_SOCKET_PATH]);
 3409:     if(conn->unix_domain_socket == NULL) {
 3410:       result = CURLE_OUT_OF_MEMORY;
 3411:       goto out;
 3412:     }
 3413:     conn->abstract_unix_socket = data->set.abstract_unix_socket;
 3414:   }
 3415: #endif
 3416: 
 3417:   /* After the unix socket init but before the proxy vars are used, parse and
 3418:      initialize the proxy vars */
 3419: #ifndef CURL_DISABLE_PROXY
 3420:   result = create_conn_helper_init_proxy(conn);
 3421:   if(result)
 3422:     goto out;
 3423: #endif
 3424: 
 3425:   /*************************************************************
 3426:    * If the protocol is using SSL and HTTP proxy is used, we set
 3427:    * the tunnel_proxy bit.
 3428:    *************************************************************/
 3429:   if((conn->given->flags&PROTOPT_SSL) && conn->bits.httpproxy)
 3430:     conn->bits.tunnel_proxy = TRUE;
 3431: 
 3432:   /*************************************************************
 3433:    * Figure out the remote port number and fix it in the URL
 3434:    *************************************************************/
 3435:   result = parse_remote_port(data, conn);
 3436:   if(result)
 3437:     goto out;
 3438: 
 3439:   /* Check for overridden login details and set them accordingly so they
 3440:      they are known when protocol->setup_connection is called! */
 3441:   result = override_login(data, conn, &conn->user, &conn->passwd,
 3442:                           &conn->options);
 3443:   if(result)
 3444:     goto out;
 3445: 
 3446:   result = set_login(conn); /* default credentials */
 3447:   if(result)
 3448:     goto out;
 3449: 
 3450:   /*************************************************************
 3451:    * Process the "connect to" linked list of hostname/port mappings.
 3452:    * Do this after the remote port number has been fixed in the URL.
 3453:    *************************************************************/
 3454:   result = parse_connect_to_slist(data, conn, data->set.connect_to);
 3455:   if(result)
 3456:     goto out;
 3457: 
 3458:   /*************************************************************
 3459:    * IDN-convert the hostnames
 3460:    *************************************************************/
 3461:   result = Curl_idnconvert_hostname(conn, &conn->host);
 3462:   if(result)
 3463:     goto out;
 3464:   if(conn->bits.conn_to_host) {
 3465:     result = Curl_idnconvert_hostname(conn, &conn->conn_to_host);
 3466:     if(result)
 3467:       goto out;
 3468:   }
 3469:   if(conn->bits.httpproxy) {
 3470:     result = Curl_idnconvert_hostname(conn, &conn->http_proxy.host);
 3471:     if(result)
 3472:       goto out;
 3473:   }
 3474:   if(conn->bits.socksproxy) {
 3475:     result = Curl_idnconvert_hostname(conn, &conn->socks_proxy.host);
 3476:     if(result)
 3477:       goto out;
 3478:   }
 3479: 
 3480:   /*************************************************************
 3481:    * Check whether the host and the "connect to host" are equal.
 3482:    * Do this after the hostnames have been IDN-converted.
 3483:    *************************************************************/
 3484:   if(conn->bits.conn_to_host &&
 3485:      strcasecompare(conn->conn_to_host.name, conn->host.name)) {
 3486:     conn->bits.conn_to_host = FALSE;
 3487:   }
 3488: 
 3489:   /*************************************************************
 3490:    * Check whether the port and the "connect to port" are equal.
 3491:    * Do this after the remote port number has been fixed in the URL.
 3492:    *************************************************************/
 3493:   if(conn->bits.conn_to_port && conn->conn_to_port == conn->remote_port) {
 3494:     conn->bits.conn_to_port = FALSE;
 3495:   }
 3496: 
 3497:   /*************************************************************
 3498:    * If the "connect to" feature is used with an HTTP proxy,
 3499:    * we set the tunnel_proxy bit.
 3500:    *************************************************************/
 3501:   if((conn->bits.conn_to_host || conn->bits.conn_to_port) &&
 3502:       conn->bits.httpproxy)
 3503:     conn->bits.tunnel_proxy = TRUE;
 3504: 
 3505:   /*************************************************************
 3506:    * Setup internals depending on protocol. Needs to be done after
 3507:    * we figured out what/if proxy to use.
 3508:    *************************************************************/
 3509:   result = setup_connection_internals(conn);
 3510:   if(result)
 3511:     goto out;
 3512: 
 3513:   conn->recv[FIRSTSOCKET] = Curl_recv_plain;
 3514:   conn->send[FIRSTSOCKET] = Curl_send_plain;
 3515:   conn->recv[SECONDARYSOCKET] = Curl_recv_plain;
 3516:   conn->send[SECONDARYSOCKET] = Curl_send_plain;
 3517: 
 3518:   conn->bits.tcp_fastopen = data->set.tcp_fastopen;
 3519: 
 3520:   /***********************************************************************
 3521:    * file: is a special case in that it doesn't need a network connection
 3522:    ***********************************************************************/
 3523: #ifndef CURL_DISABLE_FILE
 3524:   if(conn->handler->flags & PROTOPT_NONETWORK) {
 3525:     bool done;
 3526:     /* this is supposed to be the connect function so we better at least check
 3527:        that the file is present here! */
 3528:     DEBUGASSERT(conn->handler->connect_it);
 3529:     Curl_persistconninfo(conn);
 3530:     result = conn->handler->connect_it(conn, &done);
 3531: 
 3532:     /* Setup a "faked" transfer that'll do nothing */
 3533:     if(!result) {
 3534:       conn->bits.tcpconnect[FIRSTSOCKET] = TRUE; /* we are "connected */
 3535: 
 3536:       result = Curl_conncache_add_conn(data->state.conn_cache, conn);
 3537:       if(result)
 3538:         goto out;
 3539: 
 3540:       /*
 3541:        * Setup whatever necessary for a resumed transfer
 3542:        */
 3543:       result = setup_range(data);
 3544:       if(result) {
 3545:         DEBUGASSERT(conn->handler->done);
 3546:         /* we ignore the return code for the protocol-specific DONE */
 3547:         (void)conn->handler->done(conn, result, FALSE);
 3548:         goto out;
 3549:       }
 3550:       Curl_attach_connnection(data, conn);
 3551:       Curl_setup_transfer(data, -1, -1, FALSE, -1);
 3552:     }
 3553: 
 3554:     /* since we skip do_init() */
 3555:     Curl_init_do(data, conn);
 3556: 
 3557:     goto out;
 3558:   }
 3559: #endif
 3560: 
 3561:   /* Get a cloned copy of the SSL config situation stored in the
 3562:      connection struct. But to get this going nicely, we must first make
 3563:      sure that the strings in the master copy are pointing to the correct
 3564:      strings in the session handle strings array!
 3565: 
 3566:      Keep in mind that the pointers in the master copy are pointing to strings
 3567:      that will be freed as part of the Curl_easy struct, but all cloned
 3568:      copies will be separately allocated.
 3569:   */
 3570:   data->set.ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH_ORIG];
 3571:   data->set.proxy_ssl.primary.CApath = data->set.str[STRING_SSL_CAPATH_PROXY];
 3572:   data->set.ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE_ORIG];
 3573:   data->set.proxy_ssl.primary.CAfile = data->set.str[STRING_SSL_CAFILE_PROXY];
 3574:   data->set.ssl.primary.random_file = data->set.str[STRING_SSL_RANDOM_FILE];
 3575:   data->set.proxy_ssl.primary.random_file =
 3576:     data->set.str[STRING_SSL_RANDOM_FILE];
 3577:   data->set.ssl.primary.egdsocket = data->set.str[STRING_SSL_EGDSOCKET];
 3578:   data->set.proxy_ssl.primary.egdsocket = data->set.str[STRING_SSL_EGDSOCKET];
 3579:   data->set.ssl.primary.cipher_list =
 3580:     data->set.str[STRING_SSL_CIPHER_LIST_ORIG];
 3581:   data->set.proxy_ssl.primary.cipher_list =
 3582:     data->set.str[STRING_SSL_CIPHER_LIST_PROXY];
 3583:   data->set.ssl.primary.cipher_list13 =
 3584:     data->set.str[STRING_SSL_CIPHER13_LIST_ORIG];
 3585:   data->set.proxy_ssl.primary.cipher_list13 =
 3586:     data->set.str[STRING_SSL_CIPHER13_LIST_PROXY];
 3587:   data->set.ssl.primary.pinned_key =
 3588:     data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG];
 3589:   data->set.proxy_ssl.primary.pinned_key =
 3590:     data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY];
 3591: 
 3592:   data->set.ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE_ORIG];
 3593:   data->set.proxy_ssl.CRLfile = data->set.str[STRING_SSL_CRLFILE_PROXY];
 3594:   data->set.ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT_ORIG];
 3595:   data->set.proxy_ssl.issuercert = data->set.str[STRING_SSL_ISSUERCERT_PROXY];
 3596:   data->set.ssl.cert = data->set.str[STRING_CERT_ORIG];
 3597:   data->set.proxy_ssl.cert = data->set.str[STRING_CERT_PROXY];
 3598:   data->set.ssl.cert_type = data->set.str[STRING_CERT_TYPE_ORIG];
 3599:   data->set.proxy_ssl.cert_type = data->set.str[STRING_CERT_TYPE_PROXY];
 3600:   data->set.ssl.key = data->set.str[STRING_KEY_ORIG];
 3601:   data->set.proxy_ssl.key = data->set.str[STRING_KEY_PROXY];
 3602:   data->set.ssl.key_type = data->set.str[STRING_KEY_TYPE_ORIG];
 3603:   data->set.proxy_ssl.key_type = data->set.str[STRING_KEY_TYPE_PROXY];
 3604:   data->set.ssl.key_passwd = data->set.str[STRING_KEY_PASSWD_ORIG];
 3605:   data->set.proxy_ssl.key_passwd = data->set.str[STRING_KEY_PASSWD_PROXY];
 3606:   data->set.ssl.primary.clientcert = data->set.str[STRING_CERT_ORIG];
 3607:   data->set.proxy_ssl.primary.clientcert = data->set.str[STRING_CERT_PROXY];
 3608: #ifdef USE_TLS_SRP
 3609:   data->set.ssl.username = data->set.str[STRING_TLSAUTH_USERNAME_ORIG];
 3610:   data->set.proxy_ssl.username = data->set.str[STRING_TLSAUTH_USERNAME_PROXY];
 3611:   data->set.ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD_ORIG];
 3612:   data->set.proxy_ssl.password = data->set.str[STRING_TLSAUTH_PASSWORD_PROXY];
 3613: #endif
 3614: 
 3615:   if(!Curl_clone_primary_ssl_config(&data->set.ssl.primary,
 3616:      &conn->ssl_config)) {
 3617:     result = CURLE_OUT_OF_MEMORY;
 3618:     goto out;
 3619:   }
 3620: 
 3621:   if(!Curl_clone_primary_ssl_config(&data->set.proxy_ssl.primary,
 3622:                                     &conn->proxy_ssl_config)) {
 3623:     result = CURLE_OUT_OF_MEMORY;
 3624:     goto out;
 3625:   }
 3626: 
 3627:   prune_dead_connections(data);
 3628: 
 3629:   /*************************************************************
 3630:    * Check the current list of connections to see if we can
 3631:    * re-use an already existing one or if we have to create a
 3632:    * new one.
 3633:    *************************************************************/
 3634: 
 3635:   DEBUGASSERT(conn->user);
 3636:   DEBUGASSERT(conn->passwd);
 3637: 
 3638:   /* reuse_fresh is TRUE if we are told to use a new connection by force, but
 3639:      we only acknowledge this option if this is not a re-used connection
 3640:      already (which happens due to follow-location or during a HTTP
 3641:      authentication phase). CONNECT_ONLY transfers also refuse reuse. */
 3642:   if((data->set.reuse_fresh && !data->state.this_is_a_follow) ||
 3643:      data->set.connect_only)
 3644:     reuse = FALSE;
 3645:   else
 3646:     reuse = ConnectionExists(data, conn, &conn_temp, &force_reuse, &waitpipe);
 3647: 
 3648:   if(reuse) {
 3649:     /*
 3650:      * We already have a connection for this, we got the former connection
 3651:      * in the conn_temp variable and thus we need to cleanup the one we
 3652:      * just allocated before we can move along and use the previously
 3653:      * existing one.
 3654:      */
 3655:     reuse_conn(conn, conn_temp);
 3656: #ifdef USE_SSL
 3657:     free(conn->ssl_extra);
 3658: #endif
 3659:     free(conn);          /* we don't need this anymore */
 3660:     conn = conn_temp;
 3661:     *in_connect = conn;
 3662: 
 3663:     infof(data, "Re-using existing connection! (#%ld) with %s %s\n",
 3664:           conn->connection_id,
 3665:           conn->bits.proxy?"proxy":"host",
 3666:           conn->socks_proxy.host.name ? conn->socks_proxy.host.dispname :
 3667:           conn->http_proxy.host.name ? conn->http_proxy.host.dispname :
 3668:                                        conn->host.dispname);
 3669:   }
 3670:   else {
 3671:     /* We have decided that we want a new connection. However, we may not
 3672:        be able to do that if we have reached the limit of how many
 3673:        connections we are allowed to open. */
 3674: 
 3675:     if(conn->handler->flags & PROTOPT_ALPN_NPN) {
 3676:       /* The protocol wants it, so set the bits if enabled in the easy handle
 3677:          (default) */
 3678:       if(data->set.ssl_enable_alpn)
 3679:         conn->bits.tls_enable_alpn = TRUE;
 3680:       if(data->set.ssl_enable_npn)
 3681:         conn->bits.tls_enable_npn = TRUE;
 3682:     }
 3683: 
 3684:     if(waitpipe)
 3685:       /* There is a connection that *might* become usable for multiplexing
 3686:          "soon", and we wait for that */
 3687:       connections_available = FALSE;
 3688:     else {
 3689:       /* this gets a lock on the conncache */
 3690:       const char *bundlehost;
 3691:       struct connectbundle *bundle =
 3692:         Curl_conncache_find_bundle(conn, data->state.conn_cache, &bundlehost);
 3693: 
 3694:       if(max_host_connections > 0 && bundle &&
 3695:          (bundle->num_connections >= max_host_connections)) {
 3696:         struct connectdata *conn_candidate;
 3697: 
 3698:         /* The bundle is full. Extract the oldest connection. */
 3699:         conn_candidate = Curl_conncache_extract_bundle(data, bundle);
 3700:         Curl_conncache_unlock(data);
 3701: 
 3702:         if(conn_candidate)
 3703:           (void)Curl_disconnect(data, conn_candidate,
 3704:                                 /* dead_connection */ FALSE);
 3705:         else {
 3706:           infof(data, "No more connections allowed to host %s: %zu\n",
 3707:                 bundlehost, max_host_connections);
 3708:           connections_available = FALSE;
 3709:         }
 3710:       }
 3711:       else
 3712:         Curl_conncache_unlock(data);
 3713: 
 3714:     }
 3715: 
 3716:     if(connections_available &&
 3717:        (max_total_connections > 0) &&
 3718:        (Curl_conncache_size(data) >= max_total_connections)) {
 3719:       struct connectdata *conn_candidate;
 3720: 
 3721:       /* The cache is full. Let's see if we can kill a connection. */
 3722:       conn_candidate = Curl_conncache_extract_oldest(data);
 3723:       if(conn_candidate)
 3724:         (void)Curl_disconnect(data, conn_candidate,
 3725:                               /* dead_connection */ FALSE);
 3726:       else {
 3727:         infof(data, "No connections available in cache\n");
 3728:         connections_available = FALSE;
 3729:       }
 3730:     }
 3731: 
 3732:     if(!connections_available) {
 3733:       infof(data, "No connections available.\n");
 3734: 
 3735:       conn_free(conn);
 3736:       *in_connect = NULL;
 3737: 
 3738:       result = CURLE_NO_CONNECTION_AVAILABLE;
 3739:       goto out;
 3740:     }
 3741:     else {
 3742:       /*
 3743:        * This is a brand new connection, so let's store it in the connection
 3744:        * cache of ours!
 3745:        */
 3746:       result = Curl_conncache_add_conn(data->state.conn_cache, conn);
 3747:       if(result)
 3748:         goto out;
 3749:     }
 3750: 
 3751: #if defined(USE_NTLM)
 3752:     /* If NTLM is requested in a part of this connection, make sure we don't
 3753:        assume the state is fine as this is a fresh connection and NTLM is
 3754:        connection based. */
 3755:     if((data->state.authhost.picked & (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) &&
 3756:        data->state.authhost.done) {
 3757:       infof(data, "NTLM picked AND auth done set, clear picked!\n");
 3758:       data->state.authhost.picked = CURLAUTH_NONE;
 3759:       data->state.authhost.done = FALSE;
 3760:     }
 3761: 
 3762:     if((data->state.authproxy.picked & (CURLAUTH_NTLM | CURLAUTH_NTLM_WB)) &&
 3763:        data->state.authproxy.done) {
 3764:       infof(data, "NTLM-proxy picked AND auth done set, clear picked!\n");
 3765:       data->state.authproxy.picked = CURLAUTH_NONE;
 3766:       data->state.authproxy.done = FALSE;
 3767:     }
 3768: #endif
 3769:   }
 3770: 
 3771:   /* Setup and init stuff before DO starts, in preparing for the transfer. */
 3772:   Curl_init_do(data, conn);
 3773: 
 3774:   /*
 3775:    * Setup whatever necessary for a resumed transfer
 3776:    */
 3777:   result = setup_range(data);
 3778:   if(result)
 3779:     goto out;
 3780: 
 3781:   /* Continue connectdata initialization here. */
 3782: 
 3783:   /*
 3784:    * Inherit the proper values from the urldata struct AFTER we have arranged
 3785:    * the persistent connection stuff
 3786:    */
 3787:   conn->seek_func = data->set.seek_func;
 3788:   conn->seek_client = data->set.seek_client;
 3789: 
 3790:   /*************************************************************
 3791:    * Resolve the address of the server or proxy
 3792:    *************************************************************/
 3793:   result = resolve_server(data, conn, async);
 3794: 
 3795:   /* Strip trailing dots. resolve_server copied the name. */
 3796:   strip_trailing_dot(&conn->host);
 3797:   if(conn->bits.httpproxy)
 3798:     strip_trailing_dot(&conn->http_proxy.host);
 3799:   if(conn->bits.socksproxy)
 3800:     strip_trailing_dot(&conn->socks_proxy.host);
 3801:   if(conn->bits.conn_to_host)
 3802:     strip_trailing_dot(&conn->conn_to_host);
 3803: 
 3804: out:
 3805:   return result;
 3806: }
 3807: 
 3808: /* Curl_setup_conn() is called after the name resolve initiated in
 3809:  * create_conn() is all done.
 3810:  *
 3811:  * Curl_setup_conn() also handles reused connections
 3812:  *
 3813:  * conn->data MUST already have been setup fine (in create_conn)
 3814:  */
 3815: 
 3816: CURLcode Curl_setup_conn(struct connectdata *conn,
 3817:                          bool *protocol_done)
 3818: {
 3819:   CURLcode result = CURLE_OK;
 3820:   struct Curl_easy *data = conn->data;
 3821: 
 3822:   Curl_pgrsTime(data, TIMER_NAMELOOKUP);
 3823: 
 3824:   if(conn->handler->flags & PROTOPT_NONETWORK) {
 3825:     /* nothing to setup when not using a network */
 3826:     *protocol_done = TRUE;
 3827:     return result;
 3828:   }
 3829:   *protocol_done = FALSE; /* default to not done */
 3830: 
 3831:   /* set proxy_connect_closed to false unconditionally already here since it
 3832:      is used strictly to provide extra information to a parent function in the
 3833:      case of proxy CONNECT failures and we must make sure we don't have it
 3834:      lingering set from a previous invoke */
 3835:   conn->bits.proxy_connect_closed = FALSE;
 3836: 
 3837:   /*
 3838:    * Set user-agent. Used for HTTP, but since we can attempt to tunnel
 3839:    * basically anything through a http proxy we can't limit this based on
 3840:    * protocol.
 3841:    */
 3842:   if(data->set.str[STRING_USERAGENT]) {
 3843:     Curl_safefree(conn->allocptr.uagent);
 3844:     conn->allocptr.uagent =
 3845:       aprintf("User-Agent: %s\r\n", data->set.str[STRING_USERAGENT]);
 3846:     if(!conn->allocptr.uagent)
 3847:       return CURLE_OUT_OF_MEMORY;
 3848:   }
 3849: 
 3850:   data->req.headerbytecount = 0;
 3851: 
 3852: #ifdef CURL_DO_LINEEND_CONV
 3853:   data->state.crlf_conversions = 0; /* reset CRLF conversion counter */
 3854: #endif /* CURL_DO_LINEEND_CONV */
 3855: 
 3856:   /* set start time here for timeout purposes in the connect procedure, it
 3857:      is later set again for the progress meter purpose */
 3858:   conn->now = Curl_now();
 3859: 
 3860:   if(CURL_SOCKET_BAD == conn->sock[FIRSTSOCKET]) {
 3861:     conn->bits.tcpconnect[FIRSTSOCKET] = FALSE;
 3862:     result = Curl_connecthost(conn, conn->dns_entry);
 3863:     if(result)
 3864:       return result;
 3865:   }
 3866:   else {
 3867:     Curl_pgrsTime(data, TIMER_CONNECT);    /* we're connected already */
 3868:     if(conn->ssl[FIRSTSOCKET].use ||
 3869:        (conn->handler->protocol & PROTO_FAMILY_SSH))
 3870:       Curl_pgrsTime(data, TIMER_APPCONNECT); /* we're connected already */
 3871:     conn->bits.tcpconnect[FIRSTSOCKET] = TRUE;
 3872:     *protocol_done = TRUE;
 3873:     Curl_updateconninfo(conn, conn->sock[FIRSTSOCKET]);
 3874:     Curl_verboseconnect(conn);
 3875:   }
 3876: 
 3877:   conn->now = Curl_now(); /* time this *after* the connect is done, we set
 3878:                              this here perhaps a second time */
 3879:   return result;
 3880: }
 3881: 
 3882: CURLcode Curl_connect(struct Curl_easy *data,
 3883:                       bool *asyncp,
 3884:                       bool *protocol_done)
 3885: {
 3886:   CURLcode result;
 3887:   struct connectdata *conn;
 3888: 
 3889:   *asyncp = FALSE; /* assume synchronous resolves by default */
 3890: 
 3891:   /* init the single-transfer specific data */
 3892:   Curl_free_request_state(data);
 3893:   memset(&data->req, 0, sizeof(struct SingleRequest));
 3894:   data->req.maxdownload = -1;
 3895: 
 3896:   /* call the stuff that needs to be called */
 3897:   result = create_conn(data, &conn, asyncp);
 3898: 
 3899:   if(!result) {
 3900:     if(CONN_INUSE(conn))
 3901:       /* multiplexed */
 3902:       *protocol_done = TRUE;
 3903:     else if(!*asyncp) {
 3904:       /* DNS resolution is done: that's either because this is a reused
 3905:          connection, in which case DNS was unnecessary, or because DNS
 3906:          really did finish already (synch resolver/fast async resolve) */
 3907:       result = Curl_setup_conn(conn, protocol_done);
 3908:     }
 3909:   }
 3910: 
 3911:   if(result == CURLE_NO_CONNECTION_AVAILABLE) {
 3912:     return result;
 3913:   }
 3914:   else if(result && conn) {
 3915:     /* We're not allowed to return failure with memory left allocated in the
 3916:        connectdata struct, free those here */
 3917:     Curl_disconnect(data, conn, TRUE);
 3918:   }
 3919:   else if(!result && !data->conn)
 3920:     /* FILE: transfers already have the connection attached */
 3921:     Curl_attach_connnection(data, conn);
 3922: 
 3923:   return result;
 3924: }
 3925: 
 3926: /*
 3927:  * Curl_init_do() inits the readwrite session. This is inited each time (in
 3928:  * the DO function before the protocol-specific DO functions are invoked) for
 3929:  * a transfer, sometimes multiple times on the same Curl_easy. Make sure
 3930:  * nothing in here depends on stuff that are setup dynamically for the
 3931:  * transfer.
 3932:  *
 3933:  * Allow this function to get called with 'conn' set to NULL.
 3934:  */
 3935: 
 3936: CURLcode Curl_init_do(struct Curl_easy *data, struct connectdata *conn)
 3937: {
 3938:   struct SingleRequest *k = &data->req;
 3939: 
 3940:   if(conn) {
 3941:     conn->bits.do_more = FALSE; /* by default there's no curl_do_more() to
 3942:                                    use */
 3943:     /* if the protocol used doesn't support wildcards, switch it off */
 3944:     if(data->state.wildcardmatch &&
 3945:        !(conn->handler->flags & PROTOPT_WILDCARD))
 3946:       data->state.wildcardmatch = FALSE;
 3947:   }
 3948: 
 3949:   data->state.done = FALSE; /* *_done() is not called yet */
 3950:   data->state.expect100header = FALSE;
 3951: 
 3952: 
 3953:   if(data->set.opt_no_body)
 3954:     /* in HTTP lingo, no body means using the HEAD request... */
 3955:     data->set.httpreq = HTTPREQ_HEAD;
 3956:   else if(HTTPREQ_HEAD == data->set.httpreq)
 3957:     /* ... but if unset there really is no perfect method that is the
 3958:        "opposite" of HEAD but in reality most people probably think GET
 3959:        then. The important thing is that we can't let it remain HEAD if the
 3960:        opt_no_body is set FALSE since then we'll behave wrong when getting
 3961:        HTTP. */
 3962:     data->set.httpreq = HTTPREQ_GET;
 3963: 
 3964:   k->start = Curl_now(); /* start time */
 3965:   k->now = k->start;   /* current time is now */
 3966:   k->header = TRUE; /* assume header */
 3967: 
 3968:   k->bytecount = 0;
 3969: 
 3970:   k->buf = data->state.buffer;
 3971:   k->hbufp = data->state.headerbuff;
 3972:   k->ignorebody = FALSE;
 3973: 
 3974:   Curl_speedinit(data);
 3975: 
 3976:   Curl_pgrsSetUploadCounter(data, 0);
 3977:   Curl_pgrsSetDownloadCounter(data, 0);
 3978: 
 3979:   return CURLE_OK;
 3980: }
 3981: 
 3982: /*
 3983: * get_protocol_family()
 3984: *
 3985: * This is used to return the protocol family for a given protocol.
 3986: *
 3987: * Parameters:
 3988: *
 3989: * protocol  [in]  - A single bit protocol identifier such as HTTP or HTTPS.
 3990: *
 3991: * Returns the family as a single bit protocol identifier.
 3992: */
 3993: 
 3994: static unsigned int get_protocol_family(unsigned int protocol)
 3995: {
 3996:   unsigned int family;
 3997: 
 3998:   switch(protocol) {
 3999:   case CURLPROTO_HTTP:
 4000:   case CURLPROTO_HTTPS:
 4001:     family = CURLPROTO_HTTP;
 4002:     break;
 4003: 
 4004:   case CURLPROTO_FTP:
 4005:   case CURLPROTO_FTPS:
 4006:     family = CURLPROTO_FTP;
 4007:     break;
 4008: 
 4009:   case CURLPROTO_SCP:
 4010:     family = CURLPROTO_SCP;
 4011:     break;
 4012: 
 4013:   case CURLPROTO_SFTP:
 4014:     family = CURLPROTO_SFTP;
 4015:     break;
 4016: 
 4017:   case CURLPROTO_TELNET:
 4018:     family = CURLPROTO_TELNET;
 4019:     break;
 4020: 
 4021:   case CURLPROTO_LDAP:
 4022:   case CURLPROTO_LDAPS:
 4023:     family = CURLPROTO_LDAP;
 4024:     break;
 4025: 
 4026:   case CURLPROTO_DICT:
 4027:     family = CURLPROTO_DICT;
 4028:     break;
 4029: 
 4030:   case CURLPROTO_FILE:
 4031:     family = CURLPROTO_FILE;
 4032:     break;
 4033: 
 4034:   case CURLPROTO_TFTP:
 4035:     family = CURLPROTO_TFTP;
 4036:     break;
 4037: 
 4038:   case CURLPROTO_IMAP:
 4039:   case CURLPROTO_IMAPS:
 4040:     family = CURLPROTO_IMAP;
 4041:     break;
 4042: 
 4043:   case CURLPROTO_POP3:
 4044:   case CURLPROTO_POP3S:
 4045:     family = CURLPROTO_POP3;
 4046:     break;
 4047: 
 4048:   case CURLPROTO_SMTP:
 4049:   case CURLPROTO_SMTPS:
 4050:       family = CURLPROTO_SMTP;
 4051:       break;
 4052: 
 4053:   case CURLPROTO_RTSP:
 4054:     family = CURLPROTO_RTSP;
 4055:     break;
 4056: 
 4057:   case CURLPROTO_RTMP:
 4058:   case CURLPROTO_RTMPS:
 4059:     family = CURLPROTO_RTMP;
 4060:     break;
 4061: 
 4062:   case CURLPROTO_RTMPT:
 4063:   case CURLPROTO_RTMPTS:
 4064:     family = CURLPROTO_RTMPT;
 4065:     break;
 4066: 
 4067:   case CURLPROTO_RTMPE:
 4068:     family = CURLPROTO_RTMPE;
 4069:     break;
 4070: 
 4071:   case CURLPROTO_RTMPTE:
 4072:     family = CURLPROTO_RTMPTE;
 4073:     break;
 4074: 
 4075:   case CURLPROTO_GOPHER:
 4076:     family = CURLPROTO_GOPHER;
 4077:     break;
 4078: 
 4079:   case CURLPROTO_SMB:
 4080:   case CURLPROTO_SMBS:
 4081:     family = CURLPROTO_SMB;
 4082:     break;
 4083: 
 4084:   default:
 4085:       family = 0;
 4086:       break;
 4087:   }
 4088: 
 4089:   return family;
 4090: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>