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