Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
Merge branch 'blacklion-master'
Matthew Seaman committed 11 years ago
commit ae929c4e9b0e2e8891a7b22e01e6131ee1f3f61f
parent 0c63be2
9 files changed +123 -26
modified docs/pkg.8
@@ -15,7 +15,7 @@
.\"     @(#)pkg.8
.\" $FreeBSD$
.\"
-
.Dd August 14, 2014
+
.Dd September 13, 2014
.Dt PKG 8
.Os
.\" ---------------------------------------------------------------------------
@@ -33,6 +33,7 @@
.Op Fl j Ao jail name or id Ac | Fl c Ao chroot path Ac
.Op Fl C Ao configuration file Ac
.Op Fl R Ao repository configuration directory Ac
+
.Op Fl 4 | Fl 6
.Ao command Ac Ao Ar flags Ac
.Pp
.Nm
@@ -43,6 +44,7 @@
.Op Cm --jail Ao jail name or id Ac | Cm --chroot Ao chroot path Ac
.Op Cm --config Ao configuration file Ac
.Op Cm --repo-conf-dir Ao repository configuration directory Ac
+
.Op Fl 4 | Fl 6
.Ao command Ac Ao Ar flags Ac
.\" ---------------------------------------------------------------------------
.Sh DESCRIPTION
@@ -171,6 +173,12 @@ will search the directory for per-repository configuration files.
This overrides any value of
.Ev REPOS_DIR
specified in the main configuration file.
+
.It Fl 4
+
.Nm
+
will use IPv4 for fetching repository and packages.
+
.It Fl 6
+
.Nm
+
will use IPv6 for fetching repository and packages.
.El
.\" ---------------------------------------------------------------------------
.Sh COMMANDS
modified docs/pkg.conf.5
@@ -15,7 +15,7 @@
.\"     @(#)pkg.1
.\" $FreeBSD$
.\"
-
.Dd August 17, 2014
+
.Dd September 13, 2014
.Dt PKG.CONF 5
.Os
.Sh NAME
@@ -142,6 +142,11 @@ or
Default: INDEX-N where
.Cm N
is the OS major version number.
+
.It Cm IP_VERSION: integer
+
Restrict network access to specified IP version.
+
Could be 4 for IPv4, 6 for IPv6 or any other value for system default.
+
Repositories or command line options could override this setting.
+
Default: 0.
.It Cm LOCK_RETRIES: integer
Retries performed to obtain a lock.
Default: 5.
@@ -313,6 +318,12 @@ This should be set to a path containing public key for this repository
only. (default: NONE)
.It Cm FINGERPRINTS: string
This should be set to a path containing known signatures for the repository.
+
.It Cm IP_VERSION: integer
+
Restrict network access to specified IP version.
+
Could be 4 for IPv4, 6 for IPv6 or any other value for system default.
+
This option overrides the global setting with the same name and can be
+
overwritten by a command line option.
+
Default: 0.
.El
.El
.Pp
modified libpkg/fetch.c
@@ -362,6 +362,10 @@ start_ssh(struct pkg_repo *repo, struct url *u, off_t *sz)
			sbuf_cat(cmd, "/usr/bin/ssh -e none -T ");
			if (ssh_args != NULL)
				sbuf_printf(cmd, "%s ", ssh_args);
+
			if ((repo->flags & REPO_FLAGS_USE_IPV4) == REPO_FLAGS_USE_IPV4)
+
				sbuf_cat(cmd, "-4 ");
+
			else if ((repo->flags & REPO_FLAGS_USE_IPV6) == REPO_FLAGS_USE_IPV6)
+
				sbuf_cat(cmd, "-6 ");
			if (u->port > 0)
				sbuf_printf(cmd, "-p %d ", u->port);
			if (u->user[0] != '\0')
@@ -465,6 +469,7 @@ pkg_fetch_file_to_fd(struct pkg_repo *repo, const char *url, int dest, time_t *t
	struct http_mirror	*http_current = NULL;
	off_t		 sz = 0;
	bool		 pkg_url_scheme = false;
+
	struct sbuf	*fetchOpts = NULL;

	max_retry = pkg_object_int(pkg_config_get("FETCH_RETRY"));
	fetch_timeout = pkg_object_int(pkg_config_get("FETCH_TIMEOUT"));
@@ -551,13 +556,23 @@ pkg_fetch_file_to_fd(struct pkg_repo *repo, const char *url, int dest, time_t *t
			u->port = http_current->url->port;
		}

-
		pkg_debug(1,"Fetch: fetching from: %s://%s%s%s%s",
+
 
+
		fetchOpts = sbuf_new_auto();
+
		sbuf_cat(fetchOpts, "i");
+
		if ((repo->flags & REPO_FLAGS_USE_IPV4) == REPO_FLAGS_USE_IPV4)
+
			sbuf_cat(fetchOpts, "4");
+
		else if ((repo->flags & REPO_FLAGS_USE_IPV6) == REPO_FLAGS_USE_IPV6)
+
			sbuf_cat(fetchOpts, "6");
+

+
		pkg_debug(1,"Fetch: fetching from: %s://%s%s%s%s with opts \"%s\"",
		    u->scheme,
		    u->user,
		    u->user[0] != '\0' ? "@" : "",
		    u->host,
-
		    u->doc);
-
		remote = fetchXGet(u, &st, "i");
+
		    u->doc,
+
		    sbuf_data(fetchOpts));
+
		
+
		remote = fetchXGet(u, &st, sbuf_data(fetchOpts));
		if (remote == NULL) {
			if (fetchLastErrCode == FETCH_OK) {
				retcode = EPKG_UPTODATE;
modified libpkg/pkg.h.in
@@ -144,6 +144,11 @@ typedef enum {
	PKGDB_MAYBE_REMOTE
} pkgdb_t;

+
typedef enum {
+
	PKG_INIT_FLAG_USE_IPV4 = (1U << 0),
+
	PKG_INIT_FLAG_USE_IPV6 = (1U << 1)
+
} pkg_init_flags;
+

/**
 * Specify how an argument should be used by query functions.
 */
@@ -357,7 +362,9 @@ typedef enum _pkg_flags {
	PKG_FLAG_UPGRADES_FOR_INSTALLED = (1U << 7),
	PKG_FLAG_SKIP_INSTALL = (1U << 8),
	PKG_FLAG_FORCE_MISSING = (1U << 9),
-
	PKG_FLAG_FETCH_MIRROR = (1U << 10)
+
	PKG_FLAG_FETCH_MIRROR = (1U << 10),
+
	PKG_FLAG_USE_IPV4 = (1U << 11),
+
	PKG_FLAG_USE_IPV6 = (1U << 12)
} pkg_flags;

typedef enum _pkg_stats_t {
@@ -1595,7 +1602,7 @@ typedef int(*pkg_event_cb)(void *, struct pkg_event *);
void pkg_event_register(pkg_event_cb cb, void *data);

bool pkg_compiled_for_same_os_major(void);
-
int pkg_init(const char *, const char *);
+
int pkg_init(const char *, const char *, pkg_init_flags);
int pkg_initialized(void);
void pkg_shutdown(void);

modified libpkg/pkg_config.c
@@ -1,4 +1,4 @@
-
/*-
+
/*
 * Copyright (c) 2011-2014 Baptiste Daroussin <bapt@FreeBSD.org>
 * Copyright (c) 2011-2012 Julien Laffaye <jlaffaye@FreeBSD.org>
 * Copyright (c) 2014 Matthew Seaman <matthew@FreeBSD.org>
@@ -315,6 +315,12 @@ static struct config_entry c[] = {
		"PLIST_ACCEPT_DIRECTORIES",
		"NO",
		"Accept directories listed like plain files in plist"
+
	},
+
	{
+
		PKG_INT,
+
		"IP_VERSION",
+
		"0",
+
		"Restrict network access to IPv4 or IPv6 only"
	}
};

@@ -409,7 +415,7 @@ disable_plugins_if_static(void)
}

static void
-
add_repo(const ucl_object_t *obj, struct pkg_repo *r, const char *rname)
+
add_repo(const ucl_object_t *obj, struct pkg_repo *r, const char *rname, pkg_init_flags flags)
{
	const ucl_object_t *cur, *enabled;
	ucl_object_iter_t it = NULL;
@@ -418,6 +424,7 @@ add_repo(const ucl_object_t *obj, struct pkg_repo *r, const char *rname)
	const char *signature_type = NULL, *fingerprints = NULL;
	const char *key;
	const char *type = NULL;
+
	int use_ipvx;

	pkg_debug(1, "PkgConfig: parsing repository object %s", rname);

@@ -495,6 +502,16 @@ add_repo(const ucl_object_t *obj, struct pkg_repo *r, const char *rname)
				return;
			}
			type = ucl_object_tostring(cur);
+
		} else if (strcasecmp(key, "ip_version") == 0) {
+
			if (cur->type != UCL_INT) {
+
				pkg_emit_error("Expecting a integer for the "
+
					"'%s' key of the '%s' repo",
+
					key, rname);
+
				return;
+
			}
+
			use_ipvx = ucl_object_toint(cur);
+
			if (use_ipvx != 4 && use_ipvx != 6)
+
				use_ipvx = 0;
		}
	}

@@ -538,10 +555,23 @@ add_repo(const ucl_object_t *obj, struct pkg_repo *r, const char *rname)
		else
			r->mirror_type = NOMIRROR;
	}
+

+
	if ((flags & PKG_INIT_FLAG_USE_IPV4) == PKG_INIT_FLAG_USE_IPV4)
+
		use_ipvx = 4;
+
	else if ((flags & PKG_INIT_FLAG_USE_IPV6) == PKG_INIT_FLAG_USE_IPV6)
+
		use_ipvx = 6;
+

+
	if (use_ipvx != 4 && use_ipvx != 6)
+
		use_ipvx = pkg_object_int(pkg_config_get("IP_VERSION"));
+

+
	if (use_ipvx == 4)
+
		r->flags = REPO_FLAGS_USE_IPV4;
+
	else if (use_ipvx == 6)
+
		r->flags = REPO_FLAGS_USE_IPV6;
}

static void
-
walk_repo_obj(const ucl_object_t *obj, const char *file)
+
walk_repo_obj(const ucl_object_t *obj, const char *file, pkg_init_flags flags)
{
	const ucl_object_t *cur;
	ucl_object_iter_t it = NULL;
@@ -555,7 +585,7 @@ walk_repo_obj(const ucl_object_t *obj, const char *file)
		if (r != NULL)
			pkg_debug(1, "PkgConfig: overwriting repository %s", key);
		if (cur->type == UCL_OBJECT)
-
			add_repo(cur, r, key);
+
			add_repo(cur, r, key, flags);
		else
			pkg_emit_error("Ignoring bad configuration entry in %s: %s",
			    file, ucl_object_emit(cur, UCL_EMIT_YAML));
@@ -563,7 +593,7 @@ walk_repo_obj(const ucl_object_t *obj, const char *file)
}

static void
-
load_repo_file(const char *repofile)
+
load_repo_file(const char *repofile, pkg_init_flags flags)
{
	struct ucl_parser *p;
	ucl_object_t *obj = NULL;
@@ -587,13 +617,13 @@ load_repo_file(const char *repofile)
		return;

	if (obj->type == UCL_OBJECT)
-
		walk_repo_obj(obj, repofile);
+
		walk_repo_obj(obj, repofile, flags);

	ucl_object_unref(obj);
}

static void
-
load_repo_files(const char *repodir)
+
load_repo_files(const char *repodir, pkg_init_flags flags)
{
	struct dirent *ent;
	DIR *d;
@@ -614,26 +644,26 @@ load_repo_files(const char *repodir)
			    repodir,
			    repodir[strlen(repodir) - 1] == '/' ? "" : "/",
			    ent->d_name);
-
			load_repo_file(path);
+
			load_repo_file(path, flags);
		}
	}
	closedir(d);
}

static void
-
load_repositories(const char *repodir)
+
load_repositories(const char *repodir, pkg_init_flags flags)
{
	const pkg_object *reposlist, *cur;
	pkg_iter it = NULL;

	if (repodir != NULL) {
-
		load_repo_files(repodir);
+
		load_repo_files(repodir, flags);
		return;
	}

	reposlist = pkg_config_get( "REPOS_DIR");
	while ((cur = pkg_object_iterate(reposlist, &it)))
-
		load_repo_files(pkg_object_string(cur));
+
		load_repo_files(pkg_object_string(cur), flags);
}

bool
@@ -657,7 +687,7 @@ pkg_compiled_for_same_os_major(void)


int
-
pkg_init(const char *path, const char *reposdir)
+
pkg_init(const char *path, const char *reposdir, pkg_init_flags flags)
{
	struct ucl_parser *p = NULL;
	size_t i;
@@ -681,6 +711,12 @@ pkg_init(const char *path, const char *reposdir)
		return (EPKG_FATAL);
	}

+
	if (((flags & PKG_INIT_FLAG_USE_IPV4) == PKG_INIT_FLAG_USE_IPV4) &&
+
	    ((flags & PKG_INIT_FLAG_USE_IPV6) == PKG_INIT_FLAG_USE_IPV6)) {
+
		pkg_emit_error("Invalid flags for pkg_init()");
+
		return (EPKG_FATAL);
+
	}
+

	config = ucl_object_typed_new(UCL_OBJECT);

	for (i = 0; i < c_size; i++) {
@@ -933,7 +969,7 @@ pkg_init(const char *path, const char *reposdir)
	}

	/* load the repositories */
-
	load_repositories(reposdir);
+
	load_repositories(reposdir, flags);

	setenv("HTTP_USER_AGENT", "pkg/"PKGVERSION, 1);

modified libpkg/private/pkg.h
@@ -315,6 +315,11 @@ struct pkg_repo_ops {
		const char *destdir);
};

+
typedef enum _pkg_repo_flags {
+
	REPO_FLAGS_USE_IPV4 = (1U << 0),
+
	REPO_FLAGS_USE_IPV6 = (1U << 1)
+
} pkg_repo_flags;
+

struct pkg_repo {
	struct pkg_repo_ops *ops;

@@ -344,6 +349,8 @@ struct pkg_repo {
	bool enable;
	UT_hash_handle hh;

+
	pkg_repo_flags flags;
+

	/* Opaque repository data */
	void *priv;
};
modified src/globals.c
@@ -42,3 +42,4 @@ set_globals(void)
	quiet = 0;
	newpkgversion = 0;
}
+

modified src/main.c
@@ -164,9 +164,9 @@ usage(const char *conffile, const char *reposdir, FILE *out, enum pkg_usage_reas
	}

#ifdef HAVE_LIBJAIL
-
 	fprintf(out, "Usage: pkg [-v] [-d] [-l] [-N] [-j <jail name or id>|-c <chroot path>] [-C <configuration file>] [-R <repo config dir>] [-o var=value] <command> [<args>]\n\n");
+
 	fprintf(out, "Usage: pkg [-v] [-d] [-l] [-N] [-j <jail name or id>|-c <chroot path>] [-C <configuration file>] [-R <repo config dir>] [-o var=value] [-4|-6] <command> [<args>]\n\n");
#else
-
	fprintf(out, "Usage: pkg [-v] [-d] [-l] [-N] [-c <chroot path>] [-C <configuration file>] [-R <repo config dir>] [-o var=value] <command> [<args>]\n\n");
+
	fprintf(out, "Usage: pkg [-v] [-d] [-l] [-N] [-c <chroot path>] [-C <configuration file>] [-R <repo config dir>] [-o var=value] [-4|-6] <command> [<args>]\n\n");
#endif
	if (reason == PKG_USAGE_HELP) {
		fprintf(out, "Global options supported:\n");
@@ -181,12 +181,14 @@ usage(const char *conffile, const char *reposdir, FILE *out, enum pkg_usage_reas
		fprintf(out, "\t%-15s%s\n", "-v", "Display pkg(8) version");
		fprintf(out, "\t%-15s%s\n\n", "-N", "Test if pkg(8) is activated and avoid auto-activation");
		fprintf(out, "\t%-15s%s\n\n", "-o", "Override configuration option from the command line");
+
		fprintf(out, "\t%-15s%s\n", "-4", "Only use IPv4");
+
		fprintf(out, "\t%-15s%s\n", "-6", "Only use IPv6");
		fprintf(out, "Commands supported:\n");

		for (i = 0; i < cmd_len; i++)
			fprintf(out, "\t%-15s%s\n", cmd[i].name, cmd[i].desc);

-
		if (!pkg_initialized() && pkg_init(conffile, reposdir) != EPKG_OK)
+
		if (!pkg_initialized() && pkg_init(conffile, reposdir, 0) != EPKG_OK)
			errx(EX_SOFTWARE, "Cannot parse configuration file!");

		plugins_enabled = pkg_object_bool(pkg_config_get("PKG_ENABLE_PLUGINS"));
@@ -559,6 +561,7 @@ main(int argc, char **argv)
	bool		  plugin_found = false;
	bool		  show_commands = false;
	bool		  activation_test = false;
+
	pkg_init_flags	  init_flags = 0;
	struct plugcmd	 *c;
	const char	 *conffile = NULL;
	const char	 *reposdir = NULL;
@@ -576,6 +579,8 @@ main(int argc, char **argv)
		{ "list",		no_argument,		NULL,	'l' },
		{ "version",		no_argument,		NULL,	'v' },
		{ "option",		required_argument,	NULL,	'o' },
+
		{ "only-ipv4",		no_argument,		NULL,	'4' },
+
		{ "only-ipv6",		no_argument,		NULL,	'6' },
		{ NULL,			0,			NULL,	0   },
	};

@@ -600,9 +605,9 @@ main(int argc, char **argv)
	save_argv = argv;

#ifdef HAVE_LIBJAIL
-
	while ((ch = getopt_long(argc, argv, "+dj:c:C:R:lNvo:", longopts, NULL)) != -1) {
+
	while ((ch = getopt_long(argc, argv, "+dj:c:C:R:lNvo:46", longopts, NULL)) != -1) {
#else
-
	while ((ch = getopt_long(argc, argv, "+dc:C:R:lNvo:", longopts, NULL)) != -1) {
+
	while ((ch = getopt_long(argc, argv, "+dc:C:R:lNvo:46", longopts, NULL)) != -1) {
#endif
		switch (ch) {
		case 'd':
@@ -634,6 +639,12 @@ main(int argc, char **argv)
		case 'o':
			export_arg_option (optarg);
			break;
+
		case '4':
+
			init_flags = PKG_INIT_FLAG_USE_IPV4;
+
			break;
+
		case '6':
+
			init_flags = PKG_INIT_FLAG_USE_IPV6;
+
			break;
		default:
			break;
		}
@@ -691,7 +702,7 @@ main(int argc, char **argv)
			errx(EX_SOFTWARE, "chdir() failed");
#endif

-
	if (pkg_init(conffile, reposdir) != EPKG_OK)
+
	if (pkg_init(conffile, reposdir, init_flags) != EPKG_OK)
		errx(EX_SOFTWARE, "Cannot parse configuration file!");

	if (atexit(&pkg_shutdown) != 0)
modified src/pkg.conf.sample
@@ -49,6 +49,7 @@
#SAT_SOLVER = "";
#RUN_SCRIPTS = true;
#CASE_SENSITIVE_MATCH = false;
+
#IP_VERSION = 0

# Sample alias settings
ALIAS              : {