From 63381421f5ae632a0916cbbeabaa1bd07017d0ae Mon Sep 17 00:00:00 2001 From: Stefan Eissing Date: Mon, 19 May 2025 14:38:22 +0200 Subject: [PATCH] connection: eliminate member `remote_addr` Used to be a pointer set (and cleared) by the socket connection filters to a struct in their contexts. Instead, add a filter query method to obtain the pointer when needed. Closes #17385 --- lib/cf-socket.c | 11 ++++++----- lib/cfilters.c | 18 ++++++++++++++++++ lib/cfilters.h | 7 +++++++ lib/ftp.c | 10 ++++++++-- lib/krb5.c | 10 ++++++---- lib/tftp.c | 20 ++++++++++++++++---- lib/urldata.h | 4 ---- lib/vquic/curl_msh3.c | 2 -- 8 files changed, 61 insertions(+), 21 deletions(-) diff --git a/lib/cf-socket.c b/lib/cf-socket.c index c16c914a7b..6bc0976e96 100644 --- a/lib/cf-socket.c +++ b/lib/cf-socket.c @@ -995,8 +995,6 @@ static void cf_socket_close(struct Curl_cfilter *cf, struct Curl_easy *data) cf->conn->sock[cf->sockindex] = CURL_SOCKET_BAD; socket_close(data, cf->conn, !ctx->accepted, ctx->sock); ctx->sock = CURL_SOCKET_BAD; - if(ctx->active && cf->sockindex == FIRSTSOCKET) - cf->conn->remote_addr = NULL; ctx->active = FALSE; memset(&ctx->started_at, 0, sizeof(ctx->started_at)); memset(&ctx->connected_at, 0, sizeof(ctx->connected_at)); @@ -1494,8 +1492,7 @@ static CURLcode cf_socket_send(struct Curl_cfilter *cf, struct Curl_easy *data, #if defined(MSG_FASTOPEN) && !defined(TCP_FASTOPEN_CONNECT) /* Linux */ if(cf->conn->bits.tcp_fastopen) { nwritten = sendto(ctx->sock, buf, len, MSG_FASTOPEN, - &cf->conn->remote_addr->curl_sa_addr, - cf->conn->remote_addr->addrlen); + &ctx->addr.curl_sa_addr, ctx->addr.addrlen); cf->conn->bits.tcp_fastopen = FALSE; } else @@ -1629,7 +1626,6 @@ static void cf_socket_active(struct Curl_cfilter *cf, struct Curl_easy *data) set_local_ip(cf, data); if(cf->sockindex == FIRSTSOCKET) { cf->conn->primary = ctx->ip; - cf->conn->remote_addr = &ctx->addr; #ifdef USE_IPV6 cf->conn->bits.ipv6 = (ctx->addr.family == AF_INET6); #endif @@ -1711,6 +1707,11 @@ static CURLcode cf_socket_query(struct Curl_cfilter *cf, DEBUGASSERT(pres2); *((curl_socket_t *)pres2) = ctx->sock; return CURLE_OK; + case CF_QUERY_REMOTE_ADDR: + DEBUGASSERT(pres2); + *((const struct Curl_sockaddr_ex **)pres2) = cf->connected ? + &ctx->addr : NULL; + return CURLE_OK; case CF_QUERY_CONNECT_REPLY_MS: if(ctx->got_first_byte) { timediff_t ms = curlx_timediff(ctx->first_byte_at, ctx->started_at); diff --git a/lib/cfilters.c b/lib/cfilters.c index 69cbb68e27..ffe34765ee 100644 --- a/lib/cfilters.c +++ b/lib/cfilters.c @@ -730,6 +730,17 @@ curl_socket_t Curl_conn_cf_get_socket(struct Curl_cfilter *cf, return CURL_SOCKET_BAD; } +static const struct Curl_sockaddr_ex * +cf_get_remote_addr(struct Curl_cfilter *cf, struct Curl_easy *data) +{ + const struct Curl_sockaddr_ex *remote_addr = NULL; + if(cf && + !cf->cft->query(cf, data, CF_QUERY_REMOTE_ADDR, NULL, + CURL_UNCONST(&remote_addr))) + return remote_addr; + return NULL; +} + CURLcode Curl_conn_cf_get_ip_info(struct Curl_cfilter *cf, struct Curl_easy *data, int *is_ipv6, struct ip_quadruple *ipquad) @@ -752,6 +763,13 @@ curl_socket_t Curl_conn_get_socket(struct Curl_easy *data, int sockindex) return data->conn ? data->conn->sock[sockindex] : CURL_SOCKET_BAD; } +const struct Curl_sockaddr_ex * +Curl_conn_get_remote_addr(struct Curl_easy *data, int sockindex) +{ + struct Curl_cfilter *cf = data->conn ? data->conn->cfilter[sockindex] : NULL; + return cf ? cf_get_remote_addr(cf, data) : NULL; +} + void Curl_conn_forget_socket(struct Curl_easy *data, int sockindex) { if(data->conn) { diff --git a/lib/cfilters.h b/lib/cfilters.h index edcbb6f375..6826338109 100644 --- a/lib/cfilters.h +++ b/lib/cfilters.h @@ -177,6 +177,9 @@ typedef CURLcode Curl_cft_cntrl(struct Curl_cfilter *cf, #define CF_QUERY_NEED_FLUSH 7 /* TRUE/FALSE - */ #define CF_QUERY_IP_INFO 8 /* TRUE/FALSE struct ip_quadruple */ #define CF_QUERY_HTTP_VERSION 9 /* number (10/11/20/30) - */ +/* pass in a `const struct Curl_sockaddr_ex **` as `pres2`. Gets set + * to NULL when not connected. */ +#define CF_QUERY_REMOTE_ADDR 10 /* - `Curl_sockaddr_ex *` */ /** * Query the cfilter for properties. Filters ignorant of a query will @@ -444,6 +447,10 @@ CURLcode Curl_conn_flush(struct Curl_easy *data, int sockindex); */ curl_socket_t Curl_conn_get_socket(struct Curl_easy *data, int sockindex); +/* Return a pointer to the connected socket address or NULL. */ +const struct Curl_sockaddr_ex * +Curl_conn_get_remote_addr(struct Curl_easy *data, int sockindex); + /** * Tell filters to forget about the socket at sockindex. */ diff --git a/lib/ftp.c b/lib/ftp.c index 413505e6f2..583e33a967 100644 --- a/lib/ftp.c +++ b/lib/ftp.c @@ -983,6 +983,12 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data, port_min = port_max = 0; if(addrlen) { + const struct Curl_sockaddr_ex *remote_addr = + Curl_conn_get_remote_addr(data, FIRSTSOCKET); + + DEBUGASSERT(remote_addr); + if(!remote_addr) + goto out; DEBUGASSERT(addr); if(addrlen >= sizeof(ipstr)) goto out; @@ -990,9 +996,9 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data, ipstr[addrlen] = 0; /* attempt to get the address of the given interface name */ - switch(Curl_if2ip(conn->remote_addr->family, + switch(Curl_if2ip(remote_addr->family, #ifdef USE_IPV6 - Curl_ipv6_scope(&conn->remote_addr->curl_sa_addr), + Curl_ipv6_scope(&remote_addr->curl_sa_addr), conn->scope_id, #endif ipstr, hbuf, sizeof(hbuf))) { diff --git a/lib/krb5.c b/lib/krb5.c index 9654a4399f..08f5ba4d61 100644 --- a/lib/krb5.c +++ b/lib/krb5.c @@ -215,12 +215,14 @@ krb5_auth(void *app_data, struct Curl_easy *data, struct connectdata *conn) gss_ctx_id_t *context = app_data; struct gss_channel_bindings_struct chan; size_t base64_sz = 0; - struct sockaddr_in *remote_addr = - (struct sockaddr_in *)CURL_UNCONST(&conn->remote_addr->curl_sa_addr); + const struct Curl_sockaddr_ex *remote_addr = + Curl_conn_get_remote_addr(data, FIRSTSOCKET); + struct sockaddr_in *remote_in_addr = remote_addr ? + (struct sockaddr_in *)CURL_UNCONST(&remote_addr->curl_sa_addr) : NULL; char *stringp; struct ftp_conn *ftpc = Curl_conn_meta_get(conn, CURL_META_FTP_CONN); - if(!ftpc) + if(!ftpc || !remote_in_addr) return -2; if(getsockname(conn->sock[FIRSTSOCKET], @@ -232,7 +234,7 @@ krb5_auth(void *app_data, struct Curl_easy *data, struct connectdata *conn) chan.initiator_address.value = &conn->local_addr.sin_addr.s_addr; chan.acceptor_addrtype = GSS_C_AF_INET; chan.acceptor_address.length = l - 4; - chan.acceptor_address.value = &remote_addr->sin_addr.s_addr; + chan.acceptor_address.value = &remote_in_addr->sin_addr.s_addr; chan.application_data.length = 0; chan.application_data.value = NULL; diff --git a/lib/tftp.c b/lib/tftp.c index e9f4e68ecc..5ed7258d38 100644 --- a/lib/tftp.c +++ b/lib/tftp.c @@ -48,6 +48,7 @@ #include "urldata.h" #include +#include "cfilters.h" #include "cf-socket.h" #include "transfer.h" #include "sendf.h" @@ -429,6 +430,7 @@ static CURLcode tftp_send_first(struct tftp_conn *state, const char *mode = "octet"; char *filename; struct Curl_easy *data = state->data; + const struct Curl_sockaddr_ex *remote_addr = NULL; CURLcode result = CURLE_OK; /* Set ASCII mode if -B flag was used */ @@ -525,10 +527,14 @@ static CURLcode tftp_send_first(struct tftp_conn *state, #else #define CURL_SENDTO_ARG5(x) (x) #endif + remote_addr = Curl_conn_get_remote_addr(data, FIRSTSOCKET); + if(!remote_addr) + return CURLE_FAILED_INIT; + senddata = sendto(state->sockfd, (void *)state->spacket.data, (SEND_TYPE_ARG3)sbytes, 0, - CURL_SENDTO_ARG5(&data->conn->remote_addr->curl_sa_addr), - (curl_socklen_t)data->conn->remote_addr->addrlen); + CURL_SENDTO_ARG5(&remote_addr->curl_sa_addr), + (curl_socklen_t)remote_addr->addrlen); if(senddata != (ssize_t)sbytes) { char buffer[STRERROR_LEN]; failf(data, "%s", Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); @@ -955,6 +961,7 @@ static CURLcode tftp_connect(struct Curl_easy *data, bool *done) int blksize; int need_blksize; struct connectdata *conn = data->conn; + const struct Curl_sockaddr_ex *remote_addr = NULL; blksize = TFTP_BLKSIZE_DEFAULT; @@ -998,8 +1005,13 @@ static CURLcode tftp_connect(struct Curl_easy *data, bool *done) state->blksize = TFTP_BLKSIZE_DEFAULT; /* Unless updated by OACK response */ state->requested_blksize = blksize; + remote_addr = Curl_conn_get_remote_addr(data, FIRSTSOCKET); + DEBUGASSERT(remote_addr); + if(!remote_addr) + return CURLE_FAILED_INIT; + ((struct sockaddr *)&state->local_addr)->sa_family = - (CURL_SA_FAMILY_T)(conn->remote_addr->family); + (CURL_SA_FAMILY_T)(remote_addr->family); tftp_set_timeouts(state); @@ -1018,7 +1030,7 @@ static CURLcode tftp_connect(struct Curl_easy *data, bool *done) * IPv4 and IPv6... */ int rc = bind(state->sockfd, (struct sockaddr *)&state->local_addr, - (curl_socklen_t)conn->remote_addr->addrlen); + (curl_socklen_t)remote_addr->addrlen); if(rc) { char buffer[STRERROR_LEN]; failf(data, "bind() failed; %s", diff --git a/lib/urldata.h b/lib/urldata.h index b8dbc3ca3c..20c8adf281 100644 --- a/lib/urldata.h +++ b/lib/urldata.h @@ -665,10 +665,6 @@ struct connectdata { * the connection is cleaned up (see Curl_hash_add2()).*/ struct Curl_hash meta_hash; - /* 'remote_addr' is the particular IP we connected to. it is owned, set - * and NULLed by the connected socket filter (if there is one). */ - const struct Curl_sockaddr_ex *remote_addr; - struct hostname host; char *hostname_resolve; /* hostname to resolve to address, allocated */ char *secondaryhostname; /* secondary socket hostname (ftp) */ diff --git a/lib/vquic/curl_msh3.c b/lib/vquic/curl_msh3.c index 68df32236b..947ce4fbeb 100644 --- a/lib/vquic/curl_msh3.c +++ b/lib/vquic/curl_msh3.c @@ -955,8 +955,6 @@ static void cf_msh3_close(struct Curl_cfilter *cf, struct Curl_easy *data) "conn->sock[], discarding", (int)ctx->sock[SP_LOCAL]); ctx->sock[SP_LOCAL] = CURL_SOCKET_BAD; } - if(cf->sockindex == FIRSTSOCKET) - cf->conn->remote_addr = NULL; } if(ctx->sock[SP_LOCAL] != CURL_SOCKET_BAD) { sclose(ctx->sock[SP_LOCAL]); -- 2.47.2