Commit Diff


commit - abc59930d57a2d46c310e1b0c758c948554bc1af
commit + d65a88a2f0db40d2c2ac34ee34e8aff8ac629d52
blob - 14f769b331dbbbc7a4e4a948191670b97122457d
blob + a53d25848b09acd89ddfa729b2104f4145517095
--- got/Makefile
+++ got/Makefile
@@ -12,7 +12,7 @@ SRCS=		got.c blame.c commit_graph.c delta.c diff.c \
 		gotconfig.c diff_main.c diff_atomize_text.c \
 		diff_myers.c diff_output.c diff_output_plain.c \
 		diff_output_unidiff.c diff_output_edscript.c \
-		diff_patience.c send.c deltify.c pack_create.c
+		diff_patience.c send.c deltify.c pack_create.c dial.c
 
 MAN =		${PROG}.1 got-worktree.5 git-repository.5 got.conf.5
 
blob - e7638e1bfc66827e100c0706e810805be3fa972e
blob + a907f12b2708cbb1ea36221531d27fbd95446daf
--- got/got.c
+++ got/got.c
@@ -55,6 +55,7 @@
 #include "got_privsep.h"
 #include "got_opentemp.h"
 #include "got_gotconfig.h"
+#include "got_dial.h"
 
 #ifndef nitems
 #define nitems(_a)	(sizeof((_a)) / sizeof((_a)[0]))
@@ -1598,13 +1599,10 @@ cmd_clone(int argc, char *argv[])
 		}
 	}
 
-	if (strcmp(proto, "git+ssh") == 0 || strcmp(proto, "ssh") == 0) {
-		if (unveil(GOT_FETCH_PATH_SSH, "x") != 0) {
-			error = got_error_from_errno2("unveil",
-			    GOT_FETCH_PATH_SSH);
-			goto done;
-		}
-	}
+	error = got_dial_apply_unveil(proto);
+	if (error)
+		goto done;
+
 	error = apply_unveil(repo_path, 0, NULL);
 	if (error)
 		goto done;
@@ -2408,13 +2406,10 @@ cmd_fetch(int argc, char *argv[])
 		goto done;
 	}
 
-	if (strcmp(proto, "git+ssh") == 0 || strcmp(proto, "ssh") == 0) {
-		if (unveil(GOT_FETCH_PATH_SSH, "x") != 0) {
-			error = got_error_from_errno2("unveil",
-			    GOT_FETCH_PATH_SSH);
-			goto done;
-		}
-	}
+	error = got_dial_apply_unveil(proto);
+	if (error)
+		goto done;
+
 	error = apply_unveil(got_repo_get_path(repo), 0, NULL);
 	if (error)
 		goto done;
@@ -7726,13 +7721,10 @@ cmd_send(int argc, char *argv[])
 		goto done;
 	}
 
-	if (strcmp(proto, "git+ssh") == 0 || strcmp(proto, "ssh") == 0) {
-		if (unveil(GOT_FETCH_PATH_SSH, "x") != 0) {
-			error = got_error_from_errno2("unveil",
-			    GOT_FETCH_PATH_SSH);
-			goto done;
-		}
-	}
+	error = got_dial_apply_unveil(proto);
+	if (error)
+		goto done;
+
 	error = apply_unveil(got_repo_get_path(repo), 0, NULL);
 	if (error)
 		goto done;
blob - /dev/null
blob + b213aadb14e213dfe28a280f089b6efff3e384f8 (mode 644)
--- /dev/null
+++ include/got_dial.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2021 Stefan Sperling <stsp@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+const struct got_error *got_dial_apply_unveil(const char *proto);
blob - ec4d2dc496a45f2a0804737eeb32ad4991f4c8ba
blob + 0678325a656296d677ef121766f0c17a0ea3c6cf
--- include/got_fetch.h
+++ include/got_fetch.h
@@ -14,14 +14,6 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* IANA assigned */
-#define GOT_DEFAULT_GIT_PORT		9418
-#define GOT_DEFAULT_GIT_PORT_STR	"9418"
-
-#ifndef GOT_FETCH_PATH_SSH
-#define GOT_FETCH_PATH_SSH	"/usr/bin/ssh"
-#endif
-
 #define GOT_FETCH_DEFAULT_REMOTE_NAME	"origin"
 
 #define GOT_FETCH_PKTMAX	65536
blob - 2f0388ea400f048c63027a0b901c892f672248bc
blob + a805a93b43a7bd5f89c592a6da5982f41dd96ae6
--- include/got_send.h
+++ include/got_send.h
@@ -15,14 +15,6 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* IANA assigned */
-#define GOT_DEFAULT_GIT_PORT		9418
-#define GOT_DEFAULT_GIT_PORT_STR	"9418"
-
-#ifndef GOT_SEND_PATH_SSH
-#define GOT_SEND_PATH_SSH	"/usr/bin/ssh"
-#endif
-
 #define GOT_SEND_DEFAULT_REMOTE_NAME	"origin"
 
 #define GOT_SEND_PKTMAX	65536
blob - /dev/null
blob + 43fd6d170ab25f2d04f322214d7b0ee370c4d9f5 (mode 644)
--- /dev/null
+++ lib/dial.c
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2018, 2019 Ori Bernstein <ori@openbsd.org>
+ * Copyright (c) 2021 Stefan Sperling <stsp@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "got_error.h"
+
+#include "got_lib_dial.h"
+
+#ifndef ssizeof
+#define ssizeof(_x) ((ssize_t)(sizeof(_x)))
+#endif
+
+#ifndef MIN
+#define	MIN(_a,_b) ((_a) < (_b) ? (_a) : (_b))
+#endif
+
+#ifndef GOT_DIAL_PATH_SSH
+#define GOT_DIAL_PATH_SSH	"/usr/bin/ssh"
+#endif
+
+/* IANA assigned */
+#define GOT_DEFAULT_GIT_PORT		9418
+#define GOT_DEFAULT_GIT_PORT_STR	"9418"
+
+const struct got_error *
+got_dial_apply_unveil(const char *proto)
+{
+	if (strcmp(proto, "git+ssh") == 0 || strcmp(proto, "ssh") == 0) {
+		if (unveil(GOT_DIAL_PATH_SSH, "x") != 0) {
+			return got_error_from_errno2("unveil",
+			    GOT_DIAL_PATH_SSH);
+		}
+	}
+
+	return NULL;
+}
+
+const struct got_error *
+got_dial_ssh(pid_t *newpid, int *newfd, const char *host,
+    const char *port, const char *path, const char *direction, int verbosity)
+{
+	const struct got_error *error = NULL;
+	int pid, pfd[2];
+	char cmd[64];
+	char *argv[11];
+	int i = 0, j;
+
+	*newpid = -1;
+	*newfd = -1;
+
+	argv[i++] = GOT_DIAL_PATH_SSH;
+	if (port != NULL) {
+		argv[i++] = "-p";
+		argv[i++] = (char *)port;
+	}
+	if (verbosity == -1) {
+		argv[i++] = "-q";
+	} else {
+		/* ssh(1) allows up to 3 "-v" options. */
+		for (j = 0; j < MIN(3, verbosity); j++)
+			argv[i++] = "-v";
+	}
+	argv[i++] = "--";
+	argv[i++] = (char *)host;
+	argv[i++] = (char *)cmd;
+	argv[i++] = (char *)path;
+	argv[i++] = NULL;
+
+	if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pfd) == -1)
+		return got_error_from_errno("socketpair");
+
+	pid = fork();
+	if (pid == -1) {
+		error = got_error_from_errno("fork");
+		close(pfd[0]);
+		close(pfd[1]);
+		return error;
+	} else if (pid == 0) {
+		int n;
+		if (close(pfd[1]) == -1)
+			err(1, "close");
+		if (dup2(pfd[0], 0) == -1)
+			err(1, "dup2");
+		if (dup2(pfd[0], 1) == -1)
+			err(1, "dup2");
+		n = snprintf(cmd, sizeof(cmd), "git-%s-pack", direction);
+		if (n < 0 || n >= ssizeof(cmd))
+			err(1, "snprintf");
+		if (execv(GOT_DIAL_PATH_SSH, argv) == -1)
+			err(1, "execv");
+		abort(); /* not reached */
+	} else {
+		if (close(pfd[0]) == -1)
+			return got_error_from_errno("close");
+		*newpid = pid;
+		*newfd = pfd[1];
+		return NULL;
+	}
+}
+
+const struct got_error *
+got_dial_git(int *newfd, const char *host, const char *port,
+    const char *path, const char *direction)
+{
+	const struct got_error *err = NULL;
+	struct addrinfo hints, *servinfo, *p;
+	char *cmd = NULL;
+	int fd = -1, len, r, eaicode;
+
+	*newfd = -1;
+
+	if (port == NULL)
+		port = GOT_DEFAULT_GIT_PORT_STR;
+
+	memset(&hints, 0, sizeof hints);
+	hints.ai_family = AF_UNSPEC;
+	hints.ai_socktype = SOCK_STREAM;
+	eaicode = getaddrinfo(host, port, &hints, &servinfo);
+	if (eaicode) {
+		char msg[512];
+		snprintf(msg, sizeof(msg), "%s: %s", host,
+		    gai_strerror(eaicode));
+		return got_error_msg(GOT_ERR_ADDRINFO, msg);
+	}
+
+	for (p = servinfo; p != NULL; p = p->ai_next) {
+		if ((fd = socket(p->ai_family, p->ai_socktype,
+		    p->ai_protocol)) == -1)
+			continue;
+		if (connect(fd, p->ai_addr, p->ai_addrlen) == 0) {
+			err = NULL;
+			break;
+		}
+		err = got_error_from_errno("connect");
+		close(fd);
+	}
+	if (p == NULL)
+		goto done;
+
+	if (asprintf(&cmd, "git-%s-pack %s", direction, path) == -1) {
+		err = got_error_from_errno("asprintf");
+		goto done;
+	}
+	len = 4 + strlen(cmd) + 1 + strlen("host=") + strlen(host) + 1;
+	r = dprintf(fd, "%04x%s%chost=%s%c", len, cmd, '\0', host, '\0');
+	if (r < 0)
+		err = got_error_from_errno("dprintf");
+done:
+	free(cmd);
+	if (err) {
+		if (fd != -1)
+			close(fd);
+	} else
+		*newfd = fd;
+	return err;
+}
blob - 798e728b740269a24d6c9570992490578f0ce78c
blob + 58ebe83cb10ef337c7ed983de51d61cc5f631253
--- lib/fetch.c
+++ lib/fetch.c
@@ -39,8 +39,6 @@
 #include <imsg.h>
 #include <time.h>
 #include <uuid.h>
-#include <netdb.h>
-#include <netinet/in.h>
 
 #include "got_error.h"
 #include "got_reference.h"
@@ -62,6 +60,7 @@
 #include "got_lib_privsep.h"
 #include "got_lib_object_cache.h"
 #include "got_lib_repository.h"
+#include "got_lib_dial.h"
 
 #ifndef nitems
 #define nitems(_a)	(sizeof((_a)) / sizeof((_a)[0]))
@@ -85,126 +84,6 @@ hassuffix(char *base, char *suf)
 	if (ns <= nb && strcmp(base + (nb - ns), suf) == 0)
 		return 1;
 	return 0;
-}
-
-static const struct got_error *
-dial_ssh(pid_t *fetchpid, int *fetchfd, const char *host, const char *port,
-    const char *path, const char *direction, int verbosity)
-{
-	const struct got_error *error = NULL;
-	int pid, pfd[2];
-	char cmd[64];
-	char *argv[11];
-	int i = 0, j;
-
-	*fetchpid = -1;
-	*fetchfd = -1;
-
-	argv[i++] = GOT_FETCH_PATH_SSH;
-	if (port != NULL) {
-		argv[i++] = "-p";
-		argv[i++] = (char *)port;
-	}
-	if (verbosity == -1) {
-		argv[i++] = "-q";
-	} else {
-		/* ssh(1) allows up to 3 "-v" options. */
-		for (j = 0; j < MIN(3, verbosity); j++)
-			argv[i++] = "-v";
-	}
-	argv[i++] = "--";
-	argv[i++] = (char *)host;
-	argv[i++] = (char *)cmd;
-	argv[i++] = (char *)path;
-	argv[i++] = NULL;
-
-	if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pfd) == -1)
-		return got_error_from_errno("socketpair");
-
-	pid = fork();
-	if (pid == -1) {
-		error = got_error_from_errno("fork");
-		close(pfd[0]);
-		close(pfd[1]);
-		return error;
-	} else if (pid == 0) {
-		int n;
-		if (close(pfd[1]) == -1)
-			err(1, "close");
-		if (dup2(pfd[0], 0) == -1)
-			err(1, "dup2");
-		if (dup2(pfd[0], 1) == -1)
-			err(1, "dup2");
-		n = snprintf(cmd, sizeof(cmd), "git-%s-pack", direction);
-		if (n < 0 || n >= ssizeof(cmd))
-			err(1, "snprintf");
-		if (execv(GOT_FETCH_PATH_SSH, argv) == -1)
-			err(1, "execv");
-		abort(); /* not reached */
-	} else {
-		if (close(pfd[0]) == -1)
-			return got_error_from_errno("close");
-		*fetchpid = pid;
-		*fetchfd = pfd[1];
-		return NULL;
-	}
-}
-
-static const struct got_error *
-dial_git(int *fetchfd, const char *host, const char *port, const char *path,
-    const char *direction)
-{
-	const struct got_error *err = NULL;
-	struct addrinfo hints, *servinfo, *p;
-	char *cmd = NULL;
-	int fd = -1, len, r, eaicode;
-
-	*fetchfd = -1;
-
-	if (port == NULL)
-		port = GOT_DEFAULT_GIT_PORT_STR;
-
-	memset(&hints, 0, sizeof hints);
-	hints.ai_family = AF_UNSPEC;
-	hints.ai_socktype = SOCK_STREAM;
-	eaicode = getaddrinfo(host, port, &hints, &servinfo);
-	if (eaicode) {
-		char msg[512];
-		snprintf(msg, sizeof(msg), "%s: %s", host,
-		    gai_strerror(eaicode));
-		return got_error_msg(GOT_ERR_ADDRINFO, msg);
-	}
-
-	for (p = servinfo; p != NULL; p = p->ai_next) {
-		if ((fd = socket(p->ai_family, p->ai_socktype,
-		    p->ai_protocol)) == -1)
-			continue;
-		if (connect(fd, p->ai_addr, p->ai_addrlen) == 0) {
-			err = NULL;
-			break;
-		}
-		err = got_error_from_errno("connect");
-		close(fd);
-	}
-	if (p == NULL)
-		goto done;
-
-	if (asprintf(&cmd, "git-%s-pack %s", direction, path) == -1) {
-		err = got_error_from_errno("asprintf");
-		goto done;
-	}
-	len = 4 + strlen(cmd) + 1 + strlen("host=") + strlen(host) + 1;
-	r = dprintf(fd, "%04x%s%chost=%s%c", len, cmd, '\0', host, '\0');
-	if (r < 0)
-		err = got_error_from_errno("dprintf");
-done:
-	free(cmd);
-	if (err) {
-		if (fd != -1)
-			close(fd);
-	} else
-		*fetchfd = fd;
-	return err;
 }
 
 const struct got_error *
@@ -217,10 +96,11 @@ got_fetch_connect(pid_t *fetchpid, int *fetchfd, const
 	*fetchfd = -1;
 
 	if (strcmp(proto, "ssh") == 0 || strcmp(proto, "git+ssh") == 0)
-		err = dial_ssh(fetchpid, fetchfd, host, port, server_path,
-		    "upload", verbosity);
+		err = got_dial_ssh(fetchpid, fetchfd, host, port,
+		    server_path, GOT_DIAL_DIRECTION_FETCH, verbosity);
 	else if (strcmp(proto, "git") == 0)
-		err = dial_git(fetchfd, host, port, server_path, "upload");
+		err = got_dial_git(fetchfd, host, port, server_path,
+		    GOT_DIAL_DIRECTION_FETCH);
 	else if (strcmp(proto, "http") == 0 || strcmp(proto, "git+http") == 0)
 		err = got_error_path(proto, GOT_ERR_NOT_IMPL);
 	else
blob - /dev/null
blob + cbaf4ea224445b13ae795d7ec9ddb72fda40ab52 (mode 644)
--- /dev/null
+++ lib/got_lib_dial.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2019 Ori Bernstein <ori@openbsd.org>
+ * Copyright (c) 2021 Stefan Sperling <stsp@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#define GOT_DIAL_DIRECTION_SEND		"receive"
+#define GOT_DIAL_DIRECTION_FETCH	"upload"
+
+const struct got_error *got_dial_git(int *newfd, const char *host,
+    const char *port, const char *path, const char *direction);
+
+const struct got_error *got_dial_ssh(pid_t *newpid, int *newfd,
+    const char *host, const char *port, const char *path,
+    const char *direction, int verbosity);
blob - 6c977a92f5e574ca78d050e9d534527d8b10d122
blob + 389638ce5e6ef123646ace201dde42a8e1706e20
--- lib/send.c
+++ lib/send.c
@@ -40,8 +40,6 @@
 #include <imsg.h>
 #include <time.h>
 #include <uuid.h>
-#include <netdb.h>
-#include <netinet/in.h>
 
 #include "got_error.h"
 #include "got_reference.h"
@@ -66,6 +64,7 @@
 #include "got_lib_object_cache.h"
 #include "got_lib_repository.h"
 #include "got_lib_pack_create.h"
+#include "got_lib_dial.h"
 
 #ifndef nitems
 #define nitems(_a)	(sizeof((_a)) / sizeof((_a)[0]))
@@ -78,127 +77,7 @@
 #ifndef MIN
 #define	MIN(_a,_b) ((_a) < (_b) ? (_a) : (_b))
 #endif
-
-static const struct got_error *
-dial_ssh(pid_t *sendpid, int *sendfd, const char *host, const char *port,
-    const char *path, const char *direction, int verbosity)
-{
-	const struct got_error *error = NULL;
-	int pid, pfd[2];
-	char cmd[64];
-	char *argv[11];
-	int i = 0, j;
-
-	*sendpid = -1;
-	*sendfd = -1;
-
-	argv[i++] = GOT_SEND_PATH_SSH;
-	if (port != NULL) {
-		argv[i++] = "-p";
-		argv[i++] = (char *)port;
-	}
-	if (verbosity == -1) {
-		argv[i++] = "-q";
-	} else {
-		/* ssh(1) allows up to 3 "-v" options. */
-		for (j = 0; j < MIN(3, verbosity); j++)
-			argv[i++] = "-v";
-	}
-	argv[i++] = "--";
-	argv[i++] = (char *)host;
-	argv[i++] = (char *)cmd;
-	argv[i++] = (char *)path;
-	argv[i++] = NULL;
-
-	if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pfd) == -1)
-		return got_error_from_errno("socketpair");
-
-	pid = fork();
-	if (pid == -1) {
-		error = got_error_from_errno("fork");
-		close(pfd[0]);
-		close(pfd[1]);
-		return error;
-	} else if (pid == 0) {
-		int n;
-		if (close(pfd[1]) == -1)
-			err(1, "close");
-		if (dup2(pfd[0], 0) == -1)
-			err(1, "dup2");
-		if (dup2(pfd[0], 1) == -1)
-			err(1, "dup2");
-		n = snprintf(cmd, sizeof(cmd), "git-%s-pack", direction);
-		if (n < 0 || n >= ssizeof(cmd))
-			err(1, "snprintf");
-		if (execv(GOT_SEND_PATH_SSH, argv) == -1)
-			err(1, "execv");
-		abort(); /* not reached */
-	} else {
-		if (close(pfd[0]) == -1)
-			return got_error_from_errno("close");
-		*sendpid = pid;
-		*sendfd = pfd[1];
-		return NULL;
-	}
-}
-
-static const struct got_error *
-dial_git(int *sendfd, const char *host, const char *port, const char *path,
-    const char *direction)
-{
-	const struct got_error *err = NULL;
-	struct addrinfo hints, *servinfo, *p;
-	char *cmd = NULL;
-	int fd = -1, len, r, eaicode;
 
-	*sendfd = -1;
-
-	if (port == NULL)
-		port = GOT_DEFAULT_GIT_PORT_STR;
-
-	memset(&hints, 0, sizeof hints);
-	hints.ai_family = AF_UNSPEC;
-	hints.ai_socktype = SOCK_STREAM;
-	eaicode = getaddrinfo(host, port, &hints, &servinfo);
-	if (eaicode) {
-		char msg[512];
-		snprintf(msg, sizeof(msg), "%s: %s", host,
-		    gai_strerror(eaicode));
-		return got_error_msg(GOT_ERR_ADDRINFO, msg);
-	}
-
-	for (p = servinfo; p != NULL; p = p->ai_next) {
-		if ((fd = socket(p->ai_family, p->ai_socktype,
-		    p->ai_protocol)) == -1)
-			continue;
-		if (connect(fd, p->ai_addr, p->ai_addrlen) == 0) {
-			err = NULL;
-			break;
-		}
-		err = got_error_from_errno("connect");
-		close(fd);
-	}
-	if (p == NULL)
-		goto done;
-
-	if (asprintf(&cmd, "git-%s-pack %s", direction, path) == -1) {
-		err = got_error_from_errno("asprintf");
-		goto done;
-	}
-	len = 4 + strlen(cmd) + 1 + strlen("host=") + strlen(host) + 1;
-	r = dprintf(fd, "%04x%s%chost=%s%c", len, cmd, '\0', host, '\0');
-	if (r < 0)
-		err = got_error_from_errno("dprintf");
-done:
-	free(cmd);
-	if (err) {
-		if (fd != -1)
-			close(fd);
-	} else
-		*sendfd = fd;
-	return err;
-}
-
 const struct got_error *
 got_send_connect(pid_t *sendpid, int *sendfd, const char *proto,
     const char *host, const char *port, const char *server_path, int verbosity)
@@ -209,10 +88,11 @@ got_send_connect(pid_t *sendpid, int *sendfd, const ch
 	*sendfd = -1;
 
 	if (strcmp(proto, "ssh") == 0 || strcmp(proto, "git+ssh") == 0)
-		err = dial_ssh(sendpid, sendfd, host, port, server_path,
-		    "receive", verbosity);
+		err = got_dial_ssh(sendpid, sendfd, host, port, server_path,
+		    GOT_DIAL_DIRECTION_SEND, verbosity);
 	else if (strcmp(proto, "git") == 0)
-		err = dial_git(sendfd, host, port, server_path, "receive");
+		err = got_dial_git(sendfd, host, port, server_path,
+		    GOT_DIAL_DIRECTION_SEND);
 	else if (strcmp(proto, "http") == 0 || strcmp(proto, "git+http") == 0)
 		err = got_error_path(proto, GOT_ERR_NOT_IMPL);
 	else