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#include "tool_setup.h" 25 26#include "strcase.h" 27 28#define ENABLE_CURLX_PRINTF 29/* use our own printf() functions */ 30#include "curlx.h" 31 32#include "tool_libinfo.h" 33 34#include "memdebug.h" /* keep this as LAST include */ 35 36/* global variable definitions, for libcurl run-time info */ 37 38static const char *no_protos = NULL; 39 40curl_version_info_data *curlinfo = NULL; 41const char * const *built_in_protos = &no_protos; 42 43size_t proto_count = 0; 44 45const char *proto_file = NULL; 46const char *proto_ftp = NULL; 47const char *proto_ftps = NULL; 48const char *proto_http = NULL; 49const char *proto_https = NULL; 50const char *proto_rtsp = NULL; 51const char *proto_scp = NULL; 52const char *proto_sftp = NULL; 53const char *proto_tftp = NULL; 54const char *proto_ipfs = "ipfs"; 55const char *proto_ipns = "ipns"; 56 57static struct proto_name_tokenp { 58 const char *proto_name; 59 const char **proto_tokenp; 60} const possibly_built_in[] = { 61 { "file", &proto_file }, 62 { "ftp", &proto_ftp }, 63 { "ftps", &proto_ftps }, 64 { "http", &proto_http }, 65 { "https", &proto_https }, 66 { "rtsp", &proto_rtsp }, 67 { "scp", &proto_scp }, 68 { "sftp", &proto_sftp }, 69 { "tftp", &proto_tftp }, 70 { NULL, NULL } 71}; 72 73bool feature_altsvc = FALSE; 74bool feature_brotli = FALSE; 75bool feature_hsts = FALSE; 76bool feature_http2 = FALSE; 77bool feature_http3 = FALSE; 78bool feature_httpsproxy = FALSE; 79bool feature_libz = FALSE; 80bool feature_ntlm = FALSE; 81bool feature_ntlm_wb = FALSE; 82bool feature_spnego = FALSE; 83bool feature_ssl = FALSE; 84bool feature_tls_srp = FALSE; 85bool feature_zstd = FALSE; 86 87static struct feature_name_presentp { 88 const char *feature_name; 89 bool *feature_presentp; 90 int feature_bitmask; 91} const maybe_feature[] = { 92 /* Keep alphabetically sorted. */ 93 {"alt-svc", &feature_altsvc, CURL_VERSION_ALTSVC}, 94 {"AsynchDNS", NULL, CURL_VERSION_ASYNCHDNS}, 95 {"brotli", &feature_brotli, CURL_VERSION_BROTLI}, 96 {"CharConv", NULL, CURL_VERSION_CONV}, 97 {"Debug", NULL, CURL_VERSION_DEBUG}, 98 {"gsasl", NULL, CURL_VERSION_GSASL}, 99 {"GSS-API", NULL, CURL_VERSION_GSSAPI}, 100 {"HSTS", &feature_hsts, CURL_VERSION_HSTS}, 101 {"HTTP2", &feature_http2, CURL_VERSION_HTTP2}, 102 {"HTTP3", &feature_http3, CURL_VERSION_HTTP3}, 103 {"HTTPS-proxy", &feature_httpsproxy, CURL_VERSION_HTTPS_PROXY}, 104 {"IDN", NULL, CURL_VERSION_IDN}, 105 {"IPv6", NULL, CURL_VERSION_IPV6}, 106 {"Kerberos", NULL, CURL_VERSION_KERBEROS5}, 107 {"Largefile", NULL, CURL_VERSION_LARGEFILE}, 108 {"libz", &feature_libz, CURL_VERSION_LIBZ}, 109 {"MultiSSL", NULL, CURL_VERSION_MULTI_SSL}, 110 {"NTLM", &feature_ntlm, CURL_VERSION_NTLM}, 111 {"NTLM_WB", &feature_ntlm_wb, CURL_VERSION_NTLM_WB}, 112 {"PSL", NULL, CURL_VERSION_PSL}, 113 {"SPNEGO", &feature_spnego, CURL_VERSION_SPNEGO}, 114 {"SSL", &feature_ssl, CURL_VERSION_SSL}, 115 {"SSPI", NULL, CURL_VERSION_SSPI}, 116 {"threadsafe", NULL, CURL_VERSION_THREADSAFE}, 117 {"TLS-SRP", &feature_tls_srp, CURL_VERSION_TLSAUTH_SRP}, 118 {"TrackMemory", NULL, CURL_VERSION_CURLDEBUG}, 119 {"Unicode", NULL, CURL_VERSION_UNICODE}, 120 {"UnixSockets", NULL, CURL_VERSION_UNIX_SOCKETS}, 121 {"zstd", &feature_zstd, CURL_VERSION_ZSTD}, 122 {NULL, NULL, 0} 123}; 124 125static const char *fnames[sizeof(maybe_feature) / sizeof(maybe_feature[0])]; 126const char * const *feature_names = fnames; 127 128/* 129 * libcurl_info_init: retrieves run-time information about libcurl, 130 * setting a global pointer 'curlinfo' to libcurl's run-time info 131 * struct, count protocols and flag those we are interested in. 132 * Global pointer feature_names is set to the feature names array. If 133 * the latter is not returned by curl_version_info(), it is built from 134 * the returned features bit mask. 135 */ 136 137CURLcode get_libcurl_info(void) 138{ 139 CURLcode result = CURLE_OK; 140 const char *const *builtin; 141 142 /* Pointer to libcurl's run-time version information */ 143 curlinfo = curl_version_info(CURLVERSION_NOW); 144 if(!curlinfo) 145 return CURLE_FAILED_INIT; 146 147 if(curlinfo->protocols) { 148 const struct proto_name_tokenp *p; 149 150 built_in_protos = curlinfo->protocols; 151 152 for(builtin = built_in_protos; !result && *builtin; builtin++) { 153 /* Identify protocols we are interested in. */ 154 for(p = possibly_built_in; p->proto_name; p++) 155 if(curl_strequal(p->proto_name, *builtin)) { 156 *p->proto_tokenp = *builtin; 157 break; 158 } 159 } 160 proto_count = builtin - built_in_protos; 161 } 162 163 if(curlinfo->age >= CURLVERSION_ELEVENTH && curlinfo->feature_names) 164 feature_names = curlinfo->feature_names; 165 else { 166 const struct feature_name_presentp *p; 167 const char **cpp = fnames; 168 169 for(p = maybe_feature; p->feature_name; p++) 170 if(curlinfo->features & p->feature_bitmask) 171 *cpp++ = p->feature_name; 172 *cpp = NULL; 173 } 174 175 /* Identify features we are interested in. */ 176 for(builtin = feature_names; *builtin; builtin++) { 177 const struct feature_name_presentp *p; 178 179 for(p = maybe_feature; p->feature_name; p++) 180 if(curl_strequal(p->feature_name, *builtin)) { 181 if(p->feature_presentp) 182 *p->feature_presentp = TRUE; 183 break; 184 } 185 } 186 187 return CURLE_OK; 188} 189 190/* Tokenize a protocol name. 191 * Return the address of the protocol name listed by the library, or NULL if 192 * not found. 193 * Although this may seem useless, this always returns the same address for 194 * a given protocol and thus allows comparing pointers rather than strings. 195 * In addition, the returned pointer is not deallocated until the program ends. 196 */ 197 198const char *proto_token(const char *proto) 199{ 200 const char * const *builtin; 201 202 if(!proto) 203 return NULL; 204 for(builtin = built_in_protos; *builtin; builtin++) 205 if(curl_strequal(*builtin, proto)) 206 break; 207 return *builtin; 208} 209