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