resolve: pass bool for proxy resolves

So that CURLcode failure is correct and not figured out later via
`conn->bits.proxy`. Add the flag to the async struct.

`for_proxy` is figured out by the caller of Curl_resolv() when it
figures out which host/proxy name it wants the addresses for.

Remove CONN_IS_PROXIED macro as no longer needed.

Closes #21423
This commit is contained in:
Stefan Eissing 2026-04-23 16:26:13 +02:00 committed by Daniel Stenberg
parent 0d3d9f2222
commit b6e0ecb3f2
No known key found for this signature in database
GPG key ID: 5CC908FDB71E12C2
12 changed files with 103 additions and 89 deletions

View file

@ -310,7 +310,7 @@ CURLcode Curl_async_take_result(struct Curl_easy *data,
const char *msg = NULL;
if(ares->ares_status != ARES_SUCCESS)
msg = ares_strerror(ares->ares_status);
result = Curl_resolver_error(data, msg);
result = Curl_async_failed(data, async, msg);
}
CURL_TRC_DNS(data, "ares: is_resolved() result=%d, dns=%sfound",

View file

@ -242,4 +242,24 @@ void Curl_async_destroy(struct Curl_easy *data,
}
}
CURLcode Curl_async_failed(struct Curl_easy *data,
struct Curl_resolv_async *async,
const char *detail)
{
const char *host_or_proxy = "host";
CURLcode result = CURLE_COULDNT_RESOLVE_HOST;
#ifndef CURL_DISABLE_PROXY
if(async->for_proxy) {
host_or_proxy = "proxy";
result = CURLE_COULDNT_RESOLVE_PROXY;
}
#endif
failf(data, "Could not resolve %s: %s%s%s%s",
host_or_proxy, async->hostname,
detail ? " (" : "", detail ? detail : "", detail ? ")" : "");
return result;
}
#endif /* USE_CURL_ASYNC */

View file

@ -751,7 +751,7 @@ out:
Curl_dns_entry_unlink(data, &dns);
Curl_async_thrdd_shutdown(data, async);
if(!result && !*pdns)
result = Curl_resolver_error(data, NULL);
result = Curl_async_failed(data, async, NULL);
if(result &&
(result != CURLE_COULDNT_RESOLVE_HOST) &&
(result != CURLE_COULDNT_RESOLVE_PROXY)) {

View file

@ -248,6 +248,7 @@ struct Curl_resolv_async {
uint8_t queries_ongoing;
BIT(is_ipaddr);
BIT(is_ipv4addr);
BIT(for_proxy);
BIT(done);
BIT(shutdown);
char hostname[1];
@ -264,6 +265,10 @@ void Curl_async_shutdown(struct Curl_easy *data,
void Curl_async_destroy(struct Curl_easy *data,
struct Curl_resolv_async *async);
CURLcode Curl_async_failed(struct Curl_easy *data,
struct Curl_resolv_async *async,
const char *detail);
#else /* !USE_CURL_ASYNC */
#define Curl_async_shutdown(x, y) Curl_nop_stmt
#endif /* USE_CURL_ASYNC */

View file

@ -46,6 +46,7 @@ struct cf_dns_ctx {
BIT(announced);
BIT(abstract_unix_socket);
BIT(complete_resolve);
BIT(for_proxy);
char hostname[1];
};
@ -54,6 +55,7 @@ static struct cf_dns_ctx *cf_dns_ctx_create(struct Curl_easy *data,
const char *hostname,
uint16_t port, uint8_t transport,
bool abstract_unix_socket,
bool for_proxy,
bool complete_resolve,
struct Curl_dns_entry *dns)
{
@ -68,6 +70,7 @@ static struct cf_dns_ctx *cf_dns_ctx_create(struct Curl_easy *data,
ctx->dns_queries = dns_queries;
ctx->transport = transport;
ctx->abstract_unix_socket = abstract_unix_socket;
ctx->for_proxy = for_proxy;
ctx->complete_resolve = complete_resolve;
ctx->dns = Curl_dns_entry_link(data, dns);
ctx->started = !!ctx->dns;
@ -196,7 +199,8 @@ static CURLcode cf_dns_start(struct Curl_cfilter *cf,
#endif
result = Curl_resolv(data, ctx->dns_queries,
ctx->hostname, ctx->port, ctx->transport,
timeout_ms, &ctx->resolv_id, pdns);
(bool)ctx->for_proxy, timeout_ms,
&ctx->resolv_id, pdns);
DEBUGASSERT(!result || !*pdns);
if(!result) { /* resolved right away, either sync or from dnscache */
DEBUGASSERT(*pdns);
@ -394,6 +398,7 @@ static CURLcode cf_dns_create(struct Curl_cfilter **pcf,
uint16_t port,
uint8_t transport,
bool abstract_unix_socket,
bool for_proxy,
bool complete_resolve,
struct Curl_dns_entry *dns)
{
@ -403,7 +408,8 @@ static CURLcode cf_dns_create(struct Curl_cfilter **pcf,
(void)data;
ctx = cf_dns_ctx_create(data, dns_queries, hostname, port, transport,
abstract_unix_socket, complete_resolve, dns);
abstract_unix_socket, for_proxy,
complete_resolve, dns);
if(!ctx) {
result = CURLE_OUT_OF_MEMORY;
goto out;
@ -430,7 +436,7 @@ static CURLcode cf_dns_conn_create(struct Curl_cfilter **pcf,
struct connectdata *conn = data->conn;
const char *hostname = NULL;
uint16_t port = 0;
bool abstract_unix_socket = FALSE;
bool abstract_unix_socket = FALSE, for_proxy = FALSE;
#ifdef USE_UNIX_SOCKETS
{
@ -444,13 +450,12 @@ static CURLcode cf_dns_conn_create(struct Curl_cfilter **pcf,
#endif
#ifndef CURL_DISABLE_PROXY
if(!hostname && CONN_IS_PROXIED(conn)) {
struct hostname *ehost;
ehost = conn->bits.socksproxy ? &conn->socks_proxy.host :
&conn->http_proxy.host;
hostname = ehost->name;
port = conn->bits.socksproxy ? conn->socks_proxy.port :
conn->http_proxy.port;
if(!hostname && conn->bits.proxy) {
for_proxy = TRUE;
hostname = conn->bits.socksproxy ?
conn->socks_proxy.host.name : conn->http_proxy.host.name;
port = conn->bits.socksproxy ?
conn->socks_proxy.port : conn->http_proxy.port;
}
#endif
if(!hostname) {
@ -469,7 +474,8 @@ static CURLcode cf_dns_conn_create(struct Curl_cfilter **pcf,
}
return cf_dns_create(pcf, data, dns_queries,
hostname, port, transport,
abstract_unix_socket, complete_resolve, dns);
abstract_unix_socket, for_proxy,
complete_resolve, dns);
}
/* Adds a "resolv" filter at the top of the connection's filter chain.
@ -494,7 +500,7 @@ CURLcode Curl_cf_dns_add(struct Curl_easy *data,
else if(dns) {
result = cf_dns_create(&cf, data, dns_queries,
dns->hostname, dns->port, transport,
FALSE, FALSE, dns);
FALSE, FALSE, FALSE, dns);
}
else {
DEBUGASSERT(0);
@ -526,7 +532,7 @@ CURLcode Curl_cf_dns_insert_after(struct Curl_cfilter *cf_at,
result = cf_dns_create(&cf, data, dns_queries,
hostname, port, transport,
FALSE, complete_resolve, NULL);
FALSE, FALSE, complete_resolve, NULL);
if(result)
return result;

View file

@ -673,8 +673,7 @@ static CURLcode is_connected(struct Curl_cfilter *cf,
if(!result)
return CURLE_OK;
{
else {
const char *hostname, *proxy_name = NULL;
char viamsg[160];
#ifndef CURL_DISABLE_PROXY
@ -712,14 +711,14 @@ static CURLcode is_connected(struct Curl_cfilter *cf,
curlx_ptimediff_ms(Curl_pgrs_now(data),
&data->progress.t_startsingle),
curl_easy_strerror(result));
}
#ifdef SOCKETIMEDOUT
if(SOCKETIMEDOUT == data->state.os_errno)
result = CURLE_OPERATION_TIMEDOUT;
if(SOCKETIMEDOUT == data->state.os_errno)
result = CURLE_OPERATION_TIMEDOUT;
#endif
return result;
return result;
}
}
#define IP_HE_MAX_CONCURRENT_ATTEMPTS 6

View file

@ -602,7 +602,7 @@ const char *Curl_conn_get_unix_path(struct connectdata *conn)
const char *unix_path = conn->unix_domain_socket;
#ifndef CURL_DISABLE_PROXY
if(!unix_path && CONN_IS_PROXIED(conn) && conn->socks_proxy.host.name &&
if(!unix_path && conn->bits.proxy && conn->socks_proxy.host.name &&
!strncmp(UNIX_SOCKET_PREFIX "/",
conn->socks_proxy.host.name, sizeof(UNIX_SOCKET_PREFIX)))
unix_path = conn->socks_proxy.host.name + sizeof(UNIX_SOCKET_PREFIX) - 1;

View file

@ -1230,8 +1230,8 @@ CURLcode Curl_doh_take_result(struct Curl_easy *data,
if(dohp->probe_resp[DOH_SLOT_IPV4].probe_mid == UINT32_MAX &&
dohp->probe_resp[DOH_SLOT_IPV6].probe_mid == UINT32_MAX) {
failf(data, "Could not DoH-resolve: %s", dohp->host);
return CONN_IS_PROXIED(data->conn) ? CURLE_COULDNT_RESOLVE_PROXY :
CURLE_COULDNT_RESOLVE_HOST;
return async->for_proxy ?
CURLE_COULDNT_RESOLVE_PROXY : CURLE_COULDNT_RESOLVE_HOST;
}
else if(!dohp->pending) {
DOHcode rc[DOH_SLOT_COUNT];
@ -1301,8 +1301,8 @@ CURLcode Curl_doh_take_result(struct Curl_easy *data,
*pdns = dns;
} /* address processing done */
else {
result = CONN_IS_PROXIED(data->conn) ? CURLE_COULDNT_RESOLVE_PROXY :
CURLE_COULDNT_RESOLVE_HOST;
result = async->for_proxy ?
CURLE_COULDNT_RESOLVE_PROXY : CURLE_COULDNT_RESOLVE_HOST;
}
} /* !dohp->pending */

View file

@ -74,6 +74,12 @@
#define MAX_DNS_CACHE_SIZE 29999
#define RESOLV_FAIL(for_proxy) \
((for_proxy) ? CURLE_COULDNT_RESOLVE_PROXY : CURLE_COULDNT_RESOLVE_HOST)
#define IS_RESOLV_FAIL(result) \
(((result) == CURLE_COULDNT_RESOLVE_HOST) || \
((result) == CURLE_COULDNT_RESOLVE_PROXY))
/*
* ipv6works() returns TRUE if IPv6 seems to work.
*/
@ -339,6 +345,15 @@ static bool tailmatch(const char *full, size_t flen,
return curl_strnequal(part, &full[flen - plen], plen);
}
static CURLcode hostip_resolv_failed(struct Curl_easy *data,
const char *hostname,
bool for_proxy)
{
failf(data, "Could not resolve %s: %s",
for_proxy ? "proxy" : "host", hostname);
return RESOLV_FAIL(for_proxy);
}
static bool can_resolve_dns_queries(struct Curl_easy *data,
uint8_t dns_queries)
{
@ -368,11 +383,13 @@ CURLcode Curl_resolv_announce_start(struct Curl_easy *data,
}
#ifdef USE_CURL_ASYNC
static struct Curl_resolv_async *hostip_async_new(struct Curl_easy *data,
uint8_t dns_queries,
const char *hostname,
uint16_t port,
uint8_t transport,
bool for_proxy,
timediff_t timeout_ms)
{
struct Curl_resolv_async *async;
@ -401,6 +418,7 @@ static struct Curl_resolv_async *hostip_async_new(struct Curl_easy *data,
async->dns_queries = dns_queries;
async->port = port;
async->transport = transport;
async->for_proxy = for_proxy;
async->start = *Curl_pgrs_now(data);
async->timeout_ms = timeout_ms;
if(hostlen) {
@ -439,8 +457,7 @@ static CURLcode hostip_resolv_take_result(struct Curl_easy *data,
result = CURLE_OK;
}
else if(result) {
CURL_TRC_DNS(data, "result error %d", result);
Curl_resolver_error(data, NULL);
result = Curl_async_failed(data, async, NULL);
}
else {
CURL_TRC_DNS(data, "resolve complete for %s:%u",
@ -522,6 +539,7 @@ static CURLcode hostip_resolv_start(struct Curl_easy *data,
const char *hostname,
uint16_t port,
uint8_t transport,
bool for_proxy,
timediff_t timeout_ms,
bool allowDOH,
uint32_t *presolv_id,
@ -573,7 +591,7 @@ static CURLcode hostip_resolv_start(struct Curl_easy *data,
goto out;
if(!async) {
async = hostip_async_new(data, dns_queries, hostname, port,
transport, timeout_ms);
transport, for_proxy, timeout_ms);
if(!async) {
result = CURLE_OUT_OF_MEMORY;
goto out;
@ -588,7 +606,7 @@ static CURLcode hostip_resolv_start(struct Curl_easy *data,
/* Can we provide the requested IP specifics in resolving? */
if(!can_resolve_dns_queries(data, dns_queries)) {
result = CURLE_COULDNT_RESOLVE_HOST;
result = RESOLV_FAIL(for_proxy);
goto out;
}
@ -596,7 +614,7 @@ static CURLcode hostip_resolv_start(struct Curl_easy *data,
(void)addr;
if(!async) {
async = hostip_async_new(data, dns_queries, hostname, port,
transport, timeout_ms);
transport, for_proxy, timeout_ms);
if(!async) {
result = CURLE_OUT_OF_MEMORY;
goto out;
@ -617,7 +635,7 @@ static CURLcode hostip_resolv_start(struct Curl_easy *data,
goto out;
addr = Curl_sync_getaddrinfo(data, dns_queries, hostname, port, transport);
if(!addr)
result = CURLE_COULDNT_RESOLVE_HOST;
result = RESOLV_FAIL(for_proxy);
#endif
out:
@ -657,13 +675,14 @@ static CURLcode hostip_resolv(struct Curl_easy *data,
const char *hostname,
uint16_t port,
uint8_t transport,
bool for_proxy,
timediff_t timeout_ms,
bool allowDOH,
uint32_t *presolv_id,
struct Curl_dns_entry **pdns)
{
size_t hostname_len;
CURLcode result = CURLE_COULDNT_RESOLVE_HOST;
CURLcode result = RESOLV_FAIL(for_proxy);
bool cache_dns = FALSE;
(void)timeout_ms; /* not used in all ifdefs */
@ -690,7 +709,7 @@ static CURLcode hostip_resolv(struct Curl_easy *data,
if((CURL_DNSQ_IP(dns_queries) == CURL_DNSQ_AAAA) &&
getenv("CURL_DBG_RESOLV_FAIL_IPV6")) {
infof(data, "DEBUG fail ipv6 resolve");
result = Curl_resolver_error(data, NULL);
result = hostip_resolv_failed(data, hostname, for_proxy);
goto out;
}
#endif
@ -702,21 +721,20 @@ static CURLcode hostip_resolv(struct Curl_easy *data,
}
else if(result) {
infof(data, "Negative DNS entry");
result = Curl_resolver_error(data, NULL);
result = hostip_resolv_failed(data, hostname, for_proxy);
}
else {
/* No luck, we need to start resolving. */
cache_dns = TRUE;
result = hostip_resolv_start(data, dns_queries, hostname, port,
transport, timeout_ms, allowDOH,
transport, for_proxy, timeout_ms, allowDOH,
presolv_id, pdns);
}
out:
if(result && (result != CURLE_AGAIN)) {
Curl_dns_entry_unlink(data, pdns);
if((result == CURLE_COULDNT_RESOLVE_HOST) ||
(result == CURLE_COULDNT_RESOLVE_PROXY)) {
if(IS_RESOLV_FAIL(result)) {
if(cache_dns)
Curl_dnscache_add_negative(data, dns_queries, hostname, port);
failf(data, "Could not resolve: %s:%u", hostname, port);
@ -747,7 +765,7 @@ CURLcode Curl_resolv_blocking(struct Curl_easy *data,
*pdns = NULL;
/* We cannot do a blocking resolve using DoH currently */
result = hostip_resolv(data, dns_queries,
hostname, port, transport, 0, FALSE,
hostname, port, transport, FALSE, 0, FALSE,
&resolv_id, pdns);
switch(result) {
case CURLE_OK:
@ -786,6 +804,7 @@ static CURLcode resolv_alarm_timeout(struct Curl_easy *data,
const char *hostname,
uint16_t port,
uint8_t transport,
bool for_proxy,
timediff_t timeout_ms,
uint32_t *presolv_id,
struct Curl_dns_entry **entry)
@ -865,7 +884,7 @@ static CURLcode resolv_alarm_timeout(struct Curl_easy *data,
/* Perform the actual name resolution. This might be interrupted by an
* alarm if it takes too long. */
result = hostip_resolv(data, dns_queries, hostname, port, transport,
timeout_ms, FALSE, presolv_id, entry);
for_proxy, timeout_ms, FALSE, presolv_id, entry);
clean_up:
if(!prev_alarm)
@ -934,14 +953,14 @@ clean_up:
* Return codes:
* CURLE_OK = success, *pdns set to non-NULL
* CURLE_AGAIN = resolving in progress, *pdns == NULL
* CURLE_COULDNT_RESOLVE_HOST = error, *pdns == NULL
* CURLE_OPERATION_TIMEDOUT = timeout expired, *pdns == NULL
* any other CURLcode error, *pdns == NULL
*/
CURLcode Curl_resolv(struct Curl_easy *data,
uint8_t dns_queries,
const char *hostname,
uint16_t port,
uint8_t transport,
bool for_proxy,
timediff_t timeout_ms,
uint32_t *presolv_id,
struct Curl_dns_entry **pdns)
@ -963,7 +982,7 @@ CURLcode Curl_resolv(struct Curl_easy *data,
}
if(timeout_ms && !Curl_doh_wanted(data)) {
return resolv_alarm_timeout(data, dns_queries, hostname, port, transport,
timeout_ms, presolv_id, pdns);
for_proxy, timeout_ms, presolv_id, pdns);
}
#endif /* !USE_ALARM_TIMEOUT */
@ -973,7 +992,7 @@ CURLcode Curl_resolv(struct Curl_easy *data,
#endif
return hostip_resolv(data, dns_queries, hostname, port, transport,
timeout_ms, TRUE, presolv_id, pdns);
for_proxy, timeout_ms, TRUE, presolv_id, pdns);
}
#ifdef USE_CURL_ASYNC
@ -1010,7 +1029,7 @@ CURLcode Curl_resolv_take_result(struct Curl_easy *data, uint32_t resolv_id,
}
else if(result) {
Curl_async_shutdown(data, async);
return Curl_resolver_error(data, NULL);
return Curl_async_failed(data, async, NULL);
}
result = hostip_resolv_take_result(data, async, pdns);
@ -1021,8 +1040,7 @@ CURLcode Curl_resolv_take_result(struct Curl_easy *data, uint32_t resolv_id,
if(result)
Curl_dns_entry_unlink(data, pdns);
}
else if((result == CURLE_COULDNT_RESOLVE_HOST) ||
(result == CURLE_COULDNT_RESOLVE_PROXY)) {
else if(IS_RESOLV_FAIL(result)) {
Curl_dnscache_add_negative(data, async->dns_queries,
async->hostname, async->port);
failf(data, "Could not resolve: %s:%u", async->hostname, async->port);
@ -1085,31 +1103,6 @@ void Curl_resolv_destroy_all(struct Curl_easy *data)
#endif /* USE_CURL_ASYNC */
/*
* Curl_resolver_error() calls failf() with the appropriate message after a
* resolve error
*/
CURLcode Curl_resolver_error(struct Curl_easy *data, const char *detail)
{
struct connectdata *conn = data->conn;
const char *host_or_proxy = "host";
const char *name = conn->host.dispname;
CURLcode result = CURLE_COULDNT_RESOLVE_HOST;
#ifndef CURL_DISABLE_PROXY
if(conn->bits.proxy) {
host_or_proxy = "proxy";
result = CURLE_COULDNT_RESOLVE_PROXY;
name = conn->socks_proxy.host.name ? conn->socks_proxy.host.dispname :
conn->http_proxy.host.dispname;
}
#endif
failf(data, "Could not resolve %s: %s%s%s%s", host_or_proxy, name,
detail ? " (" : "", detail ? detail : "", detail ? ")" : "");
return result;
}
#ifdef USE_UNIX_SOCKETS
CURLcode Curl_resolv_unix(struct Curl_easy *data,
const char *unix_path,

View file

@ -100,6 +100,7 @@ CURLcode Curl_resolv(struct Curl_easy *data,
const char *hostname,
uint16_t port,
uint8_t transport,
bool for_proxy,
timediff_t timeout_ms,
uint32_t *presolv_id,
struct Curl_dns_entry **pdns);
@ -170,8 +171,6 @@ bool Curl_resolv_knows_https(struct Curl_easy *data, uint32_t resolv_id);
#define Curl_resolv_destroy(x, y) Curl_nop_stmt
#endif /* USE_CURL_ASYNC */
CURLcode Curl_resolver_error(struct Curl_easy *data, const char *detail);
#ifdef CURLRES_SYNCH
/*
* Curl_sync_getaddrinfo() is the non-async low-level name resolve API.

View file

@ -1989,15 +1989,13 @@ static CURLcode parse_proxy(struct Curl_easy *data,
goto error;
}
#ifdef USE_SSL
if(!Curl_ssl_supports(data, SSLSUPP_HTTPS_PROXY))
#endif
if(IS_HTTPS_PROXY(proxytype)) {
failf(data, "Unsupported proxy \'%s\', libcurl is built without the "
"HTTPS-proxy support.", proxy);
result = CURLE_NOT_BUILT_IN;
goto error;
}
if(IS_HTTPS_PROXY(proxytype) &&
!Curl_ssl_supports(data, SSLSUPP_HTTPS_PROXY)) {
failf(data, "Unsupported proxy \'%s\', libcurl is built without the "
"HTTPS-proxy support.", proxy);
result = CURLE_NOT_BUILT_IN;
goto error;
}
sockstype =
proxytype == CURLPROXY_SOCKS5_HOSTNAME ||

View file

@ -240,12 +240,6 @@ typedef enum {
GSS_AUTHSUCC
} curlnegotiate;
#ifdef CURL_DISABLE_PROXY
#define CONN_IS_PROXIED(x) 0
#else
#define CONN_IS_PROXIED(x) (x)->bits.proxy
#endif
/*
* Boolean values that concerns this connection.
*/