1/*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 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.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 * SPDX-License-Identifier: curl 22 * 23 ***************************************************************************/ 24 25#include "curl_setup.h" 26 27#include <limits.h> 28 29#ifdef HAVE_NETINET_IN_H 30#include <netinet/in.h> 31#endif 32 33#ifdef HAVE_LINUX_TCP_H 34#include <linux/tcp.h> 35#elif defined(HAVE_NETINET_TCP_H) 36#include <netinet/tcp.h> 37#endif 38 39#include "urldata.h" 40#include "url.h" 41#include "progress.h" 42#include "content_encoding.h" 43#include "strcase.h" 44#include "share.h" 45#include "vtls/vtls.h" 46#include "warnless.h" 47#include "sendf.h" 48#include "http2.h" 49#include "setopt.h" 50#include "multiif.h" 51#include "altsvc.h" 52#include "hsts.h" 53#include "tftp.h" 54#include "strdup.h" 55/* The last 3 #include files should be in this order */ 56#include "curl_printf.h" 57#include "curl_memory.h" 58#include "memdebug.h" 59 60CURLcode Curl_setstropt(char **charp, const char *s) 61{ 62 /* Release the previous storage at `charp' and replace by a dynamic storage 63 copy of `s'. Return CURLE_OK or CURLE_OUT_OF_MEMORY. */ 64 65 Curl_safefree(*charp); 66 67 if(s) { 68 if(strlen(s) > CURL_MAX_INPUT_LENGTH) 69 return CURLE_BAD_FUNCTION_ARGUMENT; 70 71 *charp = strdup(s); 72 if(!*charp) 73 return CURLE_OUT_OF_MEMORY; 74 } 75 76 return CURLE_OK; 77} 78 79CURLcode Curl_setblobopt(struct curl_blob **blobp, 80 const struct curl_blob *blob) 81{ 82 /* free the previous storage at `blobp' and replace by a dynamic storage 83 copy of blob. If CURL_BLOB_COPY is set, the data is copied. */ 84 85 Curl_safefree(*blobp); 86 87 if(blob) { 88 struct curl_blob *nblob; 89 if(blob->len > CURL_MAX_INPUT_LENGTH) 90 return CURLE_BAD_FUNCTION_ARGUMENT; 91 nblob = (struct curl_blob *) 92 malloc(sizeof(struct curl_blob) + 93 ((blob->flags & CURL_BLOB_COPY) ? blob->len : 0)); 94 if(!nblob) 95 return CURLE_OUT_OF_MEMORY; 96 *nblob = *blob; 97 if(blob->flags & CURL_BLOB_COPY) { 98 /* put the data after the blob struct in memory */ 99 nblob->data = (char *)nblob + sizeof(struct curl_blob); 100 memcpy(nblob->data, blob->data, blob->len); 101 } 102 103 *blobp = nblob; 104 return CURLE_OK; 105 } 106 107 return CURLE_OK; 108} 109 110static CURLcode setstropt_userpwd(char *option, char **userp, char **passwdp) 111{ 112 CURLcode result = CURLE_OK; 113 char *user = NULL; 114 char *passwd = NULL; 115 116 /* Parse the login details if specified. It not then we treat NULL as a hint 117 to clear the existing data */ 118 if(option) { 119 size_t len = strlen(option); 120 if(len > CURL_MAX_INPUT_LENGTH) 121 return CURLE_BAD_FUNCTION_ARGUMENT; 122 123 result = Curl_parse_login_details(option, len, 124 (userp ? &user : NULL), 125 (passwdp ? &passwd : NULL), 126 NULL); 127 } 128 129 if(!result) { 130 /* Store the username part of option if required */ 131 if(userp) { 132 if(!user && option && option[0] == ':') { 133 /* Allocate an empty string instead of returning NULL as user name */ 134 user = strdup(""); 135 if(!user) 136 result = CURLE_OUT_OF_MEMORY; 137 } 138 139 Curl_safefree(*userp); 140 *userp = user; 141 } 142 143 /* Store the password part of option if required */ 144 if(passwdp) { 145 Curl_safefree(*passwdp); 146 *passwdp = passwd; 147 } 148 } 149 150 return result; 151} 152 153#define C_SSLVERSION_VALUE(x) (x & 0xffff) 154#define C_SSLVERSION_MAX_VALUE(x) (x & 0xffff0000) 155 156static CURLcode protocol2num(const char *str, curl_prot_t *val) 157{ 158 /* 159 * We are asked to cherry-pick protocols, so play it safe and disallow all 160 * protocols to start with, and re-add the wanted ones back in. 161 */ 162 *val = 0; 163 164 if(!str) 165 return CURLE_BAD_FUNCTION_ARGUMENT; 166 167 if(curl_strequal(str, "all")) { 168 *val = ~(curl_prot_t) 0; 169 return CURLE_OK; 170 } 171 172 do { 173 const char *token = str; 174 size_t tlen; 175 176 str = strchr(str, ','); 177 tlen = str? (size_t) (str - token): strlen(token); 178 if(tlen) { 179 const struct Curl_handler *h = Curl_getn_scheme_handler(token, tlen); 180 181 if(!h) 182 return CURLE_UNSUPPORTED_PROTOCOL; 183 184 *val |= h->protocol; 185 } 186 } while(str && str++); 187 188 if(!*val) 189 /* no protocol listed */ 190 return CURLE_BAD_FUNCTION_ARGUMENT; 191 return CURLE_OK; 192} 193 194/* 195 * Do not make Curl_vsetopt() static: it is called from 196 * packages/OS400/ccsidcurl.c. 197 */ 198CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param) 199{ 200 char *argptr; 201 CURLcode result = CURLE_OK; 202 long arg; 203 unsigned long uarg; 204 curl_off_t bigsize; 205 206 switch(option) { 207 case CURLOPT_DNS_CACHE_TIMEOUT: 208 arg = va_arg(param, long); 209 if(arg < -1) 210 return CURLE_BAD_FUNCTION_ARGUMENT; 211 else if(arg > INT_MAX) 212 arg = INT_MAX; 213 214 data->set.dns_cache_timeout = (int)arg; 215 break; 216 case CURLOPT_CA_CACHE_TIMEOUT: 217 arg = va_arg(param, long); 218 if(arg < -1) 219 return CURLE_BAD_FUNCTION_ARGUMENT; 220 else if(arg > INT_MAX) 221 arg = INT_MAX; 222 223 data->set.general_ssl.ca_cache_timeout = (int)arg; 224 break; 225 case CURLOPT_DNS_USE_GLOBAL_CACHE: 226 /* deprecated */ 227 break; 228 case CURLOPT_SSL_CIPHER_LIST: 229 /* set a list of cipher we want to use in the SSL connection */ 230 result = Curl_setstropt(&data->set.str[STRING_SSL_CIPHER_LIST], 231 va_arg(param, char *)); 232 break; 233#ifndef CURL_DISABLE_PROXY 234 case CURLOPT_PROXY_SSL_CIPHER_LIST: 235 /* set a list of cipher we want to use in the SSL connection for proxy */ 236 result = Curl_setstropt(&data->set.str[STRING_SSL_CIPHER_LIST_PROXY], 237 va_arg(param, char *)); 238 break; 239#endif 240 case CURLOPT_TLS13_CIPHERS: 241 if(Curl_ssl_supports(data, SSLSUPP_TLS13_CIPHERSUITES)) { 242 /* set preferred list of TLS 1.3 cipher suites */ 243 result = Curl_setstropt(&data->set.str[STRING_SSL_CIPHER13_LIST], 244 va_arg(param, char *)); 245 } 246 else 247 return CURLE_NOT_BUILT_IN; 248 break; 249#ifndef CURL_DISABLE_PROXY 250 case CURLOPT_PROXY_TLS13_CIPHERS: 251 if(Curl_ssl_supports(data, SSLSUPP_TLS13_CIPHERSUITES)) { 252 /* set preferred list of TLS 1.3 cipher suites for proxy */ 253 result = Curl_setstropt(&data->set.str[STRING_SSL_CIPHER13_LIST_PROXY], 254 va_arg(param, char *)); 255 } 256 else 257 return CURLE_NOT_BUILT_IN; 258 break; 259#endif 260 case CURLOPT_RANDOM_FILE: 261 break; 262 case CURLOPT_EGDSOCKET: 263 break; 264 case CURLOPT_MAXCONNECTS: 265 /* 266 * Set the absolute number of maximum simultaneous alive connection that 267 * libcurl is allowed to have. 268 */ 269 uarg = va_arg(param, unsigned long); 270 if(uarg > UINT_MAX) 271 return CURLE_BAD_FUNCTION_ARGUMENT; 272 data->set.maxconnects = (unsigned int)uarg; 273 break; 274 case CURLOPT_FORBID_REUSE: 275 /* 276 * When this transfer is done, it must not be left to be reused by a 277 * subsequent transfer but shall be closed immediately. 278 */ 279 data->set.reuse_forbid = (0 != va_arg(param, long)); 280 break; 281 case CURLOPT_FRESH_CONNECT: 282 /* 283 * This transfer shall not use a previously cached connection but 284 * should be made with a fresh new connect! 285 */ 286 data->set.reuse_fresh = (0 != va_arg(param, long)); 287 break; 288 case CURLOPT_VERBOSE: 289 /* 290 * Verbose means infof() calls that give a lot of information about 291 * the connection and transfer procedures as well as internal choices. 292 */ 293 data->set.verbose = (0 != va_arg(param, long)); 294 break; 295 case CURLOPT_HEADER: 296 /* 297 * Set to include the header in the general data output stream. 298 */ 299 data->set.include_header = (0 != va_arg(param, long)); 300 break; 301 case CURLOPT_NOPROGRESS: 302 /* 303 * Shut off the internal supported progress meter 304 */ 305 data->set.hide_progress = (0 != va_arg(param, long)); 306 if(data->set.hide_progress) 307 data->progress.flags |= PGRS_HIDE; 308 else 309 data->progress.flags &= ~PGRS_HIDE; 310 break; 311 case CURLOPT_NOBODY: 312 /* 313 * Do not include the body part in the output data stream. 314 */ 315 data->set.opt_no_body = (0 != va_arg(param, long)); 316#ifndef CURL_DISABLE_HTTP 317 if(data->set.opt_no_body) 318 /* in HTTP lingo, no body means using the HEAD request... */ 319 data->set.method = HTTPREQ_HEAD; 320 else if(data->set.method == HTTPREQ_HEAD) 321 data->set.method = HTTPREQ_GET; 322#endif 323 break; 324 case CURLOPT_FAILONERROR: 325 /* 326 * Don't output the >=400 error code HTML-page, but instead only 327 * return error. 328 */ 329 data->set.http_fail_on_error = (0 != va_arg(param, long)); 330 break; 331 case CURLOPT_KEEP_SENDING_ON_ERROR: 332 data->set.http_keep_sending_on_error = (0 != va_arg(param, long)); 333 break; 334 case CURLOPT_UPLOAD: 335 case CURLOPT_PUT: 336 /* 337 * We want to sent data to the remote host. If this is HTTP, that equals 338 * using the PUT request. 339 */ 340 arg = va_arg(param, long); 341 if(arg) { 342 /* If this is HTTP, PUT is what's needed to "upload" */ 343 data->set.method = HTTPREQ_PUT; 344 data->set.opt_no_body = FALSE; /* this is implied */ 345 } 346 else 347 /* In HTTP, the opposite of upload is GET (unless NOBODY is true as 348 then this can be changed to HEAD later on) */ 349 data->set.method = HTTPREQ_GET; 350 break; 351 case CURLOPT_REQUEST_TARGET: 352 result = Curl_setstropt(&data->set.str[STRING_TARGET], 353 va_arg(param, char *)); 354 break; 355 case CURLOPT_FILETIME: 356 /* 357 * Try to get the file time of the remote document. The time will 358 * later (possibly) become available using curl_easy_getinfo(). 359 */ 360 data->set.get_filetime = (0 != va_arg(param, long)); 361 break; 362 case CURLOPT_SERVER_RESPONSE_TIMEOUT: 363 /* 364 * Option that specifies how quickly a server response must be obtained 365 * before it is considered failure. For pingpong protocols. 366 */ 367 arg = va_arg(param, long); 368 if((arg >= 0) && (arg <= (INT_MAX/1000))) 369 data->set.server_response_timeout = (unsigned int)arg * 1000; 370 else 371 return CURLE_BAD_FUNCTION_ARGUMENT; 372 break; 373 case CURLOPT_SERVER_RESPONSE_TIMEOUT_MS: 374 /* 375 * Option that specifies how quickly a server response must be obtained 376 * before it is considered failure. For pingpong protocols. 377 */ 378 arg = va_arg(param, long); 379 if((arg >= 0) && (arg <= INT_MAX)) 380 data->set.server_response_timeout = (unsigned int)arg; 381 else 382 return CURLE_BAD_FUNCTION_ARGUMENT; 383 break; 384#ifndef CURL_DISABLE_TFTP 385 case CURLOPT_TFTP_NO_OPTIONS: 386 /* 387 * Option that prevents libcurl from sending TFTP option requests to the 388 * server. 389 */ 390 data->set.tftp_no_options = va_arg(param, long) != 0; 391 break; 392 case CURLOPT_TFTP_BLKSIZE: 393 /* 394 * TFTP option that specifies the block size to use for data transmission. 395 */ 396 arg = va_arg(param, long); 397 if(arg > TFTP_BLKSIZE_MAX || arg < TFTP_BLKSIZE_MIN) 398 return CURLE_BAD_FUNCTION_ARGUMENT; 399 data->set.tftp_blksize = arg; 400 break; 401#endif 402#ifndef CURL_DISABLE_NETRC 403 case CURLOPT_NETRC: 404 /* 405 * Parse the $HOME/.netrc file 406 */ 407 arg = va_arg(param, long); 408 if((arg < CURL_NETRC_IGNORED) || (arg >= CURL_NETRC_LAST)) 409 return CURLE_BAD_FUNCTION_ARGUMENT; 410 data->set.use_netrc = (unsigned char)arg; 411 break; 412 case CURLOPT_NETRC_FILE: 413 /* 414 * Use this file instead of the $HOME/.netrc file 415 */ 416 result = Curl_setstropt(&data->set.str[STRING_NETRC_FILE], 417 va_arg(param, char *)); 418 break; 419#endif 420 case CURLOPT_TRANSFERTEXT: 421 /* 422 * This option was previously named 'FTPASCII'. Renamed to work with 423 * more protocols than merely FTP. 424 * 425 * Transfer using ASCII (instead of BINARY). 426 */ 427 data->set.prefer_ascii = (0 != va_arg(param, long)); 428 break; 429 case CURLOPT_TIMECONDITION: 430 /* 431 * Set HTTP time condition. This must be one of the defines in the 432 * curl/curl.h header file. 433 */ 434 arg = va_arg(param, long); 435 if((arg < CURL_TIMECOND_NONE) || (arg >= CURL_TIMECOND_LAST)) 436 return CURLE_BAD_FUNCTION_ARGUMENT; 437 data->set.timecondition = (unsigned char)(curl_TimeCond)arg; 438 break; 439 case CURLOPT_TIMEVALUE: 440 /* 441 * This is the value to compare with the remote document with the 442 * method set with CURLOPT_TIMECONDITION 443 */ 444 data->set.timevalue = (time_t)va_arg(param, long); 445 break; 446 447 case CURLOPT_TIMEVALUE_LARGE: 448 /* 449 * This is the value to compare with the remote document with the 450 * method set with CURLOPT_TIMECONDITION 451 */ 452 data->set.timevalue = (time_t)va_arg(param, curl_off_t); 453 break; 454 455 case CURLOPT_SSLVERSION: 456#ifndef CURL_DISABLE_PROXY 457 case CURLOPT_PROXY_SSLVERSION: 458#endif 459 /* 460 * Set explicit SSL version to try to connect with, as some SSL 461 * implementations are lame. 462 */ 463#ifdef USE_SSL 464 { 465 long version, version_max; 466 struct ssl_primary_config *primary = &data->set.ssl.primary; 467#ifndef CURL_DISABLE_PROXY 468 if(option != CURLOPT_SSLVERSION) 469 primary = &data->set.proxy_ssl.primary; 470#endif 471 472 arg = va_arg(param, long); 473 474 version = C_SSLVERSION_VALUE(arg); 475 version_max = C_SSLVERSION_MAX_VALUE(arg); 476 477 if(version < CURL_SSLVERSION_DEFAULT || 478 version == CURL_SSLVERSION_SSLv2 || 479 version == CURL_SSLVERSION_SSLv3 || 480 version >= CURL_SSLVERSION_LAST || 481 version_max < CURL_SSLVERSION_MAX_NONE || 482 version_max >= CURL_SSLVERSION_MAX_LAST) 483 return CURLE_BAD_FUNCTION_ARGUMENT; 484 485 primary->version = (unsigned char)version; 486 primary->version_max = (unsigned int)version_max; 487 } 488#else 489 result = CURLE_NOT_BUILT_IN; 490#endif 491 break; 492 493 /* MQTT "borrows" some of the HTTP options */ 494#if !defined(CURL_DISABLE_HTTP) || !defined(CURL_DISABLE_MQTT) 495 case CURLOPT_COPYPOSTFIELDS: 496 /* 497 * A string with POST data. Makes curl HTTP POST. Even if it is NULL. 498 * If needed, CURLOPT_POSTFIELDSIZE must have been set prior to 499 * CURLOPT_COPYPOSTFIELDS and not altered later. 500 */ 501 argptr = va_arg(param, char *); 502 503 if(!argptr || data->set.postfieldsize == -1) 504 result = Curl_setstropt(&data->set.str[STRING_COPYPOSTFIELDS], argptr); 505 else { 506 /* 507 * Check that requested length does not overflow the size_t type. 508 */ 509 510 if((data->set.postfieldsize < 0) || 511 ((sizeof(curl_off_t) != sizeof(size_t)) && 512 (data->set.postfieldsize > (curl_off_t)((size_t)-1)))) 513 result = CURLE_OUT_OF_MEMORY; 514 else { 515 /* Allocate even when size == 0. This satisfies the need of possible 516 later address compare to detect the COPYPOSTFIELDS mode, and to 517 mark that postfields is used rather than read function or form 518 data. 519 */ 520 char *p = Curl_memdup0(argptr, (size_t)data->set.postfieldsize); 521 (void) Curl_setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL); 522 if(!p) 523 result = CURLE_OUT_OF_MEMORY; 524 else 525 data->set.str[STRING_COPYPOSTFIELDS] = p; 526 } 527 } 528 529 data->set.postfields = data->set.str[STRING_COPYPOSTFIELDS]; 530 data->set.method = HTTPREQ_POST; 531 break; 532 533 case CURLOPT_POSTFIELDS: 534 /* 535 * Like above, but use static data instead of copying it. 536 */ 537 data->set.postfields = va_arg(param, void *); 538 /* Release old copied data. */ 539 (void) Curl_setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL); 540 data->set.method = HTTPREQ_POST; 541 break; 542 543 case CURLOPT_POSTFIELDSIZE: 544 /* 545 * The size of the POSTFIELD data to prevent libcurl to do strlen() to 546 * figure it out. Enables binary posts. 547 */ 548 bigsize = va_arg(param, long); 549 if(bigsize < -1) 550 return CURLE_BAD_FUNCTION_ARGUMENT; 551 552 if(data->set.postfieldsize < bigsize && 553 data->set.postfields == data->set.str[STRING_COPYPOSTFIELDS]) { 554 /* Previous CURLOPT_COPYPOSTFIELDS is no longer valid. */ 555 (void) Curl_setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL); 556 data->set.postfields = NULL; 557 } 558 559 data->set.postfieldsize = bigsize; 560 break; 561 562 case CURLOPT_POSTFIELDSIZE_LARGE: 563 /* 564 * The size of the POSTFIELD data to prevent libcurl to do strlen() to 565 * figure it out. Enables binary posts. 566 */ 567 bigsize = va_arg(param, curl_off_t); 568 if(bigsize < -1) 569 return CURLE_BAD_FUNCTION_ARGUMENT; 570 571 if(data->set.postfieldsize < bigsize && 572 data->set.postfields == data->set.str[STRING_COPYPOSTFIELDS]) { 573 /* Previous CURLOPT_COPYPOSTFIELDS is no longer valid. */ 574 (void) Curl_setstropt(&data->set.str[STRING_COPYPOSTFIELDS], NULL); 575 data->set.postfields = NULL; 576 } 577 578 data->set.postfieldsize = bigsize; 579 break; 580#endif 581#ifndef CURL_DISABLE_HTTP 582 case CURLOPT_AUTOREFERER: 583 /* 584 * Switch on automatic referer that gets set if curl follows locations. 585 */ 586 data->set.http_auto_referer = (0 != va_arg(param, long)); 587 break; 588 589 case CURLOPT_ACCEPT_ENCODING: 590 /* 591 * String to use at the value of Accept-Encoding header. 592 * 593 * If the encoding is set to "" we use an Accept-Encoding header that 594 * encompasses all the encodings we support. 595 * If the encoding is set to NULL we don't send an Accept-Encoding header 596 * and ignore an received Content-Encoding header. 597 * 598 */ 599 argptr = va_arg(param, char *); 600 if(argptr && !*argptr) { 601 char all[256]; 602 Curl_all_content_encodings(all, sizeof(all)); 603 result = Curl_setstropt(&data->set.str[STRING_ENCODING], all); 604 } 605 else 606 result = Curl_setstropt(&data->set.str[STRING_ENCODING], argptr); 607 break; 608 609 case CURLOPT_TRANSFER_ENCODING: 610 data->set.http_transfer_encoding = (0 != va_arg(param, long)); 611 break; 612 613 case CURLOPT_FOLLOWLOCATION: 614 /* 615 * Follow Location: header hints on an HTTP-server. 616 */ 617 data->set.http_follow_location = (0 != va_arg(param, long)); 618 break; 619 620 case CURLOPT_UNRESTRICTED_AUTH: 621 /* 622 * Send authentication (user+password) when following locations, even when 623 * hostname changed. 624 */ 625 data->set.allow_auth_to_other_hosts = (0 != va_arg(param, long)); 626 break; 627 628 case CURLOPT_MAXREDIRS: 629 /* 630 * The maximum amount of hops you allow curl to follow Location: 631 * headers. This should mostly be used to detect never-ending loops. 632 */ 633 arg = va_arg(param, long); 634 if(arg < -1) 635 return CURLE_BAD_FUNCTION_ARGUMENT; 636 data->set.maxredirs = arg; 637 break; 638 639 case CURLOPT_POSTREDIR: 640 /* 641 * Set the behavior of POST when redirecting 642 * CURL_REDIR_GET_ALL - POST is changed to GET after 301 and 302 643 * CURL_REDIR_POST_301 - POST is kept as POST after 301 644 * CURL_REDIR_POST_302 - POST is kept as POST after 302 645 * CURL_REDIR_POST_303 - POST is kept as POST after 303 646 * CURL_REDIR_POST_ALL - POST is kept as POST after 301, 302 and 303 647 * other - POST is kept as POST after 301 and 302 648 */ 649 arg = va_arg(param, long); 650 if(arg < CURL_REDIR_GET_ALL) 651 /* no return error on too high numbers since the bitmask could be 652 extended in a future */ 653 return CURLE_BAD_FUNCTION_ARGUMENT; 654 data->set.keep_post = arg & CURL_REDIR_POST_ALL; 655 break; 656 657 case CURLOPT_POST: 658 /* Does this option serve a purpose anymore? Yes it does, when 659 CURLOPT_POSTFIELDS isn't used and the POST data is read off the 660 callback! */ 661 if(va_arg(param, long)) { 662 data->set.method = HTTPREQ_POST; 663 data->set.opt_no_body = FALSE; /* this is implied */ 664 } 665 else 666 data->set.method = HTTPREQ_GET; 667 break; 668 669#ifndef CURL_DISABLE_FORM_API 670 case CURLOPT_HTTPPOST: 671 /* 672 * Set to make us do HTTP POST. Legacy API-style. 673 */ 674 data->set.httppost = va_arg(param, struct curl_httppost *); 675 data->set.method = HTTPREQ_POST_FORM; 676 data->set.opt_no_body = FALSE; /* this is implied */ 677 Curl_mime_cleanpart(data->state.formp); 678 Curl_safefree(data->state.formp); 679 data->state.mimepost = NULL; 680 break; 681#endif 682 683#if !defined(CURL_DISABLE_AWS) 684 case CURLOPT_AWS_SIGV4: 685 /* 686 * String that is merged to some authentication 687 * parameters are used by the algorithm. 688 */ 689 result = Curl_setstropt(&data->set.str[STRING_AWS_SIGV4], 690 va_arg(param, char *)); 691 /* 692 * Basic been set by default it need to be unset here 693 */ 694 if(data->set.str[STRING_AWS_SIGV4]) 695 data->set.httpauth = CURLAUTH_AWS_SIGV4; 696 break; 697#endif 698 699 case CURLOPT_REFERER: 700 /* 701 * String to set in the HTTP Referer: field. 702 */ 703 if(data->state.referer_alloc) { 704 Curl_safefree(data->state.referer); 705 data->state.referer_alloc = FALSE; 706 } 707 result = Curl_setstropt(&data->set.str[STRING_SET_REFERER], 708 va_arg(param, char *)); 709 data->state.referer = data->set.str[STRING_SET_REFERER]; 710 break; 711 712 case CURLOPT_USERAGENT: 713 /* 714 * String to use in the HTTP User-Agent field 715 */ 716 result = Curl_setstropt(&data->set.str[STRING_USERAGENT], 717 va_arg(param, char *)); 718 break; 719 720#ifndef CURL_DISABLE_PROXY 721 case CURLOPT_PROXYHEADER: 722 /* 723 * Set a list with proxy headers to use (or replace internals with) 724 * 725 * Since CURLOPT_HTTPHEADER was the only way to set HTTP headers for a 726 * long time we remain doing it this way until CURLOPT_PROXYHEADER is 727 * used. As soon as this option has been used, if set to anything but 728 * NULL, custom headers for proxies are only picked from this list. 729 * 730 * Set this option to NULL to restore the previous behavior. 731 */ 732 data->set.proxyheaders = va_arg(param, struct curl_slist *); 733 break; 734#endif 735 case CURLOPT_HEADEROPT: 736 /* 737 * Set header option. 738 */ 739 arg = va_arg(param, long); 740 data->set.sep_headers = !!(arg & CURLHEADER_SEPARATE); 741 break; 742 743#if !defined(CURL_DISABLE_COOKIES) 744 case CURLOPT_COOKIE: 745 /* 746 * Cookie string to send to the remote server in the request. 747 */ 748 result = Curl_setstropt(&data->set.str[STRING_COOKIE], 749 va_arg(param, char *)); 750 break; 751 752 case CURLOPT_COOKIEFILE: 753 /* 754 * Set cookie file to read and parse. Can be used multiple times. 755 */ 756 argptr = (char *)va_arg(param, void *); 757 if(argptr) { 758 struct curl_slist *cl; 759 /* general protection against mistakes and abuse */ 760 if(strlen(argptr) > CURL_MAX_INPUT_LENGTH) 761 return CURLE_BAD_FUNCTION_ARGUMENT; 762 /* append the cookie file name to the list of file names, and deal with 763 them later */ 764 cl = curl_slist_append(data->state.cookielist, argptr); 765 if(!cl) { 766 curl_slist_free_all(data->state.cookielist); 767 data->state.cookielist = NULL; 768 return CURLE_OUT_OF_MEMORY; 769 } 770 data->state.cookielist = cl; /* store the list for later use */ 771 } 772 else { 773 /* clear the list of cookie files */ 774 curl_slist_free_all(data->state.cookielist); 775 data->state.cookielist = NULL; 776 777 if(!data->share || !data->share->cookies) { 778 /* throw away all existing cookies if this isn't a shared cookie 779 container */ 780 Curl_cookie_clearall(data->cookies); 781 Curl_cookie_cleanup(data->cookies); 782 } 783 /* disable the cookie engine */ 784 data->cookies = NULL; 785 } 786 break; 787 788 case CURLOPT_COOKIEJAR: 789 /* 790 * Set cookie file name to dump all cookies to when we're done. 791 */ 792 { 793 struct CookieInfo *newcookies; 794 result = Curl_setstropt(&data->set.str[STRING_COOKIEJAR], 795 va_arg(param, char *)); 796 797 /* 798 * Activate the cookie parser. This may or may not already 799 * have been made. 800 */ 801 newcookies = Curl_cookie_init(data, NULL, data->cookies, 802 data->set.cookiesession); 803 if(!newcookies) 804 result = CURLE_OUT_OF_MEMORY; 805 data->cookies = newcookies; 806 } 807 break; 808 809 case CURLOPT_COOKIESESSION: 810 /* 811 * Set this option to TRUE to start a new "cookie session". It will 812 * prevent the forthcoming read-cookies-from-file actions to accept 813 * cookies that are marked as being session cookies, as they belong to a 814 * previous session. 815 */ 816 data->set.cookiesession = (0 != va_arg(param, long)); 817 break; 818 819 case CURLOPT_COOKIELIST: 820 argptr = va_arg(param, char *); 821 822 if(!argptr) 823 break; 824 825 if(strcasecompare(argptr, "ALL")) { 826 /* clear all cookies */ 827 Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); 828 Curl_cookie_clearall(data->cookies); 829 Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); 830 } 831 else if(strcasecompare(argptr, "SESS")) { 832 /* clear session cookies */ 833 Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); 834 Curl_cookie_clearsess(data->cookies); 835 Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); 836 } 837 else if(strcasecompare(argptr, "FLUSH")) { 838 /* flush cookies to file, takes care of the locking */ 839 Curl_flush_cookies(data, FALSE); 840 } 841 else if(strcasecompare(argptr, "RELOAD")) { 842 /* reload cookies from file */ 843 Curl_cookie_loadfiles(data); 844 break; 845 } 846 else { 847 if(!data->cookies) 848 /* if cookie engine was not running, activate it */ 849 data->cookies = Curl_cookie_init(data, NULL, NULL, TRUE); 850 851 /* general protection against mistakes and abuse */ 852 if(strlen(argptr) > CURL_MAX_INPUT_LENGTH) 853 return CURLE_BAD_FUNCTION_ARGUMENT; 854 argptr = strdup(argptr); 855 if(!argptr || !data->cookies) { 856 result = CURLE_OUT_OF_MEMORY; 857 free(argptr); 858 } 859 else { 860 Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE); 861 862 if(checkprefix("Set-Cookie:", argptr)) 863 /* HTTP Header format line */ 864 Curl_cookie_add(data, data->cookies, TRUE, FALSE, argptr + 11, NULL, 865 NULL, TRUE); 866 867 else 868 /* Netscape format line */ 869 Curl_cookie_add(data, data->cookies, FALSE, FALSE, argptr, NULL, 870 NULL, TRUE); 871 872 Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE); 873 free(argptr); 874 } 875 } 876 877 break; 878#endif /* !CURL_DISABLE_COOKIES */ 879 880 case CURLOPT_HTTPGET: 881 /* 882 * Set to force us do HTTP GET 883 */ 884 if(va_arg(param, long)) { 885 data->set.method = HTTPREQ_GET; 886 data->set.opt_no_body = FALSE; /* this is implied */ 887 } 888 break; 889 890 case CURLOPT_HTTP_VERSION: 891 /* 892 * This sets a requested HTTP version to be used. The value is one of 893 * the listed enums in curl/curl.h. 894 */ 895 arg = va_arg(param, long); 896 switch(arg) { 897 case CURL_HTTP_VERSION_NONE: 898#ifdef USE_HTTP2 899 /* TODO: this seems an undesirable quirk to force a behaviour on 900 * lower implementations that they should recognize independently? */ 901 arg = CURL_HTTP_VERSION_2TLS; 902#endif 903 /* accepted */ 904 break; 905 case CURL_HTTP_VERSION_1_0: 906 case CURL_HTTP_VERSION_1_1: 907 /* accepted */ 908 break; 909#ifdef USE_HTTP2 910 case CURL_HTTP_VERSION_2_0: 911 case CURL_HTTP_VERSION_2TLS: 912 case CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE: 913 /* accepted */ 914 break; 915#endif 916#ifdef ENABLE_QUIC 917 case CURL_HTTP_VERSION_3: 918 case CURL_HTTP_VERSION_3ONLY: 919 /* accepted */ 920 break; 921#endif 922 default: 923 /* not accepted */ 924 if(arg < CURL_HTTP_VERSION_NONE) 925 return CURLE_BAD_FUNCTION_ARGUMENT; 926 return CURLE_UNSUPPORTED_PROTOCOL; 927 } 928 data->set.httpwant = (unsigned char)arg; 929 break; 930 931 case CURLOPT_EXPECT_100_TIMEOUT_MS: 932 /* 933 * Time to wait for a response to an HTTP request containing an 934 * Expect: 100-continue header before sending the data anyway. 935 */ 936 arg = va_arg(param, long); 937 if(arg < 0) 938 return CURLE_BAD_FUNCTION_ARGUMENT; 939 data->set.expect_100_timeout = arg; 940 break; 941 942 case CURLOPT_HTTP09_ALLOWED: 943 arg = va_arg(param, unsigned long); 944 if(arg > 1L) 945 return CURLE_BAD_FUNCTION_ARGUMENT; 946#ifdef USE_HYPER 947 /* Hyper does not support HTTP/0.9 */ 948 if(arg) 949 return CURLE_BAD_FUNCTION_ARGUMENT; 950#else 951 data->set.http09_allowed = !!arg; 952#endif 953 break; 954 955 case CURLOPT_HTTP200ALIASES: 956 /* 957 * Set a list of aliases for HTTP 200 in response header 958 */ 959 data->set.http200aliases = va_arg(param, struct curl_slist *); 960 break; 961#endif /* CURL_DISABLE_HTTP */ 962 963#if !defined(CURL_DISABLE_HTTP) || !defined(CURL_DISABLE_SMTP) || \ 964 !defined(CURL_DISABLE_IMAP) 965# if !defined(CURL_DISABLE_HTTP) || !defined(CURL_DISABLE_MIME) 966 case CURLOPT_HTTPHEADER: 967 /* 968 * Set a list with HTTP headers to use (or replace internals with) 969 */ 970 data->set.headers = va_arg(param, struct curl_slist *); 971 break; 972# endif 973 974# ifndef CURL_DISABLE_MIME 975 case CURLOPT_MIMEPOST: 976 /* 977 * Set to make us do MIME POST 978 */ 979 result = Curl_mime_set_subparts(&data->set.mimepost, 980 va_arg(param, curl_mime *), FALSE); 981 if(!result) { 982 data->set.method = HTTPREQ_POST_MIME; 983 data->set.opt_no_body = FALSE; /* this is implied */ 984#ifndef CURL_DISABLE_FORM_API 985 Curl_mime_cleanpart(data->state.formp); 986 Curl_safefree(data->state.formp); 987 data->state.mimepost = NULL; 988#endif 989 } 990 break; 991 992 case CURLOPT_MIME_OPTIONS: 993 arg = va_arg(param, long); 994 data->set.mime_formescape = !!(arg & CURLMIMEOPT_FORMESCAPE); 995 break; 996# endif 997#endif 998 999 case CURLOPT_HTTPAUTH: 1000 /* 1001 * Set HTTP Authentication type BITMASK. 1002 */ 1003 { 1004 int bitcheck; 1005 bool authbits; 1006 unsigned long auth = va_arg(param, unsigned long); 1007 1008 if(auth == CURLAUTH_NONE) { 1009 data->set.httpauth = auth; 1010 break; 1011 } 1012 1013 /* the DIGEST_IE bit is only used to set a special marker, for all the 1014 rest we need to handle it as normal DIGEST */ 1015 data->state.authhost.iestyle = !!(auth & CURLAUTH_DIGEST_IE); 1016 1017 if(auth & CURLAUTH_DIGEST_IE) { 1018 auth |= CURLAUTH_DIGEST; /* set standard digest bit */ 1019 auth &= ~CURLAUTH_DIGEST_IE; /* unset ie digest bit */ 1020 } 1021 1022 /* switch off bits we can't support */ 1023#ifndef USE_NTLM 1024 auth &= ~CURLAUTH_NTLM; /* no NTLM support */ 1025 auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */ 1026#elif !defined(NTLM_WB_ENABLED) 1027 auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */ 1028#endif 1029#ifndef USE_SPNEGO 1030 auth &= ~CURLAUTH_NEGOTIATE; /* no Negotiate (SPNEGO) auth without 1031 GSS-API or SSPI */ 1032#endif 1033 1034 /* check if any auth bit lower than CURLAUTH_ONLY is still set */ 1035 bitcheck = 0; 1036 authbits = FALSE; 1037 while(bitcheck < 31) { 1038 if(auth & (1UL << bitcheck++)) { 1039 authbits = TRUE; 1040 break; 1041 } 1042 } 1043 if(!authbits) 1044 return CURLE_NOT_BUILT_IN; /* no supported types left! */ 1045 1046 data->set.httpauth = auth; 1047 } 1048 break; 1049 1050 case CURLOPT_CUSTOMREQUEST: 1051 /* 1052 * Set a custom string to use as request 1053 */ 1054 result = Curl_setstropt(&data->set.str[STRING_CUSTOMREQUEST], 1055 va_arg(param, char *)); 1056 1057 /* we don't set 1058 data->set.method = HTTPREQ_CUSTOM; 1059 here, we continue as if we were using the already set type 1060 and this just changes the actual request keyword */ 1061 break; 1062 1063#ifndef CURL_DISABLE_PROXY 1064 case CURLOPT_HTTPPROXYTUNNEL: 1065 /* 1066 * Tunnel operations through the proxy instead of normal proxy use 1067 */ 1068 data->set.tunnel_thru_httpproxy = (0 != va_arg(param, long)); 1069 break; 1070 1071 case CURLOPT_PROXYPORT: 1072 /* 1073 * Explicitly set HTTP proxy port number. 1074 */ 1075 arg = va_arg(param, long); 1076 if((arg < 0) || (arg > 65535)) 1077 return CURLE_BAD_FUNCTION_ARGUMENT; 1078 data->set.proxyport = (unsigned short)arg; 1079 break; 1080 1081 case CURLOPT_PROXYAUTH: 1082 /* 1083 * Set HTTP Authentication type BITMASK. 1084 */ 1085 { 1086 int bitcheck; 1087 bool authbits; 1088 unsigned long auth = va_arg(param, unsigned long); 1089 1090 if(auth == CURLAUTH_NONE) { 1091 data->set.proxyauth = auth; 1092 break; 1093 } 1094 1095 /* the DIGEST_IE bit is only used to set a special marker, for all the 1096 rest we need to handle it as normal DIGEST */ 1097 data->state.authproxy.iestyle = !!(auth & CURLAUTH_DIGEST_IE); 1098 1099 if(auth & CURLAUTH_DIGEST_IE) { 1100 auth |= CURLAUTH_DIGEST; /* set standard digest bit */ 1101 auth &= ~CURLAUTH_DIGEST_IE; /* unset ie digest bit */ 1102 } 1103 /* switch off bits we can't support */ 1104#ifndef USE_NTLM 1105 auth &= ~CURLAUTH_NTLM; /* no NTLM support */ 1106 auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */ 1107#elif !defined(NTLM_WB_ENABLED) 1108 auth &= ~CURLAUTH_NTLM_WB; /* no NTLM_WB support */ 1109#endif 1110#ifndef USE_SPNEGO 1111 auth &= ~CURLAUTH_NEGOTIATE; /* no Negotiate (SPNEGO) auth without 1112 GSS-API or SSPI */ 1113#endif 1114 1115 /* check if any auth bit lower than CURLAUTH_ONLY is still set */ 1116 bitcheck = 0; 1117 authbits = FALSE; 1118 while(bitcheck < 31) { 1119 if(auth & (1UL << bitcheck++)) { 1120 authbits = TRUE; 1121 break; 1122 } 1123 } 1124 if(!authbits) 1125 return CURLE_NOT_BUILT_IN; /* no supported types left! */ 1126 1127 data->set.proxyauth = auth; 1128 } 1129 break; 1130 1131 case CURLOPT_PROXY: 1132 /* 1133 * Set proxy server:port to use as proxy. 1134 * 1135 * If the proxy is set to "" (and CURLOPT_SOCKS_PROXY is set to "" or NULL) 1136 * we explicitly say that we don't want to use a proxy 1137 * (even though there might be environment variables saying so). 1138 * 1139 * Setting it to NULL, means no proxy but allows the environment variables 1140 * to decide for us (if CURLOPT_SOCKS_PROXY setting it to NULL). 1141 */ 1142 result = Curl_setstropt(&data->set.str[STRING_PROXY], 1143 va_arg(param, char *)); 1144 break; 1145 1146 case CURLOPT_PRE_PROXY: 1147 /* 1148 * Set proxy server:port to use as SOCKS proxy. 1149 * 1150 * If the proxy is set to "" or NULL we explicitly say that we don't want 1151 * to use the socks proxy. 1152 */ 1153 result = Curl_setstropt(&data->set.str[STRING_PRE_PROXY], 1154 va_arg(param, char *)); 1155 break; 1156 1157 case CURLOPT_PROXYTYPE: 1158 /* 1159 * Set proxy type. 1160 */ 1161 arg = va_arg(param, long); 1162 if((arg < CURLPROXY_HTTP) || (arg > CURLPROXY_SOCKS5_HOSTNAME)) 1163 return CURLE_BAD_FUNCTION_ARGUMENT; 1164 data->set.proxytype = (unsigned char)(curl_proxytype)arg; 1165 break; 1166 1167 case CURLOPT_PROXY_TRANSFER_MODE: 1168 /* 1169 * set transfer mode (;type=<a|i>) when doing FTP via an HTTP proxy 1170 */ 1171 switch(va_arg(param, long)) { 1172 case 0: 1173 data->set.proxy_transfer_mode = FALSE; 1174 break; 1175 case 1: 1176 data->set.proxy_transfer_mode = TRUE; 1177 break; 1178 default: 1179 /* reserve other values for future use */ 1180 result = CURLE_BAD_FUNCTION_ARGUMENT; 1181 break; 1182 } 1183 break; 1184 1185 case CURLOPT_SOCKS5_AUTH: 1186 data->set.socks5auth = (unsigned char)va_arg(param, unsigned long); 1187 if(data->set.socks5auth & ~(CURLAUTH_BASIC | CURLAUTH_GSSAPI)) 1188 result = CURLE_NOT_BUILT_IN; 1189 break; 1190#endif /* CURL_DISABLE_PROXY */ 1191 1192#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) 1193 case CURLOPT_SOCKS5_GSSAPI_NEC: 1194 /* 1195 * Set flag for NEC SOCK5 support 1196 */ 1197 data->set.socks5_gssapi_nec = (0 != va_arg(param, long)); 1198 break; 1199#endif 1200#ifndef CURL_DISABLE_PROXY 1201 case CURLOPT_SOCKS5_GSSAPI_SERVICE: 1202 case CURLOPT_PROXY_SERVICE_NAME: 1203 /* 1204 * Set proxy authentication service name for Kerberos 5 and SPNEGO 1205 */ 1206 result = Curl_setstropt(&data->set.str[STRING_PROXY_SERVICE_NAME], 1207 va_arg(param, char *)); 1208 break; 1209#endif 1210 case CURLOPT_SERVICE_NAME: 1211 /* 1212 * Set authentication service name for DIGEST-MD5, Kerberos 5 and SPNEGO 1213 */ 1214 result = Curl_setstropt(&data->set.str[STRING_SERVICE_NAME], 1215 va_arg(param, char *)); 1216 break; 1217 1218 case CURLOPT_HEADERDATA: 1219 /* 1220 * Custom pointer to pass the header write callback function 1221 */ 1222 data->set.writeheader = (void *)va_arg(param, void *); 1223 break; 1224 case CURLOPT_ERRORBUFFER: 1225 /* 1226 * Error buffer provided by the caller to get the human readable 1227 * error string in. 1228 */ 1229 data->set.errorbuffer = va_arg(param, char *); 1230 break; 1231 case CURLOPT_WRITEDATA: 1232 /* 1233 * FILE pointer to write to. Or possibly 1234 * used as argument to the write callback. 1235 */ 1236 data->set.out = va_arg(param, void *); 1237 break; 1238 1239#ifdef CURL_LIST_ONLY_PROTOCOL 1240 case CURLOPT_DIRLISTONLY: 1241 /* 1242 * An option that changes the command to one that asks for a list only, no 1243 * file info details. Used for FTP, POP3 and SFTP. 1244 */ 1245 data->set.list_only = (0 != va_arg(param, long)); 1246 break; 1247#endif 1248 case CURLOPT_APPEND: 1249 /* 1250 * We want to upload and append to an existing file. Used for FTP and 1251 * SFTP. 1252 */ 1253 data->set.remote_append = (0 != va_arg(param, long)); 1254 break; 1255 1256#ifndef CURL_DISABLE_FTP 1257 case CURLOPT_FTP_FILEMETHOD: 1258 /* 1259 * How do access files over FTP. 1260 */ 1261 arg = va_arg(param, long); 1262 if((arg < CURLFTPMETHOD_DEFAULT) || (arg >= CURLFTPMETHOD_LAST)) 1263 return CURLE_BAD_FUNCTION_ARGUMENT; 1264 data->set.ftp_filemethod = (unsigned char)arg; 1265 break; 1266 case CURLOPT_FTPPORT: 1267 /* 1268 * Use FTP PORT, this also specifies which IP address to use 1269 */ 1270 result = Curl_setstropt(&data->set.str[STRING_FTPPORT], 1271 va_arg(param, char *)); 1272 data->set.ftp_use_port = !!(data->set.str[STRING_FTPPORT]); 1273 break; 1274 1275 case CURLOPT_FTP_USE_EPRT: 1276 data->set.ftp_use_eprt = (0 != va_arg(param, long)); 1277 break; 1278 1279 case CURLOPT_FTP_USE_EPSV: 1280 data->set.ftp_use_epsv = (0 != va_arg(param, long)); 1281 break; 1282 1283 case CURLOPT_FTP_USE_PRET: 1284 data->set.ftp_use_pret = (0 != va_arg(param, long)); 1285 break; 1286 1287 case CURLOPT_FTP_SSL_CCC: 1288 arg = va_arg(param, long); 1289 if((arg < CURLFTPSSL_CCC_NONE) || (arg >= CURLFTPSSL_CCC_LAST)) 1290 return CURLE_BAD_FUNCTION_ARGUMENT; 1291 data->set.ftp_ccc = (unsigned char)arg; 1292 break; 1293 1294 case CURLOPT_FTP_SKIP_PASV_IP: 1295 /* 1296 * Enable or disable FTP_SKIP_PASV_IP, which will disable/enable the 1297 * bypass of the IP address in PASV responses. 1298 */ 1299 data->set.ftp_skip_ip = (0 != va_arg(param, long)); 1300 break; 1301 1302 case CURLOPT_FTP_ACCOUNT: 1303 result = Curl_setstropt(&data->set.str[STRING_FTP_ACCOUNT], 1304 va_arg(param, char *)); 1305 break; 1306 1307 case CURLOPT_FTP_ALTERNATIVE_TO_USER: 1308 result = Curl_setstropt(&data->set.str[STRING_FTP_ALTERNATIVE_TO_USER], 1309 va_arg(param, char *)); 1310 break; 1311 1312 case CURLOPT_FTPSSLAUTH: 1313 /* 1314 * Set a specific auth for FTP-SSL transfers. 1315 */ 1316 arg = va_arg(param, long); 1317 if((arg < CURLFTPAUTH_DEFAULT) || (arg >= CURLFTPAUTH_LAST)) 1318 return CURLE_BAD_FUNCTION_ARGUMENT; 1319 data->set.ftpsslauth = (unsigned char)(curl_ftpauth)arg; 1320 break; 1321 case CURLOPT_KRBLEVEL: 1322 /* 1323 * A string that defines the kerberos security level. 1324 */ 1325 result = Curl_setstropt(&data->set.str[STRING_KRB_LEVEL], 1326 va_arg(param, char *)); 1327 data->set.krb = !!(data->set.str[STRING_KRB_LEVEL]); 1328 break; 1329#endif 1330#if !defined(CURL_DISABLE_FTP) || defined(USE_SSH) 1331 case CURLOPT_FTP_CREATE_MISSING_DIRS: 1332 /* 1333 * An FTP/SFTP option that modifies an upload to create missing 1334 * directories on the server. 1335 */ 1336 arg = va_arg(param, long); 1337 /* reserve other values for future use */ 1338 if((arg < CURLFTP_CREATE_DIR_NONE) || 1339 (arg > CURLFTP_CREATE_DIR_RETRY)) 1340 result = CURLE_BAD_FUNCTION_ARGUMENT; 1341 else 1342 data->set.ftp_create_missing_dirs = (unsigned char)arg; 1343 break; 1344 1345 case CURLOPT_POSTQUOTE: 1346 /* 1347 * List of RAW FTP commands to use after a transfer 1348 */ 1349 data->set.postquote = va_arg(param, struct curl_slist *); 1350 break; 1351 case CURLOPT_PREQUOTE: 1352 /* 1353 * List of RAW FTP commands to use prior to RETR (Wesley Laxton) 1354 */ 1355 data->set.prequote = va_arg(param, struct curl_slist *); 1356 break; 1357 case CURLOPT_QUOTE: 1358 /* 1359 * List of RAW FTP commands to use before a transfer 1360 */ 1361 data->set.quote = va_arg(param, struct curl_slist *); 1362 break; 1363#endif 1364 case CURLOPT_READDATA: 1365 /* 1366 * FILE pointer to read the file to be uploaded from. Or possibly 1367 * used as argument to the read callback. 1368 */ 1369 data->set.in_set = va_arg(param, void *); 1370 break; 1371 case CURLOPT_INFILESIZE: 1372 /* 1373 * If known, this should inform curl about the file size of the 1374 * to-be-uploaded file. 1375 */ 1376 arg = va_arg(param, long); 1377 if(arg < -1) 1378 return CURLE_BAD_FUNCTION_ARGUMENT; 1379 data->set.filesize = arg; 1380 break; 1381 case CURLOPT_INFILESIZE_LARGE: 1382 /* 1383 * If known, this should inform curl about the file size of the 1384 * to-be-uploaded file. 1385 */ 1386 bigsize = va_arg(param, curl_off_t); 1387 if(bigsize < -1) 1388 return CURLE_BAD_FUNCTION_ARGUMENT; 1389 data->set.filesize = bigsize; 1390 break; 1391 case CURLOPT_LOW_SPEED_LIMIT: 1392 /* 1393 * The low speed limit that if transfers are below this for 1394 * CURLOPT_LOW_SPEED_TIME, the transfer is aborted. 1395 */ 1396 arg = va_arg(param, long); 1397 if(arg < 0) 1398 return CURLE_BAD_FUNCTION_ARGUMENT; 1399 data->set.low_speed_limit = arg; 1400 break; 1401 case CURLOPT_MAX_SEND_SPEED_LARGE: 1402 /* 1403 * When transfer uploads are faster then CURLOPT_MAX_SEND_SPEED_LARGE 1404 * bytes per second the transfer is throttled.. 1405 */ 1406 bigsize = va_arg(param, curl_off_t); 1407 if(bigsize < 0) 1408 return CURLE_BAD_FUNCTION_ARGUMENT; 1409 data->set.max_send_speed = bigsize; 1410 break; 1411 case CURLOPT_MAX_RECV_SPEED_LARGE: 1412 /* 1413 * When receiving data faster than CURLOPT_MAX_RECV_SPEED_LARGE bytes per 1414 * second the transfer is throttled.. 1415 */ 1416 bigsize = va_arg(param, curl_off_t); 1417 if(bigsize < 0) 1418 return CURLE_BAD_FUNCTION_ARGUMENT; 1419 data->set.max_recv_speed = bigsize; 1420 break; 1421 case CURLOPT_LOW_SPEED_TIME: 1422 /* 1423 * The low speed time that if transfers are below the set 1424 * CURLOPT_LOW_SPEED_LIMIT during this time, the transfer is aborted. 1425 */ 1426 arg = va_arg(param, long); 1427 if(arg < 0) 1428 return CURLE_BAD_FUNCTION_ARGUMENT; 1429 data->set.low_speed_time = arg; 1430 break; 1431 case CURLOPT_CURLU: 1432 /* 1433 * pass CURLU to set URL 1434 */ 1435 data->set.uh = va_arg(param, CURLU *); 1436 break; 1437 case CURLOPT_URL: 1438 /* 1439 * The URL to fetch. 1440 */ 1441 if(data->state.url_alloc) { 1442 /* the already set URL is allocated, free it first! */ 1443 Curl_safefree(data->state.url); 1444 data->state.url_alloc = FALSE; 1445 } 1446 result = Curl_setstropt(&data->set.str[STRING_SET_URL], 1447 va_arg(param, char *)); 1448 data->state.url = data->set.str[STRING_SET_URL]; 1449 break; 1450 case CURLOPT_PORT: 1451 /* 1452 * The port number to use when getting the URL. 0 disables it. 1453 */ 1454 arg = va_arg(param, long); 1455 if((arg < 0) || (arg > 65535)) 1456 return CURLE_BAD_FUNCTION_ARGUMENT; 1457 data->set.use_port = (unsigned short)arg; 1458 break; 1459 case CURLOPT_TIMEOUT: 1460 /* 1461 * The maximum time you allow curl to use for a single transfer 1462 * operation. 1463 */ 1464 arg = va_arg(param, long); 1465 if((arg >= 0) && (arg <= (INT_MAX/1000))) 1466 data->set.timeout = (unsigned int)arg * 1000; 1467 else 1468 return CURLE_BAD_FUNCTION_ARGUMENT; 1469 break; 1470 1471 case CURLOPT_TIMEOUT_MS: 1472 uarg = va_arg(param, unsigned long); 1473 if(uarg > UINT_MAX) 1474 uarg = UINT_MAX; 1475 data->set.timeout = (unsigned int)uarg; 1476 break; 1477 1478 case CURLOPT_CONNECTTIMEOUT: 1479 /* 1480 * The maximum time you allow curl to use to connect. 1481 */ 1482 arg = va_arg(param, long); 1483 if((arg >= 0) && (arg <= (INT_MAX/1000))) 1484 data->set.connecttimeout = (unsigned int)arg * 1000; 1485 else 1486 return CURLE_BAD_FUNCTION_ARGUMENT; 1487 break; 1488 1489 case CURLOPT_CONNECTTIMEOUT_MS: 1490 uarg = va_arg(param, unsigned long); 1491 if(uarg > UINT_MAX) 1492 uarg = UINT_MAX; 1493 data->set.connecttimeout = (unsigned int)uarg; 1494 break; 1495 1496#ifndef CURL_DISABLE_FTP 1497 case CURLOPT_ACCEPTTIMEOUT_MS: 1498 /* 1499 * The maximum time for curl to wait for FTP server connect 1500 */ 1501 uarg = va_arg(param, unsigned long); 1502 if(uarg > UINT_MAX) 1503 uarg = UINT_MAX; 1504 data->set.accepttimeout = (unsigned int)uarg; 1505 break; 1506#endif 1507 1508 case CURLOPT_USERPWD: 1509 /* 1510 * user:password to use in the operation 1511 */ 1512 result = setstropt_userpwd(va_arg(param, char *), 1513 &data->set.str[STRING_USERNAME], 1514 &data->set.str[STRING_PASSWORD]); 1515 break; 1516 1517 case CURLOPT_USERNAME: 1518 /* 1519 * authentication user name to use in the operation 1520 */ 1521 result = Curl_setstropt(&data->set.str[STRING_USERNAME], 1522 va_arg(param, char *)); 1523 break; 1524 case CURLOPT_PASSWORD: 1525 /* 1526 * authentication password to use in the operation 1527 */ 1528 result = Curl_setstropt(&data->set.str[STRING_PASSWORD], 1529 va_arg(param, char *)); 1530 break; 1531 1532 case CURLOPT_LOGIN_OPTIONS: 1533 /* 1534 * authentication options to use in the operation 1535 */ 1536 result = Curl_setstropt(&data->set.str[STRING_OPTIONS], 1537 va_arg(param, char *)); 1538 break; 1539 1540 case CURLOPT_XOAUTH2_BEARER: 1541 /* 1542 * OAuth 2.0 bearer token to use in the operation 1543 */ 1544 result = Curl_setstropt(&data->set.str[STRING_BEARER], 1545 va_arg(param, char *)); 1546 break; 1547 1548 case CURLOPT_RESOLVE: 1549 /* 1550 * List of HOST:PORT:[addresses] strings to populate the DNS cache with 1551 * Entries added this way will remain in the cache until explicitly 1552 * removed or the handle is cleaned up. 1553 * 1554 * Prefix the HOST with plus sign (+) to have the entry expire just like 1555 * automatically added entries. 1556 * 1557 * Prefix the HOST with dash (-) to _remove_ the entry from the cache. 1558 * 1559 * This API can remove any entry from the DNS cache, but only entries 1560 * that aren't actually in use right now will be pruned immediately. 1561 */ 1562 data->set.resolve = va_arg(param, struct curl_slist *); 1563 data->state.resolve = data->set.resolve; 1564 break; 1565 case CURLOPT_PROGRESSFUNCTION: 1566 /* 1567 * Progress callback function 1568 */ 1569 data->set.fprogress = va_arg(param, curl_progress_callback); 1570 if(data->set.fprogress) 1571 data->progress.callback = TRUE; /* no longer internal */ 1572 else 1573 data->progress.callback = FALSE; /* NULL enforces internal */ 1574 break; 1575 1576 case CURLOPT_XFERINFOFUNCTION: 1577 /* 1578 * Transfer info callback function 1579 */ 1580 data->set.fxferinfo = va_arg(param, curl_xferinfo_callback); 1581 if(data->set.fxferinfo) 1582 data->progress.callback = TRUE; /* no longer internal */ 1583 else 1584 data->progress.callback = FALSE; /* NULL enforces internal */ 1585 1586 break; 1587 1588 case CURLOPT_PROGRESSDATA: 1589 /* 1590 * Custom client data to pass to the progress callback 1591 */ 1592 data->set.progress_client = va_arg(param, void *); 1593 break; 1594 1595#ifndef CURL_DISABLE_PROXY 1596 case CURLOPT_PROXYUSERPWD: 1597 /* 1598 * user:password needed to use the proxy 1599 */ 1600 result = setstropt_userpwd(va_arg(param, char *), 1601 &data->set.str[STRING_PROXYUSERNAME], 1602 &data->set.str[STRING_PROXYPASSWORD]); 1603 break; 1604 case CURLOPT_PROXYUSERNAME: 1605 /* 1606 * authentication user name to use in the operation 1607 */ 1608 result = Curl_setstropt(&data->set.str[STRING_PROXYUSERNAME], 1609 va_arg(param, char *)); 1610 break; 1611 case CURLOPT_PROXYPASSWORD: 1612 /* 1613 * authentication password to use in the operation 1614 */ 1615 result = Curl_setstropt(&data->set.str[STRING_PROXYPASSWORD], 1616 va_arg(param, char *)); 1617 break; 1618 case CURLOPT_NOPROXY: 1619 /* 1620 * proxy exception list 1621 */ 1622 result = Curl_setstropt(&data->set.str[STRING_NOPROXY], 1623 va_arg(param, char *)); 1624 break; 1625#endif 1626 1627 case CURLOPT_RANGE: 1628 /* 1629 * What range of the file you want to transfer 1630 */ 1631 result = Curl_setstropt(&data->set.str[STRING_SET_RANGE], 1632 va_arg(param, char *)); 1633 break; 1634 case CURLOPT_RESUME_FROM: 1635 /* 1636 * Resume transfer at the given file position 1637 */ 1638 arg = va_arg(param, long); 1639 if(arg < -1) 1640 return CURLE_BAD_FUNCTION_ARGUMENT; 1641 data->set.set_resume_from = arg; 1642 break; 1643 case CURLOPT_RESUME_FROM_LARGE: 1644 /* 1645 * Resume transfer at the given file position 1646 */ 1647 bigsize = va_arg(param, curl_off_t); 1648 if(bigsize < -1) 1649 return CURLE_BAD_FUNCTION_ARGUMENT; 1650 data->set.set_resume_from = bigsize; 1651 break; 1652 case CURLOPT_DEBUGFUNCTION: 1653 /* 1654 * stderr write callback. 1655 */ 1656 data->set.fdebug = va_arg(param, curl_debug_callback); 1657 /* 1658 * if the callback provided is NULL, it'll use the default callback 1659 */ 1660 break; 1661 case CURLOPT_DEBUGDATA: 1662 /* 1663 * Set to a void * that should receive all error writes. This 1664 * defaults to CURLOPT_STDERR for normal operations. 1665 */ 1666 data->set.debugdata = va_arg(param, void *); 1667 break; 1668 case CURLOPT_STDERR: 1669 /* 1670 * Set to a FILE * that should receive all error writes. This 1671 * defaults to stderr for normal operations. 1672 */ 1673 data->set.err = va_arg(param, FILE *); 1674 if(!data->set.err) 1675 data->set.err = stderr; 1676 break; 1677 case CURLOPT_HEADERFUNCTION: 1678 /* 1679 * Set header write callback 1680 */ 1681 data->set.fwrite_header = va_arg(param, curl_write_callback); 1682 break; 1683 case CURLOPT_WRITEFUNCTION: 1684 /* 1685 * Set data write callback 1686 */ 1687 data->set.fwrite_func = va_arg(param, curl_write_callback); 1688 if(!data->set.fwrite_func) 1689 /* When set to NULL, reset to our internal default function */ 1690 data->set.fwrite_func = (curl_write_callback)fwrite; 1691 break; 1692 case CURLOPT_READFUNCTION: 1693 /* 1694 * Read data callback 1695 */ 1696 data->set.fread_func_set = va_arg(param, curl_read_callback); 1697 if(!data->set.fread_func_set) { 1698 data->set.is_fread_set = 0; 1699 /* When set to NULL, reset to our internal default function */ 1700 data->set.fread_func_set = (curl_read_callback)fread; 1701 } 1702 else 1703 data->set.is_fread_set = 1; 1704 break; 1705 case CURLOPT_SEEKFUNCTION: 1706 /* 1707 * Seek callback. Might be NULL. 1708 */ 1709 data->set.seek_func = va_arg(param, curl_seek_callback); 1710 break; 1711 case CURLOPT_SEEKDATA: 1712 /* 1713 * Seek control callback. Might be NULL. 1714 */ 1715 data->set.seek_client = va_arg(param, void *); 1716 break; 1717 case CURLOPT_IOCTLFUNCTION: 1718 /* 1719 * I/O control callback. Might be NULL. 1720 */ 1721 data->set.ioctl_func = va_arg(param, curl_ioctl_callback); 1722 break; 1723 case CURLOPT_IOCTLDATA: 1724 /* 1725 * I/O control data pointer. Might be NULL. 1726 */ 1727 data->set.ioctl_client = va_arg(param, void *); 1728 break; 1729 case CURLOPT_SSLCERT: 1730 /* 1731 * String that holds file name of the SSL certificate to use 1732 */ 1733 result = Curl_setstropt(&data->set.str[STRING_CERT], 1734 va_arg(param, char *)); 1735 break; 1736 case CURLOPT_SSLCERT_BLOB: 1737 /* 1738 * Blob that holds file content of the SSL certificate to use 1739 */ 1740 result = Curl_setblobopt(&data->set.blobs[BLOB_CERT], 1741 va_arg(param, struct curl_blob *)); 1742 break; 1743#ifndef CURL_DISABLE_PROXY 1744 case CURLOPT_PROXY_SSLCERT: 1745 /* 1746 * String that holds file name of the SSL certificate to use for proxy 1747 */ 1748 result = Curl_setstropt(&data->set.str[STRING_CERT_PROXY], 1749 va_arg(param, char *)); 1750 break; 1751 case CURLOPT_PROXY_SSLCERT_BLOB: 1752 /* 1753 * Blob that holds file content of the SSL certificate to use for proxy 1754 */ 1755 result = Curl_setblobopt(&data->set.blobs[BLOB_CERT_PROXY], 1756 va_arg(param, struct curl_blob *)); 1757 break; 1758#endif 1759 case CURLOPT_SSLCERTTYPE: 1760 /* 1761 * String that holds file type of the SSL certificate to use 1762 */ 1763 result = Curl_setstropt(&data->set.str[STRING_CERT_TYPE], 1764 va_arg(param, char *)); 1765 break; 1766#ifndef CURL_DISABLE_PROXY 1767 case CURLOPT_PROXY_SSLCERTTYPE: 1768 /* 1769 * String that holds file type of the SSL certificate to use for proxy 1770 */ 1771 result = Curl_setstropt(&data->set.str[STRING_CERT_TYPE_PROXY], 1772 va_arg(param, char *)); 1773 break; 1774#endif 1775 case CURLOPT_SSLKEY: 1776 /* 1777 * String that holds file name of the SSL key to use 1778 */ 1779 result = Curl_setstropt(&data->set.str[STRING_KEY], 1780 va_arg(param, char *)); 1781 break; 1782 case CURLOPT_SSLKEY_BLOB: 1783 /* 1784 * Blob that holds file content of the SSL key to use 1785 */ 1786 result = Curl_setblobopt(&data->set.blobs[BLOB_KEY], 1787 va_arg(param, struct curl_blob *)); 1788 break; 1789#ifndef CURL_DISABLE_PROXY 1790 case CURLOPT_PROXY_SSLKEY: 1791 /* 1792 * String that holds file name of the SSL key to use for proxy 1793 */ 1794 result = Curl_setstropt(&data->set.str[STRING_KEY_PROXY], 1795 va_arg(param, char *)); 1796 break; 1797 case CURLOPT_PROXY_SSLKEY_BLOB: 1798 /* 1799 * Blob that holds file content of the SSL key to use for proxy 1800 */ 1801 result = Curl_setblobopt(&data->set.blobs[BLOB_KEY_PROXY], 1802 va_arg(param, struct curl_blob *)); 1803 break; 1804#endif 1805 case CURLOPT_SSLKEYTYPE: 1806 /* 1807 * String that holds file type of the SSL key to use 1808 */ 1809 result = Curl_setstropt(&data->set.str[STRING_KEY_TYPE], 1810 va_arg(param, char *)); 1811 break; 1812#ifndef CURL_DISABLE_PROXY 1813 case CURLOPT_PROXY_SSLKEYTYPE: 1814 /* 1815 * String that holds file type of the SSL key to use for proxy 1816 */ 1817 result = Curl_setstropt(&data->set.str[STRING_KEY_TYPE_PROXY], 1818 va_arg(param, char *)); 1819 break; 1820#endif 1821 case CURLOPT_KEYPASSWD: 1822 /* 1823 * String that holds the SSL or SSH private key password. 1824 */ 1825 result = Curl_setstropt(&data->set.str[STRING_KEY_PASSWD], 1826 va_arg(param, char *)); 1827 break; 1828#ifndef CURL_DISABLE_PROXY 1829 case CURLOPT_PROXY_KEYPASSWD: 1830 /* 1831 * String that holds the SSL private key password for proxy. 1832 */ 1833 result = Curl_setstropt(&data->set.str[STRING_KEY_PASSWD_PROXY], 1834 va_arg(param, char *)); 1835 break; 1836#endif 1837 case CURLOPT_SSLENGINE: 1838 /* 1839 * String that holds the SSL crypto engine. 1840 */ 1841 argptr = va_arg(param, char *); 1842 if(argptr && argptr[0]) { 1843 result = Curl_setstropt(&data->set.str[STRING_SSL_ENGINE], argptr); 1844 if(!result) { 1845 result = Curl_ssl_set_engine(data, argptr); 1846 } 1847 } 1848 break; 1849 1850 case CURLOPT_SSLENGINE_DEFAULT: 1851 /* 1852 * flag to set engine as default. 1853 */ 1854 Curl_setstropt(&data->set.str[STRING_SSL_ENGINE], NULL); 1855 result = Curl_ssl_set_engine_default(data); 1856 break; 1857 case CURLOPT_CRLF: 1858 /* 1859 * Kludgy option to enable CRLF conversions. Subject for removal. 1860 */ 1861 data->set.crlf = (0 != va_arg(param, long)); 1862 break; 1863#ifndef CURL_DISABLE_PROXY 1864 case CURLOPT_HAPROXYPROTOCOL: 1865 /* 1866 * Set to send the HAProxy Proxy Protocol header 1867 */ 1868 data->set.haproxyprotocol = (0 != va_arg(param, long)); 1869 break; 1870 case CURLOPT_HAPROXY_CLIENT_IP: 1871 /* 1872 * Set the client IP to send through HAProxy PROXY protocol 1873 */ 1874 result = Curl_setstropt(&data->set.str[STRING_HAPROXY_CLIENT_IP], 1875 va_arg(param, char *)); 1876 /* We enable implicitly the HAProxy protocol if we use this flag. */ 1877 data->set.haproxyprotocol = TRUE; 1878 break; 1879#endif 1880 case CURLOPT_INTERFACE: 1881 /* 1882 * Set what interface or address/hostname to bind the socket to when 1883 * performing an operation and thus what from-IP your connection will use. 1884 */ 1885 result = Curl_setstropt(&data->set.str[STRING_DEVICE], 1886 va_arg(param, char *)); 1887 break; 1888#ifndef CURL_DISABLE_BINDLOCAL 1889 case CURLOPT_LOCALPORT: 1890 /* 1891 * Set what local port to bind the socket to when performing an operation. 1892 */ 1893 arg = va_arg(param, long); 1894 if((arg < 0) || (arg > 65535)) 1895 return CURLE_BAD_FUNCTION_ARGUMENT; 1896 data->set.localport = curlx_sltous(arg); 1897 break; 1898 case CURLOPT_LOCALPORTRANGE: 1899 /* 1900 * Set number of local ports to try, starting with CURLOPT_LOCALPORT. 1901 */ 1902 arg = va_arg(param, long); 1903 if((arg < 0) || (arg > 65535)) 1904 return CURLE_BAD_FUNCTION_ARGUMENT; 1905 data->set.localportrange = curlx_sltous(arg); 1906 break; 1907#endif 1908 case CURLOPT_GSSAPI_DELEGATION: 1909 /* 1910 * GSS-API credential delegation bitmask 1911 */ 1912 uarg = va_arg(param, unsigned long); 1913 data->set.gssapi_delegation = (unsigned char)uarg& 1914 (CURLGSSAPI_DELEGATION_POLICY_FLAG|CURLGSSAPI_DELEGATION_FLAG); 1915 break; 1916 case CURLOPT_SSL_VERIFYPEER: 1917 /* 1918 * Enable peer SSL verifying. 1919 */ 1920 data->set.ssl.primary.verifypeer = (0 != va_arg(param, long)); 1921 1922 /* Update the current connection ssl_config. */ 1923 Curl_ssl_conn_config_update(data, FALSE); 1924 break; 1925#ifndef CURL_DISABLE_DOH 1926 case CURLOPT_DOH_SSL_VERIFYPEER: 1927 /* 1928 * Enable peer SSL verifying for DoH. 1929 */ 1930 data->set.doh_verifypeer = (0 != va_arg(param, long)); 1931 break; 1932#endif 1933#ifndef CURL_DISABLE_PROXY 1934 case CURLOPT_PROXY_SSL_VERIFYPEER: 1935 /* 1936 * Enable peer SSL verifying for proxy. 1937 */ 1938 data->set.proxy_ssl.primary.verifypeer = 1939 (0 != va_arg(param, long))?TRUE:FALSE; 1940 1941 /* Update the current connection proxy_ssl_config. */ 1942 Curl_ssl_conn_config_update(data, TRUE); 1943 break; 1944#endif 1945 case CURLOPT_SSL_VERIFYHOST: 1946 /* 1947 * Enable verification of the host name in the peer certificate 1948 */ 1949 arg = va_arg(param, long); 1950 1951 /* Obviously people are not reading documentation and too many thought 1952 this argument took a boolean when it wasn't and misused it. 1953 Treat 1 and 2 the same */ 1954 data->set.ssl.primary.verifyhost = !!(arg & 3); 1955 1956 /* Update the current connection ssl_config. */ 1957 Curl_ssl_conn_config_update(data, FALSE); 1958 break; 1959#ifndef CURL_DISABLE_DOH 1960 case CURLOPT_DOH_SSL_VERIFYHOST: 1961 /* 1962 * Enable verification of the host name in the peer certificate for DoH 1963 */ 1964 arg = va_arg(param, long); 1965 1966 /* Treat both 1 and 2 as TRUE */ 1967 data->set.doh_verifyhost = !!(arg & 3); 1968 break; 1969#endif 1970#ifndef CURL_DISABLE_PROXY 1971 case CURLOPT_PROXY_SSL_VERIFYHOST: 1972 /* 1973 * Enable verification of the host name in the peer certificate for proxy 1974 */ 1975 arg = va_arg(param, long); 1976 1977 /* Treat both 1 and 2 as TRUE */ 1978 data->set.proxy_ssl.primary.verifyhost = (bool)((arg & 3)?TRUE:FALSE); 1979 /* Update the current connection proxy_ssl_config. */ 1980 Curl_ssl_conn_config_update(data, TRUE); 1981 break; 1982#endif 1983 case CURLOPT_SSL_VERIFYSTATUS: 1984 /* 1985 * Enable certificate status verifying. 1986 */ 1987 if(!Curl_ssl_cert_status_request()) { 1988 result = CURLE_NOT_BUILT_IN; 1989 break; 1990 } 1991 1992 data->set.ssl.primary.verifystatus = (0 != va_arg(param, long)); 1993 1994 /* Update the current connection ssl_config. */ 1995 Curl_ssl_conn_config_update(data, FALSE); 1996 break; 1997#ifndef CURL_DISABLE_DOH 1998 case CURLOPT_DOH_SSL_VERIFYSTATUS: 1999 /* 2000 * Enable certificate status verifying for DoH. 2001 */ 2002 if(!Curl_ssl_cert_status_request()) { 2003 result = CURLE_NOT_BUILT_IN; 2004 break; 2005 } 2006 2007 data->set.doh_verifystatus = (0 != va_arg(param, long)); 2008 break; 2009#endif 2010 case CURLOPT_SSL_CTX_FUNCTION: 2011 /* 2012 * Set a SSL_CTX callback 2013 */ 2014#ifdef USE_SSL 2015 if(Curl_ssl_supports(data, SSLSUPP_SSL_CTX)) 2016 data->set.ssl.fsslctx = va_arg(param, curl_ssl_ctx_callback); 2017 else 2018#endif 2019 result = CURLE_NOT_BUILT_IN; 2020 break; 2021 case CURLOPT_SSL_CTX_DATA: 2022 /* 2023 * Set a SSL_CTX callback parameter pointer 2024 */ 2025#ifdef USE_SSL 2026 if(Curl_ssl_supports(data, SSLSUPP_SSL_CTX)) 2027 data->set.ssl.fsslctxp = va_arg(param, void *); 2028 else 2029#endif 2030 result = CURLE_NOT_BUILT_IN; 2031 break; 2032 case CURLOPT_SSL_FALSESTART: 2033 /* 2034 * Enable TLS false start. 2035 */ 2036 if(!Curl_ssl_false_start(data)) { 2037 result = CURLE_NOT_BUILT_IN; 2038 break; 2039 } 2040 2041 data->set.ssl.falsestart = (0 != va_arg(param, long)); 2042 break; 2043 case CURLOPT_CERTINFO: 2044#ifdef USE_SSL 2045 if(Curl_ssl_supports(data, SSLSUPP_CERTINFO)) 2046 data->set.ssl.certinfo = (0 != va_arg(param, long)); 2047 else 2048#endif 2049 result = CURLE_NOT_BUILT_IN; 2050 break; 2051 case CURLOPT_PINNEDPUBLICKEY: 2052 /* 2053 * Set pinned public key for SSL connection. 2054 * Specify file name of the public key in DER format. 2055 */ 2056#ifdef USE_SSL 2057 if(Curl_ssl_supports(data, SSLSUPP_PINNEDPUBKEY)) 2058 result = Curl_setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY], 2059 va_arg(param, char *)); 2060 else 2061#endif 2062 result = CURLE_NOT_BUILT_IN; 2063 break; 2064#ifndef CURL_DISABLE_PROXY 2065 case CURLOPT_PROXY_PINNEDPUBLICKEY: 2066 /* 2067 * Set pinned public key for SSL connection. 2068 * Specify file name of the public key in DER format. 2069 */ 2070#ifdef USE_SSL 2071 if(Curl_ssl_supports(data, SSLSUPP_PINNEDPUBKEY)) 2072 result = Curl_setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY], 2073 va_arg(param, char *)); 2074 else 2075#endif 2076 result = CURLE_NOT_BUILT_IN; 2077 break; 2078#endif 2079 case CURLOPT_CAINFO: 2080 /* 2081 * Set CA info for SSL connection. Specify file name of the CA certificate 2082 */ 2083 result = Curl_setstropt(&data->set.str[STRING_SSL_CAFILE], 2084 va_arg(param, char *)); 2085 break; 2086 case CURLOPT_CAINFO_BLOB: 2087 /* 2088 * Blob that holds CA info for SSL connection. 2089 * Specify entire PEM of the CA certificate 2090 */ 2091#ifdef USE_SSL 2092 if(Curl_ssl_supports(data, SSLSUPP_CAINFO_BLOB)) { 2093 result = Curl_setblobopt(&data->set.blobs[BLOB_CAINFO], 2094 va_arg(param, struct curl_blob *)); 2095 break; 2096 } 2097 else 2098#endif 2099 return CURLE_NOT_BUILT_IN; 2100#ifndef CURL_DISABLE_PROXY 2101 case CURLOPT_PROXY_CAINFO: 2102 /* 2103 * Set CA info SSL connection for proxy. Specify file name of the 2104 * CA certificate 2105 */ 2106 result = Curl_setstropt(&data->set.str[STRING_SSL_CAFILE_PROXY], 2107 va_arg(param, char *)); 2108 break; 2109 case CURLOPT_PROXY_CAINFO_BLOB: 2110 /* 2111 * Blob that holds CA info for SSL connection proxy. 2112 * Specify entire PEM of the CA certificate 2113 */ 2114#ifdef USE_SSL 2115 if(Curl_ssl_supports(data, SSLSUPP_CAINFO_BLOB)) { 2116 result = Curl_setblobopt(&data->set.blobs[BLOB_CAINFO_PROXY], 2117 va_arg(param, struct curl_blob *)); 2118 break; 2119 } 2120 else 2121#endif 2122 return CURLE_NOT_BUILT_IN; 2123#endif 2124 case CURLOPT_CAPATH: 2125 /* 2126 * Set CA path info for SSL connection. Specify directory name of the CA 2127 * certificates which have been prepared using openssl c_rehash utility. 2128 */ 2129#ifdef USE_SSL 2130 if(Curl_ssl_supports(data, SSLSUPP_CA_PATH)) 2131 /* This does not work on windows. */ 2132 result = Curl_setstropt(&data->set.str[STRING_SSL_CAPATH], 2133 va_arg(param, char *)); 2134 else 2135#endif 2136 result = CURLE_NOT_BUILT_IN; 2137 break; 2138#ifndef CURL_DISABLE_PROXY 2139 case CURLOPT_PROXY_CAPATH: 2140 /* 2141 * Set CA path info for SSL connection proxy. Specify directory name of the 2142 * CA certificates which have been prepared using openssl c_rehash utility. 2143 */ 2144#ifdef USE_SSL 2145 if(Curl_ssl_supports(data, SSLSUPP_CA_PATH)) 2146 /* This does not work on windows. */ 2147 result = Curl_setstropt(&data->set.str[STRING_SSL_CAPATH_PROXY], 2148 va_arg(param, char *)); 2149 else 2150#endif 2151 result = CURLE_NOT_BUILT_IN; 2152 break; 2153#endif 2154 case CURLOPT_CRLFILE: 2155 /* 2156 * Set CRL file info for SSL connection. Specify file name of the CRL 2157 * to check certificates revocation 2158 */ 2159 result = Curl_setstropt(&data->set.str[STRING_SSL_CRLFILE], 2160 va_arg(param, char *)); 2161 break; 2162#ifndef CURL_DISABLE_PROXY 2163 case CURLOPT_PROXY_CRLFILE: 2164 /* 2165 * Set CRL file info for SSL connection for proxy. Specify file name of the 2166 * CRL to check certificates revocation 2167 */ 2168 result = Curl_setstropt(&data->set.str[STRING_SSL_CRLFILE_PROXY], 2169 va_arg(param, char *)); 2170 break; 2171#endif 2172 case CURLOPT_ISSUERCERT: 2173 /* 2174 * Set Issuer certificate file 2175 * to check certificates issuer 2176 */ 2177 result = Curl_setstropt(&data->set.str[STRING_SSL_ISSUERCERT], 2178 va_arg(param, char *)); 2179 break; 2180 case CURLOPT_ISSUERCERT_BLOB: 2181 /* 2182 * Blob that holds Issuer certificate to check certificates issuer 2183 */ 2184 result = Curl_setblobopt(&data->set.blobs[BLOB_SSL_ISSUERCERT], 2185 va_arg(param, struct curl_blob *)); 2186 break; 2187#ifndef CURL_DISABLE_PROXY 2188 case CURLOPT_PROXY_ISSUERCERT: 2189 /* 2190 * Set Issuer certificate file 2191 * to check certificates issuer 2192 */ 2193 result = Curl_setstropt(&data->set.str[STRING_SSL_ISSUERCERT_PROXY], 2194 va_arg(param, char *)); 2195 break; 2196 case CURLOPT_PROXY_ISSUERCERT_BLOB: 2197 /* 2198 * Blob that holds Issuer certificate to check certificates issuer 2199 */ 2200 result = Curl_setblobopt(&data->set.blobs[BLOB_SSL_ISSUERCERT_PROXY], 2201 va_arg(param, struct curl_blob *)); 2202 break; 2203#endif 2204#ifndef CURL_DISABLE_TELNET 2205 case CURLOPT_TELNETOPTIONS: 2206 /* 2207 * Set a linked list of telnet options 2208 */ 2209 data->set.telnet_options = va_arg(param, struct curl_slist *); 2210 break; 2211#endif 2212 case CURLOPT_BUFFERSIZE: 2213 /* 2214 * The application kindly asks for a differently sized receive buffer. 2215 * If it seems reasonable, we'll use it. 2216 */ 2217 if(data->state.buffer) 2218 return CURLE_BAD_FUNCTION_ARGUMENT; 2219 2220 arg = va_arg(param, long); 2221 2222 if(arg > READBUFFER_MAX) 2223 arg = READBUFFER_MAX; 2224 else if(arg < 1) 2225 arg = READBUFFER_SIZE; 2226 else if(arg < READBUFFER_MIN) 2227 arg = READBUFFER_MIN; 2228 2229 data->set.buffer_size = (unsigned int)arg; 2230 break; 2231 2232 case CURLOPT_UPLOAD_BUFFERSIZE: 2233 /* 2234 * The application kindly asks for a differently sized upload buffer. 2235 * Cap it to sensible. 2236 */ 2237 arg = va_arg(param, long); 2238 2239 if(arg > UPLOADBUFFER_MAX) 2240 arg = UPLOADBUFFER_MAX; 2241 else if(arg < UPLOADBUFFER_MIN) 2242 arg = UPLOADBUFFER_MIN; 2243 2244 data->set.upload_buffer_size = (unsigned int)arg; 2245 Curl_safefree(data->state.ulbuf); /* force a realloc next opportunity */ 2246 break; 2247 2248 case CURLOPT_NOSIGNAL: 2249 /* 2250 * The application asks not to set any signal() or alarm() handlers, 2251 * even when using a timeout. 2252 */ 2253 data->set.no_signal = (0 != va_arg(param, long)); 2254 break; 2255 2256 case CURLOPT_SHARE: 2257 { 2258 struct Curl_share *set; 2259 set = va_arg(param, struct Curl_share *); 2260 2261 /* disconnect from old share, if any */ 2262 if(data->share) { 2263 Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE); 2264 2265 if(data->dns.hostcachetype == HCACHE_SHARED) { 2266 data->dns.hostcache = NULL; 2267 data->dns.hostcachetype = HCACHE_NONE; 2268 } 2269 2270#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES) 2271 if(data->share->cookies == data->cookies) 2272 data->cookies = NULL; 2273#endif 2274 2275#ifndef CURL_DISABLE_HSTS 2276 if(data->share->hsts == data->hsts) 2277 data->hsts = NULL; 2278#endif 2279#ifdef USE_SSL 2280 if(data->share->sslsession == data->state.session) 2281 data->state.session = NULL; 2282#endif 2283#ifdef USE_LIBPSL 2284 if(data->psl == &data->share->psl) 2285 data->psl = data->multi? &data->multi->psl: NULL; 2286#endif 2287 2288 data->share->dirty--; 2289 2290 Curl_share_unlock(data, CURL_LOCK_DATA_SHARE); 2291 data->share = NULL; 2292 } 2293 2294 if(GOOD_SHARE_HANDLE(set)) 2295 /* use new share if it set */ 2296 data->share = set; 2297 if(data->share) { 2298 2299 Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE); 2300 2301 data->share->dirty++; 2302 2303 if(data->share->specifier & (1<< CURL_LOCK_DATA_DNS)) { 2304 /* use shared host cache */ 2305 data->dns.hostcache = &data->share->hostcache; 2306 data->dns.hostcachetype = HCACHE_SHARED; 2307 } 2308#if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES) 2309 if(data->share->cookies) { 2310 /* use shared cookie list, first free own one if any */ 2311 Curl_cookie_cleanup(data->cookies); 2312 /* enable cookies since we now use a share that uses cookies! */ 2313 data->cookies = data->share->cookies; 2314 } 2315#endif /* CURL_DISABLE_HTTP */ 2316#ifndef CURL_DISABLE_HSTS 2317 if(data->share->hsts) { 2318 /* first free the private one if any */ 2319 Curl_hsts_cleanup(&data->hsts); 2320 data->hsts = data->share->hsts; 2321 } 2322#endif /* CURL_DISABLE_HTTP */ 2323#ifdef USE_SSL 2324 if(data->share->sslsession) { 2325 data->set.general_ssl.max_ssl_sessions = data->share->max_ssl_sessions; 2326 data->state.session = data->share->sslsession; 2327 } 2328#endif 2329#ifdef USE_LIBPSL 2330 if(data->share->specifier & (1 << CURL_LOCK_DATA_PSL)) 2331 data->psl = &data->share->psl; 2332#endif 2333 2334 Curl_share_unlock(data, CURL_LOCK_DATA_SHARE); 2335 } 2336 /* check for host cache not needed, 2337 * it will be done by curl_easy_perform */ 2338 } 2339 break; 2340 2341 case CURLOPT_PRIVATE: 2342 /* 2343 * Set private data pointer. 2344 */ 2345 data->set.private_data = va_arg(param, void *); 2346 break; 2347 2348 case CURLOPT_MAXFILESIZE: 2349 /* 2350 * Set the maximum size of a file to download. 2351 */ 2352 arg = va_arg(param, long); 2353 if(arg < 0) 2354 return CURLE_BAD_FUNCTION_ARGUMENT; 2355 data->set.max_filesize = arg; 2356 break; 2357 2358#ifdef USE_SSL 2359 case CURLOPT_USE_SSL: 2360 /* 2361 * Make transfers attempt to use SSL/TLS. 2362 */ 2363 arg = va_arg(param, long); 2364 if((arg < CURLUSESSL_NONE) || (arg >= CURLUSESSL_LAST)) 2365 return CURLE_BAD_FUNCTION_ARGUMENT; 2366 data->set.use_ssl = (unsigned char)arg; 2367 break; 2368 2369 case CURLOPT_SSL_OPTIONS: 2370 arg = va_arg(param, long); 2371 data->set.ssl.primary.ssl_options = (unsigned char)(arg & 0xff); 2372 data->set.ssl.enable_beast = !!(arg & CURLSSLOPT_ALLOW_BEAST); 2373 data->set.ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE); 2374 data->set.ssl.no_partialchain = !!(arg & CURLSSLOPT_NO_PARTIALCHAIN); 2375 data->set.ssl.revoke_best_effort = !!(arg & CURLSSLOPT_REVOKE_BEST_EFFORT); 2376 data->set.ssl.native_ca_store = !!(arg & CURLSSLOPT_NATIVE_CA); 2377 data->set.ssl.auto_client_cert = !!(arg & CURLSSLOPT_AUTO_CLIENT_CERT); 2378 /* If a setting is added here it should also be added in dohprobe() 2379 which sets its own CURLOPT_SSL_OPTIONS based on these settings. */ 2380 break; 2381 2382#ifndef CURL_DISABLE_PROXY 2383 case CURLOPT_PROXY_SSL_OPTIONS: 2384 arg = va_arg(param, long); 2385 data->set.proxy_ssl.primary.ssl_options = (unsigned char)(arg & 0xff); 2386 data->set.proxy_ssl.enable_beast = !!(arg & CURLSSLOPT_ALLOW_BEAST); 2387 data->set.proxy_ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE); 2388 data->set.proxy_ssl.no_partialchain = !!(arg & CURLSSLOPT_NO_PARTIALCHAIN); 2389 data->set.proxy_ssl.revoke_best_effort = 2390 !!(arg & CURLSSLOPT_REVOKE_BEST_EFFORT); 2391 data->set.proxy_ssl.native_ca_store = !!(arg & CURLSSLOPT_NATIVE_CA); 2392 data->set.proxy_ssl.auto_client_cert = 2393 !!(arg & CURLSSLOPT_AUTO_CLIENT_CERT); 2394 break; 2395#endif 2396 2397 case CURLOPT_SSL_EC_CURVES: 2398 /* 2399 * Set accepted curves in SSL connection setup. 2400 * Specify colon-delimited list of curve algorithm names. 2401 */ 2402 result = Curl_setstropt(&data->set.str[STRING_SSL_EC_CURVES], 2403 va_arg(param, char *)); 2404 break; 2405#endif 2406 case CURLOPT_IPRESOLVE: 2407 arg = va_arg(param, long); 2408 if((arg < CURL_IPRESOLVE_WHATEVER) || (arg > CURL_IPRESOLVE_V6)) 2409 return CURLE_BAD_FUNCTION_ARGUMENT; 2410 data->set.ipver = (unsigned char) arg; 2411 break; 2412 2413 case CURLOPT_MAXFILESIZE_LARGE: 2414 /* 2415 * Set the maximum size of a file to download. 2416 */ 2417 bigsize = va_arg(param, curl_off_t); 2418 if(bigsize < 0) 2419 return CURLE_BAD_FUNCTION_ARGUMENT; 2420 data->set.max_filesize = bigsize; 2421 break; 2422 2423 case CURLOPT_TCP_NODELAY: 2424 /* 2425 * Enable or disable TCP_NODELAY, which will disable/enable the Nagle 2426 * algorithm 2427 */ 2428 data->set.tcp_nodelay = (0 != va_arg(param, long)); 2429 break; 2430 2431 case CURLOPT_IGNORE_CONTENT_LENGTH: 2432 data->set.ignorecl = (0 != va_arg(param, long)); 2433 break; 2434 2435 case CURLOPT_CONNECT_ONLY: 2436 /* 2437 * No data transfer. 2438 * (1) - only do connection 2439 * (2) - do first get request but get no content 2440 */ 2441 arg = va_arg(param, long); 2442 if(arg > 2) 2443 return CURLE_BAD_FUNCTION_ARGUMENT; 2444 data->set.connect_only = (unsigned char)arg; 2445 break; 2446 2447 case CURLOPT_SOCKOPTFUNCTION: 2448 /* 2449 * socket callback function: called after socket() but before connect() 2450 */ 2451 data->set.fsockopt = va_arg(param, curl_sockopt_callback); 2452 break; 2453 2454 case CURLOPT_SOCKOPTDATA: 2455 /* 2456 * socket callback data pointer. Might be NULL. 2457 */ 2458 data->set.sockopt_client = va_arg(param, void *); 2459 break; 2460 2461 case CURLOPT_OPENSOCKETFUNCTION: 2462 /* 2463 * open/create socket callback function: called instead of socket(), 2464 * before connect() 2465 */ 2466 data->set.fopensocket = va_arg(param, curl_opensocket_callback); 2467 break; 2468 2469 case CURLOPT_OPENSOCKETDATA: 2470 /* 2471 * socket callback data pointer. Might be NULL. 2472 */ 2473 data->set.opensocket_client = va_arg(param, void *); 2474 break; 2475 2476 case CURLOPT_CLOSESOCKETFUNCTION: 2477 /* 2478 * close socket callback function: called instead of close() 2479 * when shutting down a connection 2480 */ 2481 data->set.fclosesocket = va_arg(param, curl_closesocket_callback); 2482 break; 2483 2484 case CURLOPT_RESOLVER_START_FUNCTION: 2485 /* 2486 * resolver start callback function: called before a new resolver request 2487 * is started 2488 */ 2489 data->set.resolver_start = va_arg(param, curl_resolver_start_callback); 2490 break; 2491 2492 case CURLOPT_RESOLVER_START_DATA: 2493 /* 2494 * resolver start callback data pointer. Might be NULL. 2495 */ 2496 data->set.resolver_start_client = va_arg(param, void *); 2497 break; 2498 2499 case CURLOPT_CLOSESOCKETDATA: 2500 /* 2501 * socket callback data pointer. Might be NULL. 2502 */ 2503 data->set.closesocket_client = va_arg(param, void *); 2504 break; 2505 2506 case CURLOPT_SSL_SESSIONID_CACHE: 2507 data->set.ssl.primary.sessionid = (0 != va_arg(param, long)); 2508#ifndef CURL_DISABLE_PROXY 2509 data->set.proxy_ssl.primary.sessionid = data->set.ssl.primary.sessionid; 2510#endif 2511 break; 2512 2513#ifdef USE_SSH 2514 /* we only include SSH options if explicitly built to support SSH */ 2515 case CURLOPT_SSH_AUTH_TYPES: 2516 data->set.ssh_auth_types = (unsigned int)va_arg(param, long); 2517 break; 2518 2519 case CURLOPT_SSH_PUBLIC_KEYFILE: 2520 /* 2521 * Use this file instead of the $HOME/.ssh/id_dsa.pub file 2522 */ 2523 result = Curl_setstropt(&data->set.str[STRING_SSH_PUBLIC_KEY], 2524 va_arg(param, char *)); 2525 break; 2526 2527 case CURLOPT_SSH_PRIVATE_KEYFILE: 2528 /* 2529 * Use this file instead of the $HOME/.ssh/id_dsa file 2530 */ 2531 result = Curl_setstropt(&data->set.str[STRING_SSH_PRIVATE_KEY], 2532 va_arg(param, char *)); 2533 break; 2534 case CURLOPT_SSH_HOST_PUBLIC_KEY_MD5: 2535 /* 2536 * Option to allow for the MD5 of the host public key to be checked 2537 * for validation purposes. 2538 */ 2539 result = Curl_setstropt(&data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5], 2540 va_arg(param, char *)); 2541 break; 2542 2543 case CURLOPT_SSH_KNOWNHOSTS: 2544 /* 2545 * Store the file name to read known hosts from. 2546 */ 2547 result = Curl_setstropt(&data->set.str[STRING_SSH_KNOWNHOSTS], 2548 va_arg(param, char *)); 2549 break; 2550#ifdef USE_LIBSSH2 2551 case CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256: 2552 /* 2553 * Option to allow for the SHA256 of the host public key to be checked 2554 * for validation purposes. 2555 */ 2556 result = Curl_setstropt(&data->set.str[STRING_SSH_HOST_PUBLIC_KEY_SHA256], 2557 va_arg(param, char *)); 2558 break; 2559 2560 case CURLOPT_SSH_HOSTKEYFUNCTION: 2561 /* the callback to check the hostkey without the knownhost file */ 2562 data->set.ssh_hostkeyfunc = va_arg(param, curl_sshhostkeycallback); 2563 break; 2564 2565 case CURLOPT_SSH_HOSTKEYDATA: 2566 /* 2567 * Custom client data to pass to the SSH keyfunc callback 2568 */ 2569 data->set.ssh_hostkeyfunc_userp = va_arg(param, void *); 2570 break; 2571#endif 2572 2573 case CURLOPT_SSH_KEYFUNCTION: 2574 /* setting to NULL is fine since the ssh.c functions themselves will 2575 then revert to use the internal default */ 2576 data->set.ssh_keyfunc = va_arg(param, curl_sshkeycallback); 2577 break; 2578 2579 case CURLOPT_SSH_KEYDATA: 2580 /* 2581 * Custom client data to pass to the SSH keyfunc callback 2582 */ 2583 data->set.ssh_keyfunc_userp = va_arg(param, void *); 2584 break; 2585 2586 case CURLOPT_SSH_COMPRESSION: 2587 data->set.ssh_compression = (0 != va_arg(param, long))?TRUE:FALSE; 2588 break; 2589#endif /* USE_SSH */ 2590 2591 case CURLOPT_HTTP_TRANSFER_DECODING: 2592 /* 2593 * disable libcurl transfer encoding is used 2594 */ 2595#ifndef USE_HYPER 2596 data->set.http_te_skip = (0 == va_arg(param, long)); 2597 break; 2598#else 2599 return CURLE_NOT_BUILT_IN; /* hyper doesn't support */ 2600#endif 2601 2602 case CURLOPT_HTTP_CONTENT_DECODING: 2603 /* 2604 * raw data passed to the application when content encoding is used 2605 */ 2606 data->set.http_ce_skip = (0 == va_arg(param, long)); 2607 break; 2608 2609#if !defined(CURL_DISABLE_FTP) || defined(USE_SSH) 2610 case CURLOPT_NEW_FILE_PERMS: 2611 /* 2612 * Uses these permissions instead of 0644 2613 */ 2614 arg = va_arg(param, long); 2615 if((arg < 0) || (arg > 0777)) 2616 return CURLE_BAD_FUNCTION_ARGUMENT; 2617 data->set.new_file_perms = (unsigned int)arg; 2618 break; 2619#endif 2620#ifdef USE_SSH 2621 case CURLOPT_NEW_DIRECTORY_PERMS: 2622 /* 2623 * Uses these permissions instead of 0755 2624 */ 2625 arg = va_arg(param, long); 2626 if((arg < 0) || (arg > 0777)) 2627 return CURLE_BAD_FUNCTION_ARGUMENT; 2628 data->set.new_directory_perms = (unsigned int)arg; 2629 break; 2630#endif 2631 2632#ifdef ENABLE_IPV6 2633 case CURLOPT_ADDRESS_SCOPE: 2634 /* 2635 * Use this scope id when using IPv6 2636 * We always get longs when passed plain numericals so we should check 2637 * that the value fits into an unsigned 32 bit integer. 2638 */ 2639 uarg = va_arg(param, unsigned long); 2640#if SIZEOF_LONG > 4 2641 if(uarg > UINT_MAX) 2642 return CURLE_BAD_FUNCTION_ARGUMENT; 2643#endif 2644 data->set.scope_id = (unsigned int)uarg; 2645 break; 2646#endif 2647 2648 case CURLOPT_PROTOCOLS: 2649 /* set the bitmask for the protocols that are allowed to be used for the 2650 transfer, which thus helps the app which takes URLs from users or other 2651 external inputs and want to restrict what protocol(s) to deal 2652 with. Defaults to CURLPROTO_ALL. */ 2653 data->set.allowed_protocols = (curl_prot_t)va_arg(param, long); 2654 break; 2655 2656 case CURLOPT_REDIR_PROTOCOLS: 2657 /* set the bitmask for the protocols that libcurl is allowed to follow to, 2658 as a subset of the CURLOPT_PROTOCOLS ones. That means the protocol needs 2659 to be set in both bitmasks to be allowed to get redirected to. */ 2660 data->set.redir_protocols = (curl_prot_t)va_arg(param, long); 2661 break; 2662 2663 case CURLOPT_PROTOCOLS_STR: { 2664 argptr = va_arg(param, char *); 2665 result = protocol2num(argptr, &data->set.allowed_protocols); 2666 if(result) 2667 return result; 2668 break; 2669 } 2670 2671 case CURLOPT_REDIR_PROTOCOLS_STR: { 2672 argptr = va_arg(param, char *); 2673 result = protocol2num(argptr, &data->set.redir_protocols); 2674 if(result) 2675 return result; 2676 break; 2677 } 2678 2679 case CURLOPT_DEFAULT_PROTOCOL: 2680 /* Set the protocol to use when the URL doesn't include any protocol */ 2681 result = Curl_setstropt(&data->set.str[STRING_DEFAULT_PROTOCOL], 2682 va_arg(param, char *)); 2683 break; 2684#ifndef CURL_DISABLE_SMTP 2685 case CURLOPT_MAIL_FROM: 2686 /* Set the SMTP mail originator */ 2687 result = Curl_setstropt(&data->set.str[STRING_MAIL_FROM], 2688 va_arg(param, char *)); 2689 break; 2690 2691 case CURLOPT_MAIL_AUTH: 2692 /* Set the SMTP auth originator */ 2693 result = Curl_setstropt(&data->set.str[STRING_MAIL_AUTH], 2694 va_arg(param, char *)); 2695 break; 2696 2697 case CURLOPT_MAIL_RCPT: 2698 /* Set the list of mail recipients */ 2699 data->set.mail_rcpt = va_arg(param, struct curl_slist *); 2700 break; 2701 case CURLOPT_MAIL_RCPT_ALLOWFAILS: 2702 /* allow RCPT TO command to fail for some recipients */ 2703 data->set.mail_rcpt_allowfails = (0 != va_arg(param, long)); 2704 break; 2705#endif 2706 2707 case CURLOPT_SASL_AUTHZID: 2708 /* Authorization identity (identity to act as) */ 2709 result = Curl_setstropt(&data->set.str[STRING_SASL_AUTHZID], 2710 va_arg(param, char *)); 2711 break; 2712 2713 case CURLOPT_SASL_IR: 2714 /* Enable/disable SASL initial response */ 2715 data->set.sasl_ir = (0 != va_arg(param, long)); 2716 break; 2717#ifndef CURL_DISABLE_RTSP 2718 case CURLOPT_RTSP_REQUEST: 2719 { 2720 /* 2721 * Set the RTSP request method (OPTIONS, SETUP, PLAY, etc...) 2722 * Would this be better if the RTSPREQ_* were just moved into here? 2723 */ 2724 long in_rtspreq = va_arg(param, long); 2725 Curl_RtspReq rtspreq = RTSPREQ_NONE; 2726 switch(in_rtspreq) { 2727 case CURL_RTSPREQ_OPTIONS: 2728 rtspreq = RTSPREQ_OPTIONS; 2729 break; 2730 2731 case CURL_RTSPREQ_DESCRIBE: 2732 rtspreq = RTSPREQ_DESCRIBE; 2733 break; 2734 2735 case CURL_RTSPREQ_ANNOUNCE: 2736 rtspreq = RTSPREQ_ANNOUNCE; 2737 break; 2738 2739 case CURL_RTSPREQ_SETUP: 2740 rtspreq = RTSPREQ_SETUP; 2741 break; 2742 2743 case CURL_RTSPREQ_PLAY: 2744 rtspreq = RTSPREQ_PLAY; 2745 break; 2746 2747 case CURL_RTSPREQ_PAUSE: 2748 rtspreq = RTSPREQ_PAUSE; 2749 break; 2750 2751 case CURL_RTSPREQ_TEARDOWN: 2752 rtspreq = RTSPREQ_TEARDOWN; 2753 break; 2754 2755 case CURL_RTSPREQ_GET_PARAMETER: 2756 rtspreq = RTSPREQ_GET_PARAMETER; 2757 break; 2758 2759 case CURL_RTSPREQ_SET_PARAMETER: 2760 rtspreq = RTSPREQ_SET_PARAMETER; 2761 break; 2762 2763 case CURL_RTSPREQ_RECORD: 2764 rtspreq = RTSPREQ_RECORD; 2765 break; 2766 2767 case CURL_RTSPREQ_RECEIVE: 2768 rtspreq = RTSPREQ_RECEIVE; 2769 break; 2770 default: 2771 rtspreq = RTSPREQ_NONE; 2772 } 2773 2774 data->set.rtspreq = rtspreq; 2775 break; 2776 } 2777 2778 2779 case CURLOPT_RTSP_SESSION_ID: 2780 /* 2781 * Set the RTSP Session ID manually. Useful if the application is 2782 * resuming a previously established RTSP session 2783 */ 2784 result = Curl_setstropt(&data->set.str[STRING_RTSP_SESSION_ID], 2785 va_arg(param, char *)); 2786 break; 2787 2788 case CURLOPT_RTSP_STREAM_URI: 2789 /* 2790 * Set the Stream URI for the RTSP request. Unless the request is 2791 * for generic server options, the application will need to set this. 2792 */ 2793 result = Curl_setstropt(&data->set.str[STRING_RTSP_STREAM_URI], 2794 va_arg(param, char *)); 2795 break; 2796 2797 case CURLOPT_RTSP_TRANSPORT: 2798 /* 2799 * The content of the Transport: header for the RTSP request 2800 */ 2801 result = Curl_setstropt(&data->set.str[STRING_RTSP_TRANSPORT], 2802 va_arg(param, char *)); 2803 break; 2804 2805 case CURLOPT_RTSP_CLIENT_CSEQ: 2806 /* 2807 * Set the CSEQ number to issue for the next RTSP request. Useful if the 2808 * application is resuming a previously broken connection. The CSEQ 2809 * will increment from this new number henceforth. 2810 */ 2811 data->state.rtsp_next_client_CSeq = va_arg(param, long); 2812 break; 2813 2814 case CURLOPT_RTSP_SERVER_CSEQ: 2815 /* Same as the above, but for server-initiated requests */ 2816 data->state.rtsp_next_server_CSeq = va_arg(param, long); 2817 break; 2818 2819 case CURLOPT_INTERLEAVEDATA: 2820 data->set.rtp_out = va_arg(param, void *); 2821 break; 2822 case CURLOPT_INTERLEAVEFUNCTION: 2823 /* Set the user defined RTP write function */ 2824 data->set.fwrite_rtp = va_arg(param, curl_write_callback); 2825 break; 2826#endif 2827#ifndef CURL_DISABLE_FTP 2828 case CURLOPT_WILDCARDMATCH: 2829 data->set.wildcard_enabled = (0 != va_arg(param, long)); 2830 break; 2831 case CURLOPT_CHUNK_BGN_FUNCTION: 2832 data->set.chunk_bgn = va_arg(param, curl_chunk_bgn_callback); 2833 break; 2834 case CURLOPT_CHUNK_END_FUNCTION: 2835 data->set.chunk_end = va_arg(param, curl_chunk_end_callback); 2836 break; 2837 case CURLOPT_FNMATCH_FUNCTION: 2838 data->set.fnmatch = va_arg(param, curl_fnmatch_callback); 2839 break; 2840 case CURLOPT_CHUNK_DATA: 2841 data->set.wildcardptr = va_arg(param, void *); 2842 break; 2843 case CURLOPT_FNMATCH_DATA: 2844 data->set.fnmatch_data = va_arg(param, void *); 2845 break; 2846#endif 2847#ifdef USE_TLS_SRP 2848 case CURLOPT_TLSAUTH_USERNAME: 2849 result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_USERNAME], 2850 va_arg(param, char *)); 2851 break; 2852#ifndef CURL_DISABLE_PROXY 2853 case CURLOPT_PROXY_TLSAUTH_USERNAME: 2854 result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_USERNAME_PROXY], 2855 va_arg(param, char *)); 2856 break; 2857#endif 2858 case CURLOPT_TLSAUTH_PASSWORD: 2859 result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD], 2860 va_arg(param, char *)); 2861 break; 2862#ifndef CURL_DISABLE_PROXY 2863 case CURLOPT_PROXY_TLSAUTH_PASSWORD: 2864 result = Curl_setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD_PROXY], 2865 va_arg(param, char *)); 2866 break; 2867#endif 2868 case CURLOPT_TLSAUTH_TYPE: 2869 argptr = va_arg(param, char *); 2870 if(argptr && !strncasecompare(argptr, "SRP", strlen("SRP"))) 2871 return CURLE_BAD_FUNCTION_ARGUMENT; 2872 break; 2873#ifndef CURL_DISABLE_PROXY 2874 case CURLOPT_PROXY_TLSAUTH_TYPE: 2875 argptr = va_arg(param, char *); 2876 if(argptr || !strncasecompare(argptr, "SRP", strlen("SRP"))) 2877 return CURLE_BAD_FUNCTION_ARGUMENT; 2878 break; 2879#endif 2880#endif 2881#ifdef USE_ARES 2882 case CURLOPT_DNS_SERVERS: 2883 result = Curl_setstropt(&data->set.str[STRING_DNS_SERVERS], 2884 va_arg(param, char *)); 2885 if(result) 2886 return result; 2887 result = Curl_set_dns_servers(data, data->set.str[STRING_DNS_SERVERS]); 2888 break; 2889 case CURLOPT_DNS_INTERFACE: 2890 result = Curl_setstropt(&data->set.str[STRING_DNS_INTERFACE], 2891 va_arg(param, char *)); 2892 if(result) 2893 return result; 2894 result = Curl_set_dns_interface(data, data->set.str[STRING_DNS_INTERFACE]); 2895 break; 2896 case CURLOPT_DNS_LOCAL_IP4: 2897 result = Curl_setstropt(&data->set.str[STRING_DNS_LOCAL_IP4], 2898 va_arg(param, char *)); 2899 if(result) 2900 return result; 2901 result = Curl_set_dns_local_ip4(data, data->set.str[STRING_DNS_LOCAL_IP4]); 2902 break; 2903 case CURLOPT_DNS_LOCAL_IP6: 2904 result = Curl_setstropt(&data->set.str[STRING_DNS_LOCAL_IP6], 2905 va_arg(param, char *)); 2906 if(result) 2907 return result; 2908 result = Curl_set_dns_local_ip6(data, data->set.str[STRING_DNS_LOCAL_IP6]); 2909 break; 2910#endif 2911 case CURLOPT_TCP_KEEPALIVE: 2912 data->set.tcp_keepalive = (0 != va_arg(param, long)); 2913 break; 2914 case CURLOPT_TCP_KEEPIDLE: 2915 arg = va_arg(param, long); 2916 if(arg < 0) 2917 return CURLE_BAD_FUNCTION_ARGUMENT; 2918 else if(arg > INT_MAX) 2919 arg = INT_MAX; 2920 data->set.tcp_keepidle = (int)arg; 2921 break; 2922 case CURLOPT_TCP_KEEPINTVL: 2923 arg = va_arg(param, long); 2924 if(arg < 0) 2925 return CURLE_BAD_FUNCTION_ARGUMENT; 2926 else if(arg > INT_MAX) 2927 arg = INT_MAX; 2928 data->set.tcp_keepintvl = (int)arg; 2929 break; 2930 case CURLOPT_TCP_FASTOPEN: 2931#if defined(CONNECT_DATA_IDEMPOTENT) || defined(MSG_FASTOPEN) || \ 2932 defined(TCP_FASTOPEN_CONNECT) 2933 data->set.tcp_fastopen = (0 != va_arg(param, long))?TRUE:FALSE; 2934#else 2935 result = CURLE_NOT_BUILT_IN; 2936#endif 2937 break; 2938 case CURLOPT_SSL_ENABLE_NPN: 2939 break; 2940 case CURLOPT_SSL_ENABLE_ALPN: 2941 data->set.ssl_enable_alpn = (0 != va_arg(param, long)); 2942 break; 2943#ifdef USE_UNIX_SOCKETS 2944 case CURLOPT_UNIX_SOCKET_PATH: 2945 data->set.abstract_unix_socket = FALSE; 2946 result = Curl_setstropt(&data->set.str[STRING_UNIX_SOCKET_PATH], 2947 va_arg(param, char *)); 2948 break; 2949 case CURLOPT_ABSTRACT_UNIX_SOCKET: 2950 data->set.abstract_unix_socket = TRUE; 2951 result = Curl_setstropt(&data->set.str[STRING_UNIX_SOCKET_PATH], 2952 va_arg(param, char *)); 2953 break; 2954#endif 2955 2956 case CURLOPT_PATH_AS_IS: 2957 data->set.path_as_is = (0 != va_arg(param, long)); 2958 break; 2959 case CURLOPT_PIPEWAIT: 2960 data->set.pipewait = (0 != va_arg(param, long)); 2961 break; 2962 case CURLOPT_STREAM_WEIGHT: 2963#if defined(USE_HTTP2) || defined(USE_HTTP3) 2964 arg = va_arg(param, long); 2965 if((arg >= 1) && (arg <= 256)) 2966 data->set.priority.weight = (int)arg; 2967 break; 2968#else 2969 return CURLE_NOT_BUILT_IN; 2970#endif 2971 case CURLOPT_STREAM_DEPENDS: 2972 case CURLOPT_STREAM_DEPENDS_E: 2973 { 2974 struct Curl_easy *dep = va_arg(param, struct Curl_easy *); 2975 if(!dep || GOOD_EASY_HANDLE(dep)) { 2976 return Curl_data_priority_add_child(dep, data, 2977 option == CURLOPT_STREAM_DEPENDS_E); 2978 } 2979 break; 2980 } 2981 case CURLOPT_CONNECT_TO: 2982 data->set.connect_to = va_arg(param, struct curl_slist *); 2983 break; 2984 case CURLOPT_SUPPRESS_CONNECT_HEADERS: 2985 data->set.suppress_connect_headers = (0 != va_arg(param, long))?TRUE:FALSE; 2986 break; 2987 case CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS: 2988 uarg = va_arg(param, unsigned long); 2989 if(uarg > UINT_MAX) 2990 uarg = UINT_MAX; 2991 data->set.happy_eyeballs_timeout = (unsigned int)uarg; 2992 break; 2993#ifndef CURL_DISABLE_SHUFFLE_DNS 2994 case CURLOPT_DNS_SHUFFLE_ADDRESSES: 2995 data->set.dns_shuffle_addresses = (0 != va_arg(param, long)); 2996 break; 2997#endif 2998 case CURLOPT_DISALLOW_USERNAME_IN_URL: 2999 data->set.disallow_username_in_url = (0 != va_arg(param, long)); 3000 break; 3001#ifndef CURL_DISABLE_DOH 3002 case CURLOPT_DOH_URL: 3003 result = Curl_setstropt(&data->set.str[STRING_DOH], 3004 va_arg(param, char *)); 3005 data->set.doh = data->set.str[STRING_DOH]?TRUE:FALSE; 3006 break; 3007#endif 3008 case CURLOPT_UPKEEP_INTERVAL_MS: 3009 arg = va_arg(param, long); 3010 if(arg < 0) 3011 return CURLE_BAD_FUNCTION_ARGUMENT; 3012 data->set.upkeep_interval_ms = arg; 3013 break; 3014 case CURLOPT_MAXAGE_CONN: 3015 arg = va_arg(param, long); 3016 if(arg < 0) 3017 return CURLE_BAD_FUNCTION_ARGUMENT; 3018 data->set.maxage_conn = arg; 3019 break; 3020 case CURLOPT_MAXLIFETIME_CONN: 3021 arg = va_arg(param, long); 3022 if(arg < 0) 3023 return CURLE_BAD_FUNCTION_ARGUMENT; 3024 data->set.maxlifetime_conn = arg; 3025 break; 3026 case CURLOPT_TRAILERFUNCTION: 3027#ifndef CURL_DISABLE_HTTP 3028 data->set.trailer_callback = va_arg(param, curl_trailer_callback); 3029#endif 3030 break; 3031 case CURLOPT_TRAILERDATA: 3032#ifndef CURL_DISABLE_HTTP 3033 data->set.trailer_data = va_arg(param, void *); 3034#endif 3035 break; 3036#ifndef CURL_DISABLE_HSTS 3037 case CURLOPT_HSTSREADFUNCTION: 3038 data->set.hsts_read = va_arg(param, curl_hstsread_callback); 3039 break; 3040 case CURLOPT_HSTSREADDATA: 3041 data->set.hsts_read_userp = va_arg(param, void *); 3042 break; 3043 case CURLOPT_HSTSWRITEFUNCTION: 3044 data->set.hsts_write = va_arg(param, curl_hstswrite_callback); 3045 break; 3046 case CURLOPT_HSTSWRITEDATA: 3047 data->set.hsts_write_userp = va_arg(param, void *); 3048 break; 3049 case CURLOPT_HSTS: { 3050 struct curl_slist *h; 3051 if(!data->hsts) { 3052 data->hsts = Curl_hsts_init(); 3053 if(!data->hsts) 3054 return CURLE_OUT_OF_MEMORY; 3055 } 3056 argptr = va_arg(param, char *); 3057 if(argptr) { 3058 result = Curl_setstropt(&data->set.str[STRING_HSTS], argptr); 3059 if(result) 3060 return result; 3061 /* this needs to build a list of file names to read from, so that it can 3062 read them later, as we might get a shared HSTS handle to load them 3063 into */ 3064 h = curl_slist_append(data->state.hstslist, argptr); 3065 if(!h) { 3066 curl_slist_free_all(data->state.hstslist); 3067 data->state.hstslist = NULL; 3068 return CURLE_OUT_OF_MEMORY; 3069 } 3070 data->state.hstslist = h; /* store the list for later use */ 3071 } 3072 else { 3073 /* clear the list of HSTS files */ 3074 curl_slist_free_all(data->state.hstslist); 3075 data->state.hstslist = NULL; 3076 if(!data->share || !data->share->hsts) 3077 /* throw away the HSTS cache unless shared */ 3078 Curl_hsts_cleanup(&data->hsts); 3079 } 3080 break; 3081 } 3082 case CURLOPT_HSTS_CTRL: 3083 arg = va_arg(param, long); 3084 if(arg & CURLHSTS_ENABLE) { 3085 if(!data->hsts) { 3086 data->hsts = Curl_hsts_init(); 3087 if(!data->hsts) 3088 return CURLE_OUT_OF_MEMORY; 3089 } 3090 } 3091 else 3092 Curl_hsts_cleanup(&data->hsts); 3093 break; 3094#endif 3095#ifndef CURL_DISABLE_ALTSVC 3096 case CURLOPT_ALTSVC: 3097 if(!data->asi) { 3098 data->asi = Curl_altsvc_init(); 3099 if(!data->asi) 3100 return CURLE_OUT_OF_MEMORY; 3101 } 3102 argptr = va_arg(param, char *); 3103 result = Curl_setstropt(&data->set.str[STRING_ALTSVC], argptr); 3104 if(result) 3105 return result; 3106 if(argptr) 3107 (void)Curl_altsvc_load(data->asi, argptr); 3108 break; 3109 case CURLOPT_ALTSVC_CTRL: 3110 if(!data->asi) { 3111 data->asi = Curl_altsvc_init(); 3112 if(!data->asi) 3113 return CURLE_OUT_OF_MEMORY; 3114 } 3115 arg = va_arg(param, long); 3116 if(!arg) { 3117 DEBUGF(infof(data, "bad CURLOPT_ALTSVC_CTRL input")); 3118 return CURLE_BAD_FUNCTION_ARGUMENT; 3119 } 3120 result = Curl_altsvc_ctrl(data->asi, arg); 3121 if(result) 3122 return result; 3123 break; 3124#endif 3125 case CURLOPT_PREREQFUNCTION: 3126 data->set.fprereq = va_arg(param, curl_prereq_callback); 3127 break; 3128 case CURLOPT_PREREQDATA: 3129 data->set.prereq_userp = va_arg(param, void *); 3130 break; 3131#ifdef USE_WEBSOCKETS 3132 case CURLOPT_WS_OPTIONS: { 3133 bool raw; 3134 arg = va_arg(param, long); 3135 raw = (arg & CURLWS_RAW_MODE); 3136 data->set.ws_raw_mode = raw; 3137 break; 3138 } 3139#endif 3140 case CURLOPT_QUICK_EXIT: 3141 data->set.quick_exit = (0 != va_arg(param, long)) ? 1L:0L; 3142 break; 3143 default: 3144 /* unknown tag and its companion, just ignore: */ 3145 result = CURLE_UNKNOWN_OPTION; 3146 break; 3147 } 3148 3149 return result; 3150} 3151 3152/* 3153 * curl_easy_setopt() is the external interface for setting options on an 3154 * easy handle. 3155 * 3156 * NOTE: This is one of few API functions that are allowed to be called from 3157 * within a callback. 3158 */ 3159 3160#undef curl_easy_setopt 3161CURLcode curl_easy_setopt(struct Curl_easy *data, CURLoption tag, ...) 3162{ 3163 va_list arg; 3164 CURLcode result; 3165 3166 if(!data) 3167 return CURLE_BAD_FUNCTION_ARGUMENT; 3168 3169 va_start(arg, tag); 3170 3171 result = Curl_vsetopt(data, tag, arg); 3172 3173 va_end(arg); 3174#ifdef DEBUGBUILD 3175 if(result == CURLE_BAD_FUNCTION_ARGUMENT) 3176 infof(data, "setopt arg 0x%x returned CURLE_BAD_FUNCTION_ARGUMENT", tag); 3177#endif 3178 return result; 3179} 3180