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