summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorjamie <jamie@FreeBSD.org>2009-06-24 18:18:35 +0000
committerjamie <jamie@FreeBSD.org>2009-06-24 18:18:35 +0000
commit7c0019fd3084503b16686588e9e052c1a6b6c371 (patch)
treea9cec75f7b2e1076b5455019e71bbc78faac9225 /lib
parentbd3587c757355e28ac6abbaf11703661599270bb (diff)
downloadFreeBSD-src-7c0019fd3084503b16686588e9e052c1a6b6c371.zip
FreeBSD-src-7c0019fd3084503b16686588e9e052c1a6b6c371.tar.gz
Add libjail, a (somewhat) simpler interface to the jail_set and jail_get
system calls and the security.jail.param sysctls. Approved by: bz (mentor)
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile4
-rw-r--r--lib/libjail/Makefile29
-rw-r--r--lib/libjail/jail.3275
-rw-r--r--lib/libjail/jail.c972
-rw-r--r--lib/libjail/jail.h68
-rw-r--r--lib/libjail/jail_getid.c104
6 files changed, 1450 insertions, 2 deletions
diff --git a/lib/Makefile b/lib/Makefile
index ec866e5..7cacb70 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -35,8 +35,8 @@ SUBDIR= ${_csu} libc libbsm libauditd libcom_err libcrypt libelf libkvm msun \
libcalendar libcam libcompat libdevinfo libdevstat libdisk \
libdwarf libedit libexpat libfetch libftpio libgeom ${_libgpib} \
${_libgssapi} ${_librpcsec_gss} libipsec \
- ${_libipx} libkiconv libmagic libmemstat ${_libmilter} ${_libmp} \
- ${_libncp} ${_libngatm} libopie libpam libpcap \
+ ${_libipx} libjail libkiconv libmagic libmemstat ${_libmilter} \
+ ${_libmp} ${_libncp} ${_libngatm} libopie libpam libpcap \
${_libpmc} libproc librt ${_libsdp} ${_libsm} ${_libsmb} \
${_libsmdb} \
${_libsmutil} libstand ${_libtelnet} ${_libthr} libthread_db libufs \
diff --git a/lib/libjail/Makefile b/lib/libjail/Makefile
new file mode 100644
index 0000000..678d59e
--- /dev/null
+++ b/lib/libjail/Makefile
@@ -0,0 +1,29 @@
+# $FreeBSD$
+
+LIB= jail
+SHLIBDIR?= /lib
+SHLIB_MAJOR= 1
+SRCS= jail.c jail_getid.c
+INCS= jail.h
+
+MAN= jail.3
+
+MLINKS+=jail.3 jail_getid.3
+MLINKS+=jail.3 jail_getname.3
+MLINKS+=jail.3 jail_getv.3
+MLINKS+=jail.3 jail_setv.3
+MLINKS+=jail.3 jailparam.3
+MLINKS+=jail.3 jailparam_all.3
+MLINKS+=jail.3 jailparam_init.3
+MLINKS+=jail.3 jailparam_import.3
+MLINKS+=jail.3 jailparam_import_raw.3
+MLINKS+=jail.3 jailparam_get.3
+MLINKS+=jail.3 jailparam_set.3
+MLINKS+=jail.3 jailparam_export.3
+MLINKS+=jail.3 jailparam_free.3
+
+CFLAGS+=-I${.CURDIR}
+
+WARNS?= 6
+
+.include <bsd.lib.mk>
diff --git a/lib/libjail/jail.3 b/lib/libjail/jail.3
new file mode 100644
index 0000000..7fec585
--- /dev/null
+++ b/lib/libjail/jail.3
@@ -0,0 +1,275 @@
+.\" Copyright (c) 2009 James Gritton.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd June 24, 2009
+.Dt JAIL 3
+.Os
+.Sh NAME
+.Nm jail_getid ,
+.Nm jail_getname ,
+.Nm jail_setv ,
+.Nm jail_getv ,
+.Nm jailparam_all ,
+.Nm jailparam_init ,
+.Nm jailparam_import ,
+.Nm jailparam_import_raw ,
+.Nm jailparam_set ,
+.Nm jailparam_get ,
+.Nm jailparam_export ,
+.Nm jailparam_free ,
+.Nd create and manage system jails
+.Sh LIBRARY
+.Lb libjail
+.Sh SYNOPSIS
+.In sys/param.h
+.In sys/jail.h
+.In jail.h
+.Vt extern char jail_errmsg[] ;
+.Ft int
+.Fn jail_getid "const char *name"
+.Ft char *
+.Fn jail_getname "int jid"
+.Ft int
+.Fn jail_setv "int flags" ...
+.Ft int
+.Fn jail_getv "int flags" ...
+.Ft int
+.Fn jailparam_all "struct jailparam **jpp"
+.Ft int
+.Fn jailparam_init "struct jailparam *jp" "const char *name"
+.Ft int
+.Fn jailparam_import "struct jailparam *jp" "const char *value"
+.Ft int
+.Fn jailparam_import_raw "struct jailparam *jp" "void *value" "size_t valuelen"
+.Ft int
+.Fn jailparam_set "struct jailparam *jp" "unsigned njp" "int flags"
+.Ft int
+.Fn jailparam_get "struct jailparam *jp" "unsigned njp" "int flags"
+.Ft char *
+.Fn jailparam_export "struct jailparam *jp"
+.Ft void
+.Fn jailparam_free "struct jailparam *jp" "unsigned njp"
+.Sh DESCRIPTION
+The
+.Nm jail
+library is an interface to the
+.Xr jail_set 2
+and
+.Xr jail_get 2
+system calls, and the
+.Va security.jail.param
+MIB entries.
+It simplifies the conversion of prison parameters between internal and
+string formats, allowing the setting and querying of prisons without
+knowing the parameter formats.
+.Pp
+The
+.Fn jail_getid
+function returns the JID of the jail identified by
+.Ar name ,
+or \-1 if the jail does not exist.
+.Pp
+The
+.Fn jail_getname
+function returns the name of the jail identified by
+.Ar jid ,
+or NULL if the jail does not exist.
+.Pp
+The
+.Fn jail_setv
+function takes a null-terminated list of name and value strings,
+and passes it to
+.Xr jail_set 2 .
+.Pp
+The
+.Fn jail_getv
+function takes a null-terminated list of name and value strings,
+and passes it to
+.Xr jail_get 2 .
+It is the caller's responsibility to ensure that the value strings point
+to buffers large enough to hold the string representation of the
+returned parameters.
+.Pp
+The
+.Fn jailparam_all
+function sets
+.Ar jpp
+to a list of all known jail parameters, and returns the number of
+parameters.
+The list should later be freed with
+.Fn jailparam_free
+and
+.Xr free 3 .
+.Pp
+The
+.Fn jailparam_init
+function clears a parameter record and copies the
+.Ar name
+to it. After use, it should be freed with
+.Fn jailparam_free .
+.Pp
+The
+.Fn jailparam_import
+function adds a
+.Ar value
+to a parameter record, converting it from a string to its native form.
+The
+.Fn jailparam_import_raw
+function adds a value without performing any conversion.
+.Pp
+The
+.Fn jailparam_set
+function passes a list of parameters to
+.Xr jail_set 2 .
+The parameters are assumed to have been created with
+.Fn jailparam_init
+and
+.Fn jailparam_import .
+.Pp
+The
+.Fn jailparam_get
+function function passes a list of parameters to
+.Xr jail_get 2 .
+The parameters are assumed to have been created with
+.Fn jailparam_init
+or
+.Fn jailparam_list ,
+with one parameter (the key) having been given a value with
+.Fn jailparam_import .
+.Pp
+The
+.Fn jailparam_export
+function returns the string equivalent of a parameter value.
+The returned string should freed after use.
+.Pp
+The
+.Fn jailparam_free
+function frees the stored names and values in a parameter list.
+If the list itself came from
+.Fn jailparam_all ,
+it should be freed as well.
+.Sh EXAMPLES
+Set the hostname of jail
+.Dq foo
+to
+.Dq foo.bar :
+.Bd -literal -offset indent
+jail_setv(JAIL_UPDATE, "name", "foo", "host.hostname", "foo.bar",
+ NULL);
+.Ed
+.Pp
+OR:
+.Bd -literal -offset indent
+struct jailparam params[2];
+jailparam_init(&params[0], "name");
+jailparam_import(&params[0], "foo");
+jailparam_init(&params[1], "host.hostname");
+jailparam_import(&params[1], "foo.bar");
+jailparam_set(params, 2, JAIL_UPDATE);
+jailparam_free(params, 2);
+.Ed
+.Pp
+Retrieve the hostname of jail
+.Dq foo :
+.Bd -literal -offset indent
+char hostname[MAXHOSTNAMELEN];
+jail_getv(0, "name", "foo", "host.hostname", hostname, NULL);
+.Ed
+.Pp
+OR:
+.Bd -literal -offset indent
+struct jailparam params[2];
+jailparam_init(&params[0], "name");
+jailparam_import(&params[0], "foo");
+jailparam_init(&params[1], "host.hostname");
+jailparam_get(params, 2, 0);
+hostname = jailparam_export(&params[1]);
+jailparam_free(params, 2);
+.Ed
+.Sh RETURN VALUES
+The
+.Fn jail_getid ,
+.Fn jail_setv ,
+.Fn jail_getv ,
+.Fn jailparam_set
+and
+.Fn jailparam_get
+functions return a JID on success, or \-1 on error.
+.Pp
+The
+.Fn jail_getname
+and
+.Fn jailparam_export
+functions return a dynamically allocated string on success, or NULL on error.
+.Pp
+The
+.Fn jailparam_all
+function returns the number of parameters on success, or \-1 on error.
+.Pp
+The
+.Fn jailparam_init ,
+.Fn jailparam_import
+and
+.Fn jailparam_import_raw
+functions return 0 on success, or \-1 on error.
+.Pp
+Whenever an error is returned,
+.Va errno
+is set, and the global string
+.Va jail_errmsg
+contains a descrption of the error, possibly from
+.Xr jail_set 2
+or
+.Xr jail_get 2 .
+.Sh ERRORS
+The
+.Nm jail
+functions may return errors from
+.Xr jail_set 2 ,
+.Xr jail_get 2 ,
+.Xr malloc 3
+or
+.Xr sysctl 3 .
+In addition, the following errors are possible:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+A prameter value cannot be convert from the passed string to its
+internal form.
+.It Bq Er ENOENT
+The named parameter does not exist.
+.It Bq Er ENOENT
+A parameter is of an unknown type.
+.Sh SEE ALSO
+.Xr jail 2 ,
+.Xr jail 8 ,
+.Xr sysctl 3
+.Sh HISTORY
+The
+.Nm jail
+library first appeared in
+.Fx 8.0 .
+.Sh AUTHORS
+.An James Gritton
diff --git a/lib/libjail/jail.c b/lib/libjail/jail.c
new file mode 100644
index 0000000..f4a173a
--- /dev/null
+++ b/lib/libjail/jail.c
@@ -0,0 +1,972 @@
+/*-
+ * Copyright (c) 2009 James Gritton.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/jail.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+
+#include <errno.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "jail.h"
+
+#define SJPARAM "security.jail.param"
+
+#define JPS_IN_ADDR 1
+#define JPS_IN6_ADDR 2
+
+#define ARRAY_SANITY 5
+#define ARRAY_SLOP 5
+
+
+static int jailparam_vlist(struct jailparam **jpp, va_list ap);
+static int jailparam_type(struct jailparam *jp);
+static char *noname(const char *name);
+static char *nononame(const char *name);
+
+char jail_errmsg[JAIL_ERRMSGLEN];
+
+
+/*
+ * Import a null-terminated parameter list and set a jail with the flags
+ * and parameters.
+ */
+int
+jail_setv(int flags, ...)
+{
+ va_list ap;
+ struct jailparam *jp;
+ int njp;
+
+ va_start(ap, flags);
+ njp = jailparam_vlist(&jp, ap);
+ va_end(ap);
+ if (njp < 0)
+ return (njp);
+ return (jailparam_set(jp, njp, flags));
+}
+
+/*
+ * Read a null-terminated parameter list, get the referenced jail, and export
+ * the parameters to the list.
+ */
+int
+jail_getv(int flags, ...)
+{
+ va_list ap, tap;
+ struct jailparam *jp;
+ char *valarg;
+ const char *value;
+ int njp, i, jid, namekey, zero;
+
+ va_start(ap, flags);
+ va_copy(tap, ap);
+ njp = jailparam_vlist(&jp, tap);
+ va_end(tap);
+ if (njp < 0)
+ return (njp);
+ /*
+ * See if the name is the search key. If so, we don't want to write
+ * it back in case it's a read-only string.
+ */
+ namekey = 1;
+ zero = 0;
+ for (i = 0; i < njp; i++) {
+ if (!strcmp(jp->jp_name, "lastjid") ||
+ (!strcmp(jp->jp_name, "jid") &&
+ memcmp(jp->jp_value, &zero, sizeof(zero))))
+ namekey = 0;
+ }
+ jid = jailparam_get(jp, njp, flags);
+ if (jid < 0) {
+ va_end(ap);
+ return (-1);
+ }
+ for (i = 0; i < njp; i++) {
+ (void)va_arg(ap, char *);
+ value = jailparam_export(jp + i);
+ if (value == NULL) {
+ va_end(ap);
+ return (-1);
+ }
+ valarg = va_arg(ap, char *);
+ if (!namekey || strcmp(jp[i].jp_name, "name"))
+ /* It's up to the caller to ensure there's room. */
+ strcpy(valarg, value);
+ }
+ va_end(ap);
+ return (jid);
+}
+
+/*
+ * Return a list of all known parameters.
+ */
+int
+jailparam_all(struct jailparam **jpp)
+{
+ struct jailparam *jp;
+ char *nname;
+ size_t mlen1, mlen2, buflen;
+ int njp, nlist;
+ int mib1[CTL_MAXNAME], mib2[CTL_MAXNAME - 2];
+ char buf[MAXPATHLEN];
+
+ njp = 0;
+ nlist = 32;
+ jp = malloc(nlist * sizeof(*jp));
+ if (jp == NULL) {
+ strerror_r(errno, jail_errmsg, JAIL_ERRMSGLEN);
+ return (-1);
+ }
+ mib1[0] = 0;
+ mib1[1] = 2;
+ mlen1 = CTL_MAXNAME - 2;
+ if (sysctlnametomib(SJPARAM, mib1 + 2, &mlen1) < 0) {
+ snprintf(jail_errmsg, JAIL_ERRMSGLEN,
+ "sysctlnametomib(" SJPARAM "): %s", strerror(errno));
+ goto error;
+ }
+ for (;; njp++) {
+ /* Get the next parameter. */
+ mlen2 = sizeof(mib2);
+ if (sysctl(mib1, mlen1 + 2, mib2, &mlen2, NULL, 0) < 0) {
+ snprintf(jail_errmsg, JAIL_ERRMSGLEN,
+ "sysctl(0.2): %s", strerror(errno));
+ goto error;
+ }
+ if (mib2[0] != mib1[2] || mib2[1] != mib1[3] ||
+ mib2[2] != mib1[4])
+ break;
+ /* Convert it to an ascii name. */
+ memcpy(mib1 + 2, mib2, mlen2);
+ mlen1 = mlen2 / sizeof(int);
+ mib1[1] = 1;
+ buflen = sizeof(buf);
+ if (sysctl(mib1, mlen1 + 2, buf, &buflen, NULL, 0) < 0) {
+ snprintf(jail_errmsg, JAIL_ERRMSGLEN,
+ "sysctl(0.1): %s", strerror(errno));
+ goto error;
+ }
+ /* Add the parameter to the list */
+ if (njp >= nlist) {
+ nlist *= 2;
+ jp = realloc(jp, nlist * sizeof(jp));
+ if (jp == NULL) {
+ jailparam_free(jp, njp);
+ return (-1);
+ }
+ }
+ if (jailparam_init(jp + njp, buf + sizeof(SJPARAM)) < 0)
+ goto error;
+ if (jailparam_type(jp + njp) < 0) {
+ njp++;
+ goto error;
+ }
+ /* Convert nobool parameters to bool. */
+ if (jp[njp].jp_flags & JP_NOBOOL) {
+ nname = nononame(jp[njp].jp_name);
+ if (nname == NULL) {
+ njp++;
+ goto error;
+ }
+ free(jp[njp].jp_name);
+ jp[njp].jp_name = nname;
+ jp[njp].jp_flags ^= JP_BOOL | JP_NOBOOL;
+ }
+ mib1[1] = 2;
+ }
+ jp = realloc(jp, njp * sizeof(*jp));
+ *jpp = jp;
+ return (njp);
+
+ error:
+ jailparam_free(jp, njp);
+ free(jp);
+ return (-1);
+}
+
+/*
+ * Clear a jail parameter and copy in its name.
+ */
+int
+jailparam_init(struct jailparam *jp, const char *name)
+{
+
+ memset(jp, 0, sizeof(*jp));
+ jp->jp_name = strdup(name);
+ if (jp->jp_name == NULL) {
+ strerror_r(errno, jail_errmsg, JAIL_ERRMSGLEN);
+ return (-1);
+ }
+ return (0);
+}
+
+/*
+ * Put a name and value into a jail parameter element, converting the value
+ * to internal form.
+ */
+int
+jailparam_import(struct jailparam *jp, const char *value)
+{
+ char *p, *ep, *tvalue;
+ const char *avalue;
+ int i, nval, fw;
+
+ if (!jp->jp_ctltype && jailparam_type(jp) < 0)
+ goto error;
+ if (value == NULL)
+ return (0);
+ if ((jp->jp_ctltype & CTLTYPE) == CTLTYPE_STRING) {
+ jp->jp_value = strdup(value);
+ if (!jp->jp_value) {
+ strerror_r(errno, jail_errmsg, JAIL_ERRMSGLEN);
+ goto error;
+ }
+ return (0);
+ }
+ nval = 1;
+ if (jp->jp_elemlen) {
+ if (value[0] == '\0' || (value[0] == '-' && value[1] == '\0')) {
+ jp->jp_value = strdup("");
+ if (value == NULL) {
+ strerror_r(errno, jail_errmsg, JAIL_ERRMSGLEN);
+ goto error;
+ }
+ jp->jp_valuelen = 0;
+ return (0);
+ }
+ for (p = strchr(value, ','); p; p = strchr(p + 1, ','))
+ nval++;
+ jp->jp_valuelen = jp->jp_elemlen * nval;
+ }
+ jp->jp_value = malloc(jp->jp_valuelen);
+ if (!jp->jp_value) {
+ strerror_r(errno, jail_errmsg, JAIL_ERRMSGLEN);
+ goto error;
+ }
+ avalue = value;
+ for (i = 0; i < nval; i++) {
+ fw = nval == 1 ? strlen(avalue) : strcspn(avalue, ",");
+ switch (jp->jp_ctltype & CTLTYPE) {
+ case CTLTYPE_INT:
+ if (jp->jp_flags & (JP_BOOL | JP_NOBOOL)) {
+ if (!strncasecmp(avalue, "true", 4))
+ ((int *)jp->jp_value)[i] = 1;
+ else if (!strncasecmp(avalue, "false", 5))
+ ((int *)jp->jp_value)[i] = 0;
+ else {
+ snprintf(jail_errmsg,
+ JAIL_ERRMSGLEN,
+ "%s: unknown boolean value \"%.*s\"",
+ jp->jp_name, fw, avalue);
+ errno = EINVAL;
+ goto error;
+ }
+ break;
+ }
+ ((int *)jp->jp_value)[i] = strtol(avalue, &ep, 10);
+ integer_test:
+ if (ep != avalue + fw) {
+ snprintf(jail_errmsg, JAIL_ERRMSGLEN,
+ "%s: non-integer value \"%.*s\"",
+ jp->jp_name, fw, avalue);
+ errno = EINVAL;
+ goto error;
+ }
+ break;
+ case CTLTYPE_UINT:
+ ((unsigned *)jp->jp_value)[i] =
+ strtoul(avalue, &ep, 10);
+ goto integer_test;
+ case CTLTYPE_LONG:
+ ((long *)jp->jp_value)[i] = strtol(avalue, &ep, 10);
+ goto integer_test;
+ case CTLTYPE_ULONG:
+ ((unsigned long *)jp->jp_value)[i] =
+ strtoul(avalue, &ep, 10);
+ goto integer_test;
+ case CTLTYPE_QUAD:
+ ((int64_t *)jp->jp_value)[i] =
+ strtoimax(avalue, &ep, 10);
+ goto integer_test;
+ case CTLTYPE_STRUCT:
+ tvalue = alloca(fw + 1);
+ strlcpy(tvalue, avalue, fw + 1);
+ switch (jp->jp_structtype) {
+ case JPS_IN_ADDR:
+ if (inet_pton(AF_INET, tvalue,
+ &((struct in_addr *)jp->jp_value)[i]) != 1)
+ {
+ snprintf(jail_errmsg,
+ JAIL_ERRMSGLEN,
+ "%s: not an IPv4 address: %s",
+ jp->jp_name, tvalue);
+ errno = EINVAL;
+ goto error;
+ }
+ break;
+ case JPS_IN6_ADDR:
+ if (inet_pton(AF_INET6, tvalue,
+ &((struct in6_addr *)jp->jp_value)[i]) != 1)
+ {
+ snprintf(jail_errmsg,
+ JAIL_ERRMSGLEN,
+ "%s: not an IPv6 address: %s",
+ jp->jp_name, tvalue);
+ errno = EINVAL;
+ goto error;
+ }
+ break;
+ default:
+ goto unknown_type;
+ }
+ break;
+ default:
+ unknown_type:
+ snprintf(jail_errmsg, JAIL_ERRMSGLEN,
+ "unknown type for %s", jp->jp_name);
+ errno = ENOENT;
+ goto error;
+ }
+ avalue += fw + 1;
+ }
+ return (0);
+
+ error:
+ free(jp->jp_value);
+ jp->jp_value = NULL;
+ return (-1);
+}
+
+/*
+ * Put a name and value into a jail parameter element, copying the value
+ * but not altering it.
+ */
+int
+jailparam_import_raw(struct jailparam *jp, void *value, size_t valuelen)
+{
+
+ jp->jp_value = value;
+ jp->jp_valuelen = valuelen;
+ jp->jp_flags |= JP_RAWVALUE;
+ return (0);
+}
+
+/*
+ * Run the jail_set and jail_get system calls on a parameter list.
+ */
+int
+jailparam_set(struct jailparam *jp, unsigned njp, int flags)
+{
+ struct iovec *jiov;
+ char *nname;
+ int i, jid;
+ unsigned j;
+
+ jiov = alloca(sizeof(struct iovec) * 2 * (njp + 1));
+ for (i = j = 0; j < njp; j++) {
+ jiov[i].iov_base = jp[j].jp_name;
+ jiov[i].iov_len = strlen(jp[j].jp_name) + 1;
+ i++;
+ if (jp[j].jp_flags & (JP_BOOL | JP_NOBOOL)) {
+ /*
+ * Set booleans without values. If one have a value of
+ * zero, change it to (or from) its "no" counterpart.
+ */
+ jiov[i].iov_base = NULL;
+ jiov[i].iov_len = 0;
+ if (jp[j].jp_value != NULL &&
+ jp[j].jp_valuelen == sizeof(int) &&
+ !*(int *)jp[j].jp_value) {
+ nname = jp[j].jp_flags & JP_BOOL
+ ? noname(jiov[i].iov_base)
+ : nononame(jiov[i].iov_base);
+ if (nname == NULL)
+ return (-1);
+ free(jp[j].jp_name);
+ jiov[i].iov_base = jp[j].jp_name = nname;
+ }
+ } else {
+ jiov[i].iov_base = jp[j].jp_value;
+ jiov[i].iov_len =
+ (jp[j].jp_ctltype & CTLTYPE) == CTLTYPE_STRING
+ ? strlen(jp[j].jp_value) + 1
+ : jp[j].jp_valuelen;
+ }
+ i++;
+ }
+ *(const void **)&jiov[i].iov_base = "errmsg";
+ jiov[i].iov_len = sizeof("errmsg");
+ i++;
+ jiov[i].iov_base = jail_errmsg;
+ jiov[i].iov_len = JAIL_ERRMSGLEN;
+ i++;
+ jail_errmsg[0] = 0;
+ jid = jail_set(jiov, i, flags);
+ if (jid < 0 && !jail_errmsg[0])
+ snprintf(jail_errmsg, sizeof(jail_errmsg), "jail_set: %s",
+ strerror(errno));
+ return (jid);
+}
+
+int
+jailparam_get(struct jailparam *jp, unsigned njp, int flags)
+{
+ struct iovec *jiov;
+ struct jailparam *jp_lastjid, *jp_jid, *jp_name, *jp_key;
+ int i, ai, ki, jid, arrays, sanity;
+ unsigned j;
+
+ /* Find the key and any array parameters. */
+ jiov = alloca(sizeof(struct iovec) * 2 * (njp + 1));
+ jp_lastjid = jp_jid = jp_name = NULL;
+ arrays = 0;
+ for (ai = j = 0; j < njp; j++) {
+ if (!strcmp(jp[j].jp_name, "lastjid"))
+ jp_lastjid = jp + j;
+ else if (!strcmp(jp[j].jp_name, "jid"))
+ jp_jid = jp + j;
+ else if (!strcmp(jp[j].jp_name, "name"))
+ jp_name = jp + j;
+ else if (jp[j].jp_elemlen && !(jp[j].jp_flags & JP_RAWVALUE)) {
+ arrays = 1;
+ jiov[ai].iov_base = jp[j].jp_name;
+ jiov[ai].iov_len = strlen(jp[j].jp_name) + 1;
+ ai++;
+ jiov[ai].iov_base = NULL;
+ jiov[ai].iov_len = 0;
+ ai++;
+ }
+ }
+ jp_key = jp_lastjid ? jp_lastjid :
+ jp_jid && jp_jid->jp_valuelen == sizeof(int) &&
+ *(int *)jp_jid->jp_value ? jp_jid : jp_name;
+ if (jp_key == NULL || jp_key->jp_value == NULL) {
+ strlcpy(jail_errmsg, "no jail specified", JAIL_ERRMSGLEN);
+ errno = ENOENT;
+ return (-1);
+ }
+ ki = ai;
+ jiov[ki].iov_base = jp_key->jp_name;
+ jiov[ki].iov_len = strlen(jp_key->jp_name) + 1;
+ ki++;
+ jiov[ki].iov_base = jp_key->jp_value;
+ jiov[ki].iov_len = (jp_key->jp_ctltype & CTLTYPE) == CTLTYPE_STRING
+ ? strlen(jp_key->jp_value) + 1 : jp_key->jp_valuelen;
+ ki++;
+ *(const void **)&jiov[ki].iov_base = "errmsg";
+ jiov[ki].iov_len = sizeof("errmsg");
+ ki++;
+ jiov[ki].iov_base = jail_errmsg;
+ jiov[ki].iov_len = JAIL_ERRMSGLEN;
+ ki++;
+ jail_errmsg[0] = 0;
+ if (arrays && jail_get(jiov, ki, flags) < 0) {
+ if (!jail_errmsg[0])
+ snprintf(jail_errmsg, sizeof(jail_errmsg),
+ "jail_get: %s", strerror(errno));
+ return (-1);
+ }
+ /* Allocate storage for all parameters. */
+ for (ai = j = 0, i = ki; j < njp; j++) {
+ if (jp[j].jp_elemlen && !(jp[j].jp_flags & JP_RAWVALUE)) {
+ ai++;
+ jiov[ai].iov_len += jp[j].jp_elemlen * ARRAY_SLOP;
+ jiov[ai].iov_base = jp[j].jp_value =
+ malloc(jiov[ai].iov_len);
+ if (jiov[ai].iov_base == NULL) {
+ strerror_r(errno, jail_errmsg, JAIL_ERRMSGLEN);
+ return (-1);
+ }
+ memset(jiov[ai].iov_base, 0, jiov[ai].iov_len);
+ ai++;
+ } else if (jp + j != jp_key) {
+ jiov[i].iov_base = jp[j].jp_name;
+ jiov[i].iov_len = strlen(jp[j].jp_name) + 1;
+ i++;
+ jiov[i].iov_base = jp[j].jp_value =
+ malloc(jp[j].jp_valuelen);
+ if (jiov[i].iov_base == NULL) {
+ strerror_r(errno, jail_errmsg, JAIL_ERRMSGLEN);
+ return (-1);
+ }
+ jiov[i].iov_len = jp[j].jp_valuelen;
+ memset(jiov[i].iov_base, 0, jiov[i].iov_len);
+ i++;
+ }
+ }
+ /*
+ * Get the prison. If there are array elements, retry a few times
+ * in case their sizes changed from under us.
+ */
+ for (sanity = 0;; sanity++) {
+ jid = jail_get(jiov, i, flags);
+ if (jid >= 0 || !arrays || sanity == ARRAY_SANITY ||
+ errno != EINVAL || jail_errmsg[0])
+ break;
+ for (ai = j = 0; j < njp; j++) {
+ if (jp[j].jp_elemlen &&
+ !(jp[j].jp_flags & JP_RAWVALUE)) {
+ ai++;
+ free(jiov[ai].iov_base);
+ jiov[ai].iov_base = jp[j].jp_value = NULL;
+ jiov[ai].iov_len = 0;
+ ai++;
+ }
+ }
+ if (jail_get(jiov, ki, flags) < 0)
+ break;
+ for (ai = j = 0; j < njp; j++) {
+ if (jp[j].jp_elemlen &&
+ !(jp[j].jp_flags & JP_RAWVALUE)) {
+ ai++;
+ jiov[ai].iov_len +=
+ jp[j].jp_elemlen * ARRAY_SLOP;
+ jiov[ai].iov_base = jp[j].jp_value =
+ malloc(jiov[ai].iov_len);
+ if (jiov[ai].iov_base == NULL) {
+ strerror_r(errno, jail_errmsg,
+ JAIL_ERRMSGLEN);
+ return (-1);
+ }
+ memset(jiov[ai].iov_base, 0, jiov[ai].iov_len);
+ ai++;
+ }
+ }
+ }
+ if (jid < 0 && !jail_errmsg[0])
+ snprintf(jail_errmsg, sizeof(jail_errmsg),
+ "jail_get: %s", strerror(errno));
+ for (ai = j = 0, i = ki; j < njp; j++) {
+ if (jp[j].jp_elemlen && !(jp[j].jp_flags & JP_RAWVALUE)) {
+ ai++;
+ jp[j].jp_valuelen = jiov[ai].iov_len;
+ ai++;
+ } else if (jp + j != jp_key) {
+ i++;
+ jp[j].jp_valuelen = jiov[i].iov_len;
+ i++;
+ }
+ }
+ return (jid);
+}
+
+/*
+ * Convert a jail parameter's value to external form.
+ */
+char *
+jailparam_export(struct jailparam *jp)
+{
+ char *value, *tvalue, **values;
+ size_t valuelen;
+ int i, nval;
+ char valbuf[INET6_ADDRSTRLEN];
+
+ if (!jp->jp_ctltype && jailparam_type(jp) < 0)
+ return (NULL);
+ if ((jp->jp_ctltype & CTLTYPE) == CTLTYPE_STRING) {
+ value = strdup(jp->jp_value);
+ if (value == NULL)
+ strerror_r(errno, jail_errmsg, JAIL_ERRMSGLEN);
+ return (value);
+ }
+ nval = jp->jp_elemlen ? jp->jp_valuelen / jp->jp_elemlen : 1;
+ if (nval == 0) {
+ value = strdup("");
+ if (value == NULL)
+ strerror_r(errno, jail_errmsg, JAIL_ERRMSGLEN);
+ return (value);
+ }
+ values = alloca(nval * sizeof(char *));
+ valuelen = 0;
+ for (i = 0; i < nval; i++) {
+ switch (jp->jp_ctltype & CTLTYPE) {
+ case CTLTYPE_INT:
+ if (jp->jp_flags & (JP_BOOL | JP_NOBOOL)) {
+ strlcpy(valbuf,
+ ((int *)jp->jp_value)[i] ? "true" : "false",
+ sizeof(valbuf));
+ break;
+ }
+ snprintf(valbuf, sizeof(valbuf), "%d",
+ ((int *)jp->jp_value)[i]);
+ break;
+ case CTLTYPE_UINT:
+ snprintf(valbuf, sizeof(valbuf), "%u",
+ ((unsigned *)jp->jp_value)[i]);
+ break;
+ case CTLTYPE_LONG:
+ snprintf(valbuf, sizeof(valbuf), "%ld",
+ ((long *)jp->jp_value)[i]);
+ break;
+ case CTLTYPE_ULONG:
+ snprintf(valbuf, sizeof(valbuf), "%lu",
+ ((unsigned long *)jp->jp_value)[i]);
+ break;
+ case CTLTYPE_QUAD:
+ snprintf(valbuf, sizeof(valbuf), "%jd",
+ (intmax_t)((int64_t *)jp->jp_value)[i]);
+ break;
+ case CTLTYPE_STRUCT:
+ switch (jp->jp_structtype) {
+ case JPS_IN_ADDR:
+ if (inet_ntop(AF_INET,
+ &((struct in_addr *)jp->jp_value)[i],
+ valbuf, sizeof(valbuf)) == NULL) {
+ strerror_r(errno, jail_errmsg,
+ JAIL_ERRMSGLEN);
+
+ return (NULL);
+ }
+ break;
+ case JPS_IN6_ADDR:
+ if (inet_ntop(AF_INET6,
+ &((struct in6_addr *)jp->jp_value)[i],
+ valbuf, sizeof(valbuf)) == NULL) {
+ strerror_r(errno, jail_errmsg,
+ JAIL_ERRMSGLEN);
+
+ return (NULL);
+ }
+ break;
+ default:
+ goto unknown_type;
+ }
+ break;
+ default:
+ unknown_type:
+ snprintf(jail_errmsg, JAIL_ERRMSGLEN,
+ "unknown type for %s", jp->jp_name);
+ errno = ENOENT;
+ return (NULL);
+ }
+ valuelen += strlen(valbuf) + 1;
+ values[i] = alloca(valuelen);
+ strcpy(values[i], valbuf);
+ }
+ value = malloc(valuelen + 1);
+ if (value == NULL)
+ strerror_r(errno, jail_errmsg, JAIL_ERRMSGLEN);
+ else {
+ tvalue = value;
+ for (i = 0; i < nval; i++) {
+ strcpy(tvalue, values[i]);
+ if (i < nval - 1) {
+ tvalue += strlen(values[i]);
+ *tvalue++ = ',';
+ }
+ }
+ }
+ return (value);
+}
+
+/*
+ * Free the contents of a jail parameter list (but not thst list itself).
+ */
+void
+jailparam_free(struct jailparam *jp, unsigned njp)
+{
+ unsigned j;
+
+ for (j = 0; j < njp; j++) {
+ free(jp[j].jp_name);
+ if (!(jp[j].jp_flags & JP_RAWVALUE))
+ free(jp[j].jp_value);
+ }
+}
+
+/*
+ * Create and import an array of jail parameters, given a list of name and
+ * value strings, terminated by a null name.
+ */
+static int
+jailparam_vlist(struct jailparam **jpp, va_list ap)
+{
+ va_list tap;
+ struct jailparam *jp;
+ char *name, *value;
+ int njp;
+
+ va_copy(tap, ap);
+ for (njp = 0; va_arg(tap, char *) != NULL; njp++)
+ (void)va_arg(tap, char *);
+ va_end(tap);
+ jp = calloc(njp, sizeof(struct jailparam));
+ if (jp == NULL) {
+ strerror_r(errno, jail_errmsg, JAIL_ERRMSGLEN);
+ return (-1);
+ }
+
+ for (njp = 0; (name = va_arg(ap, char *)) != NULL; njp++) {
+ value = va_arg(ap, char *);
+ if (jailparam_init(jp + njp, name) < 0 ||
+ jailparam_import(jp + njp, value) < 0) {
+ jailparam_free(jp, njp);
+ free(jp);
+ return (-1);
+ }
+ }
+ *jpp = jp;
+ return (njp);
+}
+
+/*
+ * Find a parameter's type and size from its MIB.
+ */
+static int
+jailparam_type(struct jailparam *jp)
+{
+ char *p, *nname;
+ size_t miblen, desclen;
+ int isarray;
+ struct {
+ int i;
+ char s[MAXPATHLEN];
+ } desc;
+ int mib[CTL_MAXNAME];
+
+ /* The "lastjid" parameter isn't real. */
+ if (!strcmp(jp->jp_name, "lastjid")) {
+ jp->jp_valuelen = sizeof(int);
+ jp->jp_ctltype = CTLTYPE_INT | CTLFLAG_WR;
+ return (0);
+ }
+
+ /* Find the sysctl that describes the parameter. */
+ mib[0] = 0;
+ mib[1] = 3;
+ snprintf(desc.s, sizeof(desc.s), SJPARAM ".%s", jp->jp_name);
+ miblen = sizeof(mib) - 2 * sizeof(int);
+ if (sysctl(mib, 2, mib + 2, &miblen, desc.s, strlen(desc.s)) < 0) {
+ if (errno != ENOENT) {
+ snprintf(jail_errmsg, JAIL_ERRMSGLEN,
+ "sysctl(0.3.%s): %s", jp->jp_name, strerror(errno));
+ return (-1);
+ }
+ /*
+ * The parameter probably doesn't exist. But it might be
+ * the "no" counterpart to a boolean.
+ */
+ nname = nononame(jp->jp_name);
+ if (nname != NULL) {
+ snprintf(desc.s, sizeof(desc.s), SJPARAM ".%s", nname);
+ free(nname);
+ miblen = sizeof(mib) - 2 * sizeof(int);
+ if (sysctl(mib, 2, mib + 2, &miblen, desc.s,
+ strlen(desc.s)) >= 0) {
+ mib[1] = 4;
+ desclen = sizeof(desc);
+ if (sysctl(mib, (miblen / sizeof(int)) + 2,
+ &desc, &desclen, NULL, 0) < 0) {
+ snprintf(jail_errmsg,
+ JAIL_ERRMSGLEN,
+ "sysctl(0.4.%s): %s", desc.s,
+ strerror(errno));
+ return (-1);
+ }
+ if ((desc.i & CTLTYPE) == CTLTYPE_INT &&
+ desc.s[0] == 'B') {
+ jp->jp_ctltype = desc.i;
+ jp->jp_flags |= JP_NOBOOL;
+ jp->jp_valuelen = sizeof(int);
+ return (0);
+ }
+ }
+ }
+ snprintf(jail_errmsg, JAIL_ERRMSGLEN,
+ "unknown parameter: %s", jp->jp_name);
+ errno = ENOENT;
+ return (-1);
+ }
+ mib[1] = 4;
+ desclen = sizeof(desc);
+ if (sysctl(mib, (miblen / sizeof(int)) + 2, &desc, &desclen,
+ NULL, 0) < 0) {
+ snprintf(jail_errmsg, JAIL_ERRMSGLEN,
+ "sysctl(0.4.%s): %s", jp->jp_name, strerror(errno));
+ return (-1);
+ }
+ /* See if this is an array type. */
+ p = strchr(desc.s, '\0');
+ isarray = 0;
+ if (p - 2 < desc.s || strcmp(p - 2, ",a"))
+ isarray = 0;
+ else {
+ isarray = 1;
+ p[-2] = 0;
+ }
+ /* Look for types we understand */
+ jp->jp_ctltype = desc.i;
+ switch (desc.i & CTLTYPE) {
+ case CTLTYPE_INT:
+ if (desc.s[0] == 'B')
+ jp->jp_flags |=
+ (desc.s[1] == 'N') ? JP_NOBOOL : JP_BOOL;
+ case CTLTYPE_UINT:
+ jp->jp_valuelen = sizeof(int);
+ break;
+ case CTLTYPE_LONG:
+ case CTLTYPE_ULONG:
+ jp->jp_valuelen = sizeof(long);
+ break;
+ case CTLTYPE_QUAD:
+ jp->jp_valuelen = sizeof(int64_t);
+ break;
+ case CTLTYPE_STRING:
+ desc.s[0] = 0;
+ desclen = sizeof(desc.s);
+ if (sysctl(mib + 2, miblen / sizeof(int), desc.s, &desclen,
+ NULL, 0) < 0) {
+ snprintf(jail_errmsg, JAIL_ERRMSGLEN,
+ "sysctl(" SJPARAM ".%s): %s", jp->jp_name,
+ strerror(errno));
+ return (-1);
+ }
+ jp->jp_valuelen = strtoul(desc.s, NULL, 10);
+ break;
+ case CTLTYPE_STRUCT:
+ if (!strcmp(desc.s, "S,in_addr")) {
+ jp->jp_structtype = JPS_IN_ADDR;
+ jp->jp_valuelen = sizeof(struct in_addr);
+ } else if (!strcmp(desc.s, "S,in6_addr")) {
+ jp->jp_structtype = JPS_IN6_ADDR;
+ jp->jp_valuelen = sizeof(struct in6_addr);
+ } else {
+ desclen = 0;
+ if (sysctl(mib + 2, miblen / sizeof(int),
+ NULL, &jp->jp_valuelen, NULL, 0) < 0) {
+ snprintf(jail_errmsg, JAIL_ERRMSGLEN,
+ "sysctl(" SJPARAM ".%s): %s", jp->jp_name,
+ strerror(errno));
+ return (-1);
+ }
+ }
+ break;
+ case CTLTYPE_NODE:
+ /*
+ * A node isn't normally a parameter, but may be a boolean
+ * if its "no" counterpart exists.
+ */
+ nname = noname(jp->jp_name);
+ if (nname == NULL)
+ return (-1);
+ mib[1] = 3;
+ snprintf(desc.s, sizeof(desc.s), SJPARAM ".%s", nname);
+ free(nname);
+ miblen = sizeof(mib) - 2 * sizeof(int);
+ if (sysctl(mib, 2, mib + 2, &miblen, desc.s,
+ strlen(desc.s)) < 0) {
+ snprintf(jail_errmsg, JAIL_ERRMSGLEN,
+ "unknown parameter: %s", jp->jp_name);
+ return (-1);
+ }
+ mib[1] = 4;
+ desclen = sizeof(desc);
+ if (sysctl(mib, (miblen / sizeof(int)) + 2, &desc, &desclen,
+ NULL, 0) < 0) {
+ snprintf(jail_errmsg, JAIL_ERRMSGLEN,
+ "sysctl(0.4.%s): %s", desc.s, strerror(errno));
+ return (-1);
+ }
+ if ((desc.i & CTLTYPE) != CTLTYPE_INT || desc.s[0] != 'B') {
+ snprintf(jail_errmsg, JAIL_ERRMSGLEN,
+ "unknown parameter: %s", jp->jp_name);
+ errno = ENOENT;
+ return (-1);
+ }
+ jp->jp_valuelen = sizeof(int);
+ jp->jp_ctltype = desc.i;
+ jp->jp_flags |= JP_BOOL;
+ break;
+ default:
+ snprintf(jail_errmsg, JAIL_ERRMSGLEN,
+ "unknown type for %s", jp->jp_name);
+ errno = ENOENT;
+ return (-1);
+ }
+ if (isarray) {
+ jp->jp_elemlen = jp->jp_valuelen;
+ jp->jp_valuelen = 0;
+ }
+ return (0);
+}
+
+/*
+ * Change a boolean parameter name into its "no" counterpart or vice versa.
+ */
+static char *
+noname(const char *name)
+{
+ char *nname, *p;
+
+ nname = malloc(strlen(name) + 3);
+ if (nname == NULL) {
+ strerror_r(errno, jail_errmsg, JAIL_ERRMSGLEN);
+ return (NULL);
+ }
+ p = strrchr(name, '.');
+ if (p != NULL)
+ sprintf(nname, "%.*s.no%s", (int)(p - name), name, p + 1);
+ else
+ sprintf(nname, "no%s", name);
+ return (nname);
+}
+
+static char *
+nononame(const char *name)
+{
+ char *p, *nname;
+
+ p = strrchr(name, '.');
+ if (strncmp(p ? p + 1 : name, "no", 2)) {
+ snprintf(jail_errmsg, sizeof(jail_errmsg),
+ "mismatched boolean: %s", name);
+ errno = EINVAL;
+ return (NULL);
+ }
+ nname = malloc(strlen(name) - 1);
+ if (nname == NULL) {
+ strerror_r(errno, jail_errmsg, JAIL_ERRMSGLEN);
+ return (NULL);
+ }
+ if (p != NULL)
+ sprintf(nname, "%.*s.%s", (int)(p - name), name, p + 3);
+ else
+ strcpy(nname, name + 2);
+ return (nname);
+}
diff --git a/lib/libjail/jail.h b/lib/libjail/jail.h
new file mode 100644
index 0000000..4b38001
--- /dev/null
+++ b/lib/libjail/jail.h
@@ -0,0 +1,68 @@
+/*-
+ * Copyright (c) 2009 James Gritton.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _JAIL_H
+#define _JAIL_H
+
+#define JP_RAWVALUE 0x01
+#define JP_BOOL 0x02
+#define JP_NOBOOL 0x04
+
+#define JAIL_ERRMSGLEN 1024
+
+extern char jail_errmsg[];
+
+struct jailparam {
+ char *jp_name;
+ void *jp_value;
+ size_t jp_valuelen;
+ size_t jp_elemlen;
+ int jp_ctltype;
+ int jp_structtype;
+ unsigned jp_flags;
+};
+
+__BEGIN_DECLS
+extern int jail_getid(const char *name);
+extern char *jail_getname(int jid);
+extern int jail_setv(int flags, ...);
+extern int jail_getv(int flags, ...);
+extern int jailparam_all(struct jailparam **jpp);
+extern int jailparam_init(struct jailparam *jp, const char *name);
+extern int jailparam_import(struct jailparam *jp, const char *value);
+extern int jailparam_import_raw(struct jailparam *jp, void *value,
+ size_t valuelen);
+extern int jailparam_set(struct jailparam *jp, unsigned njp, int flags);
+extern int jailparam_get(struct jailparam *jp, unsigned njp, int flags);
+extern char *jailparam_export(struct jailparam *jp);
+extern void jailparam_free(struct jailparam *jp, unsigned njp);
+__END_DECLS
+
+#endif /* _JAIL_H */
+
+
diff --git a/lib/libjail/jail_getid.c b/lib/libjail/jail_getid.c
new file mode 100644
index 0000000..e7601d5
--- /dev/null
+++ b/lib/libjail/jail_getid.c
@@ -0,0 +1,104 @@
+/*-
+ * Copyright (c) 2009 James Gritton.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/jail.h>
+#include <sys/uio.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "jail.h"
+
+
+/*
+ * Return the JID corresponding to a jail name.
+ */
+int
+jail_getid(const char *name)
+{
+ char *ep;
+ int jid;
+ struct iovec jiov[4];
+
+ jid = strtoul(name, &ep, 10);
+ if (*name && !*ep)
+ return jid;
+ *(const void **)&jiov[0].iov_base = "name";
+ jiov[0].iov_len = sizeof("name");
+ jiov[1].iov_len = strlen(name) + 1;
+ jiov[1].iov_base = alloca(jiov[1].iov_len);
+ strcpy(jiov[1].iov_base, name);
+ *(const void **)&jiov[2].iov_base = "errmsg";
+ jiov[2].iov_len = sizeof("errmsg");
+ jiov[3].iov_base = jail_errmsg;
+ jiov[3].iov_len = JAIL_ERRMSGLEN;
+ jail_errmsg[0] = 0;
+ jid = jail_get(jiov, 4, 0);
+ if (jid < 0 && !jail_errmsg[0])
+ snprintf(jail_errmsg, JAIL_ERRMSGLEN, "jail_get: %s",
+ strerror(errno));
+ return jid;
+}
+
+/*
+ * Return the name corresponding to a JID.
+ */
+char *
+jail_getname(int jid)
+{
+ struct iovec jiov[6];
+ char *name;
+ char namebuf[MAXHOSTNAMELEN];
+
+ *(const void **)&jiov[0].iov_base = "jid";
+ jiov[0].iov_len = sizeof("jid");
+ jiov[1].iov_base = &jid;
+ jiov[1].iov_len = sizeof(jid);
+ *(const void **)&jiov[2].iov_base = "name";
+ jiov[2].iov_len = sizeof("name");
+ jiov[3].iov_base = namebuf;
+ jiov[3].iov_len = sizeof(namebuf);
+ *(const void **)&jiov[4].iov_base = "errmsg";
+ jiov[4].iov_len = sizeof("errmsg");
+ jiov[5].iov_base = jail_errmsg;
+ jiov[5].iov_len = JAIL_ERRMSGLEN;
+ jail_errmsg[0] = 0;
+ jid = jail_get(jiov, 6, 0);
+ if (jid < 0 && !jail_errmsg[0])
+ snprintf(jail_errmsg, JAIL_ERRMSGLEN, "jail_get: %s",
+ strerror(errno));
+ name = strdup(namebuf);
+ if (name == NULL)
+ strerror_r(errno, jail_errmsg, JAIL_ERRMSGLEN);
+ return name;
+}
OpenPOWER on IntegriCloud