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