Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge branch 'ew/force-ipv4'
"git fetch" and friends that make network connections can now be
told to only use ipv4 (or ipv6).

* ew/force-ipv4:
  connect & http: support -4 and -6 switches for remote operations
  • Loading branch information
Junio C Hamano committed Feb 24, 2016
2 parents 8020803 + c915f11 commit e84d5e9
Show file tree
Hide file tree
Showing 13 changed files with 95 additions and 0 deletions.
8 changes: 8 additions & 0 deletions Documentation/fetch-options.txt
Expand Up @@ -158,3 +158,11 @@ endif::git-pull[]
by default when it is attached to a terminal, unless -q
is specified. This flag forces progress status even if the
standard error stream is not directed to a terminal.

-4::
--ipv4::
Use IPv4 addresses only, ignoring IPv6 addresses.

-6::
--ipv6::
Use IPv6 addresses only, ignoring IPv4 addresses.
7 changes: 7 additions & 0 deletions Documentation/git-push.txt
Expand Up @@ -277,6 +277,13 @@ origin +master` to force a push to the `master` branch). See the
default is --verify, giving the hook a chance to prevent the
push. With --no-verify, the hook is bypassed completely.

-4::
--ipv4::
Use IPv4 addresses only, ignoring IPv6 addresses.

-6::
--ipv6::
Use IPv6 addresses only, ignoring IPv4 addresses.

include::urls-remotes.txt[]

Expand Down
6 changes: 6 additions & 0 deletions builtin/clone.c
Expand Up @@ -47,6 +47,7 @@ static const char *real_git_dir;
static char *option_upload_pack = "git-upload-pack";
static int option_verbosity;
static int option_progress = -1;
static enum transport_family family;
static struct string_list option_config;
static struct string_list option_reference;
static int option_dissociate;
Expand Down Expand Up @@ -92,6 +93,10 @@ static struct option builtin_clone_options[] = {
N_("separate git dir from working tree")),
OPT_STRING_LIST('c', "config", &option_config, N_("key=value"),
N_("set config inside the new repository")),
OPT_SET_INT('4', "ipv4", &family, N_("use IPv4 addresses only"),
TRANSPORT_FAMILY_IPV4),
OPT_SET_INT('6', "ipv6", &family, N_("use IPv6 addresses only"),
TRANSPORT_FAMILY_IPV6),
OPT_END()
};

Expand Down Expand Up @@ -970,6 +975,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
remote = remote_get(option_origin);
transport = transport_get(remote, remote->url[0]);
transport_set_verbosity(transport, option_verbosity, option_progress);
transport->family = family;

path = get_repo_path(remote->url[0], &is_bundle);
is_local = option_local != 0 && path && !is_bundle;
Expand Down
6 changes: 6 additions & 0 deletions builtin/fetch.c
Expand Up @@ -38,6 +38,7 @@ static int all, append, dry_run, force, keep, multiple, update_head_ok, verbosit
static int progress = -1, recurse_submodules = RECURSE_SUBMODULES_DEFAULT;
static int tags = TAGS_DEFAULT, unshallow, update_shallow;
static int max_children = 1;
static enum transport_family family;
static const char *depth;
static const char *upload_pack;
static struct strbuf default_rla = STRBUF_INIT;
Expand Down Expand Up @@ -127,6 +128,10 @@ static struct option builtin_fetch_options[] = {
N_("accept refs that update .git/shallow")),
{ OPTION_CALLBACK, 0, "refmap", NULL, N_("refmap"),
N_("specify fetch refmap"), PARSE_OPT_NONEG, parse_refmap_arg },
OPT_SET_INT('4', "ipv4", &family, N_("use IPv4 addresses only"),
TRANSPORT_FAMILY_IPV4),
OPT_SET_INT('6', "ipv6", &family, N_("use IPv6 addresses only"),
TRANSPORT_FAMILY_IPV6),
OPT_END()
};

Expand Down Expand Up @@ -864,6 +869,7 @@ static struct transport *prepare_transport(struct remote *remote)
struct transport *transport;
transport = transport_get(remote, NULL);
transport_set_verbosity(transport, verbosity, progress);
transport->family = family;
if (upload_pack)
set_option(transport, TRANS_OPT_UPLOADPACK, upload_pack);
if (keep)
Expand Down
6 changes: 6 additions & 0 deletions builtin/push.c
Expand Up @@ -23,6 +23,7 @@ static const char *receivepack;
static int verbosity;
static int progress = -1;
static int recurse_submodules = RECURSE_SUBMODULES_DEFAULT;
static enum transport_family family;

static struct push_cas_option cas;

Expand Down Expand Up @@ -346,6 +347,7 @@ static int push_with_options(struct transport *transport, int flags)
unsigned int reject_reasons;

transport_set_verbosity(transport, verbosity, progress);
transport->family = family;

if (receivepack)
transport_set_option(transport,
Expand Down Expand Up @@ -565,6 +567,10 @@ int cmd_push(int argc, const char **argv, const char *prefix)
0, "signed", &push_cert, "yes|no|if-asked", N_("GPG sign the push"),
PARSE_OPT_OPTARG, option_parse_push_signed },
OPT_BIT(0, "atomic", &flags, N_("request atomic transaction on remote side"), TRANSPORT_PUSH_ATOMIC),
OPT_SET_INT('4', "ipv4", &family, N_("use IPv4 addresses only"),
TRANSPORT_FAMILY_IPV4),
OPT_SET_INT('6', "ipv6", &family, N_("use IPv6 addresses only"),
TRANSPORT_FAMILY_IPV6),
OPT_END()
};

Expand Down
8 changes: 8 additions & 0 deletions connect.c
Expand Up @@ -357,6 +357,10 @@ static int git_tcp_connect_sock(char *host, int flags)
port = "<none>";

memset(&hints, 0, sizeof(hints));
if (flags & CONNECT_IPV4)
hints.ai_family = AF_INET;
else if (flags & CONNECT_IPV6)
hints.ai_family = AF_INET6;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;

Expand Down Expand Up @@ -783,6 +787,10 @@ struct child_process *git_connect(int fd[2], const char *url,
}

argv_array_push(&conn->args, ssh);
if (flags & CONNECT_IPV4)
argv_array_push(&conn->args, "-4");
else if (flags & CONNECT_IPV6)
argv_array_push(&conn->args, "-6");
if (tortoiseplink)
argv_array_push(&conn->args, "-batch");
if (port) {
Expand Down
2 changes: 2 additions & 0 deletions connect.h
Expand Up @@ -3,6 +3,8 @@

#define CONNECT_VERBOSE (1u << 0)
#define CONNECT_DIAG_URL (1u << 1)
#define CONNECT_IPV4 (1u << 2)
#define CONNECT_IPV6 (1u << 3)
extern struct child_process *git_connect(int fd[2], const char *url, const char *prog, int flags);
extern int finish_connect(struct child_process *conn);
extern int git_connection_is_socket(struct child_process *conn);
Expand Down
9 changes: 9 additions & 0 deletions http.c
Expand Up @@ -11,6 +11,11 @@
#include "gettext.h"
#include "transport.h"

#if LIBCURL_VERSION_NUM >= 0x070a08
long int git_curl_ipresolve = CURL_IPRESOLVE_WHATEVER;
#else
long int git_curl_ipresolve;
#endif
int active_requests;
int http_is_verbose;
size_t http_post_buffer = 16 * LARGE_PACKET_MAX;
Expand Down Expand Up @@ -824,6 +829,10 @@ struct active_request_slot *get_active_slot(void)
curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1);
curl_easy_setopt(slot->curl, CURLOPT_FAILONERROR, 1);
curl_easy_setopt(slot->curl, CURLOPT_RANGE, NULL);

#if LIBCURL_VERSION_NUM >= 0x070a08
curl_easy_setopt(slot->curl, CURLOPT_IPRESOLVE, git_curl_ipresolve);
#endif
#ifdef LIBCURL_CAN_HANDLE_AUTH_ANY
curl_easy_setopt(slot->curl, CURLOPT_HTTPAUTH, http_auth_methods);
#endif
Expand Down
1 change: 1 addition & 0 deletions http.h
Expand Up @@ -107,6 +107,7 @@ extern void http_init(struct remote *remote, const char *url,
int proactive_auth);
extern void http_cleanup(void);

extern long int git_curl_ipresolve;
extern int active_requests;
extern int http_is_verbose;
extern size_t http_post_buffer;
Expand Down
13 changes: 13 additions & 0 deletions remote-curl.c
Expand Up @@ -119,6 +119,19 @@ static int set_option(const char *name, const char *value)
else
return -1;
return 0;

#if LIBCURL_VERSION_NUM >= 0x070a08
} else if (!strcmp(name, "family")) {
if (!strcmp(value, "ipv4"))
git_curl_ipresolve = CURL_IPRESOLVE_V4;
else if (!strcmp(value, "ipv6"))
git_curl_ipresolve = CURL_IPRESOLVE_V6;
else if (!strcmp(value, "all"))
git_curl_ipresolve = CURL_IPRESOLVE_WHATEVER;
else
return -1;
return 0;
#endif /* LIBCURL_VERSION_NUM >= 0x070a08 */
} else {
return 1 /* unsupported */;
}
Expand Down
15 changes: 15 additions & 0 deletions transport-helper.c
Expand Up @@ -321,6 +321,21 @@ static void standard_options(struct transport *t)
if (n >= sizeof(buf))
die("impossibly large verbosity value");
set_helper_option(t, "verbosity", buf);

switch (t->family) {
case TRANSPORT_FAMILY_ALL:
/*
* this is already the default,
* do not break old remote helpers by setting "all" here
*/
break;
case TRANSPORT_FAMILY_IPV4:
set_helper_option(t, "family", "ipv4");
break;
case TRANSPORT_FAMILY_IPV6:
set_helper_option(t, "family", "ipv6");
break;
}
}

static int release_helper(struct transport *transport)
Expand Down
6 changes: 6 additions & 0 deletions transport.c
Expand Up @@ -163,6 +163,12 @@ static int connect_setup(struct transport *transport, int for_push)
if (data->conn)
return 0;

switch (transport->family) {
case TRANSPORT_FAMILY_ALL: break;
case TRANSPORT_FAMILY_IPV4: flags |= CONNECT_IPV4; break;
case TRANSPORT_FAMILY_IPV6: flags |= CONNECT_IPV6; break;
}

data->conn = git_connect(data->fd, transport->url,
for_push ? data->options.receivepack :
data->options.uploadpack,
Expand Down
8 changes: 8 additions & 0 deletions transport.h
Expand Up @@ -18,6 +18,12 @@ struct git_transport_options {
struct push_cas_option *cas;
};

enum transport_family {
TRANSPORT_FAMILY_ALL = 0,
TRANSPORT_FAMILY_IPV4,
TRANSPORT_FAMILY_IPV6
};

struct transport {
struct remote *remote;
const char *url;
Expand Down Expand Up @@ -110,6 +116,8 @@ struct transport {
* actually turns out to be smart.
*/
struct git_transport_options *smart_options;

enum transport_family family;
};

#define TRANSPORT_PUSH_ALL 1
Expand Down

0 comments on commit e84d5e9

Please sign in to comment.