? compile/GENERIC
? i386/conf/REGRESSION
? i386/conf/REGRESSION_ACL
Index: compat/linux/linux_mib.c
===================================================================
RCS file: /home/ncvs/src/sys/compat/linux/linux_mib.c,v
retrieving revision 1.10
diff -u -r1.10 linux_mib.c
--- compat/linux/linux_mib.c	2001/02/21 06:39:54	1.10
+++ compat/linux/linux_mib.c	2001/04/23 16:17:42
@@ -34,17 +34,10 @@
 #include <sys/sysctl.h>
 #include <sys/proc.h>
 #include <sys/malloc.h>
-#include <sys/jail.h>
 
 #include <machine/../linux/linux.h>
 #include <compat/linux/linux_mib.h>
 
-struct linux_prison {
-	char	pr_osname[LINUX_MAX_UTSNAME];
-	char	pr_osrelease[LINUX_MAX_UTSNAME];
-	int	pr_oss_version;
-};
-
 SYSCTL_NODE(_compat, OID_AUTO, linux, CTLFLAG_RW, 0,
 	    "Linux mode");
 
@@ -111,39 +104,10 @@
 	    0, 0, linux_sysctl_oss_version, "I",
 	    "Linux OSS version");
 
-static struct linux_prison *
-get_prison(struct proc *p)
-{
-	register struct prison *pr;
-	register struct linux_prison *lpr;
-
-	if (!jailed(p->p_ucred))
-		return (NULL);
-
-	pr = p->p_ucred->cr_prison;
-
-	if (pr->pr_linux == NULL) {
-		MALLOC(lpr, struct linux_prison *, sizeof *lpr,
-		    M_PRISON, M_WAITOK|M_ZERO);
-		pr->pr_linux = lpr;
-	}
-
-	return (pr->pr_linux);
-}
-
 char *
 linux_get_osname(p)
 	struct proc *p;
 {
-	register struct prison *pr;
-	register struct linux_prison *lpr;
-
-	pr = p->p_ucred->cr_prison;
-	if (pr != NULL && pr->pr_linux != NULL) {
-		lpr = pr->pr_linux;
-		if (lpr->pr_osname[0])
-			return (lpr->pr_osname);
-	}
 
 	return (linux_osname);
 }
@@ -153,13 +117,8 @@
 	struct proc *p;
 	char *osname;
 {
-	register struct linux_prison *lpr;
 
-	lpr = get_prison(p);
-	if (lpr != NULL)
-		strcpy(lpr->pr_osname, osname);
-	else
-		strcpy(linux_osname, osname);
+	strcpy(linux_osname, osname);
 
 	return (0);
 }
@@ -168,16 +127,7 @@
 linux_get_osrelease(p)
 	struct proc *p;
 {
-	register struct prison *pr;
-	register struct linux_prison *lpr;
 
-	pr = p->p_ucred->cr_prison;
-	if (pr != NULL && pr->pr_linux != NULL) {
-		lpr = pr->pr_linux;
-		if (lpr->pr_osrelease[0])
-			return (lpr->pr_osrelease);
-	}
-
 	return (linux_osrelease);
 }
 
@@ -186,13 +136,8 @@
 	struct proc *p;
 	char *osrelease;
 {
-	register struct linux_prison *lpr;
 
-	lpr = get_prison(p);
-	if (lpr != NULL)
-		strcpy(lpr->pr_osrelease, osrelease);
-	else
-		strcpy(linux_osrelease, osrelease);
+	strcpy(linux_osrelease, osrelease);
 
 	return (0);
 }
@@ -201,15 +146,6 @@
 linux_get_oss_version(p)
 	struct proc *p;
 {
-	register struct prison *pr;
-	register struct linux_prison *lpr;
-
-	pr = p->p_ucred->cr_prison;
-	if (pr != NULL && pr->pr_linux != NULL) {
-		lpr = pr->pr_linux;
-		if (lpr->pr_oss_version)
-			return (lpr->pr_oss_version);
-	}
 
 	return (linux_oss_version);
 }
@@ -219,13 +155,8 @@
 	struct proc *p;
 	int oss_version;
 {
-	register struct linux_prison *lpr;
 
-	lpr = get_prison(p);
-	if (lpr != NULL)
-		lpr->pr_oss_version = oss_version;
-	else
-		linux_oss_version = oss_version;
+	linux_oss_version = oss_version;
 
 	return (0);
 }
Index: kern/init_main.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/init_main.c,v
retrieving revision 1.166
diff -u -r1.166 init_main.c
--- kern/init_main.c	2001/04/11 18:50:50	1.166
+++ kern/init_main.c	2001/04/23 16:17:52
@@ -66,6 +66,7 @@
 #include <sys/unistd.h>
 #include <sys/malloc.h>
 #include <sys/conf.h>
+#include <sys/jail.h>
 
 #include <machine/cpu.h>
 #include <machine/globals.h>
@@ -327,7 +328,7 @@
 	p->p_ucred = crget();
 	p->p_ucred->cr_ngroups = 1;	/* group 0 */
 	p->p_ucred->cr_uidinfo = uifind(0);
-	p->p_ucred->cr_prison = NULL;	/* Don't jail it. */
+	jail_crfirst(p->p_ucred);	/* initialize jail support */
 
 	/* Create procsig. */
 	p->p_procsig = &procsig0;
Index: kern/init_sysent.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/init_sysent.c,v
retrieving revision 1.98
diff -u -r1.98 init_sysent.c
--- kern/init_sysent.c	2001/04/11 20:21:36	1.98
+++ kern/init_sysent.c	2001/04/23 16:17:53
@@ -2,7 +2,7 @@
  * System call switch table.
  *
  * DO NOT EDIT-- this file is automatically generated.
- * $FreeBSD: src/sys/kern/init_sysent.c,v 1.98 2001/04/11 20:21:36 rwatson Exp $
+ * $FreeBSD$
  * created from FreeBSD: src/sys/kern/syscalls.master,v 1.88 2001/04/11 20:20:40 rwatson Exp 
  */
 
@@ -397,4 +397,5 @@
 	{ AS(extattr_get_fd_args), (sy_call_t *)extattr_get_fd },	/* 372 = extattr_get_fd */
 	{ AS(extattr_delete_fd_args), (sy_call_t *)extattr_delete_fd },	/* 373 = extattr_delete_fd */
 	{ AS(__setugid_args), (sy_call_t *)__setugid },	/* 374 = __setugid */
+	{ AS(jailconf_args), (sy_call_t *)jailconf },	/* 375 = jailconf */
 };
Index: kern/kern_jail.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/kern_jail.c,v
retrieving revision 1.10
diff -u -r1.10 kern_jail.c
--- kern/kern_jail.c	2001/02/21 06:39:54	1.10
+++ kern/kern_jail.c	2001/04/23 16:17:54
@@ -1,196 +1,1054 @@
-/*
- * ----------------------------------------------------------------------------
- * "THE BEER-WARE LICENSE" (Revision 42):
- * <phk@FreeBSD.ORG> wrote this file.  As long as you retain this notice you
- * can do whatever you want with this stuff. If we meet some day, and you think
- * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
- * ----------------------------------------------------------------------------
+/*-
+ * Copyright (c) 2001 Robert N. M. Watson
+ * 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.
  *
- * $FreeBSD: src/sys/kern/kern_jail.c,v 1.10 2001/02/21 06:39:54 rwatson Exp $
+ * 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: $
  */
+/*
+ * JailNG: from-scratch reimplementation of the jail(8) service devised by
+ * Poul-Henning Kamp <phk@FreeBSD.org> and originally included in FreeBSD
+ * 4.0-RELEASE.  Allow processes with appropriate privilege to confine
+ * themselves, and their descendants, to a restricted execution
+ * environment.  They are prohibited from directly interacting with
+ * processes outside the environment, and by relying on a series of
+ * limits to superuser privilege, prevented from modifying other existing
+ * namespaces, such as the filesystem namespace.
+ */
 
 #include <sys/param.h>
-#include <sys/types.h>
-#include <sys/kernel.h>
 #include <sys/systm.h>
-#include <sys/errno.h>
 #include <sys/sysproto.h>
+#include <sys/kernel.h>
 #include <sys/malloc.h>
+#include <sys/lock.h>
 #include <sys/proc.h>
-#include <sys/jail.h>
+#include <sys/sysent.h>
+#include <sys/ucred.h>
 #include <sys/socket.h>
 #include <sys/sysctl.h>
-#include <net/if.h>
+#include <sys/jail.h>
+
 #include <netinet/in.h>
+
+/* Flags for jaildesc.jd_flags field. */
+#define	JAIL_FLAGS_INCREATE	0x00000001
+#define	JAIL_FLAGS_INDESTROY	0x00000002
+
+/*
+ * struct jaildescr: per-jail description structure.
+ * 
+ * Locking:
+ * i - imutable once shared
+ * j - locked by jd_mtx
+ * l - locked by jd_list_mtx
+ */
+struct jaildescr {
+	struct mtx	jd_mtx;
+	int		jd_refcount;			/* (j) */
+	int		jd_flags;			/* (j) */
+	char		jd_name[JAIL_MAX_NAME];		/* (i) */
+
+	LIST_ENTRY(jaildescr)	 jd_list;		/* (l) */
+
+	struct sysctl_ctx_list	 jd_sysctltree;		/* (j) */
+	struct sysctl_oid	*jd_sysctltreetop;	/* (j) */
+	struct {
+		char	jdd_hostname[MAXHOSTNAMELEN];
+		int	jdd_sysvipc_permitted;
+		int	jdd_set_hostname_permitted;
+		int	jdd_socket_ipv4_permitted;
+		int	jdd_socket_unix_permitted;
+		int	jdd_socket_route_permitted;
+		int	jdd_socket_other_permitted;
+		u_int32_t	jdd_ipv4addr;
+	} jd_data;					/* (j) */
+};
+
+static MALLOC_DEFINE(M_JAIL, "jail", "Jail structures");
+
+static struct mtx		jd_list_mtx;
+static LIST_HEAD(, jaildescr)	jaildescr_list;
+
+SYSCTL_NODE(, OID_AUTO, jail, CTLFLAG_RD, 0, "jail parameters");
+SYSCTL_NODE(_jail, OID_AUTO, instance, CTLFLAG_RD, 0, "per-instance settings");
+
+/*
+ * jail_init(): Initialize the jail subsystem, including appropriate
+ *              locks and lists.
+ * Arguments: none
+ * Returns: none
+ * Locks: none
+ * Side effects: none
+ * References: none
+ * Notes: This call must be made before any other jail calls are invoked.
+ */
+static void
+jail_init(void)
+{
+
+	mtx_init(&jd_list_mtx, "jail list", MTX_DEF);
+	LIST_INIT(&jaildescr_list);
+}
+SYSINIT(jail, SI_SUB_PSEUDO, SI_ORDER_ANY, jail_init, NULL)
+
+/*
+ * jail_find(name): Return the jaildescr for a jail with name "name".
+ * Arguments: const char *name
+ * Returns: struct jaildescr * on success, NULL otherwise
+ * Locks: jd_list_mtx must be held
+ * Side effects: none
+ * References: none
+ * Notes: jd->jd_refcount will not be bumped on return.
+ */
+static struct jaildescr *
+jail_find(const char *name)
+{
+	struct jaildescr *jd;
+
+	mtx_assert(&jd_list_mtx, MA_OWNED);
 
-MALLOC_DEFINE(M_PRISON, "prison", "Prison structures");
+	LIST_FOREACH(jd, &jaildescr_list, jd_list)
+		if (!strncmp(name, jd->jd_name, JAIL_MAX_NAME))
+			return (jd);
+	return (NULL);
+}
 
-SYSCTL_NODE(, OID_AUTO, jail, CTLFLAG_RW, 0,
-    "Jail rules");
+/*
+ * jail_uniquename(jd): Replace jd's "name" with a unique name not present
+ *                      in any other reachable jails.
+ * Arguments: struct jaildescr *jd
+ * Returns: 1 on success, 0 on failure
+ * Locks: jd_list_mtx must be held
+ * Side effects: jd->jd_name will be modified on success or failure
+ * References: jd must be an exclusive jaildescr reference for the duration
+ *             of the call.
+ * Notes: none
+ */
+static int
+jail_uniquename(struct jaildescr *jd)
+{
+	struct jaildescr *jd_try;
+	pid_t pid_try;
+	int len;
+
+	mtx_assert(&jd_list_mtx, MA_OWNED);
+
+	/*
+	 * Create named based on possible PID values.  Because the number
+	 * of jails cannot exceed the number of processes, there should
+	 * always be a jail name available.  However, because of cached
+	 * credentials and possible garbage collection scenarios, it's
+	 * possible to imagine otherwise, so reserve the possibility of
+	 * failing.
+	 */
+	for (pid_try = 1; pid_try < PID_MAX; pid_try++) {
+		len = snprintf(jd->jd_name, JAIL_MAX_NAME, "%d", pid_try);
+		if (len >= JAIL_MAX_NAME)
+			panic("jail_uniquename: %%d doesn't fit into "
+			    "JAIL_MAX_NAME");
+
+		/* Test for any matches. */
+		jd_try = jail_find(jd->jd_name);
+		if (jd_try == NULL)
+			return (1);
+	}
 
-int	jail_set_hostname_allowed = 1;
-SYSCTL_INT(_jail, OID_AUTO, set_hostname_allowed, CTLFLAG_RW,
-    &jail_set_hostname_allowed, 0,
-    "Processes in jail can set their hostnames");
-
-int	jail_socket_unixiproute_only = 1;
-SYSCTL_INT(_jail, OID_AUTO, socket_unixiproute_only, CTLFLAG_RW,
-    &jail_socket_unixiproute_only, 0,
-    "Processes in jail are limited to creating UNIX/IPv4/route sockets only");
-
-int	jail_sysvipc_allowed = 0;
-SYSCTL_INT(_jail, OID_AUTO, sysvipc_allowed, CTLFLAG_RW,
-    &jail_sysvipc_allowed, 0,
-    "Processes in jail can use System V IPC primitives");
-
-int
-jail(p, uap)
-	struct proc *p;
-	struct jail_args /* {
-		syscallarg(struct jail *) jail;
-	} */ *uap;
+	/* No valid name. */
+	return (0);
+}
+
+/*
+ * jail_addjail(jd, name_provided): Given a partially completed jaildescr,
+ *                                  add "jd" to the global jail list,
+ *                                  filling in some remaining fields.
+ * Arguments: struct jaildescr *jd, int name_provided
+ * Returns: 0 on success, error number on failure
+ * Locks: jd_list_mtx must be held
+ * Side effects: jd->jd_name will be modified if name_provided==0
+ *               jd will be added to jd_list
+ * References: jd must be an exclusive jaildescr reference for the duration
+ *             of the call.
+ * Notes: Guarantees that on success, jail name is unique.
+ */
+static int
+jail_addjail(struct jaildescr *jd, int name_provided)
 {
+	struct jaildescr *jd_try;
 	int error;
-	struct prison *pr;
-	struct jail j;
-	struct chroot_args ca;
-
-	/* Implicitly fail if already in jail.  */
-	error = suser(p);
-	if (error)
-		return (error);
-	error = copyin(uap->jail, &j, sizeof j);
-	if (error)
-		return (error);
-	if (j.version != 0)
-		return (EINVAL);
-	MALLOC(pr, struct prison *, sizeof *pr , M_PRISON, M_WAITOK | M_ZERO);
-	error = copyinstr(j.hostname, &pr->pr_host, sizeof pr->pr_host, 0);
-	if (error) 
-		goto bail;
-	pr->pr_ip = j.ip_number;
-
-	ca.path = j.path;
-	error = chroot(p, &ca);
-	if (error)
-		goto bail;
-
-	p->p_ucred = crcopy(p->p_ucred);
-	p->p_ucred->cr_prison = pr;
-	pr->pr_ref = 1;
+
+	mtx_assert(&jd_list_mtx, MA_OWNED);
+
+	if (name_provided) {
+		jd_try = jail_find(jd->jd_name);
+		if (jd_try != NULL)
+			return (EBUSY);
+	} else {
+		error = jail_uniquename(jd);
+		if (error)
+			return (error);
+	}
+
+	LIST_INSERT_HEAD(&jaildescr_list, jd, jd_list);
+
 	return (0);
+}
 
-bail:
-	FREE(pr, M_PRISON);
-	return (error);
+/*
+ * jail_removejail(jd): Given a jaildescr, remove "jd" from the global
+ *                      jail list.
+ * Arguments: struct jaildescr *jd
+ * Returns: none
+ * Locks: jd_list_mtx must be held
+ * Side effects: jd will be removed from jd_list
+ * Referneces: jd must be an exclusive jaildescr reference for the duration
+ *             of the call.
+ * Notes: none
+ */
+static void
+jail_removejail(struct jaildescr *jd)
+{
+
+	mtx_assert(&jd_list_mtx, MA_OWNED);
+
+	LIST_REMOVE(jd, jd_list);
+}
+
+/*
+ * jail_newjaildescr(): Allocate a new struct jaildescr and fill in some
+ *                      fields.
+ * Arguments: none
+ * Returns: struct jaildescr *
+ * Locks: none
+ * Side effects: none
+ * References: none
+ * Notes: initial refcount will be set to 0
+ */
+static struct jaildescr *
+jail_newjaildescr(void)
+{
+	struct jaildescr *jd;
+
+	MALLOC(jd, struct jaildescr *, sizeof(*jd), M_JAIL, M_WAITOK|M_ZERO);
+
+	mtx_init(&jd->jd_mtx, "jaildescr", MTX_DEF);
+
+	jd->jd_refcount = 0;
+	jd->jd_flags = 0;
+	sysctl_ctx_init(&jd->jd_sysctltree);
+
+	return (jd);
 }
 
+/*
+ * jail_crfirst(cr): Initialize jail support for the root of the credential
+ *                   tree.
+ * Arguments: exclusive struct ucred *cr
+ * Returns: none
+ * Locks: none
+ * Side effects: none
+ * References: cr must be an exclusive credential reference for the duration
+ *             of the call.
+ * Notes: Intended to be called only on cred0 during credential creation;
+ *        will initialize such that the first credential is not in a jail.
+ */
 void
-prison_free(struct prison *pr)
+jail_crfirst(struct ucred *cr)
 {
 
-	pr->pr_ref--;
-	if (pr->pr_ref == 0) {
-		if (pr->pr_linux != NULL)
-			FREE(pr->pr_linux, M_PRISON);
-		FREE(pr, M_PRISON);
-	}
+	cr->cr_jail = NULL;
 }
 
+/*
+ * jail_crdup(cr1, cr2): When a credential copy is performed on "cr1",
+ *                       propagate necessary information concerning jails
+ *                       to "cr2".
+ * Arguments: shared struct ucred *cr1, exclusive struct ucred *cr2
+ * Returns: none
+ * Locks: none
+ * Side effects: cr1->cr_jail->jd_refcount will be incremented
+ * References: cr1 must be a shared or exclusive credential reference for
+ *             the durection of the call.  cr2 must be an exclusive
+ *             credential reference for the duration of the call.
+ * Notes: none
+ */
 void
-prison_hold(struct prison *pr)
+jail_crdup(struct ucred *cr1, struct ucred *cr2)
 {
+	struct jaildescr *jd;
 
-	pr->pr_ref++;
+	if (cr1->cr_jail != NULL) {
+		jd = cr1->cr_jail;
+		mtx_lock(&jd->jd_mtx);
+		jd->jd_refcount++;
+		mtx_unlock(&jd->jd_mtx);
+		cr2->cr_jail = jd;
+	} else
+		cr2->cr_jail = NULL;
 }
 
+/*
+ * jail_crfree(cr): Deallocate any jail state associated with the credential
+ *                  "cr".
+ * Arguments: exclusive struct ucred *cr
+ * Returns: none
+ * Locks: none
+ * Side effects: cr->cr_jail->jd_refcount will be decremented
+ * References: cr must be an exclusive credential reference for the
+ *             duration of the call.
+ * Notes: none
+ */
+void
+jail_crfree(struct ucred *cr)
+{
+	struct jaildescr *jd;
+
+	if (cr->cr_jail != NULL) {
+		jd = cr->cr_jail;
+
+		mtx_lock(&jd->jd_mtx);
+		jd->jd_refcount--;
+		mtx_unlock(&jd->jd_mtx);
+
+		cr->cr_jail = NULL;
+	}
+}
+
+/*
+ * jail_freejaildescr(jd): Clean up and free a struct jaildescr allocated
+ *                         using jail_newjaildescr().
+ * Arguments: struct jaildescr *
+ * Returns: none
+ * Locks: none
+ * Side effects: jd will be freed
+ * References: jd must be an exclusive jaildescr reference for the duration
+ *             of the call.
+ * Notes: none
+ */
+static void
+jail_freejaildescr(struct jaildescr *jd)
+{
+
+	mtx_destroy(&jd->jd_mtx);
+	FREE(jd, M_JAIL);
+}
+
+/*
+ * jail_create(p, name, name_provided): Create a new jail, link it to
+ *                                      the gloal list, generating a
+ *                                      unique name if one is not
+ *                                      provided.  Return the name to
+ *                                      the caller if it was generated
+ *                                      internally.
+ * Arguments: struct proc *p, char *name, int name_provided
+ * Returns: 0 on success, error number otherwise
+ * Locks: none
+ * Side effects: jaildescr will be allocated, linked to global list,
+ *               sysctl's to manage the jail will be created.
+ *               name may be modified if name_provided was 0; caller must
+ *               assure that at least JAIL_MAX_NAME space is available in
+ *               name if name_provided == 0
+ * References: none
+ * Notes: To prevent the jail from being used during creation, the
+ *        JAIL_INCREATE flag is set, which will cause other calls to
+ *        return EBUSY.  This allows the list and jail mutices to be
+ *        released during potentially sleep()ing calls.  If the reserved
+ *        name for no-jail-present, JAIL_NOJAIL_NAME, is provided, an
+ *        error will be returned.
+ */
+static int
+jail_create(struct proc *p, char *name, int name_provided)
+{
+	struct jaildescr *jd;
+	int error;
+
+	/* Don't permit use of the reserved name. */
+	if (name_provided) {
+		if (!strncmp(name, JAIL_NOJAIL_NAME, JAIL_MAX_NAME))
+			return (EINVAL);
+	}
+
+	jd = jail_newjaildescr();
+
+	/* XXX fill in jail data fields. */
+
+	jd->jd_data.jdd_sysvipc_permitted = 0;
+	jd->jd_data.jdd_set_hostname_permitted = 1;
+
+	jd->jd_data.jdd_socket_ipv4_permitted = 1;
+	jd->jd_data.jdd_socket_unix_permitted = 1;
+	jd->jd_data.jdd_socket_route_permitted = 1;
+	jd->jd_data.jdd_socket_other_permitted = 0;
+
+	if (name_provided)
+		strncpy(jd->jd_name, name, JAIL_MAX_NAME);
+
+	jd->jd_flags |= JAIL_FLAGS_INCREATE;
+
+	mtx_lock(&jd_list_mtx);
+	error = jail_addjail(jd, name_provided);
+	mtx_unlock(&jd_list_mtx);
+	if (error) {
+		jail_freejaildescr(jd);
+		return (error);
+	}
+
+	/* printf("jail_create(%s)\n", jd->jd_name); */
+	jd->jd_sysctltreetop = SYSCTL_ADD_NODE(&jd->jd_sysctltree,
+	    SYSCTL_STATIC_CHILDREN(_jail_instance), OID_AUTO,
+	    jd->jd_name, CTLFLAG_RD, 0, "jail name");
+	if (jd->jd_sysctltreetop == NULL) {
+		mtx_lock(&jd_list_mtx);
+		jail_removejail(jd);
+		mtx_unlock(&jd_list_mtx);
+		jail_freejaildescr(jd);
+		return (EBUSY);
+	}
+
+	SYSCTL_ADD_INT(&jd->jd_sysctltree,
+	    SYSCTL_CHILDREN(jd->jd_sysctltreetop), OID_AUTO,
+	    "sysvipc_permitted", CTLFLAG_RW,
+	    &jd->jd_data.jdd_sysvipc_permitted, 0, "System V IPC permitted");
+	SYSCTL_ADD_INT(&jd->jd_sysctltree,
+	    SYSCTL_CHILDREN(jd->jd_sysctltreetop), OID_AUTO,
+	    "set_hostname_permitted", CTLFLAG_RW,
+	    &jd->jd_data.jdd_set_hostname_permitted, 0,
+	    "sethostname() permitted");
+	SYSCTL_ADD_INT(&jd->jd_sysctltree,
+	    SYSCTL_CHILDREN(jd->jd_sysctltreetop), OID_AUTO,
+	    "socket_ipv4_permitted", CTLFLAG_RW,
+	    &jd->jd_data.jdd_socket_ipv4_permitted, 0,
+	    "IPv4 sockets permitted");
+	SYSCTL_ADD_INT(&jd->jd_sysctltree,
+	    SYSCTL_CHILDREN(jd->jd_sysctltreetop), OID_AUTO,
+	    "socket_unix_permitted", CTLFLAG_RW,
+	    &jd->jd_data.jdd_socket_unix_permitted, 0,
+	    "UNIX domain sockets permitted");
+	SYSCTL_ADD_INT(&jd->jd_sysctltree,
+	    SYSCTL_CHILDREN(jd->jd_sysctltreetop), OID_AUTO,
+	    "socket_route_permitted", CTLFLAG_RW,
+	    &jd->jd_data.jdd_socket_route_permitted, 0,
+	    "routing sockets permitted");
+	SYSCTL_ADD_INT(&jd->jd_sysctltree,
+	    SYSCTL_CHILDREN(jd->jd_sysctltreetop), OID_AUTO,
+	    "socket_other_permitted", CTLFLAG_RW,
+	    &jd->jd_data.jdd_socket_other_permitted, 0,
+	    "other sockets permitted");
+	SYSCTL_ADD_INT(&jd->jd_sysctltree,
+	    SYSCTL_CHILDREN(jd->jd_sysctltreetop), OID_AUTO,
+	    "ipv4addr", CTLFLAG_RW,
+	    &jd->jd_data.jdd_ipv4addr, 0,
+	    "IPv4 address");
+
+	/* Copy out the name for the caller. */
+	strncpy(name, jd->jd_name, JAIL_MAX_NAME);
+
+	mtx_lock(&jd->jd_mtx);
+	jd->jd_flags &= ~JAIL_FLAGS_INCREATE;
+	mtx_unlock(&jd->jd_mtx);
+
+	return (0);
+}
+
+/*
+ * jail_destroy(p, name): Destroy the jail with passed name, if it is
+ *                        not in use.
+ * Arguments: struct proc *p, char *name
+ * Returns: 0 on success, error number otherwise
+ * Locks: none
+ * Side effects: jaildesc will be unlinked from the global list,
+ *               deallocated, and its sysctl context (and associated
+ *               sysctls) will be freed.
+ * References: none
+ * Notes: Because this call may sleep during various freeing operations,
+ *        a flag is set on the jail while it is unlocked, JAIL_INDESTROY,
+ *        which prevents new references from being generated or name
+ *        collisions from occuring during the removal of the jail.
+ */
+static int
+jail_destroy(struct proc *p, const char *name)
+{
+	struct jaildescr *jd;
+
+	/* Don't permit use of the reserved name. */
+	if (!strncmp(name, JAIL_NOJAIL_NAME, JAIL_MAX_NAME))
+		return (EINVAL);
+
+	mtx_lock(&jd_list_mtx);
+	jd = jail_find(name);
+	if (jd == NULL) {
+		mtx_unlock(&jd_list_mtx);
+		return (ENOENT);
+	}
+	mtx_lock(&jd->jd_mtx);
+
+	if (jd->jd_flags & (JAIL_FLAGS_INCREATE | JAIL_FLAGS_INDESTROY)) {
+		mtx_unlock(&jd->jd_mtx);
+		mtx_unlock(&jd_list_mtx);
+		return (EBUSY);
+	}
+
+	if (jd->jd_refcount > 0) {
+		mtx_unlock(&jd->jd_mtx);
+		mtx_unlock(&jd_list_mtx);
+		return (EBUSY);
+	}
+
+	jd->jd_flags |= JAIL_FLAGS_INDESTROY;
+	jd->jd_sysctltreetop = NULL;
+
+	mtx_unlock(&jd->jd_mtx);
+	mtx_unlock(&jd_list_mtx);
+
+	sysctl_ctx_free(&jd->jd_sysctltree);
+
+	mtx_lock(&jd_list_mtx);
+
+	jail_removejail(jd);
+
+	mtx_unlock(&jd_list_mtx);
+
+	jail_freejaildescr(jd);
+
+	return (0);
+}
+
+/*
+ * jail_join(p, name): Attach the calling process to the jail named by
+ *                     name.
+ * Arguments: struct proc *p, char *name
+ * Returns: 0 on success, error number otherwise
+ * Locks: none
+ * Side effects: p's ucred will be updated (replaced) to reflect jail
+ *               pointer changes.  jd->jd_refcount will be incremented.
+ *               P_SUGID flag will be set on p to protect its resources
+ *               from other processes in the jail, as this constitutes
+ *               a credential downgrade.
+ * References: none
+ * Notes: To prevent attaching to jails still in creation or deletion,
+ *        checks for the JAIL_INCREATE and JAIL_INDELETE flags are
+ *        performed; EBUSY is returned if they are set.
+ */
+static int
+jail_join(struct proc *p, const char *name)
+{
+	struct jaildescr *jd;
+	struct ucred *cr, *oldcr;
+
+	/* Don't permit use of the reserved name. */
+	if (!strncmp(name, JAIL_NOJAIL_NAME, JAIL_MAX_NAME))
+		return (EINVAL);
+
+	mtx_lock(&jd_list_mtx);
+	jd = jail_find(name);
+	if (jd == NULL) {
+		mtx_unlock(&jd_list_mtx);
+		return (ENOENT);
+	}
+	mtx_lock(&jd->jd_mtx);
+
+	if (jd->jd_flags & (JAIL_FLAGS_INCREATE | JAIL_FLAGS_INDESTROY)) {
+		mtx_unlock(&jd->jd_mtx);
+		mtx_unlock(&jd_list_mtx);
+		return (EBUSY);
+	}
+
+	jd->jd_refcount++;
+
+	mtx_unlock(&jd->jd_mtx);
+	mtx_unlock(&jd_list_mtx);
+
+	cr = crdup(p->p_ucred);
+	cr->cr_jail = jd;
+	PROC_LOCK(p);
+	setsugid(p);
+	oldcr = p->p_ucred;
+	p->p_ucred = cr;
+	PROC_UNLOCK(p);
+	crfree(oldcr);
+
+	return (0);
+}
+
 int
-prison_ip(struct ucred *cred, int flag, u_int32_t *ip)
+jailconf(struct proc *p, struct jailconf_args *uap)
 {
-	u_int32_t tmp;
+	char name[JAIL_MAX_NAME];
+	int error, name_provided;
 
-	if (!jailed(cred))
+	if ((error = suser(p)))
+		return (error);
+
+	if (name != NULL) {
+		error = copyinstr(SCARG(uap, name), name, JAIL_MAX_NAME, NULL);
+		if (error)
+			return (error);
+		name_provided = 1;
+	} else
+		name_provided = 0;
+
+	switch (SCARG(uap, cmd)) {
+	case JAIL_CREATE:
+		error = jail_create(p, name, name_provided);
+		if (error)
+			return (error);
+
+		if (!name_provided) {
+			error = copyout(name, SCARG(uap, name),
+			    strlen(name)+1);
+			if (error)
+				return (error);
+		}
+
 		return (0);
-	if (flag) 
-		tmp = *ip;
-	else
-		tmp = ntohl(*ip);
-	if (tmp == INADDR_ANY) {
-		if (flag) 
-			*ip = cred->cr_prison->pr_ip;
-		else
-			*ip = htonl(cred->cr_prison->pr_ip);
+
+	case JAIL_DESTROY:
+		if (!name_provided)
+			return (EINVAL);
+		return (jail_destroy(p, name));
+
+	case JAIL_JOIN:
+		if (!name_provided)
+			return (EINVAL);
+		return (jail_join(p, name));
+
+	default:
+		return (EINVAL);
+	}
+}
+
+/*
+ * jailed(cr): Determine if the passed credential is in a jail.
+ * Arguments: shared or exclusive struct cred *cr
+ * Returns: 1 if in jail, 0 otherwise
+ * Locks: none
+ * Side effects: none
+ * References: cr must be a shared or exclusive credential reference for
+ *             the duration of the call.
+ * Notes: none
+ */
+int
+jailed(struct ucred *cr)
+{
+
+	return (cr->cr_jail != NULL);
+}
+
+/*
+ * jail_ucansee(cr1, cr2): Determine if passed credential cr1 "can see"
+ *                         subjects with credential cr2.
+ * Arguments: shared or exclusive struct cred *cr1, *cr2
+ * Returns: 0 on success, error number otherwise
+ * Locks: none
+ * Side effects: none
+ * References: cr1 and cr2 must be shared or exclusive credential
+ *             references for the duration of the call.
+ * Notes: none
+ */
+int
+jail_ucansee(struct ucred *cr1, struct ucred *cr2)
+{
+
+	if (cr1->cr_jail != NULL) {
+		if (cr2->cr_jail == NULL)
+			return (ESRCH);
+		if (cr1->cr_jail != cr2->cr_jail)
+			return (ESRCH);
+	}
+
+	return (0);
+}
+
+/*
+ * jail_ucansignal(cr1, cr2, int signam): Determine if passed credential
+ *                                        cr1 "can signal" cr2 using signal
+ *                                        signum.
+ * Arguments: shared or exclusive struct cred *cr1, *cr2, signal number
+ *            int signum
+ * Returns: 0 on success, error number otherwise
+ * Locks: none
+ * Side effects: none
+ * References: cr1 and cr2 must be shared or exclusive credential
+ *             references for the duration of the call.
+ * Notes: none
+ */
+int
+jail_ucansignal(struct ucred *cr1, struct ucred *cr2, int signum)
+{
+
+	return (jail_ucansee(cr1, cr2));
+}
+
+/*
+ * jail_ucansched(cr1, cr2): Determine if passed credential cr1 "can
+ *                           reschedule" cr2.
+ * Arguments: shared or exclusive struct cred *cr1, *cr2
+ * Returns: 0 on success, error number otherwise
+ * Locks: none
+ * Side effects: none
+ * References: cr1 and cr2 must be shared or exclusive credential
+ *             references for the duration of the call.
+ * Notes: none
+ */
+int
+jail_ucansched(struct ucred *cr1, struct ucred *cr2)
+{
+
+	return (jail_ucansee(cr1, cr2));
+}
+
+/*
+ * jail_ucandebug(cr1, cr2): Determine if passed credential cr1 "can debug"
+ *                           subjects with credential cr2.
+ * Arguments: shared or exclusive struct cred *cr1, *cr2
+ * Returns: 0 on success, error number otherwise
+ * Locks: none
+ * Side effects: none
+ * References: cr1 and cr2 must be shared or exclusive credential
+ *             references for the duration of the call.
+ * Notes: none
+ */
+int
+jail_ucandebug(struct ucred *cr1, struct ucred *cr2)
+{
+
+	return (jail_ucansee(cr1, cr2));
+}
+
+/*
+ * jail_ucansysvipc(cr): Determine if the passed credential cr can make use
+ *                       of System V IPC.
+ * Arguments: shared or exclusive struct ucred *cr
+ * Returns: 0 on success, error number otherwise
+ * Locks: none
+ * Side effects: none
+ * References: cr must be a shared or exclusive credential references for the
+ *             duration of the call.
+ * Notes: none
+ */
+int
+jail_ucansysvipc(struct ucred *cr)
+{
+	struct jaildescr *jd;
+
+	jd = cr->cr_jail;
+	if (jd == NULL)
 		return (0);
+	mtx_lock(&jd->jd_mtx);
+
+	if (!jd->jd_data.jdd_sysvipc_permitted) {
+		mtx_unlock(&jd->jd_mtx);
+		return (ENOSYS);
 	}
-	if (cred->cr_prison->pr_ip != tmp)
-		return (1);
+
+	mtx_unlock(&jd->jd_mtx);
 	return (0);
 }
 
-void
-prison_remote_ip(struct ucred *cred, int flag, u_int32_t *ip)
+/*
+ * jail_ucanopenpty(cr1, cr2): Determine if the passed credential cr1 can
+ *                             open a pty originally opened by cr2.
+ * Arguments: shared or exclusive struct ucred *cr1, *cr2
+ * Returns: 0 on success, error number otherwise
+ * Locks: none
+ * Side effects: none
+ * References: cr1 and cr2 must be shared or exclusive credential references
+ *             for the duration of the call.
+ * Notes: none
+ */
+int
+jail_ucanopenpty(struct ucred *cr1, struct ucred *cr2)
 {
-	u_int32_t tmp;
 
-	if (!jailed(cred))
-		return;
-	if (flag)
-		tmp = *ip;
-	else
-		tmp = ntohl(*ip);
-	if (tmp == 0x7f000001) {
-		if (flag)
-			*ip = cred->cr_prison->pr_ip;
-		else
-			*ip = htonl(cred->cr_prison->pr_ip);
-		return;
+	if (cr1->cr_jail != NULL) {
+		if (cr2->cr_jail == NULL)
+			return (EBUSY);
+		if (cr1->cr_jail != cr2->cr_jail)
+			return (EBUSY);
+	}
+	return (0);
+}
+
+/*
+ * jail_cansocreate(cr, domfamily, type): Determine if credential cr can
+ *                                        create a socket of family
+ *                                        domfamily and type type.
+ * Arguments: shared or exclusive struct ucred *cr, int domfamily, int type
+ * Returns: 0 on success, error number otherwise
+ * Locks: none
+ * Side effects: none
+ * References: cr must be a shared or exclusive credential reference for the
+ *             duration of the call.
+ * Notes: none
+ */
+int
+jail_ucansocreate(struct ucred *cr, int domfamily, int type)
+{
+	struct jaildescr *jd;
+	int error = 0;
+
+	jd = cr->cr_jail;
+	if (jd != NULL) {
+		mtx_lock(&jd->jd_mtx);
+
+		switch (domfamily) {
+		case PF_LOCAL:
+			if (jd->jd_data.jdd_socket_unix_permitted)
+				error = 0;
+			else
+				error = EPROTONOSUPPORT;
+			break;
+	
+		case PF_INET:
+			if (jd->jd_data.jdd_socket_ipv4_permitted)
+				error = 0;
+			else
+				error = EPROTONOSUPPORT;
+			break;
+
+		case PF_ROUTE:
+			if (jd->jd_data.jdd_socket_route_permitted)
+				error = 0;
+			else
+				error = EPROTONOSUPPORT;
+
+			break;
+		default:
+			if (jd->jd_data.jdd_socket_other_permitted)
+				error = 0;
+			else
+				error = EPROTONOSUPPORT;
+		}
+
+		mtx_unlock(&jd->jd_mtx);
 	}
-	return;
+
+	return (error);
 }
 
+/*
+ * jail_gethostname(cr, hostname): Get the hostname for the jail associated
+ *                                 with the passed credential cr.
+ * Arguments: shared or exclusive struct cred *cr, char *hostname
+ * Returns: 0 on success, error number otherwise
+ * Locks: none
+ * Side effects: hostname will be updated on success.
+ * References: cr must be a shared or exclusive credential reference for
+ *             the duration of the call.
+ * Notes: hostname buffer must be >= MAXHOSTNAMELEN in length.
+ */
 int
-prison_if(struct ucred *cred, struct sockaddr *sa)
+jail_gethostname(struct ucred *cr, char *hostname)
 {
-	struct sockaddr_in *sai = (struct sockaddr_in*) sa;
-	int ok;
+	struct jaildescr *jd;
 
-	if ((sai->sin_family != AF_INET) && jail_socket_unixiproute_only)
-		ok = 1;
-	else if (sai->sin_family != AF_INET)
-		ok = 0;
-	else if (cred->cr_prison->pr_ip != ntohl(sai->sin_addr.s_addr))
-		ok = 1;
-	else
-		ok = 0;
-	return (ok);
+	jd = cr->cr_jail;
+	if (jd == NULL)
+		return (EINVAL);
+	mtx_lock(&jd->jd_mtx);
+
+	strncpy(hostname, jd->jd_data.jdd_hostname, MAXHOSTNAMELEN);
+
+	mtx_unlock(&jd->jd_mtx);
+	return (0);
 }
 
 /*
- * Return 0 if jails permit p1 to frob p2, otherwise ESRCH.
+ * jail_sethostname(cr, hostname): Set the hostname for the jail associated
+ *                                 with passed credential cr to hostname.
+ * Arguments: shared or exclusive struct cred *cr, char *hostname
+ * Returns: 0 on success, error number otherwise
+ * Locks: none
+ * Side effects: jd->jd_data.jdd_hostname is updated on success.
+ * References: cr must be a shared or exclusive credential reference for
+ *             the duration of the call.
+ * Notes: hostname must be <= MAXHOSTNAMELEN in length, including NUL.
  */
 int
-prison_check(cred1, cred2)
-	struct ucred *cred1, *cred2;
+jail_sethostname(struct ucred *cr, const char *hostname)
 {
+	struct jaildescr *jd;
 
-	if (jailed(cred1)) {
-		if (!jailed(cred2))
-			return (ESRCH);
-		if (cred2->cr_prison != cred1->cr_prison)
-			return (ESRCH);
+	jd = cr->cr_jail;
+	if (jd == NULL)
+		return (EINVAL);
+	mtx_lock(&jd->jd_mtx);
+
+	if (!jd->jd_data.jdd_set_hostname_permitted) {
+		mtx_unlock(&jd->jd_mtx);
+		return (EPERM);
 	}
 
+	strncpy(jd->jd_data.jdd_hostname, hostname, MAXHOSTNAMELEN);
+
+	mtx_unlock(&jd->jd_mtx);
 	return (0);
 }
 
+/*
+ * jail_name(cr, buf, buflen, format): Print the jail name associated with
+ *                                 the passed credential cr in the caller-
+ *                                 provided buffer buf, of length buflen,
+ *                                 using the provided format string, where
+ *                                 one string (%s) is expected to be
+ *                                 specified.
+ * Arguments: char *buf, length int buflen, char *format
+ * Returns: if the return value is greater than or equal to the buflen
+ *          argument, the buffer was too short and results were truncated;
+ *          otherwise, the length of the resulting string in buf.
+ * Locks: none
+ * Side effects: character buffer buf is modified to include the jail
+ *               name.
+ * References: cr must be a shared or exclusive credential reference for
+ *             the duration of the call.
+ * Notes: The return value should be interpreted and handled in the style
+ *        of an snprintf() return value.  If no jail is associated with
+ *        the passed credential, an empty string will be substituted for
+ *        the %s in the format string.
+ */
+int
+jail_name(struct ucred *cr, char *buf, int buflen, char *format)
+{
+	struct jaildescr *jd;
+
+	jd = cr->cr_jail;
+	if (jd == NULL)
+		return (snprintf(buf, buflen, format, JAIL_NOJAIL_NAME));
+	else
+		return (snprintf(buf, buflen, format, jd->jd_name));
+}
+
 /*
- * Return 1 if the passed credential is in a jail, otherwise 0.
+ * XXX: Compatibility.
  */
+u_int32_t
+prison_getipv4addr(struct ucred *cr)
+{
+	struct jaildescr *jd;
+	u_int32_t addr;
+
+	jd = cr->cr_jail;
+	KASSERT(jd != NULL, ("prison_getip: credential not in jail"));
+	mtx_lock(&jd->jd_mtx);
+
+	addr = jd->jd_data.jdd_ipv4addr;
+
+	mtx_unlock(&jd->jd_mtx);
+	return (addr);
+}
+
+int
+prison_if(struct ucred *cr, struct sockaddr *sa)
+{
+	struct jaildescr *jd;
+	struct sockaddr_in *sai = (struct sockaddr_in *) sa;
+	u_int32_t addr;
+	int socket_ipv4_permitted, socket_other_permitted;
+
+	jd = cr->cr_jail;
+	KASSERT(jd != NULL, ("prison_if: credential not in jail"));
+	mtx_lock(&jd->jd_mtx);
+	addr = jd->jd_data.jdd_ipv4addr;
+	socket_ipv4_permitted = jd->jd_data.jdd_socket_ipv4_permitted;
+	socket_other_permitted = jd->jd_data.jdd_socket_other_permitted;
+	mtx_unlock(&jd->jd_mtx);
+
+	switch (sai->sin_family) {
+	case AF_INET:
+		if (socket_ipv4_permitted) {
+			if (addr == ntohl(sai->sin_addr.s_addr))
+				return (0);
+		}
+		break;
+
+	default:
+		if (socket_other_permitted)
+			return (0);
+	}
+
+	return (1);
+}
+
+int
+prison_ip(struct ucred *cr, int flag, u_int32_t *ip)
+{
+	struct jaildescr *jd;
+	u_int32_t jailaddr, reqaddr;
+
+	jd = cr->cr_jail;
+	if (jd == NULL)
+		return (0);
+
+	mtx_lock(&jd->jd_mtx);
+	jailaddr = jd->jd_data.jdd_ipv4addr;
+	mtx_unlock(&jd->jd_mtx);
+
+	if (flag)
+		reqaddr = *ip;
+	else
+		reqaddr = ntohl(*ip);
+	if (reqaddr == INADDR_ANY) {
+		if (flag)
+			*ip = jailaddr;
+		else
+			*ip = htonl(jailaddr);
+		return (0);
+	}
+	if (jailaddr != reqaddr)
+		return (1);
+	return (0);
+}
+
+void
+prison_remote_ip(struct ucred *cr, int flag, u_int32_t *ip)
+{
+	struct jaildescr *jd;
+	u_int32_t oldaddr, newaddr;
+
+	jd = cr->cr_jail;
+	if (jd == NULL)
+		return;
+
+	mtx_lock(&jd->jd_mtx);
+	newaddr = jd->jd_data.jdd_ipv4addr;
+	mtx_unlock(&jd->jd_mtx);
+
+	if (flag)
+		oldaddr = *ip;
+	else
+		oldaddr = ntohl(*ip);
+	if (oldaddr == 0x7f000001) {
+		if (flag)
+			*ip = newaddr;
+		else
+			*ip = htonl(newaddr);
+		return;
+	}
+}
+
 int
-jailed(cred)
-	struct ucred *cred;
+jail(struct proc *p, struct jail_args *uap)
 {
 
-	return (cred->cr_prison != NULL);
+	return (ENOSYS);
 }
Index: kern/kern_ktrace.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/kern_ktrace.c,v
retrieving revision 1.50
diff -u -r1.50 kern_ktrace.c
--- kern/kern_ktrace.c	2001/03/28 11:52:53	1.50
+++ kern/kern_ktrace.c	2001/04/23 16:17:55
@@ -532,7 +532,7 @@
 	register struct pcred *caller = callp->p_cred;
 	register struct pcred *target = targetp->p_cred;
 
-	if (prison_check(callp->p_ucred, targetp->p_ucred))
+	if (jail_ucandebug(callp->p_ucred, targetp->p_ucred))
 		return (0);
 	if ((caller->pc_ucred->cr_uid == target->p_ruid &&
 	     target->p_ruid == target->p_svuid &&
Index: kern/kern_mib.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/kern_mib.c,v
retrieving revision 1.39
diff -u -r1.39 kern_mib.c
--- kern/kern_mib.c	2001/02/21 06:39:54	1.39
+++ kern/kern_mib.c	2001/04/23 16:17:56
@@ -144,14 +144,22 @@
 static int
 sysctl_hostname(SYSCTL_HANDLER_ARGS)
 {
+	char hostname_stack[MAXHOSTNAMELEN];
 	int error;
 
 	if (jailed(req->p->p_ucred)) {
-		if (!jail_set_hostname_allowed && req->newptr)
-			return(EPERM);
-		error = sysctl_handle_string(oidp, 
-		    req->p->p_ucred->cr_prison->pr_host,
-		    sizeof req->p->p_ucred->cr_prison->pr_host, req);
+		error = jail_gethostname(req->p->p_ucred, hostname_stack);
+		if (error)
+			return (error);
+
+		error = sysctl_handle_string(oidp, hostname_stack,
+		    sizeof(hostname_stack), req);
+		if (error)
+			return (error);
+
+		if (req->newptr)
+			error = jail_sethostname(req->p->p_ucred,
+			    hostname_stack);
 	} else
 		error = sysctl_handle_string(oidp, 
 		    hostname, sizeof hostname, req);
Index: kern/kern_prot.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/kern_prot.c,v
retrieving revision 1.86
diff -u -r1.86 kern_prot.c
--- kern/kern_prot.c	2001/04/21 22:41:45	1.86
+++ kern/kern_prot.c	2001/04/23 16:17:56
@@ -1013,7 +1013,7 @@
 {
 	int error;
 
-	if ((error = prison_check(u1, u2)))
+	if ((error = jail_ucansee(u1, u2)))
 		return (error);
 	if (!ps_showallprocs && u1->cr_uid != u2->cr_uid) {
 		if (suser_xxx(u1, NULL, PRISON_ROOT) != 0)
@@ -1048,7 +1048,7 @@
 	 * Jail semantics limit the scope of signalling to p2 in the same
 	 * jail as p1, if p1 is in jail.
 	 */
-	if ((error = prison_check(p1->p_ucred, p2->p_ucred)))
+	if ((error = jail_ucansignal(p1->p_ucred, p2->p_ucred, signum)))
 		return (error);
 
 	/*
@@ -1114,7 +1114,7 @@
 	if (p1 == p2)
 		return (0);
 
-	if ((error = prison_check(p1->p_ucred, p2->p_ucred)))
+	if ((error = jail_ucansched(p1->p_ucred, p2->p_ucred)))
 		return (error);
 
 	if (p1->p_cred->p_ruid == p2->p_cred->p_ruid)
@@ -1161,7 +1161,7 @@
 	if (p1 == p2)
 		return (0);
 
-	if ((error = prison_check(p1->p_ucred, p2->p_ucred)))
+	if ((error = jail_ucandebug(p1->p_ucred, p2->p_ucred)))
 		return (error);
 
 	/* not owned by you, has done setuid (unless you're root) */
@@ -1252,11 +1252,8 @@
 		 */
 		if (cr->cr_uidinfo != NULL)
 			uifree(cr->cr_uidinfo);
-		/*
-		 * Free a prison, if any.
-		 */
-		if (jailed(cr))
-			prison_free(cr->cr_prison);
+		/* Recover any jail state for the credential. */
+		jail_crfree(cr);
 		FREE((caddr_t)cr, M_CRED);
 	} else {
 		mtx_unlock(&cr->cr_mtx);
@@ -1296,8 +1293,7 @@
 	*newcr = *cr;
 	mtx_init(&newcr->cr_mtx, "ucred", MTX_DEF);
 	uihold(newcr->cr_uidinfo);
-	if (jailed(newcr))
-		prison_hold(newcr->cr_prison);
+	jail_crdup(cr, newcr);
 	newcr->cr_ref = 1;
 	return (newcr);
 }
Index: kern/syscalls.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/syscalls.c,v
retrieving revision 1.87
diff -u -r1.87 syscalls.c
--- kern/syscalls.c	2001/04/11 20:21:36	1.87
+++ kern/syscalls.c	2001/04/23 16:17:56
@@ -2,7 +2,7 @@
  * System call names.
  *
  * DO NOT EDIT-- this file is automatically generated.
- * $FreeBSD: src/sys/kern/syscalls.c,v 1.87 2001/04/11 20:21:36 rwatson Exp $
+ * $FreeBSD$
  * created from FreeBSD: src/sys/kern/syscalls.master,v 1.88 2001/04/11 20:20:40 rwatson Exp 
  */
 
@@ -382,4 +382,5 @@
 	"extattr_get_fd",			/* 372 = extattr_get_fd */
 	"extattr_delete_fd",			/* 373 = extattr_delete_fd */
 	"__setugid",			/* 374 = __setugid */
+	"jailconf",			/* 375 = jailconf */
 };
Index: kern/syscalls.master
===================================================================
RCS file: /home/ncvs/src/sys/kern/syscalls.master,v
retrieving revision 1.88
diff -u -r1.88 syscalls.master
--- kern/syscalls.master	2001/04/11 20:20:40	1.88
+++ kern/syscalls.master	2001/04/23 16:17:57
@@ -542,3 +542,4 @@
 373	STD	BSD	{ int extattr_delete_fd(int fd, int attrnamespace, \
 			    const char *attrname); }
 374	STD	BSD	{ int __setugid(int flag); }
+375	STD	BSD	{ int jailconf(int cmd, char *name); }
Index: kern/sysv_msg.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/sysv_msg.c,v
retrieving revision 1.30
diff -u -r1.30 sysv_msg.c
--- kern/sysv_msg.c	2001/02/21 06:39:54	1.30
+++ kern/sysv_msg.c	2001/04/23 16:17:58
@@ -277,9 +277,11 @@
 		int	a6;
 	} */ *uap;
 {
+	int error;
 
-	if (!jail_sysvipc_allowed && jailed(p->p_ucred))
-		return (ENOSYS);
+	error = jail_ucansysvipc(p->p_ucred);
+	if (error)
+		return (error);
 
 	if (uap->which >= sizeof(msgcalls)/sizeof(msgcalls[0]))
 		return (EINVAL);
@@ -326,7 +328,7 @@
 	int msqid = uap->msqid;
 	int cmd = uap->cmd;
 	struct msqid_ds *user_msqptr = uap->buf;
-	int rval, eval;
+	int rval, eval, error;
 	struct msqid_ds msqbuf;
 	register struct msqid_ds *msqptr;
 
@@ -334,8 +336,9 @@
 	printf("call to msgctl(%d, %d, 0x%x)\n", msqid, cmd, user_msqptr);
 #endif
 
-	if (!jail_sysvipc_allowed && jailed(p->p_ucred))
-		return (ENOSYS);
+	error = jail_ucansysvipc(p->p_ucred);
+	if (error)
+		return (error);
 
 	msqid = IPCID_TO_IX(msqid);
 
@@ -463,7 +466,7 @@
 	struct proc *p;
 	register struct msgget_args *uap;
 {
-	int msqid, eval;
+	int msqid, eval, error;
 	int key = uap->key;
 	int msgflg = uap->msgflg;
 	struct ucred *cred = p->p_ucred;
@@ -473,8 +476,9 @@
 	printf("msgget(0x%x, 0%o)\n", key, msgflg);
 #endif
 
-	if (!jail_sysvipc_allowed && jailed(p->p_ucred))
-		return (ENOSYS);
+	error = jail_ucansysvipc(cred);
+	if (error)
+		return (error);
 
 	if (key != IPC_PRIVATE) {
 		for (msqid = 0; msqid < msginfo.msgmni; msqid++) {
@@ -578,7 +582,7 @@
 	void *user_msgp = uap->msgp;
 	size_t msgsz = uap->msgsz;
 	int msgflg = uap->msgflg;
-	int segs_needed, eval;
+	int segs_needed, eval, error;
 	register struct msqid_ds *msqptr;
 	register struct msg *msghdr;
 	short next;
@@ -588,8 +592,9 @@
 	    msgflg);
 #endif
 
-	if (!jail_sysvipc_allowed && jailed(p->p_ucred))
-		return (ENOSYS);
+	error = jail_ucansysvipc(p->p_ucred);
+	if (error)
+		return (error);
 
 	msqid = IPCID_TO_IX(msqid);
 
@@ -907,7 +912,7 @@
 	size_t len;
 	register struct msqid_ds *msqptr;
 	register struct msg *msghdr;
-	int eval;
+	int eval, error;
 	short next;
 
 #ifdef MSG_DEBUG_OK
@@ -915,8 +920,9 @@
 	    msgsz, msgtyp, msgflg);
 #endif
 
-	if (!jail_sysvipc_allowed && jailed(p->p_ucred))
-		return (ENOSYS);
+	error = jail_ucansysvipc(p->p_ucred);
+	if (error)
+		return (error);
 
 	msqid = IPCID_TO_IX(msqid);
 
Index: kern/sysv_sem.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/sysv_sem.c,v
retrieving revision 1.32
diff -u -r1.32 sysv_sem.c
--- kern/sysv_sem.c	2001/02/21 06:39:54	1.32
+++ kern/sysv_sem.c	2001/04/23 16:17:59
@@ -254,9 +254,11 @@
 		int	a5;
 	} */ *uap;
 {
+	int error;
 
-	if (!jail_sysvipc_allowed && jailed(p->p_ucred))
-		return (ENOSYS);
+	error = jail_ucansysvipc(p->p_ucred);
+	if (error)
+		return (error);
 
 	if (uap->which >= sizeof(semcalls)/sizeof(semcalls[0]))
 		return (EINVAL);
@@ -456,7 +458,7 @@
 	union semun *arg = uap->arg;
 	union semun real_arg;
 	struct ucred *cred = p->p_ucred;
-	int i, rval, eval;
+	int i, rval, eval, error;
 	struct semid_ds sbuf;
 	register struct semid_ds *semaptr;
 
@@ -464,8 +466,9 @@
 	printf("call to semctl(%d, %d, %d, 0x%x)\n", semid, semnum, cmd, arg);
 #endif
 
-	if (!jail_sysvipc_allowed && jailed(p->p_ucred))
-		return (ENOSYS);
+	error = jail_ucansysvipc(cred);
+	if (error)
+		return (error);
 
 	semid = IPCID_TO_IX(semid);
 	if (semid < 0 || semid >= seminfo.semmsl)
@@ -617,7 +620,7 @@
 	struct proc *p;
 	register struct semget_args *uap;
 {
-	int semid, eval;
+	int semid, eval, error;
 	int key = uap->key;
 	int nsems = uap->nsems;
 	int semflg = uap->semflg;
@@ -627,8 +630,9 @@
 	printf("semget(0x%x, %d, 0%o)\n", key, nsems, semflg);
 #endif
 
-	if (!jail_sysvipc_allowed && jailed(p->p_ucred))
-		return (ENOSYS);
+	error = jail_ucansysvipc(cred);
+	if (error)
+		return (error);
 
 	if (key != IPC_PRIVATE) {
 		for (semid = 0; semid < seminfo.semmni; semid++) {
@@ -741,15 +745,16 @@
 	register struct sembuf *sopptr;
 	register struct sem *semptr;
 	struct sem_undo *suptr = NULL;
-	int i, j, eval;
+	int i, j, eval, error;
 	int do_wakeup, do_undos;
 
 #ifdef SEM_DEBUG
 	printf("call to semop(%d, 0x%x, %d)\n", semid, sops, nsops);
 #endif
 
-	if (!jail_sysvipc_allowed && jailed(p->p_ucred))
-		return (ENOSYS);
+	error = jail_ucansysvipc(p->p_ucred);
+	if (error)
+		return (error);
 
 	semid = IPCID_TO_IX(semid);	/* Convert back to zero origin */
 
Index: kern/sysv_shm.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/sysv_shm.c,v
retrieving revision 1.53
diff -u -r1.53 sysv_shm.c
--- kern/sysv_shm.c	2001/02/21 06:39:55	1.53
+++ kern/sysv_shm.c	2001/04/23 16:17:59
@@ -227,10 +227,11 @@
 	struct shmdt_args *uap;
 {
 	struct shmmap_state *shmmap_s;
-	int i;
+	int i, error;
 
-	if (!jail_sysvipc_allowed && jailed(p->p_ucred))
-		return (ENOSYS);
+	error = jail_ucansysvipc(p->p_ucred);
+	if (error)
+		return (error);
 
 	shmmap_s = (struct shmmap_state *)p->p_vmspace->vm_shm;
  	if (shmmap_s == NULL)
@@ -266,8 +267,9 @@
 	vm_size_t size;
 	int rv;
 
-	if (!jail_sysvipc_allowed && jailed(p->p_ucred))
-		return (ENOSYS);
+	error = jail_ucansysvipc(p->p_ucred);
+	if (error)
+		return (error);
 
 	shmmap_s = (struct shmmap_state *)p->p_vmspace->vm_shm;
 	if (shmmap_s == NULL) {
@@ -360,8 +362,9 @@
 	struct shmid_ds *shmseg;
 	struct oshmid_ds outbuf;
 
-	if (!jail_sysvipc_allowed && jailed(p->p_ucred))
-		return (ENOSYS);
+	error = jail_ucansysvipc(p->p_ucred);
+	if (error)
+		return (error);
 
 	shmseg = shm_find_segment_by_shmid(uap->shmid);
 	if (shmseg == NULL)
@@ -411,8 +414,9 @@
 	struct shmid_ds inbuf;
 	struct shmid_ds *shmseg;
 
-	if (!jail_sysvipc_allowed && jailed(p->p_ucred))
-		return (ENOSYS);
+	error = jail_ucansysvipc(p->p_ucred);
+	if (error)
+		return (error);
 
 	shmseg = shm_find_segment_by_shmid(uap->shmid);
 	if (shmseg == NULL)
@@ -590,8 +594,9 @@
 {
 	int segnum, mode, error;
 
-	if (!jail_sysvipc_allowed && jailed(p->p_ucred))
-		return (ENOSYS);
+	error = jail_ucansysvipc(p->p_ucred);
+	if (error)
+		return (error);
 
 	mode = uap->shmflg & ACCESSPERMS;
 	if (uap->key != IPC_PRIVATE) {
@@ -620,9 +625,11 @@
 		int	a4;
 	} */ *uap;
 {
+	int error;
 
-	if (!jail_sysvipc_allowed && jailed(p->p_ucred))
-		return (ENOSYS);
+	error = jail_ucansysvipc(p->p_ucred);
+	if (error)
+		return (error);
 
 	if (uap->which >= sizeof(shmcalls)/sizeof(shmcalls[0]))
 		return EINVAL;
Index: kern/tty_pty.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/tty_pty.c,v
retrieving revision 1.85
diff -u -r1.85 tty_pty.c
--- kern/tty_pty.c	2001/03/26 12:41:01	1.85
+++ kern/tty_pty.c	2001/04/23 16:18:00
@@ -53,6 +53,7 @@
 #include <sys/vnode.h>
 #include <sys/signalvar.h>
 #include <sys/malloc.h>
+#include <sys/jail.h>
 
 static MALLOC_DEFINE(M_PTY, "ptys", "pty data structures");
 
@@ -117,7 +118,7 @@
 	u_char	pt_ucntl;
 	struct tty pt_tty;
 	dev_t	devs, devc;
-	struct	prison *pt_prison;
+	struct	ucred *pt_ucred;	/* XXX Really should be an objlabel. */
 };
 
 #define	PF_PKT		0x08		/* packet mode */
@@ -185,8 +186,8 @@
 		tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
 	} else if (tp->t_state & TS_XCLUDE && suser(p)) {
 		return (EBUSY);
-	} else if (pti->pt_prison != p->p_ucred->cr_prison) {
-		return (EBUSY);
+	} else if ((error = jail_ucanopenpty(p->p_ucred, pti->pt_ucred))) {
+		return (error);
 	}
 	if (tp->t_oproc)			/* Ctrlr still around. */
 		(void)(*linesw[tp->t_line].l_modem)(tp, 1);
@@ -346,7 +347,9 @@
 	(void)(*linesw[tp->t_line].l_modem)(tp, 1);
 	tp->t_lflag &= ~EXTPROC;
 	pti = dev->si_drv1;
-	pti->pt_prison = p->p_ucred->cr_prison;
+
+	pti->pt_ucred = p->p_ucred;
+	crhold(pti->pt_ucred);
 	pti->pt_flags = 0;
 	pti->pt_send = 0;
 	pti->pt_ucntl = 0;
Index: kern/uipc_socket.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/uipc_socket.c,v
retrieving revision 1.95
diff -u -r1.95 uipc_socket.c
--- kern/uipc_socket.c	2001/03/16 22:37:06	1.95
+++ kern/uipc_socket.c	2001/04/23 16:18:05
@@ -141,12 +141,9 @@
 	if (prp == 0 || prp->pr_usrreqs->pru_attach == 0)
 		return (EPROTONOSUPPORT);
 
-	if (jailed(p->p_ucred) && jail_socket_unixiproute_only &&
-	    prp->pr_domain->dom_family != PF_LOCAL &&
-	    prp->pr_domain->dom_family != PF_INET &&
-	    prp->pr_domain->dom_family != PF_ROUTE) {
-		return (EPROTONOSUPPORT);
-	}
+	if ((error = jail_ucansocreate(p->p_ucred,
+	    prp->pr_domain->dom_family, prp->pr_type)))
+		return (error);
 
 	if (prp->pr_type != type)
 		return (EPROTOTYPE);
Index: miscfs/procfs/procfs_status.c
===================================================================
RCS file: /home/ncvs/src/sys/miscfs/procfs/procfs_status.c,v
retrieving revision 1.28
diff -u -r1.28 procfs_status.c
--- miscfs/procfs/procfs_status.c	2001/03/07 03:10:20	1.28
+++ miscfs/procfs/procfs_status.c	2001/04/23 16:18:05
@@ -163,11 +163,8 @@
 		DOCHECK();
 	}
 
-	if (jailed(p->p_ucred))
-		ps += snprintf(ps, psbuf + sizeof(psbuf) - ps,
-		    " %s", p->p_ucred->cr_prison->pr_host);
-	else
-		ps += snprintf(ps, psbuf + sizeof(psbuf) - ps, " -");
+	ps += jail_name(p->p_ucred, ps, psbuf + sizeof(psbuf) - ps,
+	    " %s");
 	DOCHECK();
 	ps += snprintf(ps, psbuf + sizeof(psbuf) - ps, "\n");
 	DOCHECK();
Index: netinet/in_pcb.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet/in_pcb.c,v
retrieving revision 1.83
diff -u -r1.83 in_pcb.c
--- netinet/in_pcb.c	2001/03/16 19:36:23	1.83
+++ netinet/in_pcb.c	2001/04/23 16:18:24
@@ -499,7 +499,7 @@
 	cred = inp->inp_socket->so_cred;
 	if (inp->inp_laddr.s_addr == INADDR_ANY && jailed(cred)) {
 		bzero(&sa, sizeof (sa));
-		sa.sin_addr.s_addr = htonl(cred->cr_prison->pr_ip);
+		sa.sin_addr.s_addr = htonl(prison_getipv4addr(cred));
 		sa.sin_len=sizeof (sa);
 		sa.sin_family = AF_INET;
 		error = in_pcbbind(inp, (struct sockaddr *)&sa, p);
@@ -1008,7 +1008,7 @@
 {
 	if (!jailed(p->p_ucred))
 		return (0);
-	if (ntohl(inp->inp_laddr.s_addr) == p->p_ucred->cr_prison->pr_ip)
+	if (ntohl(inp->inp_laddr.s_addr) == prison_getipv4addr(p->p_ucred))
 		return (0);
 	return (1);
 }
Index: sys/jail.h
===================================================================
RCS file: /home/ncvs/src/sys/sys/jail.h,v
retrieving revision 1.11
diff -u -r1.11 jail.h
--- sys/jail.h	2001/02/21 06:39:57	1.11
+++ sys/jail.h	2001/04/23 16:18:25
@@ -1,70 +1,78 @@
-/*
- * ----------------------------------------------------------------------------
- * "THE BEER-WARE LICENSE" (Revision 42):
- * <phk@FreeBSD.org> wrote this file.  As long as you retain this notice you
- * can do whatever you want with this stuff. If we meet some day, and you think
- * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
- * ----------------------------------------------------------------------------
+/*-
+ * Copyright (c) 2001 Robert N. M. Watson
+ * 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.
  *
- * $FreeBSD: src/sys/sys/jail.h,v 1.11 2001/02/21 06:39:57 rwatson Exp $
+ * 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 _SYS_JAIL_H_
-#define _SYS_JAIL_H_
-
-struct jail {
-	u_int32_t	version;
-	char		*path;
-	char		*hostname;
-	u_int32_t	ip_number;
-};
 
-#ifndef _KERNEL
+#ifndef _SYS_JAIL_H
+#define _SYS_JAIL_H
 
-int jail __P((struct jail *));
+#define	JAIL_CREATE	1
+#define	JAIL_DESTROY	2
+#define	JAIL_JOIN	3
 
-#else /* _KERNEL */
-
-#ifdef MALLOC_DECLARE
-MALLOC_DECLARE(M_PRISON);
-#endif
-
-/*
- * This structure describes a prison.  It is pointed to by all struct
- * ucreds's of the inmates.  pr_ref keeps track of them and is used to
- * delete the struture when the last inmate is dead.
- *
- * XXX: Note: this structure needs a mutex to protect the reference count
- * and other mutable fields (pr_host, pr_linux).
- */
+#define	JAIL_MAX_NAME	64
+#define	JAIL_NOJAIL_NAME	"NONE"	/* reserved name for no jail present */
 
-struct prison {
-	int		pr_ref;
-	char 		pr_host[MAXHOSTNAMELEN];
-	u_int32_t	pr_ip;
-	void		*pr_linux;
-};
+#ifdef _KERNEL
 
 /*
- * Sysctl-set variables that determine global jail policy
+ * Public jail() functions intended to be consumed by the remainder of
+ * the kernel.
  */
-extern int	jail_set_hostname_allowed;
-extern int	jail_socket_unixiproute_only;
-extern int	jail_sysvipc_allowed;
+struct ucred;
+void	jail_crdup __P((struct ucred *cr1, struct ucred *cr2));
+void	jail_crfirst __P((struct ucred *cr));
+void	jail_crfree __P((struct ucred *cr));
+int	jail_gethostname __P((struct ucred *cr, char *hostname));
+int	jail_name __P((struct ucred *cr, char *buf, int buflen, char *format));
+int	jail_sethostname __P((struct ucred *cr, const char *hostname));
+int	jail_ucansocreate __P((struct ucred *cr, int domfamily, int type));
+int	jail_ucandebug __P((struct ucred *cr1, struct ucred *cr2));
+int	jail_ucanopenpty __P((struct ucred *cr1, struct ucred *cr2));
+int	jail_ucansched __P((struct ucred *cr1, struct ucred *cr2));
+int	jail_ucansee __P((struct ucred *cr1, struct ucred *cr2));
+int	jail_ucansignal __P((struct ucred *cr1, struct ucred *cr2,
+	    int signum));
+int	jail_ucansysvipc __P((struct ucred *cr));
+int	jailed __P((struct ucred *cr));
 
 /*
- * Kernel support functions for jail().
+ * Compatibility from oldjail.
  */
-struct ucred;
+struct prison;
 struct sockaddr;
-int jailed __P((struct ucred *cred));
-int prison_check __P((struct ucred *cred1, struct ucred *cred2));
-void prison_free __P((struct prison *pr));
-void prison_hold __P((struct prison *pr));
+u_int32_t prison_getipv4addr __P((struct ucred *cr));
 int prison_if __P((struct ucred *cred, struct sockaddr *sa));
 int prison_ip __P((struct ucred *cred, int flag, u_int32_t *ip));
 void prison_remote_ip __P((struct ucred *cred, int flags, u_int32_t *ip));
 
+#else /* !_KERNEL */
+
+int	jailconf __P((int cmd, const char *name));
+
 #endif /* !_KERNEL */
-#endif /* !_SYS_JAIL_H_ */
+
+#endif /* !_SYS_JAIL_H */
Index: sys/syscall-hide.h
===================================================================
RCS file: /home/ncvs/src/sys/sys/syscall-hide.h,v
retrieving revision 1.81
diff -u -r1.81 syscall-hide.h
--- sys/syscall-hide.h	2001/04/11 20:21:37	1.81
+++ sys/syscall-hide.h	2001/04/23 16:18:25
@@ -2,7 +2,7 @@
  * System call hiders.
  *
  * DO NOT EDIT-- this file is automatically generated.
- * $FreeBSD: src/sys/sys/syscall-hide.h,v 1.81 2001/04/11 20:21:37 rwatson Exp $
+ * $FreeBSD$
  * created from FreeBSD: src/sys/kern/syscalls.master,v 1.88 2001/04/11 20:20:40 rwatson Exp 
  */
 
@@ -288,3 +288,4 @@
 HIDE_BSD(extattr_get_fd)
 HIDE_BSD(extattr_delete_fd)
 HIDE_BSD(__setugid)
+HIDE_BSD(jailconf)
Index: sys/syscall.h
===================================================================
RCS file: /home/ncvs/src/sys/sys/syscall.h,v
retrieving revision 1.85
diff -u -r1.85 syscall.h
--- sys/syscall.h	2001/04/11 20:21:37	1.85
+++ sys/syscall.h	2001/04/23 16:18:25
@@ -2,7 +2,7 @@
  * System call numbers.
  *
  * DO NOT EDIT-- this file is automatically generated.
- * $FreeBSD: src/sys/sys/syscall.h,v 1.85 2001/04/11 20:21:37 rwatson Exp $
+ * $FreeBSD$
  * created from FreeBSD: src/sys/kern/syscalls.master,v 1.88 2001/04/11 20:20:40 rwatson Exp 
  */
 
@@ -295,4 +295,5 @@
 #define	SYS_extattr_get_fd	372
 #define	SYS_extattr_delete_fd	373
 #define	SYS___setugid	374
-#define	SYS_MAXSYSCALL	375
+#define	SYS_jailconf	375
+#define	SYS_MAXSYSCALL	376
Index: sys/syscall.mk
===================================================================
RCS file: /home/ncvs/src/sys/sys/syscall.mk,v
retrieving revision 1.39
diff -u -r1.39 syscall.mk
--- sys/syscall.mk	2001/04/11 20:21:37	1.39
+++ sys/syscall.mk	2001/04/23 16:18:25
@@ -1,6 +1,6 @@
 # FreeBSD system call names.
 # DO NOT EDIT-- this file is automatically generated.
-# $FreeBSD: src/sys/sys/syscall.mk,v 1.39 2001/04/11 20:21:37 rwatson Exp $
+# $FreeBSD$
 # created from FreeBSD: src/sys/kern/syscalls.master,v 1.88 2001/04/11 20:20:40 rwatson Exp 
 MIASM =  \
 	syscall.o \
@@ -243,4 +243,5 @@
 	extattr_set_fd.o \
 	extattr_get_fd.o \
 	extattr_delete_fd.o \
-	__setugid.o
+	__setugid.o \
+	jailconf.o
Index: sys/sysproto.h
===================================================================
RCS file: /home/ncvs/src/sys/sys/sysproto.h,v
retrieving revision 1.75
diff -u -r1.75 sysproto.h
--- sys/sysproto.h	2001/04/11 20:21:37	1.75
+++ sys/sysproto.h	2001/04/23 16:18:27
@@ -2,7 +2,7 @@
  * System call prototypes.
  *
  * DO NOT EDIT-- this file is automatically generated.
- * $FreeBSD: src/sys/sys/sysproto.h,v 1.75 2001/04/11 20:21:37 rwatson Exp $
+ * $FreeBSD$
  * created from FreeBSD: src/sys/kern/syscalls.master,v 1.88 2001/04/11 20:20:40 rwatson Exp 
  */
 
@@ -1063,6 +1063,10 @@
 struct	__setugid_args {
 	int	flag;	char flag_[PAD_(int)];
 };
+struct	jailconf_args {
+	int	cmd;	char cmd_[PAD_(int)];
+	char *	name;	char name_[PAD_(char *)];
+};
 int	nosys __P((struct proc *, struct nosys_args *));
 void	sys_exit __P((struct proc *, struct sys_exit_args *));
 int	fork __P((struct proc *, struct fork_args *));
@@ -1303,6 +1307,7 @@
 int	extattr_get_fd __P((struct proc *, struct extattr_get_fd_args *));
 int	extattr_delete_fd __P((struct proc *, struct extattr_delete_fd_args *));
 int	__setugid __P((struct proc *, struct __setugid_args *));
+int	jailconf __P((struct proc *, struct jailconf_args *));
 
 #ifdef COMPAT_43
 
Index: sys/ucred.h
===================================================================
RCS file: /home/ncvs/src/sys/sys/ucred.h,v
retrieving revision 1.22
diff -u -r1.22 ucred.h
--- sys/ucred.h	2001/03/28 09:17:56	1.22
+++ sys/ucred.h	2001/04/23 16:18:27
@@ -52,7 +52,7 @@
 	short	cr_ngroups;		/* number of groups */
 	gid_t	cr_groups[NGROUPS];	/* groups */
 	struct	uidinfo *cr_uidinfo;	/* per uid resource consumption */
-	struct	prison *cr_prison;	/* jail(4) */
+	struct	jaildescr *cr_jail;	/* jail(4) */
 	struct	mtx cr_mtx;		/* protect refcount */
 };
 #define cr_gid cr_groups[0]
