[curl issue 20897](https://github.com/curl/curl/issues/20897)
[curl issue 12303](https://github.com/curl/curl/issues/12303)
+## ECH not working through Proxy Tunnels
+
+[curl issue 22043](https://github.com/curl/curl/issues/22043)
+
# Email protocols
## IMAP `SEARCH ALL` truncated response
/* Return the resolv result from the first "resolv" filter, starting
* the given filter `cf` downwards.
*/
-static CURLcode cf_dns_result(struct Curl_cfilter *cf)
+static CURLcode cf_dns_result(struct Curl_cfilter *cf,
+ struct Curl_peer *peer)
{
for(; cf; cf = cf->next) {
if(cf->cft == &Curl_cft_dns) {
struct cf_dns_ctx *ctx = cf->ctx;
- if(ctx->dns || ctx->resolv_result)
- return ctx->resolv_result;
- return CURLE_AGAIN;
+ if(Curl_peer_same_destination(ctx->peer, peer)) {
+ if(ctx->dns || ctx->resolv_result)
+ return ctx->resolv_result;
+ return CURLE_AGAIN;
+ }
+ return CURLE_OK; /* ok, but no results */
}
}
return CURLE_FAILED_INIT;
}
-/* Return the result of the DNS resolution. Searches for a "resolv"
+/* Return the result of the DNS resolution for peer. Searches for a "resolv"
* filter from the top of the filter chain down. Returns
* - CURLE_AGAIN when not done yet
* - CURLE_OK when DNS was successfully resolved
* - CURLR_FAILED_INIT when no resolv filter was found
* - error returned by the DNS resolv
*/
-CURLcode Curl_conn_dns_result(struct connectdata *conn, int sockindex)
+CURLcode Curl_conn_dns_result(struct connectdata *conn,
+ int sockindex,
+ struct Curl_peer *peer)
{
- return cf_dns_result(conn->cfilter[sockindex]);
+ return cf_dns_result(conn->cfilter[sockindex], peer);
}
static const struct Curl_addrinfo *cf_dns_get_nth_ai(
*/
const struct Curl_addrinfo *Curl_cf_dns_get_ai(struct Curl_cfilter *cf,
struct Curl_easy *data,
+ struct Curl_peer *peer,
int ai_family,
unsigned int index)
{
for(; cf; cf = cf->next) {
if(cf->cft == &Curl_cft_dns) {
struct cf_dns_ctx *ctx = cf->ctx;
- if(ctx->resolv_result)
- return NULL;
- else if(ctx->dns)
- return cf_dns_get_nth_ai(cf, ctx->dns->addr, ai_family, index);
- else
- return Curl_resolv_get_ai(data, ctx->resolv_id, ai_family, index);
+ if(Curl_peer_same_destination(ctx->peer, peer)) {
+ if(ctx->resolv_result)
+ return NULL;
+ else if(ctx->dns)
+ return cf_dns_get_nth_ai(cf, ctx->dns->addr, ai_family, index);
+ else
+ return Curl_resolv_get_ai(data, ctx->resolv_id, ai_family, index);
+ }
}
}
return NULL;
* not done yet or if no address for the family exists, returns NULL.
*/
const struct Curl_addrinfo *Curl_conn_dns_get_ai(struct Curl_easy *data,
- int sockindex, int ai_family,
+ struct Curl_peer *peer,
+ int sockindex,
+ int ai_family,
unsigned int index)
{
struct connectdata *conn = data->conn;
- return Curl_cf_dns_get_ai(conn->cfilter[sockindex], data, ai_family, index);
+ return Curl_cf_dns_get_ai(conn->cfilter[sockindex], data, peer,
+ ai_family, index);
}
#ifdef USE_HTTPSRR
* connection. If the DNS resolving is not done yet or if there
* is no HTTPS-RR info, returns NULL.
*/
-const struct Curl_https_rrinfo *Curl_conn_dns_get_https(struct Curl_easy *data,
- int sockindex)
+const struct Curl_https_rrinfo *
+Curl_conn_dns_get_https(struct Curl_easy *data,
+ int sockindex,
+ struct Curl_peer *peer)
{
struct Curl_cfilter *cf = data->conn->cfilter[sockindex];
for(; cf; cf = cf->next) {
if(cf->cft == &Curl_cft_dns) {
struct cf_dns_ctx *ctx = cf->ctx;
- if(ctx->dns)
- return ctx->dns->hinfo;
- else
- return Curl_resolv_get_https(data, ctx->resolv_id);
+ if(Curl_peer_same_destination(ctx->peer, peer)) {
+ if(ctx->dns)
+ return ctx->dns->hinfo;
+ else
+ return Curl_resolv_get_https(data, ctx->resolv_id);
+ }
}
}
return NULL;
}
-bool Curl_conn_dns_resolved_https(struct Curl_easy *data, int sockindex)
+bool Curl_conn_dns_resolved_https(struct Curl_easy *data,
+ int sockindex,
+ struct Curl_peer *peer)
{
struct Curl_cfilter *cf = data->conn->cfilter[sockindex];
for(; cf; cf = cf->next) {
if(cf->cft == &Curl_cft_dns) {
struct cf_dns_ctx *ctx = cf->ctx;
- if(ctx->dns)
- return TRUE;
- else
- return Curl_resolv_knows_https(data, ctx->resolv_id);
+ if(Curl_peer_same_destination(ctx->peer, peer)) {
+ if(ctx->dns)
+ return TRUE;
+ else
+ return Curl_resolv_knows_https(data, ctx->resolv_id);
+ }
}
}
- return FALSE;
+ return TRUE;
}
#endif /* USE_HTTPSRR */
uint8_t transport,
bool complete_resolve);
-CURLcode Curl_conn_dns_result(struct connectdata *conn, int sockindex);
+CURLcode Curl_conn_dns_result(struct connectdata *conn,
+ int sockindex,
+ struct Curl_peer *peer);
const struct Curl_addrinfo *Curl_conn_dns_get_ai(struct Curl_easy *data,
+ struct Curl_peer *peer,
int sockindex,
int ai_family,
unsigned int index);
const struct Curl_addrinfo *Curl_cf_dns_get_ai(struct Curl_cfilter *cf,
struct Curl_easy *data,
+ struct Curl_peer *peer,
int ai_family,
unsigned int index);
#ifdef USE_HTTPSRR
-const struct Curl_https_rrinfo *Curl_conn_dns_get_https(struct Curl_easy *data,
- int sockindex);
-bool Curl_conn_dns_resolved_https(struct Curl_easy *data, int sockindex);
+const struct Curl_https_rrinfo *
+Curl_conn_dns_get_https(struct Curl_easy *data,
+ int sockindex,
+ struct Curl_peer *peer);
+bool Curl_conn_dns_resolved_https(struct Curl_easy *data,
+ int sockindex,
+ struct Curl_peer *peer);
#else
-#define Curl_conn_dns_get_https(a, b) NULL
-#define Curl_conn_dns_resolved_https(a, b) TRUE
+#define Curl_conn_dns_get_https(a, b, c) NULL
+#define Curl_conn_dns_resolved_https(a, b, c) TRUE
#endif
extern struct Curl_cftype Curl_cft_dns;
size_t i;
/* Do we have HTTPS-RR information? */
- rr = Curl_conn_dns_get_https(data, cf->sockindex);
+ rr = Curl_conn_dns_get_https(
+ data, cf->sockindex, Curl_conn_get_destination(cf->conn, cf->sockindex));
/* We do not support `rr->no_def_alpn`. */
if(Curl_httpsrr_applicable(data, rr) && !rr->no_def_alpn) {
*done = FALSE;
if(!ctx->httpsrr_resolved) {
- ctx->httpsrr_resolved = Curl_conn_dns_resolved_https(data, cf->sockindex);
+ ctx->httpsrr_resolved = Curl_conn_dns_resolved_https(
+ data, cf->sockindex, Curl_conn_get_destination(cf->conn, cf->sockindex));
#ifdef DEBUGBUILD
if(!ctx->httpsrr_resolved && getenv("CURL_DBG_AWAIT_HTTPSRR")) {
CURL_TRC_CF(data, cf, "awaiting HTTPS-RR");
struct cf_ai_iter {
struct Curl_cfilter *cf;
+ struct Curl_peer *peer;
int ai_family;
unsigned int n;
};
static void cf_ai_iter_init(struct cf_ai_iter *iter,
struct Curl_cfilter *cf,
+ struct Curl_peer *peer,
int ai_family)
{
iter->cf = cf;
+ iter->peer = peer; /* not linked, ctx->ballers owns and has same lifetime */
iter->ai_family = ai_family;
iter->n = 0;
}
if(!iter->cf)
return NULL;
- addr = Curl_conn_dns_get_ai(data, iter->cf->sockindex,
+ addr = Curl_conn_dns_get_ai(data, iter->peer, iter->cf->sockindex,
iter->ai_family, iter->n);
if(addr)
iter->n++;
struct Curl_easy *data)
{
return (iter->cf &&
- !!Curl_conn_dns_get_ai(data, iter->cf->sockindex,
+ !!Curl_conn_dns_get_ai(data, iter->peer, iter->cf->sockindex,
iter->ai_family, iter->n));
}
if(ctx->ballers.transport_peer == TRNSPRT_UNIX) {
#ifdef USE_UNIX_SOCKETS
- cf_ai_iter_init(&ctx->ballers.addr_iter, cf, AF_UNIX);
+ cf_ai_iter_init(&ctx->ballers.addr_iter, cf, ctx->ballers.peer, AF_UNIX);
#else
return CURLE_UNSUPPORTED_PROTOCOL;
#endif
}
else { /* TCP/UDP/QUIC */
#ifdef USE_IPV6
- cf_ai_iter_init(&ctx->ballers.ipv6_iter, cf, AF_INET6);
+ cf_ai_iter_init(&ctx->ballers.ipv6_iter, cf, ctx->ballers.peer, AF_INET6);
#endif
- cf_ai_iter_init(&ctx->ballers.addr_iter, cf, AF_INET);
+ cf_ai_iter_init(&ctx->ballers.addr_iter, cf, ctx->ballers.peer, AF_INET);
}
CURL_TRC_CF(data, cf, "init ip ballers for transport %u",
*done = FALSE;
if(!ctx->dns_resolved) {
- result = Curl_conn_dns_result(cf->conn, cf->sockindex);
+ result = Curl_conn_dns_result(cf->conn, cf->sockindex, ctx->ballers.peer);
if(!result)
ctx->dns_resolved = TRUE;
else if(result == CURLE_AGAIN) {
else if(!dns_done)
return CURLPX_OK;
- ai = Curl_cf_dns_get_ai(cf->next, data, AF_INET, 0);
+ ai = Curl_cf_dns_get_ai(cf->next, data, sx->dest, AF_INET, 0);
if(ai) {
struct sockaddr_in *saddr_in;
char ipbuf[64];
#ifdef USE_IPV6
if(data->set.ipver != CURL_IPRESOLVE_V4)
- ai = Curl_cf_dns_get_ai(cf->next, data, AF_INET6, 0);
+ ai = Curl_cf_dns_get_ai(cf->next, data, sx->dest, AF_INET6, 0);
#endif
if(!ai)
- ai = Curl_cf_dns_get_ai(cf->next, data, AF_INET, 0);
+ ai = Curl_cf_dns_get_ai(cf->next, data, sx->dest, AF_INET, 0);
if(!ai) {
failf(data, "Failed to resolve \"%s\" for SOCKS5 connect.",
*done = FALSE;
if(cf_ngtcp2_need_httpsrr(data) &&
- !Curl_conn_dns_resolved_https(data, cf->sockindex)) {
+ !Curl_conn_dns_resolved_https(data, cf->sockindex, ctx->ssl_peer.peer)) {
CURL_TRC_CF(data, cf, "need HTTPS-RR, delaying connect");
return CURLE_OK;
}
*done = FALSE;
if(Curl_ossl_need_httpsrr(data) &&
- !Curl_conn_dns_resolved_https(data, cf->sockindex)) {
+ !Curl_conn_dns_resolved_https(data, cf->sockindex, ctx->ssl_peer.peer)) {
CURL_TRC_CF(data, cf, "need HTTPS-RR, delaying connect");
return CURLE_OK;
}
}
else {
const struct Curl_https_rrinfo *rinfo =
- Curl_conn_dns_get_https(data, cf->sockindex);
+ Curl_conn_dns_get_https(data, cf->sockindex, peer->peer);
if(rinfo && rinfo->echconfiglist) {
const unsigned char *ecl = rinfo->echconfiglist;
if(ssl_connect_1 == connssl->connecting_state) {
if(Curl_ossl_need_httpsrr(data) &&
- !Curl_conn_dns_resolved_https(data, cf->sockindex)) {
+ !Curl_conn_dns_resolved_https(data, cf->sockindex,
+ connssl->peer.peer)) {
CURL_TRC_CF(data, cf, "need HTTPS-RR, delaying connect");
return CURLE_OK;
}
}
}
else {
+ const struct ssl_connect_data *connssl = cf->ctx;
const struct Curl_https_rrinfo *rinfo =
- Curl_conn_dns_get_https(data, cf->sockindex);
+ Curl_conn_dns_get_https(data, cf->sockindex, connssl->peer.peer);
if(!rinfo || !rinfo->echconfiglist) {
failf(data, "rustls: ECH requested but no ECHConfig available");
/* if we do ECH and need the HTTPS-RR information for it,
* we delay the connect until it arrives or DNS resolve fails. */
if(cr_ech_need_httpsrr(data) &&
- !Curl_conn_dns_resolved_https(data, cf->sockindex)) {
+ !Curl_conn_dns_resolved_https(data, cf->sockindex,
+ connssl->peer.peer)) {
CURL_TRC_CF(data, cf, "need HTTPS-RR for ECH, delaying connect");
return CURLE_OK;
}
#ifdef HAVE_WOLFSSL_CTX_GENERATEECHCONFIG
static CURLcode wssl_init_ech(struct wssl_ctx *wctx,
struct Curl_cfilter *cf,
- struct Curl_easy *data)
+ struct Curl_easy *data,
+ struct ssl_peer *peer)
{
int trying_ech_now = 0;
}
else {
const struct Curl_https_rrinfo *rinfo =
- Curl_conn_dns_get_https(data, cf->sockindex);
+ Curl_conn_dns_get_https(data, cf->sockindex, peer->peer);
if(rinfo && rinfo->echconfiglist) {
const unsigned char *ecl = rinfo->echconfiglist;
#ifdef HAVE_WOLFSSL_CTX_GENERATEECHCONFIG
if(CURLECH_ENABLED(data)) {
- result = wssl_init_ech(wctx, cf, data);
+ result = wssl_init_ech(wctx, cf, data, peer);
if(result)
goto out;
}
/* if we do ECH and need the HTTPS-RR information for it,
* we delay the connect until it arrives or DNS resolve fails. */
if(Curl_wssl_need_httpsrr(data) &&
- !Curl_conn_dns_resolved_https(data, cf->sockindex)) {
+ !Curl_conn_dns_resolved_https(data, cf->sockindex,
+ connssl->peer.peer)) {
CURL_TRC_CF(data, cf, "need HTTPS-RR for ECH, delaying connect");
return CURLE_OK;
}