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