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