xref: /curl/lib/setopt.c (revision 878bc429)
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 #ifdef USE_HYPER
648     /* Hyper does not support HTTP/0.9 */
649     if(enabled)
650       return CURLE_BAD_FUNCTION_ARGUMENT;
651 #else
652     data->set.http09_allowed = enabled;
653 #endif
654     break;
655 #endif /* ! CURL_DISABLE_HTTP */
656 
657 #ifndef CURL_DISABLE_MIME
658   case CURLOPT_MIME_OPTIONS:
659     data->set.mime_formescape = !!(arg & CURLMIMEOPT_FORMESCAPE);
660     break;
661 #endif
662 #ifndef CURL_DISABLE_PROXY
663   case CURLOPT_HTTPPROXYTUNNEL:
664     /*
665      * Tunnel operations through the proxy instead of normal proxy use
666      */
667     data->set.tunnel_thru_httpproxy = enabled;
668     break;
669 
670   case CURLOPT_PROXYPORT:
671     /*
672      * Explicitly set HTTP proxy port number.
673      */
674     if((arg < 0) || (arg > 65535))
675       return CURLE_BAD_FUNCTION_ARGUMENT;
676     data->set.proxyport = (unsigned short)arg;
677     break;
678 
679   case CURLOPT_PROXYAUTH:
680     return httpauth(data, TRUE, uarg);
681 
682   case CURLOPT_PROXYTYPE:
683     /*
684      * Set proxy type.
685      */
686     if((arg < CURLPROXY_HTTP) || (arg > CURLPROXY_SOCKS5_HOSTNAME))
687       return CURLE_BAD_FUNCTION_ARGUMENT;
688     data->set.proxytype = (unsigned char)(curl_proxytype)arg;
689     break;
690 
691   case CURLOPT_PROXY_TRANSFER_MODE:
692     /*
693      * set transfer mode (;type=<a|i>) when doing FTP via an HTTP proxy
694      */
695     if(uarg > 1)
696       /* reserve other values for future use */
697       return CURLE_BAD_FUNCTION_ARGUMENT;
698     data->set.proxy_transfer_mode = (bool)uarg;
699     break;
700   case CURLOPT_SOCKS5_AUTH:
701     if(data->set.socks5auth & ~(CURLAUTH_BASIC | CURLAUTH_GSSAPI))
702       return CURLE_NOT_BUILT_IN;
703     data->set.socks5auth = (unsigned char)uarg;
704     break;
705   case CURLOPT_HAPROXYPROTOCOL:
706     /*
707      * Set to send the HAProxy Proxy Protocol header
708      */
709     data->set.haproxyprotocol = enabled;
710     break;
711   case CURLOPT_PROXY_SSL_VERIFYPEER:
712     /*
713      * Enable peer SSL verifying for proxy.
714      */
715     data->set.proxy_ssl.primary.verifypeer = enabled;
716 
717     /* Update the current connection proxy_ssl_config. */
718     Curl_ssl_conn_config_update(data, TRUE);
719     break;
720   case CURLOPT_PROXY_SSL_VERIFYHOST:
721     /*
722      * Enable verification of the hostname in the peer certificate for proxy
723      */
724     data->set.proxy_ssl.primary.verifyhost = enabled;
725 
726     /* Update the current connection proxy_ssl_config. */
727     Curl_ssl_conn_config_update(data, TRUE);
728     break;
729 #endif /* ! CURL_DISABLE_PROXY */
730 
731 #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
732   case CURLOPT_SOCKS5_GSSAPI_NEC:
733     /*
734      * Set flag for NEC SOCK5 support
735      */
736     data->set.socks5_gssapi_nec = enabled;
737     break;
738 #endif
739 #ifdef CURL_LIST_ONLY_PROTOCOL
740   case CURLOPT_DIRLISTONLY:
741     /*
742      * An option that changes the command to one that asks for a list only, no
743      * file info details. Used for FTP, POP3 and SFTP.
744      */
745     data->set.list_only = enabled;
746     break;
747 #endif
748   case CURLOPT_APPEND:
749     /*
750      * We want to upload and append to an existing file. Used for FTP and
751      * SFTP.
752      */
753     data->set.remote_append = enabled;
754     break;
755 
756 #ifndef CURL_DISABLE_FTP
757   case CURLOPT_FTP_FILEMETHOD:
758     /*
759      * How do access files over FTP.
760      */
761     if((arg < CURLFTPMETHOD_DEFAULT) || (arg >= CURLFTPMETHOD_LAST))
762       return CURLE_BAD_FUNCTION_ARGUMENT;
763     data->set.ftp_filemethod = (unsigned char)arg;
764     break;
765   case CURLOPT_FTP_USE_EPRT:
766     data->set.ftp_use_eprt = enabled;
767     break;
768 
769   case CURLOPT_FTP_USE_EPSV:
770     data->set.ftp_use_epsv = enabled;
771     break;
772 
773   case CURLOPT_FTP_USE_PRET:
774     data->set.ftp_use_pret = enabled;
775     break;
776 
777   case CURLOPT_FTP_SSL_CCC:
778     if((arg < CURLFTPSSL_CCC_NONE) || (arg >= CURLFTPSSL_CCC_LAST))
779       return CURLE_BAD_FUNCTION_ARGUMENT;
780     data->set.ftp_ccc = (unsigned char)arg;
781     break;
782 
783   case CURLOPT_FTP_SKIP_PASV_IP:
784     /*
785      * Enable or disable FTP_SKIP_PASV_IP, which will disable/enable the
786      * bypass of the IP address in PASV responses.
787      */
788     data->set.ftp_skip_ip = enabled;
789     break;
790 
791   case CURLOPT_FTPSSLAUTH:
792     /*
793      * Set a specific auth for FTP-SSL transfers.
794      */
795     if((arg < CURLFTPAUTH_DEFAULT) || (arg >= CURLFTPAUTH_LAST))
796       return CURLE_BAD_FUNCTION_ARGUMENT;
797     data->set.ftpsslauth = (unsigned char)(curl_ftpauth)arg;
798     break;
799   case CURLOPT_ACCEPTTIMEOUT_MS:
800     /*
801      * The maximum time for curl to wait for FTP server connect
802      */
803     if(uarg > UINT_MAX)
804       uarg = UINT_MAX;
805     data->set.accepttimeout = (unsigned int)uarg;
806     break;
807   case CURLOPT_WILDCARDMATCH:
808     data->set.wildcard_enabled = enabled;
809     break;
810 #endif /* ! CURL_DISABLE_FTP */
811 #if !defined(CURL_DISABLE_FTP) || defined(USE_SSH)
812   case CURLOPT_FTP_CREATE_MISSING_DIRS:
813     /*
814      * An FTP/SFTP option that modifies an upload to create missing
815      * directories on the server.
816      */
817     /* reserve other values for future use */
818     if((arg < CURLFTP_CREATE_DIR_NONE) || (arg > CURLFTP_CREATE_DIR_RETRY))
819       return CURLE_BAD_FUNCTION_ARGUMENT;
820     data->set.ftp_create_missing_dirs = (unsigned char)arg;
821     break;
822 #endif /* ! CURL_DISABLE_FTP || USE_SSH */
823   case CURLOPT_INFILESIZE:
824     /*
825      * If known, this should inform curl about the file size of the
826      * to-be-uploaded file.
827      */
828     if(arg < -1)
829       return CURLE_BAD_FUNCTION_ARGUMENT;
830     data->set.filesize = arg;
831     break;
832   case CURLOPT_LOW_SPEED_LIMIT:
833     /*
834      * The low speed limit that if transfers are below this for
835      * CURLOPT_LOW_SPEED_TIME, the transfer is aborted.
836      */
837     if(arg < 0)
838       return CURLE_BAD_FUNCTION_ARGUMENT;
839     data->set.low_speed_limit = arg;
840     break;
841   case CURLOPT_LOW_SPEED_TIME:
842     /*
843      * The low speed time that if transfers are below the set
844      * CURLOPT_LOW_SPEED_LIMIT during this time, the transfer is aborted.
845      */
846     if(arg < 0)
847       return CURLE_BAD_FUNCTION_ARGUMENT;
848     data->set.low_speed_time = arg;
849     break;
850   case CURLOPT_PORT:
851     /*
852      * The port number to use when getting the URL. 0 disables it.
853      */
854     if((arg < 0) || (arg > 65535))
855       return CURLE_BAD_FUNCTION_ARGUMENT;
856     data->set.use_port = (unsigned short)arg;
857     break;
858   case CURLOPT_TIMEOUT:
859     /*
860      * The maximum time you allow curl to use for a single transfer
861      * operation.
862      */
863     if((arg >= 0) && (arg <= (INT_MAX/1000)))
864       data->set.timeout = (unsigned int)arg * 1000;
865     else
866       return CURLE_BAD_FUNCTION_ARGUMENT;
867     break;
868 
869   case CURLOPT_TIMEOUT_MS:
870     if(uarg > UINT_MAX)
871       uarg = UINT_MAX;
872     data->set.timeout = (unsigned int)uarg;
873     break;
874 
875   case CURLOPT_CONNECTTIMEOUT:
876     /*
877      * The maximum time you allow curl to use to connect.
878      */
879     if((arg >= 0) && (arg <= (INT_MAX/1000)))
880       data->set.connecttimeout = (unsigned int)arg * 1000;
881     else
882       return CURLE_BAD_FUNCTION_ARGUMENT;
883     break;
884 
885   case CURLOPT_CONNECTTIMEOUT_MS:
886     if(uarg > UINT_MAX)
887       uarg = UINT_MAX;
888     data->set.connecttimeout = (unsigned int)uarg;
889     break;
890 
891   case CURLOPT_RESUME_FROM:
892     /*
893      * Resume transfer at the given file position
894      */
895     if(arg < -1)
896       return CURLE_BAD_FUNCTION_ARGUMENT;
897     data->set.set_resume_from = arg;
898     break;
899 
900   case CURLOPT_CRLF:
901     /*
902      * Kludgy option to enable CRLF conversions. Subject for removal.
903      */
904     data->set.crlf = enabled;
905     break;
906 
907 #ifndef CURL_DISABLE_BINDLOCAL
908   case CURLOPT_LOCALPORT:
909     /*
910      * Set what local port to bind the socket to when performing an operation.
911      */
912     if((arg < 0) || (arg > 65535))
913       return CURLE_BAD_FUNCTION_ARGUMENT;
914     data->set.localport = curlx_sltous(arg);
915     break;
916   case CURLOPT_LOCALPORTRANGE:
917     /*
918      * Set number of local ports to try, starting with CURLOPT_LOCALPORT.
919      */
920     if((arg < 0) || (arg > 65535))
921       return CURLE_BAD_FUNCTION_ARGUMENT;
922     data->set.localportrange = curlx_sltous(arg);
923     break;
924 #endif
925 
926   case CURLOPT_GSSAPI_DELEGATION:
927     /*
928      * GSS-API credential delegation bitmask
929      */
930     data->set.gssapi_delegation = (unsigned char)uarg&
931       (CURLGSSAPI_DELEGATION_POLICY_FLAG|CURLGSSAPI_DELEGATION_FLAG);
932     break;
933   case CURLOPT_SSL_VERIFYPEER:
934     /*
935      * Enable peer SSL verifying.
936      */
937     data->set.ssl.primary.verifypeer = enabled;
938 
939     /* Update the current connection ssl_config. */
940     Curl_ssl_conn_config_update(data, FALSE);
941     break;
942 #ifndef CURL_DISABLE_DOH
943   case CURLOPT_DOH_SSL_VERIFYPEER:
944     /*
945      * Enable peer SSL verifying for DoH.
946      */
947     data->set.doh_verifypeer = enabled;
948     break;
949   case CURLOPT_DOH_SSL_VERIFYHOST:
950     /*
951      * Enable verification of the hostname in the peer certificate for DoH
952      */
953     data->set.doh_verifyhost = enabled;
954     break;
955   case CURLOPT_DOH_SSL_VERIFYSTATUS:
956     /*
957      * Enable certificate status verifying for DoH.
958      */
959     if(!Curl_ssl_cert_status_request())
960       return CURLE_NOT_BUILT_IN;
961 
962     data->set.doh_verifystatus = enabled;
963     break;
964 #endif /* ! CURL_DISABLE_DOH */
965   case CURLOPT_SSL_VERIFYHOST:
966     /*
967      * Enable verification of the hostname in the peer certificate
968      */
969 
970     /* Obviously people are not reading documentation and too many thought
971        this argument took a boolean when it was not and misused it.
972        Treat 1 and 2 the same */
973     data->set.ssl.primary.verifyhost = enabled;
974 
975     /* Update the current connection ssl_config. */
976     Curl_ssl_conn_config_update(data, FALSE);
977     break;
978   case CURLOPT_SSL_VERIFYSTATUS:
979     /*
980      * Enable certificate status verifying.
981      */
982     if(!Curl_ssl_cert_status_request())
983       return CURLE_NOT_BUILT_IN;
984 
985     data->set.ssl.primary.verifystatus = enabled;
986 
987     /* Update the current connection ssl_config. */
988     Curl_ssl_conn_config_update(data, FALSE);
989     break;
990   case CURLOPT_SSL_FALSESTART:
991     /*
992      * Enable TLS false start.
993      */
994     if(!Curl_ssl_false_start(data))
995       return CURLE_NOT_BUILT_IN;
996 
997     data->set.ssl.falsestart = enabled;
998     break;
999   case CURLOPT_CERTINFO:
1000 #ifdef USE_SSL
1001     if(Curl_ssl_supports(data, SSLSUPP_CERTINFO))
1002       data->set.ssl.certinfo = enabled;
1003     else
1004 #endif
1005       return CURLE_NOT_BUILT_IN;
1006     break;
1007   case CURLOPT_BUFFERSIZE:
1008     /*
1009      * The application kindly asks for a differently sized receive buffer.
1010      * If it seems reasonable, we will use it.
1011      */
1012     if(arg > READBUFFER_MAX)
1013       arg = READBUFFER_MAX;
1014     else if(arg < 1)
1015       arg = READBUFFER_SIZE;
1016     else if(arg < READBUFFER_MIN)
1017       arg = READBUFFER_MIN;
1018 
1019     data->set.buffer_size = (unsigned int)arg;
1020     break;
1021 
1022   case CURLOPT_UPLOAD_BUFFERSIZE:
1023     /*
1024      * The application kindly asks for a differently sized upload buffer.
1025      * Cap it to sensible.
1026      */
1027     if(arg > UPLOADBUFFER_MAX)
1028       arg = UPLOADBUFFER_MAX;
1029     else if(arg < UPLOADBUFFER_MIN)
1030       arg = UPLOADBUFFER_MIN;
1031 
1032     data->set.upload_buffer_size = (unsigned int)arg;
1033     break;
1034 
1035   case CURLOPT_NOSIGNAL:
1036     /*
1037      * The application asks not to set any signal() or alarm() handlers,
1038      * even when using a timeout.
1039      */
1040     data->set.no_signal = enabled;
1041     break;
1042   case CURLOPT_MAXFILESIZE:
1043     /*
1044      * Set the maximum size of a file to download.
1045      */
1046     if(arg < 0)
1047       return CURLE_BAD_FUNCTION_ARGUMENT;
1048     data->set.max_filesize = arg;
1049     break;
1050 
1051 #ifdef USE_SSL
1052   case CURLOPT_USE_SSL:
1053     /*
1054      * Make transfers attempt to use SSL/TLS.
1055      */
1056     if((arg < CURLUSESSL_NONE) || (arg >= CURLUSESSL_LAST))
1057       return CURLE_BAD_FUNCTION_ARGUMENT;
1058     data->set.use_ssl = (unsigned char)arg;
1059     break;
1060   case CURLOPT_SSL_OPTIONS:
1061     data->set.ssl.primary.ssl_options = (unsigned char)(arg & 0xff);
1062     data->set.ssl.enable_beast = !!(arg & CURLSSLOPT_ALLOW_BEAST);
1063     data->set.ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE);
1064     data->set.ssl.no_partialchain = !!(arg & CURLSSLOPT_NO_PARTIALCHAIN);
1065     data->set.ssl.revoke_best_effort = !!(arg & CURLSSLOPT_REVOKE_BEST_EFFORT);
1066     data->set.ssl.native_ca_store = !!(arg & CURLSSLOPT_NATIVE_CA);
1067     data->set.ssl.auto_client_cert = !!(arg & CURLSSLOPT_AUTO_CLIENT_CERT);
1068     data->set.ssl.earlydata = !!(arg & CURLSSLOPT_EARLYDATA);
1069     /* If a setting is added here it should also be added in dohprobe()
1070        which sets its own CURLOPT_SSL_OPTIONS based on these settings. */
1071     break;
1072 
1073 #ifndef CURL_DISABLE_PROXY
1074   case CURLOPT_PROXY_SSL_OPTIONS:
1075     data->set.proxy_ssl.primary.ssl_options = (unsigned char)(arg & 0xff);
1076     data->set.proxy_ssl.enable_beast = !!(arg & CURLSSLOPT_ALLOW_BEAST);
1077     data->set.proxy_ssl.no_revoke = !!(arg & CURLSSLOPT_NO_REVOKE);
1078     data->set.proxy_ssl.no_partialchain = !!(arg & CURLSSLOPT_NO_PARTIALCHAIN);
1079     data->set.proxy_ssl.revoke_best_effort =
1080       !!(arg & CURLSSLOPT_REVOKE_BEST_EFFORT);
1081     data->set.proxy_ssl.native_ca_store = !!(arg & CURLSSLOPT_NATIVE_CA);
1082     data->set.proxy_ssl.auto_client_cert =
1083       !!(arg & CURLSSLOPT_AUTO_CLIENT_CERT);
1084     break;
1085 #endif
1086 
1087 #endif /* USE_SSL */
1088   case CURLOPT_IPRESOLVE:
1089     if((arg < CURL_IPRESOLVE_WHATEVER) || (arg > CURL_IPRESOLVE_V6))
1090       return CURLE_BAD_FUNCTION_ARGUMENT;
1091     data->set.ipver = (unsigned char) arg;
1092     break;
1093   case CURLOPT_TCP_NODELAY:
1094     /*
1095      * Enable or disable TCP_NODELAY, which will disable/enable the Nagle
1096      * algorithm
1097      */
1098     data->set.tcp_nodelay = enabled;
1099     break;
1100 
1101   case CURLOPT_IGNORE_CONTENT_LENGTH:
1102     data->set.ignorecl = enabled;
1103     break;
1104 
1105   case CURLOPT_CONNECT_ONLY:
1106     /*
1107      * No data transfer.
1108      * (1) - only do connection
1109      * (2) - do first get request but get no content
1110      */
1111     if(arg > 2)
1112       return CURLE_BAD_FUNCTION_ARGUMENT;
1113     data->set.connect_only = (unsigned char)arg;
1114     break;
1115 
1116   case CURLOPT_SSL_SESSIONID_CACHE:
1117     data->set.ssl.primary.cache_session = enabled;
1118 #ifndef CURL_DISABLE_PROXY
1119     data->set.proxy_ssl.primary.cache_session =
1120       data->set.ssl.primary.cache_session;
1121 #endif
1122     break;
1123 
1124 #ifdef USE_SSH
1125     /* we only include SSH options if explicitly built to support SSH */
1126   case CURLOPT_SSH_AUTH_TYPES:
1127     data->set.ssh_auth_types = (int)arg;
1128     break;
1129   case CURLOPT_SSH_COMPRESSION:
1130     data->set.ssh_compression = enabled;
1131     break;
1132 #endif
1133 
1134   case CURLOPT_HTTP_TRANSFER_DECODING:
1135     /*
1136      * disable libcurl transfer encoding is used
1137      */
1138 #ifndef USE_HYPER
1139     data->set.http_te_skip = !enabled; /* reversed */
1140     break;
1141 #else
1142     return CURLE_NOT_BUILT_IN; /* hyper does not support */
1143 #endif
1144 
1145   case CURLOPT_HTTP_CONTENT_DECODING:
1146     /*
1147      * raw data passed to the application when content encoding is used
1148      */
1149     data->set.http_ce_skip = !enabled; /* reversed */
1150     break;
1151 
1152 #if !defined(CURL_DISABLE_FTP) || defined(USE_SSH)
1153   case CURLOPT_NEW_FILE_PERMS:
1154     /*
1155      * Uses these permissions instead of 0644
1156      */
1157     if((arg < 0) || (arg > 0777))
1158       return CURLE_BAD_FUNCTION_ARGUMENT;
1159     data->set.new_file_perms = (unsigned int)arg;
1160     break;
1161 #endif
1162 #ifdef USE_SSH
1163   case CURLOPT_NEW_DIRECTORY_PERMS:
1164     /*
1165      * Uses these permissions instead of 0755
1166      */
1167     if((arg < 0) || (arg > 0777))
1168       return CURLE_BAD_FUNCTION_ARGUMENT;
1169     data->set.new_directory_perms = (unsigned int)arg;
1170     break;
1171 #endif
1172 #ifdef USE_IPV6
1173   case CURLOPT_ADDRESS_SCOPE:
1174     /*
1175      * Use this scope id when using IPv6
1176      * We always get longs when passed plain numericals so we should check
1177      * that the value fits into an unsigned 32-bit integer.
1178      */
1179 #if SIZEOF_LONG > 4
1180     if(uarg > UINT_MAX)
1181       return CURLE_BAD_FUNCTION_ARGUMENT;
1182 #endif
1183     data->set.scope_id = (unsigned int)uarg;
1184     break;
1185 #endif
1186   case CURLOPT_PROTOCOLS:
1187     /* set the bitmask for the protocols that are allowed to be used for the
1188        transfer, which thus helps the app which takes URLs from users or other
1189        external inputs and want to restrict what protocol(s) to deal with.
1190        Defaults to CURLPROTO_ALL. */
1191     data->set.allowed_protocols = (curl_prot_t)arg;
1192     break;
1193 
1194   case CURLOPT_REDIR_PROTOCOLS:
1195     /* set the bitmask for the protocols that libcurl is allowed to follow to,
1196        as a subset of the CURLOPT_PROTOCOLS ones. That means the protocol
1197        needs to be set in both bitmasks to be allowed to get redirected to. */
1198     data->set.redir_protocols = (curl_prot_t)arg;
1199     break;
1200 
1201 #ifndef CURL_DISABLE_SMTP
1202   case CURLOPT_MAIL_RCPT_ALLOWFAILS:
1203     /* allow RCPT TO command to fail for some recipients */
1204     data->set.mail_rcpt_allowfails = enabled;
1205     break;
1206 #endif /* !CURL_DISABLE_SMTP */
1207   case CURLOPT_SASL_IR:
1208     /* Enable/disable SASL initial response */
1209     data->set.sasl_ir = enabled;
1210     break;
1211 #ifndef CURL_DISABLE_RTSP
1212   case CURLOPT_RTSP_REQUEST:
1213   {
1214     /*
1215      * Set the RTSP request method (OPTIONS, SETUP, PLAY, etc...)
1216      * Would this be better if the RTSPREQ_* were just moved into here?
1217      */
1218     Curl_RtspReq rtspreq = RTSPREQ_NONE;
1219     switch(arg) {
1220     case CURL_RTSPREQ_OPTIONS:
1221       rtspreq = RTSPREQ_OPTIONS;
1222       break;
1223 
1224     case CURL_RTSPREQ_DESCRIBE:
1225       rtspreq = RTSPREQ_DESCRIBE;
1226       break;
1227 
1228     case CURL_RTSPREQ_ANNOUNCE:
1229       rtspreq = RTSPREQ_ANNOUNCE;
1230       break;
1231 
1232     case CURL_RTSPREQ_SETUP:
1233       rtspreq = RTSPREQ_SETUP;
1234       break;
1235 
1236     case CURL_RTSPREQ_PLAY:
1237       rtspreq = RTSPREQ_PLAY;
1238       break;
1239 
1240     case CURL_RTSPREQ_PAUSE:
1241       rtspreq = RTSPREQ_PAUSE;
1242       break;
1243 
1244     case CURL_RTSPREQ_TEARDOWN:
1245       rtspreq = RTSPREQ_TEARDOWN;
1246       break;
1247 
1248     case CURL_RTSPREQ_GET_PARAMETER:
1249       rtspreq = RTSPREQ_GET_PARAMETER;
1250       break;
1251 
1252     case CURL_RTSPREQ_SET_PARAMETER:
1253       rtspreq = RTSPREQ_SET_PARAMETER;
1254       break;
1255 
1256     case CURL_RTSPREQ_RECORD:
1257       rtspreq = RTSPREQ_RECORD;
1258       break;
1259 
1260     case CURL_RTSPREQ_RECEIVE:
1261       rtspreq = RTSPREQ_RECEIVE;
1262       break;
1263     default:
1264       return CURLE_BAD_FUNCTION_ARGUMENT;
1265     }
1266 
1267     data->set.rtspreq = rtspreq;
1268     break;
1269   }
1270   case CURLOPT_RTSP_CLIENT_CSEQ:
1271     /*
1272      * Set the CSEQ number to issue for the next RTSP request. Useful if the
1273      * application is resuming a previously broken connection. The CSEQ
1274      * will increment from this new number henceforth.
1275      */
1276     data->state.rtsp_next_client_CSeq = arg;
1277     break;
1278 
1279   case CURLOPT_RTSP_SERVER_CSEQ:
1280     /* Same as the above, but for server-initiated requests */
1281     data->state.rtsp_next_server_CSeq = arg;
1282     break;
1283 
1284 #endif /* ! CURL_DISABLE_RTSP */
1285 
1286   case CURLOPT_TCP_KEEPALIVE:
1287     data->set.tcp_keepalive = enabled;
1288     break;
1289   case CURLOPT_TCP_KEEPIDLE:
1290     if(arg < 0)
1291       return CURLE_BAD_FUNCTION_ARGUMENT;
1292     else if(arg > INT_MAX)
1293       arg = INT_MAX;
1294     data->set.tcp_keepidle = (int)arg;
1295     break;
1296   case CURLOPT_TCP_KEEPINTVL:
1297     if(arg < 0)
1298       return CURLE_BAD_FUNCTION_ARGUMENT;
1299     else if(arg > INT_MAX)
1300       arg = INT_MAX;
1301     data->set.tcp_keepintvl = (int)arg;
1302     break;
1303   case CURLOPT_TCP_KEEPCNT:
1304     if(arg < 0)
1305       return CURLE_BAD_FUNCTION_ARGUMENT;
1306     else if(arg > INT_MAX)
1307       arg = INT_MAX;
1308     data->set.tcp_keepcnt = (int)arg;
1309     break;
1310   case CURLOPT_TCP_FASTOPEN:
1311 #if defined(CONNECT_DATA_IDEMPOTENT) || defined(MSG_FASTOPEN) ||        \
1312   defined(TCP_FASTOPEN_CONNECT)
1313     data->set.tcp_fastopen = enabled;
1314 #else
1315     return CURLE_NOT_BUILT_IN;
1316 #endif
1317     break;
1318   case CURLOPT_SSL_ENABLE_NPN:
1319     break;
1320   case CURLOPT_SSL_ENABLE_ALPN:
1321     data->set.ssl_enable_alpn = enabled;
1322     break;
1323   case CURLOPT_PATH_AS_IS:
1324     data->set.path_as_is = enabled;
1325     break;
1326   case CURLOPT_PIPEWAIT:
1327     data->set.pipewait = enabled;
1328     break;
1329   case CURLOPT_STREAM_WEIGHT:
1330 #if defined(USE_HTTP2) || defined(USE_HTTP3)
1331     if((arg >= 1) && (arg <= 256))
1332       data->set.priority.weight = (int)arg;
1333     break;
1334 #else
1335     return CURLE_NOT_BUILT_IN;
1336 #endif
1337   case CURLOPT_SUPPRESS_CONNECT_HEADERS:
1338     data->set.suppress_connect_headers = enabled;
1339     break;
1340   case CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS:
1341     if(uarg > UINT_MAX)
1342       uarg = UINT_MAX;
1343     data->set.happy_eyeballs_timeout = (unsigned int)uarg;
1344     break;
1345 #ifndef CURL_DISABLE_SHUFFLE_DNS
1346   case CURLOPT_DNS_SHUFFLE_ADDRESSES:
1347     data->set.dns_shuffle_addresses = enabled;
1348     break;
1349 #endif
1350   case CURLOPT_DISALLOW_USERNAME_IN_URL:
1351     data->set.disallow_username_in_url = enabled;
1352     break;
1353 
1354   case CURLOPT_UPKEEP_INTERVAL_MS:
1355     if(arg < 0)
1356       return CURLE_BAD_FUNCTION_ARGUMENT;
1357     data->set.upkeep_interval_ms = arg;
1358     break;
1359   case CURLOPT_MAXAGE_CONN:
1360     if(arg < 0)
1361       return CURLE_BAD_FUNCTION_ARGUMENT;
1362     data->set.maxage_conn = arg;
1363     break;
1364   case CURLOPT_MAXLIFETIME_CONN:
1365     if(arg < 0)
1366       return CURLE_BAD_FUNCTION_ARGUMENT;
1367     data->set.maxlifetime_conn = arg;
1368     break;
1369 #ifndef CURL_DISABLE_HSTS
1370   case CURLOPT_HSTS_CTRL:
1371     if(arg & CURLHSTS_ENABLE) {
1372       if(!data->hsts) {
1373         data->hsts = Curl_hsts_init();
1374         if(!data->hsts)
1375           return CURLE_OUT_OF_MEMORY;
1376       }
1377     }
1378     else
1379       Curl_hsts_cleanup(&data->hsts);
1380     break;
1381 #endif /* ! CURL_DISABLE_HSTS */
1382 #ifndef CURL_DISABLE_ALTSVC
1383   case CURLOPT_ALTSVC_CTRL:
1384     if(!arg) {
1385       DEBUGF(infof(data, "bad CURLOPT_ALTSVC_CTRL input"));
1386       return CURLE_BAD_FUNCTION_ARGUMENT;
1387     }
1388     if(!data->asi) {
1389       data->asi = Curl_altsvc_init();
1390       if(!data->asi)
1391         return CURLE_OUT_OF_MEMORY;
1392     }
1393     return Curl_altsvc_ctrl(data->asi, arg);
1394 #endif /* ! CURL_DISABLE_ALTSVC */
1395 #ifndef CURL_DISABLE_WEBSOCKETS
1396   case CURLOPT_WS_OPTIONS:
1397     data->set.ws_raw_mode =  (bool)(arg & CURLWS_RAW_MODE);
1398     break;
1399 #endif
1400   case CURLOPT_QUICK_EXIT:
1401     data->set.quick_exit = enabled;
1402     break;
1403   case CURLOPT_DNS_USE_GLOBAL_CACHE:
1404     /* deprecated */
1405     break;
1406   case CURLOPT_SSLENGINE_DEFAULT:
1407     /*
1408      * flag to set engine as default.
1409      */
1410     Curl_safefree(data->set.str[STRING_SSL_ENGINE]);
1411     return Curl_ssl_set_engine_default(data);
1412 
1413   default:
1414     /* unknown option */
1415     return CURLE_UNKNOWN_OPTION;
1416   }
1417   return CURLE_OK;
1418 }
1419 
setopt_slist(struct Curl_easy * data,CURLoption option,struct curl_slist * slist)1420 static CURLcode setopt_slist(struct Curl_easy *data, CURLoption option,
1421                              struct curl_slist *slist)
1422 {
1423   CURLcode result = CURLE_OK;
1424   switch(option) {
1425 #ifndef CURL_DISABLE_PROXY
1426   case CURLOPT_PROXYHEADER:
1427     /*
1428      * Set a list with proxy headers to use (or replace internals with)
1429      *
1430      * Since CURLOPT_HTTPHEADER was the only way to set HTTP headers for a
1431      * long time we remain doing it this way until CURLOPT_PROXYHEADER is
1432      * used. As soon as this option has been used, if set to anything but
1433      * NULL, custom headers for proxies are only picked from this list.
1434      *
1435      * Set this option to NULL to restore the previous behavior.
1436      */
1437     data->set.proxyheaders = slist;
1438     break;
1439 #endif
1440 #ifndef CURL_DISABLE_HTTP
1441   case CURLOPT_HTTP200ALIASES:
1442     /*
1443      * Set a list of aliases for HTTP 200 in response header
1444      */
1445     data->set.http200aliases = slist;
1446     break;
1447 #endif
1448 #if !defined(CURL_DISABLE_FTP) || defined(USE_SSH)
1449   case CURLOPT_POSTQUOTE:
1450     /*
1451      * List of RAW FTP commands to use after a transfer
1452      */
1453     data->set.postquote = slist;
1454     break;
1455   case CURLOPT_PREQUOTE:
1456     /*
1457      * List of RAW FTP commands to use prior to RETR (Wesley Laxton)
1458      */
1459     data->set.prequote = slist;
1460     break;
1461   case CURLOPT_QUOTE:
1462     /*
1463      * List of RAW FTP commands to use before a transfer
1464      */
1465     data->set.quote = slist;
1466     break;
1467 #endif
1468   case CURLOPT_RESOLVE:
1469     /*
1470      * List of HOST:PORT:[addresses] strings to populate the DNS cache with
1471      * Entries added this way will remain in the cache until explicitly
1472      * removed or the handle is cleaned up.
1473      *
1474      * Prefix the HOST with plus sign (+) to have the entry expire just like
1475      * automatically added entries.
1476      *
1477      * Prefix the HOST with dash (-) to _remove_ the entry from the cache.
1478      *
1479      * This API can remove any entry from the DNS cache, but only entries
1480      * that are not actually in use right now will be pruned immediately.
1481      */
1482     data->set.resolve = slist;
1483     data->state.resolve = data->set.resolve;
1484     break;
1485 #if !defined(CURL_DISABLE_HTTP) || !defined(CURL_DISABLE_MIME)
1486   case CURLOPT_HTTPHEADER:
1487     /*
1488      * Set a list with HTTP headers to use (or replace internals with)
1489      */
1490     data->set.headers = slist;
1491     break;
1492 #endif
1493 #ifndef CURL_DISABLE_TELNET
1494   case CURLOPT_TELNETOPTIONS:
1495     /*
1496      * Set a linked list of telnet options
1497      */
1498     data->set.telnet_options = slist;
1499     break;
1500 #endif
1501 #ifndef CURL_DISABLE_SMTP
1502   case CURLOPT_MAIL_RCPT:
1503     /* Set the list of mail recipients */
1504     data->set.mail_rcpt = slist;
1505     break;
1506 #endif
1507   case CURLOPT_CONNECT_TO:
1508     data->set.connect_to = slist;
1509     break;
1510   default:
1511     return CURLE_UNKNOWN_OPTION;
1512   }
1513   return result;
1514 }
1515 
1516 /* assorted pointer type arguments */
setopt_pointers(struct Curl_easy * data,CURLoption option,va_list param)1517 static CURLcode setopt_pointers(struct Curl_easy *data, CURLoption option,
1518                                 va_list param)
1519 {
1520   CURLcode result = CURLE_OK;
1521   switch(option) {
1522 #ifndef CURL_DISABLE_HTTP
1523 #ifndef CURL_DISABLE_FORM_API
1524   case CURLOPT_HTTPPOST:
1525     /*
1526      * Set to make us do HTTP POST. Legacy API-style.
1527      */
1528     data->set.httppost = va_arg(param, struct curl_httppost *);
1529     data->set.method = HTTPREQ_POST_FORM;
1530     data->set.opt_no_body = FALSE; /* this is implied */
1531     Curl_mime_cleanpart(data->state.formp);
1532     Curl_safefree(data->state.formp);
1533     data->state.mimepost = NULL;
1534     break;
1535 #endif /* ! CURL_DISABLE_FORM_API */
1536 #endif /* ! CURL_DISABLE_HTTP */
1537 #if !defined(CURL_DISABLE_HTTP) || !defined(CURL_DISABLE_SMTP) ||       \
1538     !defined(CURL_DISABLE_IMAP)
1539 # ifndef CURL_DISABLE_MIME
1540     case CURLOPT_MIMEPOST:
1541     /*
1542      * Set to make us do MIME POST
1543      */
1544     result = Curl_mime_set_subparts(&data->set.mimepost,
1545                                     va_arg(param, curl_mime *),
1546                                     FALSE);
1547     if(!result) {
1548       data->set.method = HTTPREQ_POST_MIME;
1549       data->set.opt_no_body = FALSE; /* this is implied */
1550 #ifndef CURL_DISABLE_FORM_API
1551       Curl_mime_cleanpart(data->state.formp);
1552       Curl_safefree(data->state.formp);
1553       data->state.mimepost = NULL;
1554 #endif
1555     }
1556     break;
1557 #endif /* ! CURL_DISABLE_MIME */
1558 #endif /* ! disabled HTTP, SMTP or IMAP */
1559   case CURLOPT_STDERR:
1560     /*
1561      * Set to a FILE * that should receive all error writes. This
1562      * defaults to stderr for normal operations.
1563      */
1564     data->set.err = va_arg(param, FILE *);
1565     if(!data->set.err)
1566       data->set.err = stderr;
1567     break;
1568   case CURLOPT_SHARE:
1569   {
1570     struct Curl_share *set = va_arg(param, struct Curl_share *);
1571 
1572     /* disconnect from old share, if any */
1573     if(data->share) {
1574       Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
1575 
1576       if(data->dns.hostcachetype == HCACHE_SHARED) {
1577         data->dns.hostcache = NULL;
1578         data->dns.hostcachetype = HCACHE_NONE;
1579       }
1580 
1581 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
1582       if(data->share->cookies == data->cookies)
1583         data->cookies = NULL;
1584 #endif
1585 
1586 #ifndef CURL_DISABLE_HSTS
1587       if(data->share->hsts == data->hsts)
1588         data->hsts = NULL;
1589 #endif
1590 #ifdef USE_SSL
1591       if(data->share->sslsession == data->state.session)
1592         data->state.session = NULL;
1593 #endif
1594 #ifdef USE_LIBPSL
1595       if(data->psl == &data->share->psl)
1596         data->psl = data->multi ? &data->multi->psl : NULL;
1597 #endif
1598 
1599       data->share->dirty--;
1600 
1601       Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
1602       data->share = NULL;
1603     }
1604 
1605     if(GOOD_SHARE_HANDLE(set))
1606       /* use new share if it set */
1607       data->share = set;
1608     if(data->share) {
1609 
1610       Curl_share_lock(data, CURL_LOCK_DATA_SHARE, CURL_LOCK_ACCESS_SINGLE);
1611 
1612       data->share->dirty++;
1613 
1614       if(data->share->specifier & (1 << CURL_LOCK_DATA_DNS)) {
1615         /* use shared host cache */
1616         data->dns.hostcache = &data->share->hostcache;
1617         data->dns.hostcachetype = HCACHE_SHARED;
1618       }
1619 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
1620       if(data->share->cookies) {
1621         /* use shared cookie list, first free own one if any */
1622         Curl_cookie_cleanup(data->cookies);
1623         /* enable cookies since we now use a share that uses cookies! */
1624         data->cookies = data->share->cookies;
1625       }
1626 #endif   /* CURL_DISABLE_HTTP */
1627 #ifndef CURL_DISABLE_HSTS
1628       if(data->share->hsts) {
1629         /* first free the private one if any */
1630         Curl_hsts_cleanup(&data->hsts);
1631         data->hsts = data->share->hsts;
1632       }
1633 #endif
1634 #ifdef USE_SSL
1635       if(data->share->sslsession) {
1636         data->set.general_ssl.max_ssl_sessions = data->share->max_ssl_sessions;
1637         data->state.session = data->share->sslsession;
1638       }
1639 #endif
1640 #ifdef USE_LIBPSL
1641       if(data->share->specifier & (1 << CURL_LOCK_DATA_PSL))
1642         data->psl = &data->share->psl;
1643 #endif
1644 
1645       Curl_share_unlock(data, CURL_LOCK_DATA_SHARE);
1646     }
1647     /* check for host cache not needed,
1648      * it will be done by curl_easy_perform */
1649   }
1650   break;
1651 
1652 #ifdef USE_HTTP2
1653   case CURLOPT_STREAM_DEPENDS:
1654   case CURLOPT_STREAM_DEPENDS_E: {
1655     struct Curl_easy *dep = va_arg(param, struct Curl_easy *);
1656     if(!dep || GOOD_EASY_HANDLE(dep))
1657       return Curl_data_priority_add_child(dep, data,
1658                                           option == CURLOPT_STREAM_DEPENDS_E);
1659     break;
1660   }
1661 #endif
1662 
1663   default:
1664     return CURLE_UNKNOWN_OPTION;
1665   }
1666   return result;
1667 }
1668 
setopt_cptr(struct Curl_easy * data,CURLoption option,char * ptr)1669 static CURLcode setopt_cptr(struct Curl_easy *data, CURLoption option,
1670                             char *ptr)
1671 {
1672   CURLcode result = CURLE_OK;
1673   switch(option) {
1674   case CURLOPT_SSL_CIPHER_LIST:
1675     if(Curl_ssl_supports(data, SSLSUPP_CIPHER_LIST))
1676       /* set a list of cipher we want to use in the SSL connection */
1677       return Curl_setstropt(&data->set.str[STRING_SSL_CIPHER_LIST], ptr);
1678     return CURLE_NOT_BUILT_IN;
1679     break;
1680 #ifndef CURL_DISABLE_PROXY
1681   case CURLOPT_PROXY_SSL_CIPHER_LIST:
1682     if(Curl_ssl_supports(data, SSLSUPP_CIPHER_LIST)) {
1683       /* set a list of cipher we want to use in the SSL connection for proxy */
1684       return Curl_setstropt(&data->set.str[STRING_SSL_CIPHER_LIST_PROXY],
1685                             ptr);
1686     }
1687     else
1688       return CURLE_NOT_BUILT_IN;
1689     break;
1690 #endif
1691   case CURLOPT_TLS13_CIPHERS:
1692     if(Curl_ssl_supports(data, SSLSUPP_TLS13_CIPHERSUITES)) {
1693       /* set preferred list of TLS 1.3 cipher suites */
1694       return Curl_setstropt(&data->set.str[STRING_SSL_CIPHER13_LIST], ptr);
1695     }
1696     else
1697       return CURLE_NOT_BUILT_IN;
1698     break;
1699 #ifndef CURL_DISABLE_PROXY
1700   case CURLOPT_PROXY_TLS13_CIPHERS:
1701     if(Curl_ssl_supports(data, SSLSUPP_TLS13_CIPHERSUITES))
1702       /* set preferred list of TLS 1.3 cipher suites for proxy */
1703       return Curl_setstropt(&data->set.str[STRING_SSL_CIPHER13_LIST_PROXY],
1704                             ptr);
1705     else
1706       return CURLE_NOT_BUILT_IN;
1707     break;
1708 #endif
1709   case CURLOPT_RANDOM_FILE:
1710     break;
1711   case CURLOPT_EGDSOCKET:
1712     break;
1713   case CURLOPT_REQUEST_TARGET:
1714     return Curl_setstropt(&data->set.str[STRING_TARGET], ptr);
1715 #ifndef CURL_DISABLE_NETRC
1716   case CURLOPT_NETRC_FILE:
1717     /*
1718      * Use this file instead of the $HOME/.netrc file
1719      */
1720     return Curl_setstropt(&data->set.str[STRING_NETRC_FILE], ptr);
1721 #endif
1722 
1723 #if !defined(CURL_DISABLE_HTTP) || !defined(CURL_DISABLE_MQTT)
1724   case CURLOPT_COPYPOSTFIELDS:
1725     /*
1726      * A string with POST data. Makes curl HTTP POST. Even if it is NULL.
1727      * If needed, CURLOPT_POSTFIELDSIZE must have been set prior to
1728      *  CURLOPT_COPYPOSTFIELDS and not altered later.
1729      */
1730     if(!ptr || data->set.postfieldsize == -1)
1731       result = Curl_setstropt(&data->set.str[STRING_COPYPOSTFIELDS], ptr);
1732     else {
1733       if(data->set.postfieldsize < 0)
1734         return CURLE_BAD_FUNCTION_ARGUMENT;
1735 #if SIZEOF_CURL_OFF_T > SIZEOF_SIZE_T
1736       /*
1737        *  Check that requested length does not overflow the size_t type.
1738        */
1739       else if(data->set.postfieldsize > SIZE_T_MAX)
1740         return CURLE_OUT_OF_MEMORY;
1741 #endif
1742       else {
1743         /* Allocate even when size == 0. This satisfies the need of possible
1744            later address compare to detect the COPYPOSTFIELDS mode, and to
1745            mark that postfields is used rather than read function or form
1746            data.
1747         */
1748         char *p = Curl_memdup0(ptr, (size_t)data->set.postfieldsize);
1749         if(!p)
1750           return CURLE_OUT_OF_MEMORY;
1751         else {
1752           free(data->set.str[STRING_COPYPOSTFIELDS]);
1753           data->set.str[STRING_COPYPOSTFIELDS] = p;
1754         }
1755       }
1756     }
1757 
1758     data->set.postfields = data->set.str[STRING_COPYPOSTFIELDS];
1759     data->set.method = HTTPREQ_POST;
1760     break;
1761 
1762   case CURLOPT_POSTFIELDS:
1763     /*
1764      * Like above, but use static data instead of copying it.
1765      */
1766     data->set.postfields = ptr;
1767     /* Release old copied data. */
1768     Curl_safefree(data->set.str[STRING_COPYPOSTFIELDS]);
1769     data->set.method = HTTPREQ_POST;
1770     break;
1771 
1772 #ifndef CURL_DISABLE_HTTP
1773   case CURLOPT_ACCEPT_ENCODING:
1774     /*
1775      * String to use at the value of Accept-Encoding header.
1776      *
1777      * If the encoding is set to "" we use an Accept-Encoding header that
1778      * encompasses all the encodings we support.
1779      * If the encoding is set to NULL we do not send an Accept-Encoding header
1780      * and ignore an received Content-Encoding header.
1781      *
1782      */
1783     if(ptr && !*ptr) {
1784       char all[256];
1785       Curl_all_content_encodings(all, sizeof(all));
1786       return Curl_setstropt(&data->set.str[STRING_ENCODING], all);
1787     }
1788     return Curl_setstropt(&data->set.str[STRING_ENCODING], ptr);
1789 
1790 #if !defined(CURL_DISABLE_AWS)
1791   case CURLOPT_AWS_SIGV4:
1792     /*
1793      * String that is merged to some authentication
1794      * parameters are used by the algorithm.
1795      */
1796     result = Curl_setstropt(&data->set.str[STRING_AWS_SIGV4], ptr);
1797     /*
1798      * Basic been set by default it need to be unset here
1799      */
1800     if(data->set.str[STRING_AWS_SIGV4])
1801       data->set.httpauth = CURLAUTH_AWS_SIGV4;
1802     break;
1803 #endif
1804   case CURLOPT_REFERER:
1805     /*
1806      * String to set in the HTTP Referer: field.
1807      */
1808     if(data->state.referer_alloc) {
1809       Curl_safefree(data->state.referer);
1810       data->state.referer_alloc = FALSE;
1811     }
1812     result = Curl_setstropt(&data->set.str[STRING_SET_REFERER], ptr);
1813     data->state.referer = data->set.str[STRING_SET_REFERER];
1814     break;
1815 
1816   case CURLOPT_USERAGENT:
1817     /*
1818      * String to use in the HTTP User-Agent field
1819      */
1820     return Curl_setstropt(&data->set.str[STRING_USERAGENT], ptr);
1821 
1822 #if !defined(CURL_DISABLE_COOKIES)
1823   case CURLOPT_COOKIE:
1824     /*
1825      * Cookie string to send to the remote server in the request.
1826      */
1827     return Curl_setstropt(&data->set.str[STRING_COOKIE], ptr);
1828 
1829   case CURLOPT_COOKIEFILE:
1830     /*
1831      * Set cookie file to read and parse. Can be used multiple times.
1832      */
1833     if(ptr) {
1834       struct curl_slist *cl;
1835       /* general protection against mistakes and abuse */
1836       if(strlen(ptr) > CURL_MAX_INPUT_LENGTH)
1837         return CURLE_BAD_FUNCTION_ARGUMENT;
1838       /* append the cookie filename to the list of filenames, and deal with
1839          them later */
1840       cl = curl_slist_append(data->state.cookielist, ptr);
1841       if(!cl) {
1842         curl_slist_free_all(data->state.cookielist);
1843         data->state.cookielist = NULL;
1844         return CURLE_OUT_OF_MEMORY;
1845       }
1846       data->state.cookielist = cl; /* store the list for later use */
1847     }
1848     else {
1849       /* clear the list of cookie files */
1850       curl_slist_free_all(data->state.cookielist);
1851       data->state.cookielist = NULL;
1852 
1853       if(!data->share || !data->share->cookies) {
1854         /* throw away all existing cookies if this is not a shared cookie
1855            container */
1856         Curl_cookie_clearall(data->cookies);
1857         Curl_cookie_cleanup(data->cookies);
1858       }
1859       /* disable the cookie engine */
1860       data->cookies = NULL;
1861     }
1862     break;
1863 
1864   case CURLOPT_COOKIEJAR:
1865     /*
1866      * Set cookie filename to dump all cookies to when we are done.
1867      */
1868     result = Curl_setstropt(&data->set.str[STRING_COOKIEJAR], ptr);
1869     if(!result) {
1870       /*
1871        * Activate the cookie parser. This may or may not already
1872        * have been made.
1873        */
1874       struct CookieInfo *newcookies =
1875         Curl_cookie_init(data, NULL, data->cookies, data->set.cookiesession);
1876       if(!newcookies)
1877         result = CURLE_OUT_OF_MEMORY;
1878       data->cookies = newcookies;
1879     }
1880     break;
1881 
1882   case CURLOPT_COOKIELIST:
1883     if(!ptr)
1884       break;
1885 
1886     if(strcasecompare(ptr, "ALL")) {
1887       /* clear all cookies */
1888       Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
1889       Curl_cookie_clearall(data->cookies);
1890       Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
1891     }
1892     else if(strcasecompare(ptr, "SESS")) {
1893       /* clear session cookies */
1894       Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
1895       Curl_cookie_clearsess(data->cookies);
1896       Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
1897     }
1898     else if(strcasecompare(ptr, "FLUSH")) {
1899       /* flush cookies to file, takes care of the locking */
1900       Curl_flush_cookies(data, FALSE);
1901     }
1902     else if(strcasecompare(ptr, "RELOAD")) {
1903       /* reload cookies from file */
1904       Curl_cookie_loadfiles(data);
1905       break;
1906     }
1907     else {
1908       if(!data->cookies) {
1909         /* if cookie engine was not running, activate it */
1910         data->cookies = Curl_cookie_init(data, NULL, NULL, TRUE);
1911         if(!data->cookies)
1912           return CURLE_OUT_OF_MEMORY;
1913       }
1914 
1915       /* general protection against mistakes and abuse */
1916       if(strlen(ptr) > CURL_MAX_INPUT_LENGTH)
1917         return CURLE_BAD_FUNCTION_ARGUMENT;
1918 
1919       Curl_share_lock(data, CURL_LOCK_DATA_COOKIE, CURL_LOCK_ACCESS_SINGLE);
1920       if(checkprefix("Set-Cookie:", ptr))
1921         /* HTTP Header format line */
1922         Curl_cookie_add(data, data->cookies, TRUE, FALSE, ptr + 11, NULL,
1923                         NULL, TRUE);
1924       else
1925         /* Netscape format line */
1926         Curl_cookie_add(data, data->cookies, FALSE, FALSE, ptr, NULL,
1927                         NULL, TRUE);
1928       Curl_share_unlock(data, CURL_LOCK_DATA_COOKIE);
1929     }
1930     break;
1931 #endif /* !CURL_DISABLE_COOKIES */
1932 
1933 #endif /* ! CURL_DISABLE_HTTP */
1934 
1935   case CURLOPT_CUSTOMREQUEST:
1936     /*
1937      * Set a custom string to use as request
1938      */
1939     return Curl_setstropt(&data->set.str[STRING_CUSTOMREQUEST], ptr);
1940 
1941     /* we do not set
1942        data->set.method = HTTPREQ_CUSTOM;
1943        here, we continue as if we were using the already set type
1944        and this just changes the actual request keyword */
1945 
1946 #ifndef CURL_DISABLE_PROXY
1947   case CURLOPT_PROXY:
1948     /*
1949      * Set proxy server:port to use as proxy.
1950      *
1951      * If the proxy is set to "" (and CURLOPT_SOCKS_PROXY is set to "" or NULL)
1952      * we explicitly say that we do not want to use a proxy
1953      * (even though there might be environment variables saying so).
1954      *
1955      * Setting it to NULL, means no proxy but allows the environment variables
1956      * to decide for us (if CURLOPT_SOCKS_PROXY setting it to NULL).
1957      */
1958     return Curl_setstropt(&data->set.str[STRING_PROXY], ptr);
1959     break;
1960 
1961   case CURLOPT_PRE_PROXY:
1962     /*
1963      * Set proxy server:port to use as SOCKS proxy.
1964      *
1965      * If the proxy is set to "" or NULL we explicitly say that we do not want
1966      * to use the socks proxy.
1967      */
1968     return Curl_setstropt(&data->set.str[STRING_PRE_PROXY], ptr);
1969 #endif   /* CURL_DISABLE_PROXY */
1970 
1971 #ifndef CURL_DISABLE_PROXY
1972   case CURLOPT_SOCKS5_GSSAPI_SERVICE:
1973   case CURLOPT_PROXY_SERVICE_NAME:
1974     /*
1975      * Set proxy authentication service name for Kerberos 5 and SPNEGO
1976      */
1977     return Curl_setstropt(&data->set.str[STRING_PROXY_SERVICE_NAME], ptr);
1978 #endif
1979   case CURLOPT_SERVICE_NAME:
1980     /*
1981      * Set authentication service name for DIGEST-MD5, Kerberos 5 and SPNEGO
1982      */
1983     return Curl_setstropt(&data->set.str[STRING_SERVICE_NAME], ptr);
1984     break;
1985 
1986   case CURLOPT_HEADERDATA:
1987     /*
1988      * Custom pointer to pass the header write callback function
1989      */
1990     data->set.writeheader = (void *)ptr;
1991     break;
1992   case CURLOPT_READDATA:
1993     /*
1994      * FILE pointer to read the file to be uploaded from. Or possibly used as
1995      * argument to the read callback.
1996      */
1997     data->set.in_set = (void *)ptr;
1998     break;
1999   case CURLOPT_WRITEDATA:
2000     /*
2001      * FILE pointer to write to. Or possibly used as argument to the write
2002      * callback.
2003      */
2004     data->set.out = (void *)ptr;
2005     break;
2006   case CURLOPT_DEBUGDATA:
2007     /*
2008      * Set to a void * that should receive all error writes. This
2009      * defaults to CURLOPT_STDERR for normal operations.
2010      */
2011     data->set.debugdata = (void *)ptr;
2012     break;
2013   case CURLOPT_PROGRESSDATA:
2014     /*
2015      * Custom client data to pass to the progress callback
2016      */
2017     data->set.progress_client = (void *)ptr;
2018     break;
2019   case CURLOPT_SEEKDATA:
2020     /*
2021      * Seek control callback. Might be NULL.
2022      */
2023     data->set.seek_client = (void *)ptr;
2024     break;
2025   case CURLOPT_IOCTLDATA:
2026     /*
2027      * I/O control data pointer. Might be NULL.
2028      */
2029     data->set.ioctl_client = (void *)ptr;
2030     break;
2031   case CURLOPT_SSL_CTX_DATA:
2032     /*
2033      * Set a SSL_CTX callback parameter pointer
2034      */
2035 #ifdef USE_SSL
2036     if(Curl_ssl_supports(data, SSLSUPP_SSL_CTX))
2037       data->set.ssl.fsslctxp = (void *)ptr;
2038     else
2039 #endif
2040       return CURLE_NOT_BUILT_IN;
2041     break;
2042   case CURLOPT_SOCKOPTDATA:
2043     /*
2044      * socket callback data pointer. Might be NULL.
2045      */
2046     data->set.sockopt_client = (void *)ptr;
2047     break;
2048   case CURLOPT_OPENSOCKETDATA:
2049     /*
2050      * socket callback data pointer. Might be NULL.
2051      */
2052     data->set.opensocket_client = (void *)ptr;
2053     break;
2054   case CURLOPT_RESOLVER_START_DATA:
2055     /*
2056      * resolver start callback data pointer. Might be NULL.
2057      */
2058     data->set.resolver_start_client = (void *)ptr;
2059     break;
2060   case CURLOPT_CLOSESOCKETDATA:
2061     /*
2062      * socket callback data pointer. Might be NULL.
2063      */
2064     data->set.closesocket_client = (void *)ptr;
2065     break;
2066   case CURLOPT_TRAILERDATA:
2067 #ifndef CURL_DISABLE_HTTP
2068     data->set.trailer_data = (void *)ptr;
2069 #endif
2070     break;
2071   case CURLOPT_PREREQDATA:
2072     data->set.prereq_userp = (void *)ptr;
2073     break;
2074 
2075   case CURLOPT_ERRORBUFFER:
2076     /*
2077      * Error buffer provided by the caller to get the human readable error
2078      * string in.
2079      */
2080     data->set.errorbuffer = ptr;
2081     break;
2082 
2083 #ifndef CURL_DISABLE_FTP
2084   case CURLOPT_FTPPORT:
2085     /*
2086      * Use FTP PORT, this also specifies which IP address to use
2087      */
2088     result = Curl_setstropt(&data->set.str[STRING_FTPPORT], ptr);
2089     data->set.ftp_use_port = !!(data->set.str[STRING_FTPPORT]);
2090     break;
2091 
2092   case CURLOPT_FTP_ACCOUNT:
2093     return Curl_setstropt(&data->set.str[STRING_FTP_ACCOUNT], ptr);
2094 
2095   case CURLOPT_FTP_ALTERNATIVE_TO_USER:
2096     return Curl_setstropt(&data->set.str[STRING_FTP_ALTERNATIVE_TO_USER], ptr);
2097 
2098 #ifdef HAVE_GSSAPI
2099   case CURLOPT_KRBLEVEL:
2100     /*
2101      * A string that defines the kerberos security level.
2102      */
2103     result = Curl_setstropt(&data->set.str[STRING_KRB_LEVEL], ptr);
2104     data->set.krb = !!(data->set.str[STRING_KRB_LEVEL]);
2105     break;
2106 #endif
2107 #endif
2108   case CURLOPT_URL:
2109     /*
2110      * The URL to fetch.
2111      */
2112     if(data->state.url_alloc) {
2113       /* the already set URL is allocated, free it first! */
2114       Curl_safefree(data->state.url);
2115       data->state.url_alloc = FALSE;
2116     }
2117     result = Curl_setstropt(&data->set.str[STRING_SET_URL], ptr);
2118     data->state.url = data->set.str[STRING_SET_URL];
2119     break;
2120 
2121   case CURLOPT_USERPWD:
2122     /*
2123      * user:password to use in the operation
2124      */
2125     return setstropt_userpwd(ptr, &data->set.str[STRING_USERNAME],
2126                              &data->set.str[STRING_PASSWORD]);
2127 
2128   case CURLOPT_USERNAME:
2129     /*
2130      * authentication username to use in the operation
2131      */
2132     return Curl_setstropt(&data->set.str[STRING_USERNAME], ptr);
2133 
2134   case CURLOPT_PASSWORD:
2135     /*
2136      * authentication password to use in the operation
2137      */
2138     return Curl_setstropt(&data->set.str[STRING_PASSWORD], ptr);
2139 
2140   case CURLOPT_LOGIN_OPTIONS:
2141     /*
2142      * authentication options to use in the operation
2143      */
2144     return Curl_setstropt(&data->set.str[STRING_OPTIONS], ptr);
2145 
2146   case CURLOPT_XOAUTH2_BEARER:
2147     /*
2148      * OAuth 2.0 bearer token to use in the operation
2149      */
2150     return Curl_setstropt(&data->set.str[STRING_BEARER], ptr);
2151 
2152 #ifndef CURL_DISABLE_PROXY
2153   case CURLOPT_PROXYUSERPWD: {
2154     /*
2155      * user:password needed to use the proxy
2156      */
2157     char *u = NULL;
2158     char *p = NULL;
2159     result = setstropt_userpwd(ptr, &u, &p);
2160 
2161     /* URL decode the components */
2162     if(!result && u)
2163       result = Curl_urldecode(u, 0, &data->set.str[STRING_PROXYUSERNAME], NULL,
2164                               REJECT_ZERO);
2165     if(!result && p)
2166       result = Curl_urldecode(p, 0, &data->set.str[STRING_PROXYPASSWORD], NULL,
2167                               REJECT_ZERO);
2168     free(u);
2169     free(p);
2170   }
2171     break;
2172   case CURLOPT_PROXYUSERNAME:
2173     /*
2174      * authentication username to use in the operation
2175      */
2176     return Curl_setstropt(&data->set.str[STRING_PROXYUSERNAME], ptr);
2177 
2178   case CURLOPT_PROXYPASSWORD:
2179     /*
2180      * authentication password to use in the operation
2181      */
2182     return Curl_setstropt(&data->set.str[STRING_PROXYPASSWORD], ptr);
2183 
2184   case CURLOPT_NOPROXY:
2185     /*
2186      * proxy exception list
2187      */
2188     return Curl_setstropt(&data->set.str[STRING_NOPROXY], ptr);
2189 #endif
2190 
2191   case CURLOPT_RANGE:
2192     /*
2193      * What range of the file you want to transfer
2194      */
2195     return Curl_setstropt(&data->set.str[STRING_SET_RANGE], ptr);
2196 
2197 #endif /* ! CURL_DISABLE_PROXY */
2198   case CURLOPT_CURLU:
2199     /*
2200      * pass CURLU to set URL
2201      */
2202     data->set.uh = (CURLU *)ptr;
2203     break;
2204   case CURLOPT_SSLCERT:
2205     /*
2206      * String that holds filename of the SSL certificate to use
2207      */
2208     return Curl_setstropt(&data->set.str[STRING_CERT], ptr);
2209 
2210 #ifndef CURL_DISABLE_PROXY
2211   case CURLOPT_PROXY_SSLCERT:
2212     /*
2213      * String that holds filename of the SSL certificate to use for proxy
2214      */
2215     return Curl_setstropt(&data->set.str[STRING_CERT_PROXY], ptr);
2216 
2217 #endif
2218   case CURLOPT_SSLCERTTYPE:
2219     /*
2220      * String that holds file type of the SSL certificate to use
2221      */
2222     return Curl_setstropt(&data->set.str[STRING_CERT_TYPE], ptr);
2223 
2224 #ifndef CURL_DISABLE_PROXY
2225   case CURLOPT_PROXY_SSLCERTTYPE:
2226     /*
2227      * String that holds file type of the SSL certificate to use for proxy
2228      */
2229     return Curl_setstropt(&data->set.str[STRING_CERT_TYPE_PROXY], ptr);
2230 #endif
2231   case CURLOPT_SSLKEY:
2232     /*
2233      * String that holds filename of the SSL key to use
2234      */
2235     return Curl_setstropt(&data->set.str[STRING_KEY], ptr);
2236 
2237 #ifndef CURL_DISABLE_PROXY
2238   case CURLOPT_PROXY_SSLKEY:
2239     /*
2240      * String that holds filename of the SSL key to use for proxy
2241      */
2242     return Curl_setstropt(&data->set.str[STRING_KEY_PROXY], ptr);
2243 
2244 #endif
2245   case CURLOPT_SSLKEYTYPE:
2246     /*
2247      * String that holds file type of the SSL key to use
2248      */
2249     return Curl_setstropt(&data->set.str[STRING_KEY_TYPE], ptr);
2250     break;
2251 #ifndef CURL_DISABLE_PROXY
2252   case CURLOPT_PROXY_SSLKEYTYPE:
2253     /*
2254      * String that holds file type of the SSL key to use for proxy
2255      */
2256     return Curl_setstropt(&data->set.str[STRING_KEY_TYPE_PROXY], ptr);
2257 
2258 #endif
2259   case CURLOPT_KEYPASSWD:
2260     /*
2261      * String that holds the SSL or SSH private key password.
2262      */
2263     return Curl_setstropt(&data->set.str[STRING_KEY_PASSWD], ptr);
2264 
2265 #ifndef CURL_DISABLE_PROXY
2266   case CURLOPT_PROXY_KEYPASSWD:
2267     /*
2268      * String that holds the SSL private key password for proxy.
2269      */
2270     return Curl_setstropt(&data->set.str[STRING_KEY_PASSWD_PROXY], ptr);
2271 #endif
2272   case CURLOPT_SSLENGINE:
2273     /*
2274      * String that holds the SSL crypto engine.
2275      */
2276     if(ptr && ptr[0]) {
2277       result = Curl_setstropt(&data->set.str[STRING_SSL_ENGINE], ptr);
2278       if(!result) {
2279         result = Curl_ssl_set_engine(data, ptr);
2280       }
2281     }
2282     break;
2283 
2284 #ifndef CURL_DISABLE_PROXY
2285   case CURLOPT_HAPROXY_CLIENT_IP:
2286     /*
2287      * Set the client IP to send through HAProxy PROXY protocol
2288      */
2289     result = Curl_setstropt(&data->set.str[STRING_HAPROXY_CLIENT_IP], ptr);
2290     /* enable the HAProxy protocol */
2291     data->set.haproxyprotocol = TRUE;
2292     break;
2293 #endif
2294   case CURLOPT_INTERFACE:
2295     /*
2296      * Set what interface or address/hostname to bind the socket to when
2297      * performing an operation and thus what from-IP your connection will use.
2298      */
2299     return setstropt_interface(ptr,
2300                                &data->set.str[STRING_DEVICE],
2301                                &data->set.str[STRING_INTERFACE],
2302                                &data->set.str[STRING_BINDHOST]);
2303 
2304   case CURLOPT_PINNEDPUBLICKEY:
2305     /*
2306      * Set pinned public key for SSL connection.
2307      * Specify filename of the public key in DER format.
2308      */
2309 #ifdef USE_SSL
2310     if(Curl_ssl_supports(data, SSLSUPP_PINNEDPUBKEY))
2311       return Curl_setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY], ptr);
2312 #endif
2313     return CURLE_NOT_BUILT_IN;
2314 
2315 #ifndef CURL_DISABLE_PROXY
2316   case CURLOPT_PROXY_PINNEDPUBLICKEY:
2317     /*
2318      * Set pinned public key for SSL connection.
2319      * Specify filename of the public key in DER format.
2320      */
2321 #ifdef USE_SSL
2322     if(Curl_ssl_supports(data, SSLSUPP_PINNEDPUBKEY))
2323       return Curl_setstropt(&data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY],
2324                             ptr);
2325 #endif
2326     return CURLE_NOT_BUILT_IN;
2327 #endif
2328   case CURLOPT_CAINFO:
2329     /*
2330      * Set CA info for SSL connection. Specify filename of the CA certificate
2331      */
2332     return Curl_setstropt(&data->set.str[STRING_SSL_CAFILE], ptr);
2333 
2334 #ifndef CURL_DISABLE_PROXY
2335   case CURLOPT_PROXY_CAINFO:
2336     /*
2337      * Set CA info SSL connection for proxy. Specify filename of the
2338      * CA certificate
2339      */
2340     return Curl_setstropt(&data->set.str[STRING_SSL_CAFILE_PROXY], ptr);
2341 #endif
2342 
2343   case CURLOPT_CAPATH:
2344     /*
2345      * Set CA path info for SSL connection. Specify directory name of the CA
2346      * certificates which have been prepared using openssl c_rehash utility.
2347      */
2348 #ifdef USE_SSL
2349     if(Curl_ssl_supports(data, SSLSUPP_CA_PATH))
2350       /* This does not work on Windows. */
2351       return Curl_setstropt(&data->set.str[STRING_SSL_CAPATH], ptr);
2352 #endif
2353     return CURLE_NOT_BUILT_IN;
2354 #ifndef CURL_DISABLE_PROXY
2355   case CURLOPT_PROXY_CAPATH:
2356     /*
2357      * Set CA path info for SSL connection proxy. Specify directory name of the
2358      * CA certificates which have been prepared using openssl c_rehash utility.
2359      */
2360 #ifdef USE_SSL
2361     if(Curl_ssl_supports(data, SSLSUPP_CA_PATH))
2362       /* This does not work on Windows. */
2363       return Curl_setstropt(&data->set.str[STRING_SSL_CAPATH_PROXY], ptr);
2364 #endif
2365     return CURLE_NOT_BUILT_IN;
2366 #endif
2367   case CURLOPT_CRLFILE:
2368     /*
2369      * Set CRL file info for SSL connection. Specify filename of the CRL
2370      * to check certificates revocation
2371      */
2372     return Curl_setstropt(&data->set.str[STRING_SSL_CRLFILE], ptr);
2373 
2374 #ifndef CURL_DISABLE_PROXY
2375   case CURLOPT_PROXY_CRLFILE:
2376     /*
2377      * Set CRL file info for SSL connection for proxy. Specify filename of the
2378      * CRL to check certificates revocation
2379      */
2380     return Curl_setstropt(&data->set.str[STRING_SSL_CRLFILE_PROXY], ptr);
2381 #endif
2382   case CURLOPT_ISSUERCERT:
2383     /*
2384      * Set Issuer certificate file
2385      * to check certificates issuer
2386      */
2387     return Curl_setstropt(&data->set.str[STRING_SSL_ISSUERCERT], ptr);
2388 
2389 #ifndef CURL_DISABLE_PROXY
2390   case CURLOPT_PROXY_ISSUERCERT:
2391     /*
2392      * Set Issuer certificate file
2393      * to check certificates issuer
2394      */
2395     return Curl_setstropt(&data->set.str[STRING_SSL_ISSUERCERT_PROXY], ptr);
2396 
2397 #endif
2398 
2399   case CURLOPT_PRIVATE:
2400     /*
2401      * Set private data pointer.
2402      */
2403     data->set.private_data = (void *)ptr;
2404     break;
2405 
2406 #ifdef USE_SSL
2407   case CURLOPT_SSL_EC_CURVES:
2408     /*
2409      * Set accepted curves in SSL connection setup.
2410      * Specify colon-delimited list of curve algorithm names.
2411      */
2412     return Curl_setstropt(&data->set.str[STRING_SSL_EC_CURVES], ptr);
2413 #endif
2414 #ifdef USE_SSH
2415   case CURLOPT_SSH_PUBLIC_KEYFILE:
2416     /*
2417      * Use this file instead of the $HOME/.ssh/id_dsa.pub file
2418      */
2419     return Curl_setstropt(&data->set.str[STRING_SSH_PUBLIC_KEY], ptr);
2420 
2421   case CURLOPT_SSH_PRIVATE_KEYFILE:
2422     /*
2423      * Use this file instead of the $HOME/.ssh/id_dsa file
2424      */
2425     return Curl_setstropt(&data->set.str[STRING_SSH_PRIVATE_KEY], ptr);
2426 
2427   case CURLOPT_SSH_HOST_PUBLIC_KEY_MD5:
2428     /*
2429      * Option to allow for the MD5 of the host public key to be checked
2430      * for validation purposes.
2431      */
2432     return Curl_setstropt(&data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5], ptr);
2433 
2434   case CURLOPT_SSH_KNOWNHOSTS:
2435     /*
2436      * Store the filename to read known hosts from.
2437      */
2438     return Curl_setstropt(&data->set.str[STRING_SSH_KNOWNHOSTS], ptr);
2439 
2440   case CURLOPT_SSH_KEYDATA:
2441     /*
2442      * Custom client data to pass to the SSH keyfunc callback
2443      */
2444     data->set.ssh_keyfunc_userp = (void *)ptr;
2445     break;
2446 #ifdef USE_LIBSSH2
2447   case CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256:
2448     /*
2449      * Option to allow for the SHA256 of the host public key to be checked
2450      * for validation purposes.
2451      */
2452     return Curl_setstropt(&data->set.str[STRING_SSH_HOST_PUBLIC_KEY_SHA256],
2453                           ptr);
2454 
2455   case CURLOPT_SSH_HOSTKEYDATA:
2456     /*
2457      * Custom client data to pass to the SSH keyfunc callback
2458      */
2459     data->set.ssh_hostkeyfunc_userp = (void *)ptr;
2460     break;
2461 #endif /* USE_LIBSSH2 */
2462 #endif /* USE_SSH */
2463   case CURLOPT_PROTOCOLS_STR:
2464     if(ptr)
2465       return protocol2num(ptr, &data->set.allowed_protocols);
2466     /* make a NULL argument reset to default */
2467     data->set.allowed_protocols = (curl_prot_t) CURLPROTO_ALL;
2468     break;
2469 
2470   case CURLOPT_REDIR_PROTOCOLS_STR:
2471     if(ptr)
2472       return protocol2num(ptr, &data->set.redir_protocols);
2473     /* make a NULL argument reset to default */
2474     data->set.redir_protocols = (curl_prot_t) CURLPROTO_REDIR;
2475     break;
2476 
2477   case CURLOPT_DEFAULT_PROTOCOL:
2478     /* Set the protocol to use when the URL does not include any protocol */
2479     return Curl_setstropt(&data->set.str[STRING_DEFAULT_PROTOCOL], ptr);
2480 
2481 #ifndef CURL_DISABLE_SMTP
2482   case CURLOPT_MAIL_FROM:
2483     /* Set the SMTP mail originator */
2484     return Curl_setstropt(&data->set.str[STRING_MAIL_FROM], ptr);
2485 
2486   case CURLOPT_MAIL_AUTH:
2487     /* Set the SMTP auth originator */
2488     return Curl_setstropt(&data->set.str[STRING_MAIL_AUTH], ptr);
2489 #endif
2490 
2491   case CURLOPT_SASL_AUTHZID:
2492     /* Authorization identity (identity to act as) */
2493     return Curl_setstropt(&data->set.str[STRING_SASL_AUTHZID], ptr);
2494 
2495 #ifndef CURL_DISABLE_RTSP
2496   case CURLOPT_RTSP_SESSION_ID:
2497     /*
2498      * Set the RTSP Session ID manually. Useful if the application is
2499      * resuming a previously established RTSP session
2500      */
2501     return Curl_setstropt(&data->set.str[STRING_RTSP_SESSION_ID], ptr);
2502 
2503   case CURLOPT_RTSP_STREAM_URI:
2504     /*
2505      * Set the Stream URI for the RTSP request. Unless the request is
2506      * for generic server options, the application will need to set this.
2507      */
2508     return Curl_setstropt(&data->set.str[STRING_RTSP_STREAM_URI], ptr);
2509     break;
2510 
2511   case CURLOPT_RTSP_TRANSPORT:
2512     /*
2513      * The content of the Transport: header for the RTSP request
2514      */
2515     return Curl_setstropt(&data->set.str[STRING_RTSP_TRANSPORT], ptr);
2516 
2517   case CURLOPT_INTERLEAVEDATA:
2518     data->set.rtp_out = (void *)ptr;
2519     break;
2520 #endif /* ! CURL_DISABLE_RTSP */
2521 #ifndef CURL_DISABLE_FTP
2522   case CURLOPT_CHUNK_DATA:
2523     data->set.wildcardptr = (void *)ptr;
2524     break;
2525   case CURLOPT_FNMATCH_DATA:
2526     data->set.fnmatch_data = (void *)ptr;
2527     break;
2528 #endif
2529 #ifdef USE_TLS_SRP
2530   case CURLOPT_TLSAUTH_USERNAME:
2531     return Curl_setstropt(&data->set.str[STRING_TLSAUTH_USERNAME], ptr);
2532 
2533 #ifndef CURL_DISABLE_PROXY
2534   case CURLOPT_PROXY_TLSAUTH_USERNAME:
2535     return Curl_setstropt(&data->set.str[STRING_TLSAUTH_USERNAME_PROXY], ptr);
2536 
2537 #endif
2538   case CURLOPT_TLSAUTH_PASSWORD:
2539     return Curl_setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD], ptr);
2540 
2541 #ifndef CURL_DISABLE_PROXY
2542   case CURLOPT_PROXY_TLSAUTH_PASSWORD:
2543     return Curl_setstropt(&data->set.str[STRING_TLSAUTH_PASSWORD_PROXY], ptr);
2544 #endif
2545   case CURLOPT_TLSAUTH_TYPE:
2546     if(ptr && !strcasecompare(ptr, "SRP"))
2547       return CURLE_BAD_FUNCTION_ARGUMENT;
2548     break;
2549 #ifndef CURL_DISABLE_PROXY
2550   case CURLOPT_PROXY_TLSAUTH_TYPE:
2551     if(ptr && !strcasecompare(ptr, "SRP"))
2552       return CURLE_BAD_FUNCTION_ARGUMENT;
2553     break;
2554 #endif
2555 #endif
2556 #ifdef USE_ARES
2557   case CURLOPT_DNS_SERVERS:
2558     result = Curl_setstropt(&data->set.str[STRING_DNS_SERVERS], ptr);
2559     if(result)
2560       return result;
2561     return Curl_set_dns_servers(data, data->set.str[STRING_DNS_SERVERS]);
2562 
2563   case CURLOPT_DNS_INTERFACE:
2564     result = Curl_setstropt(&data->set.str[STRING_DNS_INTERFACE], ptr);
2565     if(result)
2566       return result;
2567     return Curl_set_dns_interface(data, data->set.str[STRING_DNS_INTERFACE]);
2568 
2569   case CURLOPT_DNS_LOCAL_IP4:
2570     result = Curl_setstropt(&data->set.str[STRING_DNS_LOCAL_IP4], ptr);
2571     if(result)
2572       return result;
2573     return Curl_set_dns_local_ip4(data, data->set.str[STRING_DNS_LOCAL_IP4]);
2574 
2575   case CURLOPT_DNS_LOCAL_IP6:
2576     result = Curl_setstropt(&data->set.str[STRING_DNS_LOCAL_IP6], ptr);
2577     if(result)
2578       return result;
2579     return Curl_set_dns_local_ip6(data, data->set.str[STRING_DNS_LOCAL_IP6]);
2580 
2581 #endif
2582 #ifdef USE_UNIX_SOCKETS
2583   case CURLOPT_UNIX_SOCKET_PATH:
2584     data->set.abstract_unix_socket = FALSE;
2585     return Curl_setstropt(&data->set.str[STRING_UNIX_SOCKET_PATH], ptr);
2586 
2587   case CURLOPT_ABSTRACT_UNIX_SOCKET:
2588     data->set.abstract_unix_socket = TRUE;
2589     return Curl_setstropt(&data->set.str[STRING_UNIX_SOCKET_PATH], ptr);
2590 
2591 #endif
2592 
2593 #ifndef CURL_DISABLE_DOH
2594   case CURLOPT_DOH_URL:
2595     result = Curl_setstropt(&data->set.str[STRING_DOH], ptr);
2596     data->set.doh = !!(data->set.str[STRING_DOH]);
2597     break;
2598 #endif
2599 #ifndef CURL_DISABLE_HSTS
2600   case CURLOPT_HSTSREADDATA:
2601     data->set.hsts_read_userp = (void *)ptr;
2602     break;
2603   case CURLOPT_HSTSWRITEDATA:
2604     data->set.hsts_write_userp = (void *)ptr;
2605     break;
2606   case CURLOPT_HSTS: {
2607     struct curl_slist *h;
2608     if(!data->hsts) {
2609       data->hsts = Curl_hsts_init();
2610       if(!data->hsts)
2611         return CURLE_OUT_OF_MEMORY;
2612     }
2613     if(ptr) {
2614       result = Curl_setstropt(&data->set.str[STRING_HSTS], ptr);
2615       if(result)
2616         return result;
2617       /* this needs to build a list of filenames to read from, so that it can
2618          read them later, as we might get a shared HSTS handle to load them
2619          into */
2620       h = curl_slist_append(data->state.hstslist, ptr);
2621       if(!h) {
2622         curl_slist_free_all(data->state.hstslist);
2623         data->state.hstslist = NULL;
2624         return CURLE_OUT_OF_MEMORY;
2625       }
2626       data->state.hstslist = h; /* store the list for later use */
2627     }
2628     else {
2629       /* clear the list of HSTS files */
2630       curl_slist_free_all(data->state.hstslist);
2631       data->state.hstslist = NULL;
2632       if(!data->share || !data->share->hsts)
2633         /* throw away the HSTS cache unless shared */
2634         Curl_hsts_cleanup(&data->hsts);
2635     }
2636     break;
2637   }
2638 #endif /* ! CURL_DISABLE_HSTS */
2639 #ifndef CURL_DISABLE_ALTSVC
2640   case CURLOPT_ALTSVC:
2641     if(!data->asi) {
2642       data->asi = Curl_altsvc_init();
2643       if(!data->asi)
2644         return CURLE_OUT_OF_MEMORY;
2645     }
2646     result = Curl_setstropt(&data->set.str[STRING_ALTSVC], ptr);
2647     if(result)
2648       return result;
2649     if(ptr)
2650       (void)Curl_altsvc_load(data->asi, ptr);
2651     break;
2652 #endif /* ! CURL_DISABLE_ALTSVC */
2653 #ifdef USE_ECH
2654   case CURLOPT_ECH: {
2655     size_t plen = 0;
2656 
2657     if(!ptr) {
2658       data->set.tls_ech = CURLECH_DISABLE;
2659       return CURLE_OK;
2660     }
2661     plen = strlen(ptr);
2662     if(plen > CURL_MAX_INPUT_LENGTH) {
2663       data->set.tls_ech = CURLECH_DISABLE;
2664       return CURLE_BAD_FUNCTION_ARGUMENT;
2665     }
2666     /* set tls_ech flag value, preserving CLA_CFG bit */
2667     if(!strcmp(ptr, "false"))
2668       data->set.tls_ech = CURLECH_DISABLE |
2669         (data->set.tls_ech & CURLECH_CLA_CFG);
2670     else if(!strcmp(ptr, "grease"))
2671       data->set.tls_ech = CURLECH_GREASE |
2672         (data->set.tls_ech & CURLECH_CLA_CFG);
2673     else if(!strcmp(ptr, "true"))
2674       data->set.tls_ech = CURLECH_ENABLE |
2675         (data->set.tls_ech & CURLECH_CLA_CFG);
2676     else if(!strcmp(ptr, "hard"))
2677       data->set.tls_ech = CURLECH_HARD |
2678         (data->set.tls_ech & CURLECH_CLA_CFG);
2679     else if(plen > 5 && !strncmp(ptr, "ecl:", 4)) {
2680       result = Curl_setstropt(&data->set.str[STRING_ECH_CONFIG], ptr + 4);
2681       if(result)
2682         return result;
2683       data->set.tls_ech |= CURLECH_CLA_CFG;
2684     }
2685     else if(plen > 4 && !strncmp(ptr, "pn:", 3)) {
2686       result = Curl_setstropt(&data->set.str[STRING_ECH_PUBLIC], ptr + 3);
2687       if(result)
2688         return result;
2689     }
2690     break;
2691   }
2692 #endif
2693   default:
2694     return CURLE_UNKNOWN_OPTION;
2695   }
2696   return result;
2697 }
2698 
setopt_func(struct Curl_easy * data,CURLoption option,va_list param)2699 static CURLcode setopt_func(struct Curl_easy *data, CURLoption option,
2700                             va_list param)
2701 {
2702   switch(option) {
2703   case CURLOPT_PROGRESSFUNCTION:
2704     /*
2705      * Progress callback function
2706      */
2707     data->set.fprogress = va_arg(param, curl_progress_callback);
2708     if(data->set.fprogress)
2709       data->progress.callback = TRUE; /* no longer internal */
2710     else
2711       data->progress.callback = FALSE; /* NULL enforces internal */
2712     break;
2713 
2714   case CURLOPT_XFERINFOFUNCTION:
2715     /*
2716      * Transfer info callback function
2717      */
2718     data->set.fxferinfo = va_arg(param, curl_xferinfo_callback);
2719     if(data->set.fxferinfo)
2720       data->progress.callback = TRUE; /* no longer internal */
2721     else
2722       data->progress.callback = FALSE; /* NULL enforces internal */
2723 
2724     break;
2725   case CURLOPT_DEBUGFUNCTION:
2726     /*
2727      * stderr write callback.
2728      */
2729     data->set.fdebug = va_arg(param, curl_debug_callback);
2730     /*
2731      * if the callback provided is NULL, it will use the default callback
2732      */
2733     break;
2734   case CURLOPT_HEADERFUNCTION:
2735     /*
2736      * Set header write callback
2737      */
2738     data->set.fwrite_header = va_arg(param, curl_write_callback);
2739     break;
2740   case CURLOPT_WRITEFUNCTION:
2741     /*
2742      * Set data write callback
2743      */
2744     data->set.fwrite_func = va_arg(param, curl_write_callback);
2745     if(!data->set.fwrite_func)
2746       /* When set to NULL, reset to our internal default function */
2747       data->set.fwrite_func = (curl_write_callback)fwrite;
2748     break;
2749   case CURLOPT_READFUNCTION:
2750     /*
2751      * Read data callback
2752      */
2753     data->set.fread_func_set = va_arg(param, curl_read_callback);
2754     if(!data->set.fread_func_set) {
2755       data->set.is_fread_set = 0;
2756       /* When set to NULL, reset to our internal default function */
2757       data->set.fread_func_set = (curl_read_callback)fread;
2758     }
2759     else
2760       data->set.is_fread_set = 1;
2761     break;
2762   case CURLOPT_SEEKFUNCTION:
2763     /*
2764      * Seek callback. Might be NULL.
2765      */
2766     data->set.seek_func = va_arg(param, curl_seek_callback);
2767     break;
2768   case CURLOPT_IOCTLFUNCTION:
2769     /*
2770      * I/O control callback. Might be NULL.
2771      */
2772     data->set.ioctl_func = va_arg(param, curl_ioctl_callback);
2773     break;
2774   case CURLOPT_SSL_CTX_FUNCTION:
2775     /*
2776      * Set a SSL_CTX callback
2777      */
2778 #ifdef USE_SSL
2779     if(Curl_ssl_supports(data, SSLSUPP_SSL_CTX))
2780       data->set.ssl.fsslctx = va_arg(param, curl_ssl_ctx_callback);
2781     else
2782 #endif
2783       return CURLE_NOT_BUILT_IN;
2784     break;
2785 
2786   case CURLOPT_SOCKOPTFUNCTION:
2787     /*
2788      * socket callback function: called after socket() but before connect()
2789      */
2790     data->set.fsockopt = va_arg(param, curl_sockopt_callback);
2791     break;
2792 
2793   case CURLOPT_OPENSOCKETFUNCTION:
2794     /*
2795      * open/create socket callback function: called instead of socket(),
2796      * before connect()
2797      */
2798     data->set.fopensocket = va_arg(param, curl_opensocket_callback);
2799     break;
2800 
2801   case CURLOPT_CLOSESOCKETFUNCTION:
2802     /*
2803      * close socket callback function: called instead of close()
2804      * when shutting down a connection
2805      */
2806     data->set.fclosesocket = va_arg(param, curl_closesocket_callback);
2807     break;
2808 
2809   case CURLOPT_RESOLVER_START_FUNCTION:
2810     /*
2811      * resolver start callback function: called before a new resolver request
2812      * is started
2813      */
2814     data->set.resolver_start = va_arg(param, curl_resolver_start_callback);
2815     break;
2816 
2817 
2818 #ifdef USE_SSH
2819 #ifdef USE_LIBSSH2
2820   case CURLOPT_SSH_HOSTKEYFUNCTION:
2821     /* the callback to check the hostkey without the knownhost file */
2822     data->set.ssh_hostkeyfunc = va_arg(param, curl_sshhostkeycallback);
2823     break;
2824 #endif
2825 
2826   case CURLOPT_SSH_KEYFUNCTION:
2827     /* setting to NULL is fine since the ssh.c functions themselves will
2828        then revert to use the internal default */
2829     data->set.ssh_keyfunc = va_arg(param, curl_sshkeycallback);
2830     break;
2831 
2832 #endif /* USE_SSH */
2833 
2834 #ifndef CURL_DISABLE_RTSP
2835   case CURLOPT_INTERLEAVEFUNCTION:
2836     /* Set the user defined RTP write function */
2837     data->set.fwrite_rtp = va_arg(param, curl_write_callback);
2838     break;
2839 #endif
2840 #ifndef CURL_DISABLE_FTP
2841   case CURLOPT_CHUNK_BGN_FUNCTION:
2842     data->set.chunk_bgn = va_arg(param, curl_chunk_bgn_callback);
2843     break;
2844   case CURLOPT_CHUNK_END_FUNCTION:
2845     data->set.chunk_end = va_arg(param, curl_chunk_end_callback);
2846     break;
2847   case CURLOPT_FNMATCH_FUNCTION:
2848     data->set.fnmatch = va_arg(param, curl_fnmatch_callback);
2849     break;
2850 #endif
2851 #ifndef CURL_DISABLE_HTTP
2852   case CURLOPT_TRAILERFUNCTION:
2853     data->set.trailer_callback = va_arg(param, curl_trailer_callback);
2854     break;
2855 #endif
2856 #ifndef CURL_DISABLE_HSTS
2857   case CURLOPT_HSTSREADFUNCTION:
2858     data->set.hsts_read = va_arg(param, curl_hstsread_callback);
2859     break;
2860   case CURLOPT_HSTSWRITEFUNCTION:
2861     data->set.hsts_write = va_arg(param, curl_hstswrite_callback);
2862     break;
2863 #endif
2864   case CURLOPT_PREREQFUNCTION:
2865     data->set.fprereq = va_arg(param, curl_prereq_callback);
2866     break;
2867   default:
2868     return CURLE_UNKNOWN_OPTION;
2869   }
2870   return CURLE_OK;
2871 }
2872 
setopt_offt(struct Curl_easy * data,CURLoption option,curl_off_t offt)2873 static CURLcode setopt_offt(struct Curl_easy *data, CURLoption option,
2874                             curl_off_t offt)
2875 {
2876   switch(option) {
2877   case CURLOPT_TIMEVALUE_LARGE:
2878     /*
2879      * This is the value to compare with the remote document with the
2880      * method set with CURLOPT_TIMECONDITION
2881      */
2882     data->set.timevalue = (time_t)offt;
2883     break;
2884 
2885     /* MQTT "borrows" some of the HTTP options */
2886   case CURLOPT_POSTFIELDSIZE_LARGE:
2887     /*
2888      * The size of the POSTFIELD data to prevent libcurl to do strlen() to
2889      * figure it out. Enables binary posts.
2890      */
2891     if(offt < -1)
2892       return CURLE_BAD_FUNCTION_ARGUMENT;
2893 
2894     if(data->set.postfieldsize < offt &&
2895        data->set.postfields == data->set.str[STRING_COPYPOSTFIELDS]) {
2896       /* Previous CURLOPT_COPYPOSTFIELDS is no longer valid. */
2897       Curl_safefree(data->set.str[STRING_COPYPOSTFIELDS]);
2898       data->set.postfields = NULL;
2899     }
2900     data->set.postfieldsize = offt;
2901     break;
2902   case CURLOPT_INFILESIZE_LARGE:
2903     /*
2904      * If known, this should inform curl about the file size of the
2905      * to-be-uploaded file.
2906      */
2907     if(offt < -1)
2908       return CURLE_BAD_FUNCTION_ARGUMENT;
2909     data->set.filesize = offt;
2910     break;
2911   case CURLOPT_MAX_SEND_SPEED_LARGE:
2912     /*
2913      * When transfer uploads are faster then CURLOPT_MAX_SEND_SPEED_LARGE
2914      * bytes per second the transfer is throttled..
2915      */
2916     if(offt < 0)
2917       return CURLE_BAD_FUNCTION_ARGUMENT;
2918     data->set.max_send_speed = offt;
2919     break;
2920   case CURLOPT_MAX_RECV_SPEED_LARGE:
2921     /*
2922      * When receiving data faster than CURLOPT_MAX_RECV_SPEED_LARGE bytes per
2923      * second the transfer is throttled..
2924      */
2925     if(offt < 0)
2926       return CURLE_BAD_FUNCTION_ARGUMENT;
2927     data->set.max_recv_speed = offt;
2928     break;
2929   case CURLOPT_RESUME_FROM_LARGE:
2930     /*
2931      * Resume transfer at the given file position
2932      */
2933     if(offt < -1)
2934       return CURLE_BAD_FUNCTION_ARGUMENT;
2935     data->set.set_resume_from = offt;
2936     break;
2937   case CURLOPT_MAXFILESIZE_LARGE:
2938     /*
2939      * Set the maximum size of a file to download.
2940      */
2941     if(offt < 0)
2942       return CURLE_BAD_FUNCTION_ARGUMENT;
2943     data->set.max_filesize = offt;
2944     break;
2945 
2946   default:
2947     return CURLE_UNKNOWN_OPTION;
2948   }
2949   return CURLE_OK;
2950 }
2951 
setopt_blob(struct Curl_easy * data,CURLoption option,struct curl_blob * blob)2952 static CURLcode setopt_blob(struct Curl_easy *data, CURLoption option,
2953                             struct curl_blob *blob)
2954 {
2955   switch(option) {
2956   case CURLOPT_SSLCERT_BLOB:
2957     /*
2958      * Blob that holds file content of the SSL certificate to use
2959      */
2960     return Curl_setblobopt(&data->set.blobs[BLOB_CERT], blob);
2961 #ifndef CURL_DISABLE_PROXY
2962   case CURLOPT_PROXY_SSLCERT_BLOB:
2963     /*
2964      * Blob that holds file content of the SSL certificate to use for proxy
2965      */
2966     return Curl_setblobopt(&data->set.blobs[BLOB_CERT_PROXY], blob);
2967   case CURLOPT_PROXY_SSLKEY_BLOB:
2968     /*
2969      * Blob that holds file content of the SSL key to use for proxy
2970      */
2971     return Curl_setblobopt(&data->set.blobs[BLOB_KEY_PROXY], blob);
2972   case CURLOPT_PROXY_CAINFO_BLOB:
2973     /*
2974      * Blob that holds CA info for SSL connection proxy.
2975      * Specify entire PEM of the CA certificate
2976      */
2977 #ifdef USE_SSL
2978     if(Curl_ssl_supports(data, SSLSUPP_CAINFO_BLOB))
2979       return Curl_setblobopt(&data->set.blobs[BLOB_CAINFO_PROXY], blob);
2980 #endif
2981     return CURLE_NOT_BUILT_IN;
2982   case CURLOPT_PROXY_ISSUERCERT_BLOB:
2983     /*
2984      * Blob that holds Issuer certificate to check certificates issuer
2985      */
2986     return Curl_setblobopt(&data->set.blobs[BLOB_SSL_ISSUERCERT_PROXY],
2987                            blob);
2988 #endif
2989   case CURLOPT_SSLKEY_BLOB:
2990     /*
2991      * Blob that holds file content of the SSL key to use
2992      */
2993     return Curl_setblobopt(&data->set.blobs[BLOB_KEY], blob);
2994   case CURLOPT_CAINFO_BLOB:
2995     /*
2996      * Blob that holds CA info for SSL connection.
2997      * Specify entire PEM of the CA certificate
2998      */
2999 #ifdef USE_SSL
3000     if(Curl_ssl_supports(data, SSLSUPP_CAINFO_BLOB))
3001       return Curl_setblobopt(&data->set.blobs[BLOB_CAINFO], blob);
3002 #endif
3003     return CURLE_NOT_BUILT_IN;
3004   case CURLOPT_ISSUERCERT_BLOB:
3005     /*
3006      * Blob that holds Issuer certificate to check certificates issuer
3007      */
3008     return Curl_setblobopt(&data->set.blobs[BLOB_SSL_ISSUERCERT], blob);
3009 
3010   default:
3011     return CURLE_UNKNOWN_OPTION;
3012   }
3013   /* unreachable */
3014 }
3015 
3016 /*
3017  * Do not make Curl_vsetopt() static: it is called from
3018  * packages/OS400/ccsidcurl.c.
3019  */
Curl_vsetopt(struct Curl_easy * data,CURLoption option,va_list param)3020 CURLcode Curl_vsetopt(struct Curl_easy *data, CURLoption option, va_list param)
3021 {
3022   if(option < CURLOPTTYPE_OBJECTPOINT)
3023     return setopt_long(data, option, va_arg(param, long));
3024   else if(option < CURLOPTTYPE_FUNCTIONPOINT) {
3025     /* unfortunately, different pointer types cannot be identified any other
3026        way than being listed explicitly */
3027     switch(option) {
3028     case CURLOPT_HTTPHEADER:
3029     case CURLOPT_QUOTE:
3030     case CURLOPT_POSTQUOTE:
3031     case CURLOPT_TELNETOPTIONS:
3032     case CURLOPT_PREQUOTE:
3033     case CURLOPT_HTTP200ALIASES:
3034     case CURLOPT_MAIL_RCPT:
3035     case CURLOPT_RESOLVE:
3036     case CURLOPT_PROXYHEADER:
3037     case CURLOPT_CONNECT_TO:
3038       return setopt_slist(data, option, va_arg(param, struct curl_slist *));
3039     case CURLOPT_HTTPPOST:         /* curl_httppost * */
3040     case CURLOPT_MIMEPOST:         /* curl_mime * */
3041     case CURLOPT_STDERR:           /* FILE * */
3042     case CURLOPT_SHARE:            /* CURLSH * */
3043     case CURLOPT_STREAM_DEPENDS:   /* CURL * */
3044     case CURLOPT_STREAM_DEPENDS_E: /* CURL * */
3045       return setopt_pointers(data, option, param);
3046     default:
3047       break;
3048     }
3049     /* the char pointer options */
3050     return setopt_cptr(data, option, va_arg(param, char *));
3051   }
3052   else if(option < CURLOPTTYPE_OFF_T)
3053     return setopt_func(data, option, param);
3054   else if(option < CURLOPTTYPE_BLOB)
3055     return setopt_offt(data, option, va_arg(param, curl_off_t));
3056   return setopt_blob(data, option, va_arg(param, struct curl_blob *));
3057 }
3058 
3059 /*
3060  * curl_easy_setopt() is the external interface for setting options on an
3061  * easy handle.
3062  *
3063  * NOTE: This is one of few API functions that are allowed to be called from
3064  * within a callback.
3065  */
3066 
3067 #undef curl_easy_setopt
curl_easy_setopt(CURL * d,CURLoption tag,...)3068 CURLcode curl_easy_setopt(CURL *d, CURLoption tag, ...)
3069 {
3070   va_list arg;
3071   CURLcode result;
3072   struct Curl_easy *data = d;
3073 
3074   if(!data)
3075     return CURLE_BAD_FUNCTION_ARGUMENT;
3076 
3077   va_start(arg, tag);
3078 
3079   result = Curl_vsetopt(data, tag, arg);
3080 
3081   va_end(arg);
3082 #ifdef DEBUGBUILD
3083   if(result == CURLE_BAD_FUNCTION_ARGUMENT)
3084     infof(data, "setopt arg 0x%x returned CURLE_BAD_FUNCTION_ARGUMENT", tag);
3085 #endif
3086   return result;
3087 }
3088