Skip to content

Commit fe41e58

Browse files
authored
Merge pull request libgit2#5741 from libgit2/ethomson/ipv6
Handle ipv6 addresses
2 parents 1c3f29a + 27301cd commit fe41e58

File tree

5 files changed

+469
-40
lines changed

5 files changed

+469
-40
lines changed

src/net.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -335,7 +335,7 @@ bool git_net_url_valid(git_net_url *url)
335335
return (url->host && url->port && url->path);
336336
}
337337

338-
int git_net_url_is_default_port(git_net_url *url)
338+
bool git_net_url_is_default_port(git_net_url *url)
339339
{
340340
const char *default_port;
341341

@@ -345,6 +345,11 @@ int git_net_url_is_default_port(git_net_url *url)
345345
return false;
346346
}
347347

348+
bool git_net_url_is_ipv6(git_net_url *url)
349+
{
350+
return (strchr(url->host, ':') != NULL);
351+
}
352+
348353
void git_net_url_swap(git_net_url *a, git_net_url *b)
349354
{
350355
git_net_url tmp = GIT_NET_URL_INIT;

src/net.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,11 @@ extern int git_net_url_joinpath(
3333
/** Ensures that a URL is minimally valid (contains a host, port and path) */
3434
extern bool git_net_url_valid(git_net_url *url);
3535

36-
/** Returns nonzero if the URL is on the default port. */
37-
extern int git_net_url_is_default_port(git_net_url *url);
36+
/** Returns true if the URL is on the default port. */
37+
extern bool git_net_url_is_default_port(git_net_url *url);
38+
39+
/** Returns true if the host portion of the URL is an ipv6 address. */
40+
extern bool git_net_url_is_ipv6(git_net_url *url);
3841

3942
/* Applies a redirect to the URL with a git-aware service suffix. */
4043
extern int git_net_url_apply_redirect(

src/transports/httpclient.c

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -631,6 +631,26 @@ GIT_INLINE(int) apply_proxy_credentials(
631631
request->proxy_credentials);
632632
}
633633

634+
static int puts_host_and_port(git_buf *buf, git_net_url *url, bool force_port)
635+
{
636+
bool ipv6 = git_net_url_is_ipv6(url);
637+
638+
if (ipv6)
639+
git_buf_putc(buf, '[');
640+
641+
git_buf_puts(buf, url->host);
642+
643+
if (ipv6)
644+
git_buf_putc(buf, ']');
645+
646+
if (force_port || !git_net_url_is_default_port(url)) {
647+
git_buf_putc(buf, ':');
648+
git_buf_puts(buf, url->port);
649+
}
650+
651+
return git_buf_oom(buf) ? -1 : 0;
652+
}
653+
634654
static int generate_connect_request(
635655
git_http_client *client,
636656
git_http_request *request)
@@ -641,14 +661,17 @@ static int generate_connect_request(
641661
git_buf_clear(&client->request_msg);
642662
buf = &client->request_msg;
643663

644-
git_buf_printf(buf, "CONNECT %s:%s HTTP/1.1\r\n",
645-
client->server.url.host, client->server.url.port);
664+
git_buf_puts(buf, "CONNECT ");
665+
puts_host_and_port(buf, &client->server.url, true);
666+
git_buf_puts(buf, " HTTP/1.1\r\n");
646667

647668
git_buf_puts(buf, "User-Agent: ");
648669
git_http__user_agent(buf);
649670
git_buf_puts(buf, "\r\n");
650671

651-
git_buf_printf(buf, "Host: %s\r\n", client->proxy.url.host);
672+
git_buf_puts(buf, "Host: ");
673+
puts_host_and_port(buf, &client->proxy.url, false);
674+
git_buf_puts(buf, "\r\n");
652675

653676
if ((error = apply_proxy_credentials(buf, client, request) < 0))
654677
return -1;
@@ -687,11 +710,8 @@ static int generate_request(
687710
git_http__user_agent(buf);
688711
git_buf_puts(buf, "\r\n");
689712

690-
git_buf_printf(buf, "Host: %s", request->url->host);
691-
692-
if (!git_net_url_is_default_port(request->url))
693-
git_buf_printf(buf, ":%s", request->url->port);
694-
713+
git_buf_puts(buf, "Host: ");
714+
puts_host_and_port(buf, request->url, false);
695715
git_buf_puts(buf, "\r\n");
696716

697717
if (request->accept)
@@ -902,7 +922,7 @@ static int proxy_connect(
902922
int error;
903923

904924
if (!client->proxy_connected || !client->keepalive) {
905-
git_trace(GIT_TRACE_DEBUG, "Connecting to proxy %s:%s",
925+
git_trace(GIT_TRACE_DEBUG, "Connecting to proxy %s port %s",
906926
client->proxy.url.host, client->proxy.url.port);
907927

908928
if ((error = server_create_stream(&client->proxy)) < 0 ||
@@ -1023,7 +1043,7 @@ static int http_client_connect(
10231043
goto on_error;
10241044
}
10251045

1026-
git_trace(GIT_TRACE_DEBUG, "Connecting to remote %s:%s",
1046+
git_trace(GIT_TRACE_DEBUG, "Connecting to remote %s port %s",
10271047
client->server.url.host, client->server.url.port);
10281048

10291049
if ((error = server_connect(client)) < 0)

src/transports/winhttp.c

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -451,8 +451,14 @@ static int winhttp_stream_connect(winhttp_stream *s)
451451
git_buf_puts(&processed_url, t->proxy.url.scheme);
452452
git_buf_PUTS(&processed_url, "://");
453453

454+
if (git_net_url_is_ipv6(&t->proxy.url))
455+
git_buf_putc(&processed_url, '[');
456+
454457
git_buf_puts(&processed_url, t->proxy.url.host);
455458

459+
if (git_net_url_is_ipv6(&t->proxy.url))
460+
git_buf_putc(&processed_url, ']');
461+
456462
if (!git_net_url_is_default_port(&t->proxy.url))
457463
git_buf_printf(&processed_url, ":%s", t->proxy.url.port);
458464

@@ -736,10 +742,11 @@ static void CALLBACK winhttp_status(
736742
static int winhttp_connect(
737743
winhttp_subtransport *t)
738744
{
739-
wchar_t *wide_host;
745+
wchar_t *wide_host = NULL;
740746
int32_t port;
741-
wchar_t *wide_ua;
742-
git_buf ua = GIT_BUF_INIT;
747+
wchar_t *wide_ua = NULL;
748+
git_buf ipv6 = GIT_BUF_INIT, ua = GIT_BUF_INIT;
749+
const char *host;
743750
int error = -1;
744751
int default_timeout = TIMEOUT_INFINITE;
745752
int default_connect_timeout = DEFAULT_CONNECT_TIMEOUT;
@@ -755,29 +762,33 @@ static int winhttp_connect(
755762
/* Prepare port */
756763
if (git__strntol32(&port, t->server.url.port,
757764
strlen(t->server.url.port), NULL, 10) < 0)
758-
return -1;
765+
goto on_error;
766+
767+
/* IPv6? Add braces around the host. */
768+
if (git_net_url_is_ipv6(&t->server.url)) {
769+
if (git_buf_printf(&ipv6, "[%s]", t->server.url.host) < 0)
770+
goto on_error;
771+
772+
host = ipv6.ptr;
773+
} else {
774+
host = t->server.url.host;
775+
}
759776

760777
/* Prepare host */
761-
if (git__utf8_to_16_alloc(&wide_host, t->server.url.host) < 0) {
778+
if (git__utf8_to_16_alloc(&wide_host, host) < 0) {
762779
git_error_set(GIT_ERROR_OS, "unable to convert host to wide characters");
763-
return -1;
780+
goto on_error;
764781
}
765782

766783

767-
if ((error = git_http__user_agent(&ua)) < 0) {
768-
git__free(wide_host);
769-
return error;
770-
}
784+
if (git_http__user_agent(&ua) < 0)
785+
goto on_error;
771786

772787
if (git__utf8_to_16_alloc(&wide_ua, git_buf_cstr(&ua)) < 0) {
773788
git_error_set(GIT_ERROR_OS, "unable to convert host to wide characters");
774-
git__free(wide_host);
775-
git_buf_dispose(&ua);
776-
return -1;
789+
goto on_error;
777790
}
778791

779-
git_buf_dispose(&ua);
780-
781792
/* Establish session */
782793
t->session = WinHttpOpen(
783794
wide_ua,
@@ -836,6 +847,7 @@ static int winhttp_connect(
836847
if (error < 0)
837848
winhttp_close_connection(t);
838849

850+
git_buf_dispose(&ipv6);
839851
git__free(wide_host);
840852
git__free(wide_ua);
841853

0 commit comments

Comments
 (0)