mirror of
https://github.com/curl/curl.git
synced 2026-08-24 23:43:40 +03:00
lib: introduce Curl_peer
`struct Curl_peer` keeps information about a communication endpoint together. It will replace `conn->host` and `conn->conn_to_host` and proxyinfo host. It will also become part of `struct ssl_peer`. It has a reference counter, so an instance can be shared between connections and filters. Elminiates `conn->host` and `conn->connect_to_host`, used in the proxyinfo structures. Passed to DNS resolution and socks filters, etc. Pass peer to http proxy and socks tunnel filters. Use peer in dns filter and resolving. Make `Curl_peer` a member in the `struct ssl_peer`. Add `docs/internals/PEERS.md` for documentation. Closes #21472
This commit is contained in:
parent
9c9a4f3eab
commit
bc40e09f63
67 changed files with 1902 additions and 1295 deletions
77
lib/socks.c
77
lib/socks.c
|
|
@ -98,7 +98,7 @@ static const char * const cf_socks_statename[] = {
|
|||
struct socks_ctx {
|
||||
enum socks_state_t state;
|
||||
struct bufq iobuf;
|
||||
uint16_t remote_port;
|
||||
struct Curl_peer *dest;
|
||||
const char *user;
|
||||
const char *passwd;
|
||||
CURLproxycode presult;
|
||||
|
|
@ -109,7 +109,6 @@ struct socks_ctx {
|
|||
BIT(resolve_local);
|
||||
BIT(start_resolving);
|
||||
BIT(socks4a);
|
||||
char hostname[1];
|
||||
};
|
||||
|
||||
#if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI)
|
||||
|
|
@ -273,8 +272,8 @@ static CURLproxycode socks4_req_add_hd(struct socks_ctx *sx,
|
|||
(void)data;
|
||||
buf[0] = 4; /* version (SOCKS4) */
|
||||
buf[1] = 1; /* connect */
|
||||
buf[2] = (unsigned char)((sx->remote_port >> 8) & 0xffU); /* MSB */
|
||||
buf[3] = (unsigned char)(sx->remote_port & 0xffU); /* LSB */
|
||||
buf[2] = (unsigned char)((sx->dest->port >> 8) & 0xffU); /* MSB */
|
||||
buf[3] = (unsigned char)(sx->dest->port & 0xffU); /* LSB */
|
||||
|
||||
result = Curl_bufq_write(&sx->iobuf, buf, 4, &nwritten);
|
||||
if(result || (nwritten != 4))
|
||||
|
|
@ -329,7 +328,7 @@ static CURLproxycode socks4_resolving(struct socks_ctx *sx,
|
|||
sx->start_resolving = FALSE;
|
||||
result = Curl_cf_dns_insert_after(
|
||||
cf, data, Curl_resolv_dns_queries(data, sx->ip_version),
|
||||
sx->hostname, sx->remote_port, TRNSPRT_TCP, TRUE);
|
||||
sx->dest, TRNSPRT_TCP, TRUE);
|
||||
if(result) {
|
||||
failf(data, "unable to create DNS filter for socks");
|
||||
return CURLPX_UNKNOWN_FAIL;
|
||||
|
|
@ -340,7 +339,7 @@ static CURLproxycode socks4_resolving(struct socks_ctx *sx,
|
|||
result = Curl_conn_cf_connect(cf->next, data, &dns_done);
|
||||
if(result) {
|
||||
failf(data, "Failed to resolve \"%s\" for SOCKS4 connect.",
|
||||
sx->hostname);
|
||||
sx->dest->hostname);
|
||||
return CURLPX_RESOLVE_HOST;
|
||||
}
|
||||
else if(!dns_done)
|
||||
|
|
@ -365,7 +364,7 @@ static CURLproxycode socks4_resolving(struct socks_ctx *sx,
|
|||
}
|
||||
else {
|
||||
/* No ipv4 address resolved */
|
||||
failf(data, "SOCKS4 connection to %s not supported", sx->hostname);
|
||||
failf(data, "SOCKS4 connection to %s not supported", sx->dest->hostname);
|
||||
return CURLPX_RESOLVE_HOST;
|
||||
}
|
||||
|
||||
|
|
@ -487,7 +486,8 @@ process_state:
|
|||
/* SOCKS4 can only do IPv4, insist! */
|
||||
sx->ip_version = CURL_IPRESOLVE_V4;
|
||||
CURL_TRC_CF(data, cf, "SOCKS4%s connecting to %s:%u",
|
||||
sx->socks4a ? "a" : "", sx->hostname, sx->remote_port);
|
||||
sx->socks4a ? "a" : "",
|
||||
sx->dest->hostname, sx->dest->port);
|
||||
|
||||
/*
|
||||
* Compose socks4 request
|
||||
|
|
@ -508,7 +508,7 @@ process_state:
|
|||
/* socks4a, not resolving locally, sends the hostname.
|
||||
* add an invalid address + user + hostname */
|
||||
unsigned char buf[4] = { 0, 0, 0, 1 };
|
||||
size_t hlen = strlen(sx->hostname) + 1; /* including NUL */
|
||||
size_t hlen = strlen(sx->dest->hostname) + 1; /* including NUL */
|
||||
|
||||
if(hlen > 255) {
|
||||
failf(data, "SOCKS4: too long hostname");
|
||||
|
|
@ -520,7 +520,8 @@ process_state:
|
|||
presult = socks4_req_add_user(sx, data);
|
||||
if(presult)
|
||||
return socks_failed(sx, cf, data, presult);
|
||||
result = Curl_bufq_cwrite(&sx->iobuf, sx->hostname, hlen, &nwritten);
|
||||
result = Curl_bufq_cwrite(&sx->iobuf, sx->dest->hostname, hlen,
|
||||
&nwritten);
|
||||
if(result || (nwritten != hlen))
|
||||
return socks_failed(sx, cf, data, CURLPX_SEND_REQUEST);
|
||||
/* request complete */
|
||||
|
|
@ -591,7 +592,7 @@ static CURLproxycode socks5_req0_init(struct Curl_cfilter *cf,
|
|||
|
||||
(void)cf;
|
||||
/* RFC1928 chapter 5 specifies max 255 chars for domain name in packet */
|
||||
if(!sx->resolve_local && strlen(sx->hostname) > 255) {
|
||||
if(!sx->resolve_local && strlen(sx->dest->hostname) > 255) {
|
||||
failf(data, "SOCKS5: the destination hostname is too long to be "
|
||||
"resolved remotely by the proxy.");
|
||||
return CURLPX_LONG_HOSTNAME;
|
||||
|
|
@ -779,28 +780,28 @@ static CURLproxycode socks5_req1_init(struct socks_ctx *sx,
|
|||
|
||||
/* remote resolving, send what type+addr/string to resolve */
|
||||
#ifdef USE_IPV6
|
||||
if(strchr(sx->hostname, ':')) {
|
||||
if(strchr(sx->dest->hostname, ':')) {
|
||||
desttype = 4;
|
||||
destination = ipbuf;
|
||||
destlen = 16;
|
||||
if(curlx_inet_pton(AF_INET6, sx->hostname, ipbuf) != 1)
|
||||
if(curlx_inet_pton(AF_INET6, sx->dest->hostname, ipbuf) != 1)
|
||||
return CURLPX_BAD_ADDRESS_TYPE;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if(curlx_inet_pton(AF_INET, sx->hostname, ipbuf) == 1) {
|
||||
if(curlx_inet_pton(AF_INET, sx->dest->hostname, ipbuf) == 1) {
|
||||
desttype = 1;
|
||||
destination = ipbuf;
|
||||
destlen = 4;
|
||||
}
|
||||
else {
|
||||
const size_t hostname_len = strlen(sx->hostname);
|
||||
const size_t hostname_len = strlen(sx->dest->hostname);
|
||||
/* socks5_req0_init() already rejects hostnames longer than 255 bytes, so
|
||||
this cast to unsigned char is safe. Assert to guard against future
|
||||
refactoring that might remove or reorder that earlier check. */
|
||||
DEBUGASSERT(hostname_len <= 255);
|
||||
desttype = 3;
|
||||
destination = (const unsigned char *)sx->hostname;
|
||||
destination = (const unsigned char *)sx->dest->hostname;
|
||||
destlen = (unsigned char)hostname_len; /* one byte length */
|
||||
}
|
||||
|
||||
|
|
@ -814,13 +815,13 @@ static CURLproxycode socks5_req1_init(struct socks_ctx *sx,
|
|||
if(result || (nwritten != destlen))
|
||||
return CURLPX_SEND_REQUEST;
|
||||
/* PORT MSB+LSB */
|
||||
req[0] = (unsigned char)((sx->remote_port >> 8) & 0xff);
|
||||
req[1] = (unsigned char)(sx->remote_port & 0xff);
|
||||
req[0] = (unsigned char)((sx->dest->port >> 8) & 0xff);
|
||||
req[1] = (unsigned char)(sx->dest->port & 0xff);
|
||||
result = Curl_bufq_write(&sx->iobuf, req, 2, &nwritten);
|
||||
if(result || (nwritten != 2))
|
||||
return CURLPX_SEND_REQUEST;
|
||||
CURL_TRC_CF(data, cf, "SOCKS5 connect to %s:%u (remotely resolved)",
|
||||
sx->hostname, sx->remote_port);
|
||||
sx->dest->hostname, sx->dest->port);
|
||||
return CURLPX_OK;
|
||||
}
|
||||
|
||||
|
|
@ -845,7 +846,7 @@ static CURLproxycode socks5_resolving(struct socks_ctx *sx,
|
|||
sx->start_resolving = FALSE;
|
||||
result = Curl_cf_dns_insert_after(
|
||||
cf, data, Curl_resolv_dns_queries(data, sx->ip_version),
|
||||
sx->hostname, sx->remote_port, TRNSPRT_TCP, TRUE);
|
||||
sx->dest, TRNSPRT_TCP, TRUE);
|
||||
if(result) {
|
||||
failf(data, "unable to create DNS filter for socks");
|
||||
return CURLPX_UNKNOWN_FAIL;
|
||||
|
|
@ -855,7 +856,8 @@ static CURLproxycode socks5_resolving(struct socks_ctx *sx,
|
|||
/* resolve the hostname by connecting the DNS filter */
|
||||
result = Curl_conn_cf_connect(cf->next, data, &dns_done);
|
||||
if(result) {
|
||||
failf(data, "Failed to resolve \"%s\" for SOCKS5 connect.", sx->hostname);
|
||||
failf(data, "Failed to resolve \"%s\" for SOCKS5 connect.",
|
||||
sx->dest->hostname);
|
||||
return CURLPX_RESOLVE_HOST;
|
||||
}
|
||||
else if(!dns_done)
|
||||
|
|
@ -869,7 +871,8 @@ static CURLproxycode socks5_resolving(struct socks_ctx *sx,
|
|||
ai = Curl_cf_dns_get_ai(cf->next, data, AF_INET, 0);
|
||||
|
||||
if(!ai) {
|
||||
failf(data, "Failed to resolve \"%s\" for SOCKS5 connect.", sx->hostname);
|
||||
failf(data, "Failed to resolve \"%s\" for SOCKS5 connect.",
|
||||
sx->dest->hostname);
|
||||
presult = CURLPX_RESOLVE_HOST;
|
||||
goto out;
|
||||
}
|
||||
|
|
@ -883,7 +886,7 @@ static CURLproxycode socks5_resolving(struct socks_ctx *sx,
|
|||
saddr_in = (struct sockaddr_in *)(void *)ai->ai_addr;
|
||||
destination = (const unsigned char *)&saddr_in->sin_addr.s_addr;
|
||||
CURL_TRC_CF(data, cf, "SOCKS5 connect to %s:%u (locally resolved)",
|
||||
dest, sx->remote_port);
|
||||
dest, sx->dest->port);
|
||||
}
|
||||
#ifdef USE_IPV6
|
||||
else if(ai->ai_family == AF_INET6) {
|
||||
|
|
@ -893,7 +896,7 @@ static CURLproxycode socks5_resolving(struct socks_ctx *sx,
|
|||
saddr_in6 = (struct sockaddr_in6 *)(void *)ai->ai_addr;
|
||||
destination = (const unsigned char *)&saddr_in6->sin6_addr.s6_addr;
|
||||
CURL_TRC_CF(data, cf, "SOCKS5 connect to [%s]:%u (locally resolved)",
|
||||
dest, sx->remote_port);
|
||||
dest, sx->dest->port);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -915,8 +918,8 @@ static CURLproxycode socks5_resolving(struct socks_ctx *sx,
|
|||
goto out;
|
||||
}
|
||||
/* PORT MSB+LSB */
|
||||
req[0] = (unsigned char)((sx->remote_port >> 8) & 0xffU);
|
||||
req[1] = (unsigned char)(sx->remote_port & 0xffU);
|
||||
req[0] = (unsigned char)((sx->dest->port >> 8) & 0xffU);
|
||||
req[1] = (unsigned char)(sx->dest->port & 0xffU);
|
||||
result = Curl_bufq_write(&sx->iobuf, req, 2, &nwritten);
|
||||
if(result || (nwritten != 2)) {
|
||||
presult = CURLPX_SEND_REQUEST;
|
||||
|
|
@ -971,7 +974,7 @@ static CURLproxycode socks5_recv_resp1(struct socks_ctx *sx,
|
|||
CURLproxycode rc = CURLPX_REPLY_UNASSIGNED;
|
||||
int code = resp[1];
|
||||
failf(data, "cannot complete SOCKS5 connection to %s. (%d)",
|
||||
sx->hostname, code);
|
||||
sx->dest->hostname, code);
|
||||
if(code < 9) {
|
||||
/* RFC 1928 section 6 lists: */
|
||||
static const CURLproxycode lookup[] = {
|
||||
|
|
@ -1043,7 +1046,7 @@ process_state:
|
|||
|
||||
case SOCKS5_ST_START:
|
||||
CURL_TRC_CF(data, cf, "SOCKS5: connecting to %s:%u",
|
||||
sx->hostname, sx->remote_port);
|
||||
sx->dest->hostname, sx->dest->port);
|
||||
presult = socks5_req0_init(cf, sx, data);
|
||||
if(presult)
|
||||
return socks_failed(sx, cf, data, presult);
|
||||
|
|
@ -1181,6 +1184,7 @@ process_state:
|
|||
static void socks_proxy_ctx_free(struct socks_ctx *ctx)
|
||||
{
|
||||
if(ctx) {
|
||||
Curl_peer_unlink(&ctx->dest);
|
||||
Curl_bufq_free(&ctx->iobuf);
|
||||
curlx_free(ctx);
|
||||
}
|
||||
|
|
@ -1244,7 +1248,7 @@ static CURLcode socks_proxy_cf_connect(struct Curl_cfilter *cf,
|
|||
"(via %s port %u)",
|
||||
(cf->sockindex == SECONDARYSOCKET) ? "2nd " : "",
|
||||
ipquad.local_ip, ipquad.local_port,
|
||||
ctx->hostname, ctx->remote_port,
|
||||
ctx->dest->hostname, ctx->dest->port,
|
||||
ipquad.remote_ip, ipquad.remote_port);
|
||||
else
|
||||
infof(data, "Opened %sSOCKS connection",
|
||||
|
|
@ -1315,8 +1319,8 @@ static CURLcode socks_cf_query(struct Curl_cfilter *cf,
|
|||
switch(query) {
|
||||
case CF_QUERY_HOST_PORT:
|
||||
if(sx) {
|
||||
*pres1 = sx->remote_port;
|
||||
*((const char **)pres2) = sx->hostname;
|
||||
*pres1 = sx->dest->port;
|
||||
*((const char **)pres2) = sx->dest->hostname;
|
||||
return CURLE_OK;
|
||||
}
|
||||
break;
|
||||
|
|
@ -1354,8 +1358,7 @@ struct Curl_cftype Curl_cft_socks_proxy = {
|
|||
|
||||
CURLcode Curl_cf_socks_proxy_insert_after(struct Curl_cfilter *cf_at,
|
||||
struct Curl_easy *data,
|
||||
const char *hostname,
|
||||
uint16_t port,
|
||||
struct Curl_peer *dest,
|
||||
uint8_t ip_version,
|
||||
uint8_t proxy_type,
|
||||
const char *user,
|
||||
|
|
@ -1363,10 +1366,9 @@ CURLcode Curl_cf_socks_proxy_insert_after(struct Curl_cfilter *cf_at,
|
|||
{
|
||||
struct Curl_cfilter *cf;
|
||||
struct socks_ctx *ctx;
|
||||
size_t hostlen = hostname ? strlen(hostname) : 0;
|
||||
CURLcode result;
|
||||
|
||||
if(!hostlen)
|
||||
if(!dest)
|
||||
return CURLE_FAILED_INIT;
|
||||
|
||||
switch(proxy_type) {
|
||||
|
|
@ -1381,13 +1383,12 @@ CURLcode Curl_cf_socks_proxy_insert_after(struct Curl_cfilter *cf_at,
|
|||
}
|
||||
|
||||
/* NUL byte already part of struct size */
|
||||
ctx = curlx_calloc(1, sizeof(*ctx) + hostlen);
|
||||
ctx = curlx_calloc(1, sizeof(*ctx));
|
||||
if(!ctx) {
|
||||
return CURLE_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
memcpy(ctx->hostname, hostname, hostlen);
|
||||
ctx->remote_port = port;
|
||||
Curl_peer_link(&ctx->dest, dest);
|
||||
ctx->ip_version = ip_version;
|
||||
ctx->proxy_type = proxy_type;
|
||||
ctx->user = user;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue