urldata: connection bit ipv6_ip is wrong

Eliminate `conn->bits.ipv6_ip`

The bit was only correct for the first transfer using a connection. Use
`data->state.up.hostname` instead in places that need the URL hostname
in its original form.

Fix parseurlandfillconn() to not modify `data->state.up.hostname` before
copying the connection's hostname, but modify the copy instead, leaving
the URL hostname intact.

Closes #20919
This commit is contained in:
Stefan Eissing 2026-03-13 14:29:13 +01:00 committed by Daniel Stenberg
parent eb5af3a9c7
commit 412cd2577a
No known key found for this signature in database
GPG key ID: 5CC908FDB71E12C2
8 changed files with 29 additions and 48 deletions

View file

@ -2068,9 +2068,9 @@ static CURLcode http_set_aptr_host(struct Curl_easy *data)
}
}
else {
/* When building Host: headers, we must put the hostname within
[brackets] if the hostname is a plain IPv6-address. RFC2732-style. */
const char *host = conn->host.name;
/* Use the hostname as present in the URL if it was IPv6. */
char *host = (data->state.up.hostname[0] == '[') ?
data->state.up.hostname : conn->host.name;
if(((conn->given->protocol & (CURLPROTO_HTTPS | CURLPROTO_WSS)) &&
(conn->remote_port == PORT_HTTPS)) ||
@ -2078,14 +2078,9 @@ static CURLcode http_set_aptr_host(struct Curl_easy *data)
(conn->remote_port == PORT_HTTP)))
/* if(HTTPS on port 443) OR (HTTP on port 80) then do not include
the port number in the host string */
aptr->host = curl_maprintf("Host: %s%s%s\r\n",
conn->bits.ipv6_ip ? "[" : "",
host, conn->bits.ipv6_ip ? "]" : "");
aptr->host = curl_maprintf("Host: %s\r\n", host);
else
aptr->host = curl_maprintf("Host: %s%s%s:%d\r\n",
conn->bits.ipv6_ip ? "[" : "",
host, conn->bits.ipv6_ip ? "]" : "",
conn->remote_port);
aptr->host = curl_maprintf("Host: %s:%d\r\n", host, conn->remote_port);
if(!aptr->host)
/* without Host: we cannot make a nice request */

View file

@ -183,10 +183,7 @@ void Curl_http_proxy_get_destination(struct Curl_cfilter *cf,
else
*pport = cf->conn->remote_port;
if(*phostname != cf->conn->host.name)
*pipv6_ip = (strchr(*phostname, ':') != NULL);
else
*pipv6_ip = (bool)cf->conn->bits.ipv6_ip;
*pipv6_ip = (strchr(*phostname, ':') != NULL);
}
struct cf_proxy_ctx {

View file

@ -614,11 +614,10 @@ static CURLcode oldap_connect(struct Curl_easy *data, bool *done)
if(result)
goto out;
hosturl = curl_maprintf("%s://%s%s%s:%d",
hosturl = curl_maprintf("%s://%s:%d",
conn->scheme->name,
conn->bits.ipv6_ip ? "[" : "",
conn->host.name,
conn->bits.ipv6_ip ? "]" : "",
(data->state.up.hostname[0] == '[') ?
data->state.up.hostname : conn->host.name,
conn->remote_port);
if(!hosturl) {
result = CURLE_OUT_OF_MEMORY;

View file

@ -790,7 +790,7 @@ static CURLproxycode socks5_req1_init(struct socks_state *sx,
/* remote resolving, send what type+addr/string to resolve */
#ifdef USE_IPV6
if(cf->conn->bits.ipv6_ip) {
if(strchr(sx->hostname, ':')) {
desttype = 4;
destination = ipbuf;
destlen = 16;

View file

@ -1609,6 +1609,7 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
CURLU *uh;
CURLUcode uc;
char *hostname;
size_t hlen;
bool use_set_uh = (data->set.uh && !data->state.this_is_a_follow);
up_free(data); /* cleanup previous leftovers first */
@ -1667,17 +1668,16 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
failf(data, "Too long hostname (maximum is %d)", MAX_URL_LEN);
return CURLE_URL_MALFORMAT;
}
hostname = data->state.up.hostname;
hlen = hostname ? strlen(hostname) : 0;
if(hostname && hostname[0] == '[') {
/* This looks like an IPv6 address literal. See if there is an address
scope. */
size_t hlen;
conn->bits.ipv6_ip = TRUE;
/* cut off the brackets! */
/* cut off the brackets after copying this! */
hostname++;
hlen = strlen(hostname);
hostname[hlen - 1] = 0;
hlen -= 2;
zonefrom_url(uh, data, conn);
}
@ -1686,6 +1686,7 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
conn->host.rawalloc = curlx_strdup(hostname ? hostname : "");
if(!conn->host.rawalloc)
return CURLE_OUT_OF_MEMORY;
conn->host.rawalloc[hlen] = 0; /* cut off for ipv6 case */
conn->host.name = conn->host.rawalloc;
/*************************************************************
@ -2817,19 +2818,14 @@ static CURLcode parse_connect_to_string(struct Curl_easy *data,
ptr++;
}
else {
/* check whether the URL's hostname matches */
size_t hostname_to_match_len;
char *hostname_to_match = curl_maprintf("%s%s%s",
conn->bits.ipv6_ip ? "[" : "",
conn->host.name,
conn->bits.ipv6_ip ? "]" : "");
if(!hostname_to_match)
return CURLE_OUT_OF_MEMORY;
hostname_to_match_len = strlen(hostname_to_match);
host_match = curl_strnequal(ptr, hostname_to_match,
hostname_to_match_len);
curlx_free(hostname_to_match);
ptr += hostname_to_match_len;
/* check whether the URL's hostname matches. Use the url hostname
* when it was an IPv6 address. Otherwise use the connection's hostname
* that has IDN conversion. */
char *hostname_to_match = (data->state.up.hostname[0] == '[') ?
data->state.up.hostname : conn->host.name;
size_t hlen = strlen(hostname_to_match);
host_match = curl_strnequal(ptr, hostname_to_match, hlen);
ptr += hlen;
host_match = host_match && *ptr == ':';
ptr++;

View file

@ -338,8 +338,6 @@ struct ConnectBits {
that overrides the host in the URL */
BIT(conn_to_port); /* if set, this connection has a "connect to port"
that overrides the port in the URL (remote port) */
BIT(ipv6_ip); /* we communicate with a remote site specified with pure IPv6
IP address */
BIT(ipv6); /* we communicate with a site using an IPv6 address */
BIT(do_more); /* this is set TRUE if the ->curl_do_more() function is
supposed to be called, after ->curl_do() */

View file

@ -2422,13 +2422,9 @@ static CURLcode myssh_connect(struct Curl_easy *data, bool *done)
return CURLE_FAILED_INIT;
}
if(conn->bits.ipv6_ip) {
char ipv6[MAX_IPADR_LEN];
curl_msnprintf(ipv6, sizeof(ipv6), "[%s]", conn->host.name);
rc = ssh_options_set(sshc->ssh_session, SSH_OPTIONS_HOST, ipv6);
}
else
rc = ssh_options_set(sshc->ssh_session, SSH_OPTIONS_HOST, conn->host.name);
rc = ssh_options_set(sshc->ssh_session, SSH_OPTIONS_HOST,
(data->state.up.hostname[0] == '[') ?
data->state.up.hostname : conn->host.name);
if(rc != SSH_OK) {
failf(data, "Could not set remote host");

View file

@ -31,7 +31,7 @@ Connect to specific host with IP addresses
<command>
http://10.0.0.1:8081/%TESTNUMBER --connect-to 10.0.0.1:8081:%HOSTIP:%HTTPPORT --next
http://[fc00::1]:8082/%TESTNUMBER --connect-to [fc00::1]:8082:%HOSTIP:%HTTPPORT
http://[fc00::1]:8081/%TESTNUMBER --connect-to [fc00::1]:8081:%HOSTIP:%HTTPPORT
</command>
</client>
@ -44,7 +44,7 @@ User-Agent: curl/%VERSION
Accept: */*
GET /%TESTNUMBER HTTP/1.1
Host: [fc00::1]:8082
Host: [fc00::1]:8081
User-Agent: curl/%VERSION
Accept: */*