cf-socket: keep sockaddr local in the socket filters

- copy `struct Curl_addrinfo` on filter setup into context
- remove `struct Curl_addrinfoi *` with `struct Curl_sockaddr_ex *` in
  connectdata that is set and NULLed by the socket filter
- this means we have no reference to the resolver info in connectdata or
  its filters
- trigger the CF_CTRL_CONN_INFO_UPDATE event when the complete filter
  chain reaches connected status
- update easy handle connection information on CF_CTRL_DATA_SETUP event.

Closes #10213
This commit is contained in:
Stefan Eissing 2023-01-03 13:13:37 +01:00 committed by Daniel Stenberg
parent 436d63fbb1
commit 6a8d7ef981
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2
8 changed files with 174 additions and 140 deletions

View File

@ -203,28 +203,10 @@ tcpkeepalive(struct Curl_easy *data,
} }
} }
/* static void assign_sockaddr_ex(struct Curl_sockaddr_ex *dest,
* Create a socket based on info from 'conn' and 'ai'. const struct Curl_addrinfo *ai,
* int transport)
* 'addr' should be a pointer to the correct struct to get data back, or NULL.
* 'sockfd' must be a pointer to a socket descriptor.
*
* If the open socket callback is set, used that!
*
*/
CURLcode Curl_socket_open(struct Curl_easy *data,
const struct Curl_addrinfo *ai,
struct Curl_sockaddr_ex *addr,
int transport,
curl_socket_t *sockfd)
{ {
struct connectdata *conn = data->conn;
struct Curl_sockaddr_ex dummy;
if(!addr)
/* if the caller doesn't want info back, use a local temp copy */
addr = &dummy;
/* /*
* The Curl_sockaddr_ex structure is basically libcurl's external API * The Curl_sockaddr_ex structure is basically libcurl's external API
* curl_sockaddr structure with enough space available to directly hold * curl_sockaddr structure with enough space available to directly hold
@ -232,28 +214,34 @@ CURLcode Curl_socket_open(struct Curl_easy *data,
* will be used to pass / receive data to/from the fopensocket callback * will be used to pass / receive data to/from the fopensocket callback
* if this has been set, before that, it is initialized from parameters. * if this has been set, before that, it is initialized from parameters.
*/ */
dest->family = ai->ai_family;
addr->family = ai->ai_family;
switch(transport) { switch(transport) {
case TRNSPRT_TCP: case TRNSPRT_TCP:
addr->socktype = SOCK_STREAM; dest->socktype = SOCK_STREAM;
addr->protocol = IPPROTO_TCP; dest->protocol = IPPROTO_TCP;
break; break;
case TRNSPRT_UNIX: case TRNSPRT_UNIX:
addr->socktype = SOCK_STREAM; dest->socktype = SOCK_STREAM;
addr->protocol = IPPROTO_IP; dest->protocol = IPPROTO_IP;
break; break;
default: /* UDP and QUIC */ default: /* UDP and QUIC */
addr->socktype = SOCK_DGRAM; dest->socktype = SOCK_DGRAM;
addr->protocol = IPPROTO_UDP; dest->protocol = IPPROTO_UDP;
break; break;
} }
addr->addrlen = ai->ai_addrlen; dest->addrlen = ai->ai_addrlen;
if(addr->addrlen > sizeof(struct Curl_sockaddr_storage)) if(dest->addrlen > sizeof(struct Curl_sockaddr_storage))
addr->addrlen = sizeof(struct Curl_sockaddr_storage); dest->addrlen = sizeof(struct Curl_sockaddr_storage);
memcpy(&addr->sa_addr, ai->ai_addr, addr->addrlen); memcpy(&dest->sa_addr, ai->ai_addr, dest->addrlen);
}
static CURLcode socket_open(struct Curl_easy *data,
struct Curl_sockaddr_ex *addr,
curl_socket_t *sockfd)
{
DEBUGASSERT(data);
DEBUGASSERT(data->conn);
if(data->set.fopensocket) { if(data->set.fopensocket) {
/* /*
* If the opensocket callback is set, all the destination address * If the opensocket callback is set, all the destination address
@ -278,17 +266,40 @@ CURLcode Curl_socket_open(struct Curl_easy *data,
/* no socket, no connection */ /* no socket, no connection */
return CURLE_COULDNT_CONNECT; return CURLE_COULDNT_CONNECT;
(void)conn;
#if defined(ENABLE_IPV6) && defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID) #if defined(ENABLE_IPV6) && defined(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID)
if(conn->scope_id && (addr->family == AF_INET6)) { if(data->conn->scope_id && (addr->family == AF_INET6)) {
struct sockaddr_in6 * const sa6 = (void *)&addr->sa_addr; struct sockaddr_in6 * const sa6 = (void *)&addr->sa_addr;
sa6->sin6_scope_id = conn->scope_id; sa6->sin6_scope_id = data->conn->scope_id;
} }
#endif #endif
return CURLE_OK; return CURLE_OK;
} }
/*
* Create a socket based on info from 'conn' and 'ai'.
*
* 'addr' should be a pointer to the correct struct to get data back, or NULL.
* 'sockfd' must be a pointer to a socket descriptor.
*
* If the open socket callback is set, used that!
*
*/
CURLcode Curl_socket_open(struct Curl_easy *data,
const struct Curl_addrinfo *ai,
struct Curl_sockaddr_ex *addr,
int transport,
curl_socket_t *sockfd)
{
struct Curl_sockaddr_ex dummy;
if(!addr)
/* if the caller doesn't want info back, use a local temp copy */
addr = &dummy;
assign_sockaddr_ex(addr, ai, transport);
return socket_open(data, addr, sockfd);
}
static int socket_close(struct Curl_easy *data, struct connectdata *conn, static int socket_close(struct Curl_easy *data, struct connectdata *conn,
int use_callback, curl_socket_t sock) int use_callback, curl_socket_t sock)
{ {
@ -744,11 +755,12 @@ CURLcode Curl_socket_connect_result(struct Curl_easy *data,
struct cf_socket_ctx { struct cf_socket_ctx {
int transport; int transport;
const struct Curl_addrinfo *ai; struct Curl_sockaddr_ex addr; /* address to connect to */
curl_socket_t sock; /* current attempt socket */ curl_socket_t sock; /* current attempt socket */
struct Curl_sockaddr_ex r_addr; /* remote address sock is trying */
char r_ip[MAX_IPADR_LEN]; /* remote IP as string */ char r_ip[MAX_IPADR_LEN]; /* remote IP as string */
int r_port; /* remote port number */ int r_port; /* remote port number */
char l_ip[MAX_IPADR_LEN]; /* local IP as string */
int l_port; /* local port number */
int error; /* errno of last failure or 0 */ int error; /* errno of last failure or 0 */
BIT(accepted); /* socket was accepted, not connected */ BIT(accepted); /* socket was accepted, not connected */
BIT(active); BIT(active);
@ -785,6 +797,8 @@ static void cf_socket_close(struct Curl_cfilter *cf, struct Curl_easy *data)
ctx->active = FALSE; ctx->active = FALSE;
} }
if(cf->sockindex == FIRSTSOCKET)
cf->conn->remote_addr = NULL;
cf->connected = FALSE; cf->connected = FALSE;
} }
@ -797,6 +811,56 @@ static void cf_socket_destroy(struct Curl_cfilter *cf, struct Curl_easy *data)
cf->ctx = NULL; cf->ctx = NULL;
} }
static CURLcode set_local_ip(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
struct cf_socket_ctx *ctx = cf->ctx;
#ifdef HAVE_GETSOCKNAME
char buffer[STRERROR_LEN];
struct Curl_sockaddr_storage ssloc;
curl_socklen_t slen = sizeof(struct Curl_sockaddr_storage);
memset(&ssloc, 0, sizeof(ssloc));
if(getsockname(ctx->sock, (struct sockaddr*) &ssloc, &slen)) {
int error = SOCKERRNO;
failf(data, "getsockname() failed with errno %d: %s",
error, Curl_strerror(error, buffer, sizeof(buffer)));
return CURLE_FAILED_INIT;
}
if(!Curl_addr2string((struct sockaddr*)&ssloc, slen,
ctx->l_ip, &ctx->l_port)) {
failf(data, "ssloc inet_ntop() failed with errno %d: %s",
errno, Curl_strerror(errno, buffer, sizeof(buffer)));
return CURLE_FAILED_INIT;
}
#else
(void)data;
ctx->l_ip[0] = 0;
ctx->l_port = -1;
#endif
return CURLE_OK;
}
static CURLcode set_remote_ip(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
struct cf_socket_ctx *ctx = cf->ctx;
/* store remote address and port used in this connection attempt */
if(!Curl_addr2string(&ctx->addr.sa_addr, ctx->addr.addrlen,
ctx->r_ip, &ctx->r_port)) {
char buffer[STRERROR_LEN];
ctx->error = errno;
/* malformed address or bug in inet_ntop, try next address */
failf(data, "sa_addr inet_ntop() failed with errno %d: %s",
errno, Curl_strerror(errno, buffer, sizeof(buffer)));
return CURLE_FAILED_INIT;
}
return CURLE_OK;
}
static CURLcode cf_socket_open(struct Curl_cfilter *cf, static CURLcode cf_socket_open(struct Curl_cfilter *cf,
struct Curl_easy *data) struct Curl_easy *data)
{ {
@ -809,25 +873,16 @@ static CURLcode cf_socket_open(struct Curl_cfilter *cf,
(void)data; (void)data;
ctx->sock = CURL_SOCKET_BAD; ctx->sock = CURL_SOCKET_BAD;
result = Curl_socket_open(data, ctx->ai, &ctx->r_addr, result = socket_open(data, &ctx->addr, &ctx->sock);
ctx->transport, &ctx->sock);
if(result) if(result)
goto out; goto out;
/* store remote address and port used in this connection attempt */ result = set_remote_ip(cf, data);
if(!Curl_addr2string(&ctx->r_addr.sa_addr, ctx->r_addr.addrlen, if(result)
ctx->r_ip, &ctx->r_port)) {
char buffer[STRERROR_LEN];
ctx->error = errno;
/* malformed address or bug in inet_ntop, try next address */
failf(data, "sa_addr inet_ntop() failed with errno %d: %s",
errno, Curl_strerror(errno, buffer, sizeof(buffer)));
result = CURLE_FAILED_INIT;
goto out; goto out;
}
#ifdef ENABLE_IPV6 #ifdef ENABLE_IPV6
if(ctx->r_addr.family == AF_INET6) if(ctx->addr.family == AF_INET6)
ipmsg = " Trying [%s]:%d..."; ipmsg = " Trying [%s]:%d...";
else else
#endif #endif
@ -835,12 +890,12 @@ static CURLcode cf_socket_open(struct Curl_cfilter *cf,
infof(data, ipmsg, ctx->r_ip, ctx->r_port); infof(data, ipmsg, ctx->r_ip, ctx->r_port);
#ifdef ENABLE_IPV6 #ifdef ENABLE_IPV6
is_tcp = (ctx->r_addr.family == AF_INET is_tcp = (ctx->addr.family == AF_INET
|| ctx->r_addr.family == AF_INET6) && || ctx->addr.family == AF_INET6) &&
ctx->r_addr.socktype == SOCK_STREAM; ctx->addr.socktype == SOCK_STREAM;
#else #else
is_tcp = (ctx->r_addr.family == AF_INET) && is_tcp = (ctx->addr.family == AF_INET) &&
ctx->r_addr.socktype == SOCK_STREAM; ctx->addr.socktype == SOCK_STREAM;
#endif #endif
if(is_tcp && data->set.tcp_nodelay) if(is_tcp && data->set.tcp_nodelay)
tcpnodelay(data, ctx->sock); tcpnodelay(data, ctx->sock);
@ -869,13 +924,13 @@ static CURLcode cf_socket_open(struct Curl_cfilter *cf,
} }
/* possibly bind the local end to an IP, interface or port */ /* possibly bind the local end to an IP, interface or port */
if(ctx->r_addr.family == AF_INET if(ctx->addr.family == AF_INET
#ifdef ENABLE_IPV6 #ifdef ENABLE_IPV6
|| ctx->r_addr.family == AF_INET6 || ctx->addr.family == AF_INET6
#endif #endif
) { ) {
result = bindlocal(data, cf->conn, ctx->sock, ctx->r_addr.family, result = bindlocal(data, cf->conn, ctx->sock, ctx->addr.family,
Curl_ipv6_scope(&ctx->r_addr.sa_addr)); Curl_ipv6_scope(&ctx->addr.sa_addr));
if(result) { if(result) {
if(result == CURLE_UNSUPPORTED_PROTOCOL) { if(result == CURLE_UNSUPPORTED_PROTOCOL) {
/* The address family is not supported on this interface. /* The address family is not supported on this interface.
@ -897,6 +952,7 @@ out:
} }
} }
else if(isconnected) { else if(isconnected) {
set_local_ip(cf, data);
cf->connected = TRUE; cf->connected = TRUE;
} }
return result; return result;
@ -922,34 +978,34 @@ static int do_connect(struct Curl_cfilter *cf, struct Curl_easy *data)
endpoints.sae_srcif = 0; endpoints.sae_srcif = 0;
endpoints.sae_srcaddr = NULL; endpoints.sae_srcaddr = NULL;
endpoints.sae_srcaddrlen = 0; endpoints.sae_srcaddrlen = 0;
endpoints.sae_dstaddr = &ctx->r_addr.sa_addr; endpoints.sae_dstaddr = &ctx->addr.sa_addr;
endpoints.sae_dstaddrlen = ctx->r_addr.addrlen; endpoints.sae_dstaddrlen = ctx->addr.addrlen;
rc = connectx(ctx->sock, &endpoints, SAE_ASSOCID_ANY, rc = connectx(ctx->sock, &endpoints, SAE_ASSOCID_ANY,
CONNECT_RESUME_ON_READ_WRITE | CONNECT_DATA_IDEMPOTENT, CONNECT_RESUME_ON_READ_WRITE | CONNECT_DATA_IDEMPOTENT,
NULL, 0, NULL, NULL); NULL, 0, NULL, NULL);
} }
else { else {
rc = connect(ctx->sock, &ctx->r_addr.sa_addr, ctx->r_addr.addrlen); rc = connect(ctx->sock, &ctx->addr.sa_addr, ctx->addr.addrlen);
} }
# else # else
rc = connect(ctx->sock, &ctx->r_addr.sa_addr, ctx->r_addr.addrlen); rc = connect(ctx->sock, &ctx->addr.sa_addr, ctx->addr.addrlen);
# endif /* HAVE_BUILTIN_AVAILABLE */ # endif /* HAVE_BUILTIN_AVAILABLE */
#elif defined(TCP_FASTOPEN_CONNECT) /* Linux >= 4.11 */ #elif defined(TCP_FASTOPEN_CONNECT) /* Linux >= 4.11 */
if(setsockopt(ctx->sock, IPPROTO_TCP, TCP_FASTOPEN_CONNECT, if(setsockopt(ctx->sock, IPPROTO_TCP, TCP_FASTOPEN_CONNECT,
(void *)&optval, sizeof(optval)) < 0) (void *)&optval, sizeof(optval)) < 0)
infof(data, "Failed to enable TCP Fast Open on fd %d", ctx->sock); infof(data, "Failed to enable TCP Fast Open on fd %d", ctx->sock);
rc = connect(ctx->sock, &ctx->r_addr.sa_addr, ctx->r_addr.addrlen); rc = connect(ctx->sock, &ctx->addr.sa_addr, ctx->addr.addrlen);
#elif defined(MSG_FASTOPEN) /* old Linux */ #elif defined(MSG_FASTOPEN) /* old Linux */
if(cf->conn->given->flags & PROTOPT_SSL) if(cf->conn->given->flags & PROTOPT_SSL)
rc = connect(ctx->sock, &ctx->r_addr.sa_addr, ctx->r_addr.addrlen); rc = connect(ctx->sock, &ctx->addr.sa_addr, ctx->addr.addrlen);
else else
rc = 0; /* Do nothing */ rc = 0; /* Do nothing */
#endif #endif
} }
else { else {
rc = connect(ctx->sock, &ctx->r_addr.sa_addr, ctx->r_addr.addrlen); rc = connect(ctx->sock, &ctx->addr.sa_addr, ctx->addr.addrlen);
} }
return rc; return rc;
} }
@ -1005,6 +1061,7 @@ static CURLcode cf_tcp_connect(struct Curl_cfilter *cf,
else if(rc == CURL_CSELECT_OUT || cf->conn->bits.tcp_fastopen) { else if(rc == CURL_CSELECT_OUT || cf->conn->bits.tcp_fastopen) {
if(verifyconnect(ctx->sock, &ctx->error)) { if(verifyconnect(ctx->sock, &ctx->error)) {
/* we are connected with TCP, awesome! */ /* we are connected with TCP, awesome! */
set_local_ip(cf, data);
*done = TRUE; *done = TRUE;
cf->connected = TRUE; cf->connected = TRUE;
return CURLE_OK; return CURLE_OK;
@ -1101,62 +1158,32 @@ static ssize_t cf_socket_recv(struct Curl_cfilter *cf, struct Curl_easy *data,
return nread; return nread;
} }
/* retrieves the start/end point information of a socket of an established static void conn_set_primary_ip(struct Curl_cfilter *cf,
connection */ struct Curl_easy *data)
static void conninfo_local(struct Curl_easy *data, curl_socket_t sockfd,
char *local_ip, int *local_port)
{
#ifdef HAVE_GETSOCKNAME
char buffer[STRERROR_LEN];
struct Curl_sockaddr_storage ssloc;
curl_socklen_t slen = sizeof(struct Curl_sockaddr_storage);
memset(&ssloc, 0, sizeof(ssloc));
if(getsockname(sockfd, (struct sockaddr*) &ssloc, &slen)) {
int error = SOCKERRNO;
failf(data, "getsockname() failed with errno %d: %s",
error, Curl_strerror(error, buffer, sizeof(buffer)));
return;
}
if(!Curl_addr2string((struct sockaddr*)&ssloc, slen,
local_ip, local_port)) {
failf(data, "ssloc inet_ntop() failed with errno %d: %s",
errno, Curl_strerror(errno, buffer, sizeof(buffer)));
return;
}
#else
(void)data;
(void)sockfd;
(void)local_ip;
(void)local_port;
#endif
}
/* retrieves the start/end point information of a socket of an established
connection */
static void conninfo_remote(struct Curl_easy *data,
struct connectdata *conn, curl_socket_t sockfd)
{ {
struct cf_socket_ctx *ctx = cf->ctx;
#ifdef HAVE_GETPEERNAME #ifdef HAVE_GETPEERNAME
char buffer[STRERROR_LEN]; char buffer[STRERROR_LEN];
struct Curl_sockaddr_storage ssrem; struct Curl_sockaddr_storage ssrem;
curl_socklen_t plen; curl_socklen_t plen;
int port; int port;
plen = sizeof(struct Curl_sockaddr_storage);
memset(&ssrem, 0, sizeof(ssrem)); plen = sizeof(ssrem);
if(getpeername(sockfd, (struct sockaddr*) &ssrem, &plen)) { memset(&ssrem, 0, plen);
if(getpeername(ctx->sock, (struct sockaddr*) &ssrem, &plen)) {
int error = SOCKERRNO; int error = SOCKERRNO;
failf(data, "getpeername() failed with errno %d: %s", failf(data, "getpeername() failed with errno %d: %s",
error, Curl_strerror(error, buffer, sizeof(buffer))); error, Curl_strerror(error, buffer, sizeof(buffer)));
return; return;
} }
if(!Curl_addr2string((struct sockaddr*)&ssrem, plen, if(!Curl_addr2string((struct sockaddr*)&ssrem, plen,
conn->primary_ip, &port)) { cf->conn->primary_ip, &port)) {
failf(data, "ssrem inet_ntop() failed with errno %d: %s", failf(data, "ssrem inet_ntop() failed with errno %d: %s",
errno, Curl_strerror(errno, buffer, sizeof(buffer))); errno, Curl_strerror(errno, buffer, sizeof(buffer)));
return; return;
} }
#else #else
cf->conn->primary_ip[0] = 0;
(void)data; (void)data;
(void)conn; (void)conn;
(void)sockfd; (void)sockfd;
@ -1166,22 +1193,17 @@ static void conninfo_remote(struct Curl_easy *data,
static void cf_socket_active(struct Curl_cfilter *cf, struct Curl_easy *data) static void cf_socket_active(struct Curl_cfilter *cf, struct Curl_easy *data)
{ {
struct cf_socket_ctx *ctx = cf->ctx; struct cf_socket_ctx *ctx = cf->ctx;
char local_ip[MAX_IPADR_LEN] = "";
int local_port = -1;
/* use this socket from now on */ /* use this socket from now on */
DEBUGASSERT(ctx);
DEBUGASSERT(cf->conn);
cf->conn->sock[cf->sockindex] = ctx->sock; cf->conn->sock[cf->sockindex] = ctx->sock;
/* the first socket info gets set at conn and data */
if(cf->sockindex == FIRSTSOCKET) { if(cf->sockindex == FIRSTSOCKET) {
cf->conn->ip_addr = ctx->ai; cf->conn->remote_addr = &ctx->addr;
#ifdef ENABLE_IPV6 #ifdef ENABLE_IPV6
cf->conn->bits.ipv6 = (ctx->ai->ai_family == AF_INET6)? TRUE : FALSE; cf->conn->bits.ipv6 = (ctx->addr.family == AF_INET6)? TRUE : FALSE;
#endif #endif
conninfo_remote(data, cf->conn, ctx->sock); conn_set_primary_ip(cf, data);
conninfo_local(data, ctx->sock, local_ip, &local_port); Curl_persistconninfo(data, cf->conn, ctx->l_ip, ctx->l_port);
Curl_persistconninfo(data, cf->conn, local_ip, local_port);
} }
ctx->active = TRUE; ctx->active = TRUE;
} }
@ -1190,12 +1212,17 @@ static CURLcode cf_socket_cntrl(struct Curl_cfilter *cf,
struct Curl_easy *data, struct Curl_easy *data,
int event, int arg1, void *arg2) int event, int arg1, void *arg2)
{ {
struct cf_socket_ctx *ctx = cf->ctx;
(void)arg1; (void)arg1;
(void)arg2; (void)arg2;
switch(event) { switch(event) {
case CF_CTRL_CONN_INFO_UPDATE: case CF_CTRL_CONN_INFO_UPDATE:
cf_socket_active(cf, data); cf_socket_active(cf, data);
break; break;
case CF_CTRL_DATA_SETUP:
Curl_persistconninfo(data, cf->conn, ctx->l_ip, ctx->l_port);
break;
} }
return CURLE_OK; return CURLE_OK;
} }
@ -1270,7 +1297,7 @@ CURLcode Curl_cf_tcp_create(struct Curl_cfilter **pcf,
goto out; goto out;
} }
ctx->transport = TRNSPRT_TCP; ctx->transport = TRNSPRT_TCP;
ctx->ai = ai; assign_sockaddr_ex(&ctx->addr, ai, ctx->transport);
ctx->sock = CURL_SOCKET_BAD; ctx->sock = CURL_SOCKET_BAD;
result = Curl_cf_create(&cf, &cft_tcp, ctx); result = Curl_cf_create(&cf, &cft_tcp, ctx);
@ -1307,6 +1334,7 @@ static CURLcode cf_udp_connect(struct Curl_cfilter *cf,
} }
} }
else { else {
set_local_ip(cf, data);
*done = TRUE; *done = TRUE;
cf->connected = TRUE; cf->connected = TRUE;
} }
@ -1348,7 +1376,7 @@ CURLcode Curl_cf_udp_create(struct Curl_cfilter **pcf,
goto out; goto out;
} }
ctx->transport = TRNSPRT_UDP; ctx->transport = TRNSPRT_UDP;
ctx->ai = ai; assign_sockaddr_ex(&ctx->addr, ai, ctx->transport);
ctx->sock = CURL_SOCKET_BAD; ctx->sock = CURL_SOCKET_BAD;
result = Curl_cf_create(&cf, &cft_udp, ctx); result = Curl_cf_create(&cf, &cft_udp, ctx);
@ -1398,7 +1426,7 @@ CURLcode Curl_cf_unix_create(struct Curl_cfilter **pcf,
goto out; goto out;
} }
ctx->transport = TRNSPRT_UNIX; ctx->transport = TRNSPRT_UNIX;
ctx->ai = ai; assign_sockaddr_ex(&ctx->addr, ai, ctx->transport);
ctx->sock = CURL_SOCKET_BAD; ctx->sock = CURL_SOCKET_BAD;
result = Curl_cf_create(&cf, &cft_unix, ctx); result = Curl_cf_create(&cf, &cft_unix, ctx);
@ -1470,6 +1498,8 @@ CURLcode Curl_conn_tcp_listen_set(struct Curl_easy *data,
Curl_conn_cf_add(data, conn, sockindex, cf); Curl_conn_cf_add(data, conn, sockindex, cf);
conn->sock[sockindex] = ctx->sock; conn->sock[sockindex] = ctx->sock;
set_remote_ip(cf, data);
set_local_ip(cf, data);
ctx->active = TRUE; ctx->active = TRUE;
cf->connected = TRUE; cf->connected = TRUE;
CF_DEBUGF(infof(data, CFMSG(cf, "Curl_conn_tcp_listen_set(%d)"), CF_DEBUGF(infof(data, CFMSG(cf, "Curl_conn_tcp_listen_set(%d)"),
@ -1499,6 +1529,8 @@ CURLcode Curl_conn_tcp_accepted_set(struct Curl_easy *data,
socket_close(data, conn, TRUE, ctx->sock); socket_close(data, conn, TRUE, ctx->sock);
ctx->sock = *s; ctx->sock = *s;
conn->sock[sockindex] = ctx->sock; conn->sock[sockindex] = ctx->sock;
set_remote_ip(cf, data);
set_local_ip(cf, data);
ctx->active = TRUE; ctx->active = TRUE;
ctx->accepted = TRUE; ctx->accepted = TRUE;
cf->connected = TRUE; cf->connected = TRUE;
@ -1524,7 +1556,7 @@ CURLcode Curl_cf_socket_peek(struct Curl_cfilter *cf,
struct cf_socket_ctx *ctx = cf->ctx; struct cf_socket_ctx *ctx = cf->ctx;
*psock = ctx->sock; *psock = ctx->sock;
*paddr = &ctx->r_addr; *paddr = &ctx->addr;
*premote_ip_str = ctx->r_ip; *premote_ip_str = ctx->r_ip;
*premote_port = ctx->r_port; *premote_port = ctx->r_port;
return CURLE_OK; return CURLE_OK;

View File

@ -369,10 +369,14 @@ CURLcode Curl_conn_connect(struct Curl_easy *data,
cf = data->conn->cfilter[sockindex]; cf = data->conn->cfilter[sockindex];
DEBUGASSERT(cf); DEBUGASSERT(cf);
if(!cf)
return CURLE_FAILED_INIT;
*done = cf->connected; *done = cf->connected;
if(!*done) { if(!*done) {
result = cf->cft->connect (cf, data, blocking, done); result = cf->cft->connect(cf, data, blocking, done);
if(!result && *done) { if(!result && *done) {
Curl_conn_ev_update_info(data, data->conn);
data->conn->keepalive = Curl_now(); data->conn->keepalive = Curl_now();
} }
} }

View File

@ -1010,9 +1010,9 @@ static CURLcode ftp_state_use_port(struct Curl_easy *data,
if(*addr != '\0') { if(*addr != '\0') {
/* attempt to get the address of the given interface name */ /* attempt to get the address of the given interface name */
switch(Curl_if2ip(conn->ip_addr->ai_family, switch(Curl_if2ip(conn->remote_addr->family,
#ifdef ENABLE_IPV6 #ifdef ENABLE_IPV6
Curl_ipv6_scope(conn->ip_addr->ai_addr), Curl_ipv6_scope(&conn->remote_addr->sa_addr),
conn->scope_id, conn->scope_id,
#endif #endif
addr, hbuf, sizeof(hbuf))) { addr, hbuf, sizeof(hbuf))) {

View File

@ -46,6 +46,7 @@
#endif #endif
#include "urldata.h" #include "urldata.h"
#include "cf-socket.h"
#include "curl_base64.h" #include "curl_base64.h"
#include "ftp.h" #include "ftp.h"
#include "curl_gssapi.h" #include "curl_gssapi.h"
@ -207,8 +208,8 @@ krb5_auth(void *app_data, struct Curl_easy *data, struct connectdata *conn)
gss_ctx_id_t *context = app_data; gss_ctx_id_t *context = app_data;
struct gss_channel_bindings_struct chan; struct gss_channel_bindings_struct chan;
size_t base64_sz = 0; size_t base64_sz = 0;
struct sockaddr_in **remote_addr = struct sockaddr_in *remote_addr =
(struct sockaddr_in **)&conn->ip_addr->ai_addr; (struct sockaddr_in *)&conn->remote_addr->sa_addr;
char *stringp; char *stringp;
if(getsockname(conn->sock[FIRSTSOCKET], if(getsockname(conn->sock[FIRSTSOCKET],
@ -220,7 +221,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.initiator_address.value = &conn->local_addr.sin_addr.s_addr;
chan.acceptor_addrtype = GSS_C_AF_INET; chan.acceptor_addrtype = GSS_C_AF_INET;
chan.acceptor_address.length = l - 4; chan.acceptor_address.length = l - 4;
chan.acceptor_address.value = &(*remote_addr)->sin_addr.s_addr; chan.acceptor_address.value = &remote_addr->sin_addr.s_addr;
chan.application_data.length = 0; chan.application_data.length = 0;
chan.application_data.value = NULL; chan.application_data.value = NULL;

View File

@ -363,7 +363,7 @@ ssize_t Curl_send_plain(struct Curl_easy *data, int num,
#if defined(MSG_FASTOPEN) && !defined(TCP_FASTOPEN_CONNECT) /* Linux */ #if defined(MSG_FASTOPEN) && !defined(TCP_FASTOPEN_CONNECT) /* Linux */
if(conn->bits.tcp_fastopen) { if(conn->bits.tcp_fastopen) {
bytes_written = sendto(sockfd, mem, len, MSG_FASTOPEN, bytes_written = sendto(sockfd, mem, len, MSG_FASTOPEN,
conn->ip_addr->ai_addr, conn->ip_addr->ai_addrlen); conn->remote_addr.addr, conn->remote_addr.addrlen);
conn->bits.tcp_fastopen = FALSE; conn->bits.tcp_fastopen = FALSE;
} }
else else

View File

@ -48,6 +48,7 @@
#include "urldata.h" #include "urldata.h"
#include <curl/curl.h> #include <curl/curl.h>
#include "cf-socket.h"
#include "transfer.h" #include "transfer.h"
#include "sendf.h" #include "sendf.h"
#include "tftp.h" #include "tftp.h"
@ -529,8 +530,8 @@ static CURLcode tftp_send_first(struct tftp_state_data *state,
not have a size_t argument, like older unixes that want an 'int' */ not have a size_t argument, like older unixes that want an 'int' */
senddata = sendto(state->sockfd, (void *)state->spacket.data, senddata = sendto(state->sockfd, (void *)state->spacket.data,
(SEND_TYPE_ARG3)sbytes, 0, (SEND_TYPE_ARG3)sbytes, 0,
data->conn->ip_addr->ai_addr, &data->conn->remote_addr->sa_addr,
data->conn->ip_addr->ai_addrlen); data->conn->remote_addr->addrlen);
if(senddata != (ssize_t)sbytes) { if(senddata != (ssize_t)sbytes) {
char buffer[STRERROR_LEN]; char buffer[STRERROR_LEN];
failf(data, "%s", Curl_strerror(SOCKERRNO, buffer, sizeof(buffer))); failf(data, "%s", Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
@ -1014,7 +1015,7 @@ static CURLcode tftp_connect(struct Curl_easy *data, bool *done)
state->requested_blksize = blksize; state->requested_blksize = blksize;
((struct sockaddr *)&state->local_addr)->sa_family = ((struct sockaddr *)&state->local_addr)->sa_family =
(CURL_SA_FAMILY_T)(conn->ip_addr->ai_family); (CURL_SA_FAMILY_T)(conn->remote_addr->family);
tftp_set_timeouts(state); tftp_set_timeouts(state);
@ -1033,7 +1034,7 @@ static CURLcode tftp_connect(struct Curl_easy *data, bool *done)
* IPv4 and IPv6... * IPv4 and IPv6...
*/ */
int rc = bind(state->sockfd, (struct sockaddr *)&state->local_addr, int rc = bind(state->sockfd, (struct sockaddr *)&state->local_addr,
conn->ip_addr->ai_addrlen); conn->remote_addr->addrlen);
if(rc) { if(rc) {
char buffer[STRERROR_LEN]; char buffer[STRERROR_LEN];
failf(data, "bind() failed; %s", failf(data, "bind() failed; %s",

View File

@ -3381,9 +3381,6 @@ static void reuse_conn(struct Curl_easy *data,
existing->hostname_resolve = temp->hostname_resolve; existing->hostname_resolve = temp->hostname_resolve;
temp->hostname_resolve = NULL; temp->hostname_resolve = NULL;
/* persist existing connection info in data */
Curl_conn_ev_update_info(data, existing);
conn_reset_all_postponed_data(temp); /* free buffers */ conn_reset_all_postponed_data(temp); /* free buffers */
/* re-use init */ /* re-use init */

View File

@ -907,10 +907,9 @@ struct connectdata {
there is no name resolve done. */ there is no name resolve done. */
struct Curl_dns_entry *dns_entry; struct Curl_dns_entry *dns_entry;
/* 'ip_addr' is the particular IP we connected to. It points to a struct /* 'remote_addr' is the particular IP we connected to. it is owned, set
within the DNS cache, so this pointer is only valid as long as the DNS * and NULLed by the connected socket filter (if there is one). */
cache entry remains locked. It gets unlocked in multi_done() */ const struct Curl_sockaddr_ex *remote_addr;
const struct Curl_addrinfo *ip_addr;
struct hostname host; struct hostname host;
char *hostname_resolve; /* host name to resolve to address, allocated */ char *hostname_resolve; /* host name to resolve to address, allocated */