Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 14 Jul 2004 21:21:30 +0200
From:      "Meno Abels" <abels@adviser.com>
To:        FreeBSD-gnats-submit@FreeBSD.org
Cc:        Meno Abels <abels@adviser.com>
Subject:   kern/69064: No multiple ip4/6's could assigned to a jail.
Message-ID:  <20040714192137.A623484040@pmff.de>
Resent-Message-ID: <200407141930.i6EJUWVY016744@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         69064
>Category:       kern
>Synopsis:       No multiple ip4/6's could assigned to a jail.
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Wed Jul 14 19:30:32 GMT 2004
>Closed-Date:
>Last-Modified:
>Originator:     Meno Abels
>Release:        FreeBSD 5.2-CURRENT
>Organization:
Adviser.com
>Environment:
System: FreeBSD race 5.2-CURRENT FreeBSD 5.2-CURRENT #29: Fri May 28 23:44:16 CEST 2004 root@neo.abels.adviser.com:/usr/obj/usr/src/sys/DISKLESS i386

>Description:
	I missed the feature that a jail is able to handle multiple ip
        numbers. Also i want that ipv6 is working with the jail.
>How-To-Repeat:
	no way
>Fix:
	Here is the patch for this feature. 
	I tested it, but I'am not very safe about the ipv6 stuff. 
	I'am not a expert in ipv6 so it could be that
        i missed some checks for the prison. I also change the 
	jail/jls utility.  


Index: sys/kern/kern_fork.c
===================================================================
RCS file: /usr/freebsd.cvs/src/sys/kern/kern_fork.c,v
retrieving revision 1.228
diff -r1.228 kern_fork.c
303c303
< 	if ((nprocs >= maxproc - 10 && suser(td->td_ucred) != 0) ||
---
> 	if ((nprocs >= maxproc - 10 && suser(td) != 0) ||
Index: sys/kern/kern_jail.c
===================================================================
RCS file: /usr/freebsd.cvs/src/sys/kern/kern_jail.c,v
retrieving revision 1.44
diff -r1.44 kern_jail.c
35a36
> #include <netinet6/in6_var.h>
37a39,40
> MALLOC_DEFINE(M_PRISON_IP4, "prison", "Prison ipv4 addresses");
> MALLOC_DEFINE(M_PRISON_IP6, "prison", "Prison ipv6 addresses");
77a81,85
> static int 		 prison_add_ip4(struct in_addr *tmpv4, struct prison *pr, void *pr_new, void **pr_old);
> static int 		 prison_add_ip6(struct in6_addr *tmpv4, struct prison *pr, void *pr_new, void **pr_old);
> static int 		 prison_del_ip4(struct in_addr *tmpv4, struct prison *pr, void *pr_new, void **pr_old);
> static int 		 prison_del_ip6(struct in6_addr *tmpv4, struct prison *pr, void *pr_new, void **pr_old);
> static int               prison_check_duplicate(char *hostname, char *path);
98,99c106,107
< int
< jail(struct thread *td, struct jail_args *uap)
---
> static int 
> jail_createjail(struct thread *td, char *user_hostname, char *user_path, struct prison **pr)
100a109
> 	int error;
102,105d110
< 	struct prison *pr, *tpr;
< 	struct jail j;
< 	struct jail_attach_args jaa;
< 	int error, tryprid;
107c112,115
< 	error = copyin(uap->jail, &j, sizeof(j));
---
> 	MALLOC(*pr, struct prison *, sizeof(**pr), M_PRISON, M_WAITOK | M_ZERO);
> 	mtx_init(&(*pr)->pr_mtx, "jail mutex", NULL, MTX_DEF);
> 	(*pr)->pr_ref = 1;
> 	error = copyinstr(user_path, &(*pr)->pr_path, sizeof((*pr)->pr_path), 0);
109,116c117,118
< 		return (error);
< 	if (j.version != 0)
< 		return (EINVAL);
< 
< 	MALLOC(pr, struct prison *, sizeof(*pr), M_PRISON, M_WAITOK | M_ZERO);
< 	mtx_init(&pr->pr_mtx, "jail mutex", NULL, MTX_DEF);
< 	pr->pr_ref = 1;
< 	error = copyinstr(j.path, &pr->pr_path, sizeof(pr->pr_path), 0);
---
> 		goto e_killmtx;
> 	error = copyinstr(user_hostname, &(*pr)->pr_host, sizeof((*pr)->pr_host), 0);
118a121,125
> 	if (prison_check_duplicate((*pr)->pr_host, (*pr)->pr_path)) {
> 		error = EAGAIN;
> 		goto e_killmtx;
> 	}
> 
120c127
< 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, pr->pr_path, td);
---
> 	NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, (*pr)->pr_path, td);
126c133
< 	pr->pr_root = nd.ni_vp;
---
> 	(*pr)->pr_root = nd.ni_vp;
130,135d136
< 	error = copyinstr(j.hostname, &pr->pr_host, sizeof(pr->pr_host), 0);
< 	if (error)
< 		goto e_dropvnref;
< 	pr->pr_ip = j.ip_number;
< 	pr->pr_linux = NULL;
< 	pr->pr_securelevel = securelevel;
136a138,278
> 	(*pr)->pr_linux = NULL;
> 	(*pr)->pr_securelevel = securelevel;
> 	return (0);
> 
> e_killmtx:
> 	mtx_destroy(&(*pr)->pr_mtx);
> 	FREE(*pr, M_PRISON);
> 	return (error);
> 
> }
> 
> 
> static void 
> jail_dropvnref(struct prison *pr)
> {
> 	mtx_lock(&Giant);
> 	vrele(pr->pr_root);
> 	mtx_unlock(&Giant);
> }
> 
> int
> jail(struct thread *td, struct jail_args *uap)
> {
> 	struct prison *pr, *tpr;
> 	struct jail j;
> 	struct jail_attach_args jaa;
> 	int error, tryprid;
> 	void *pr_new = 0;
> 	void *pr_old = 0;
> 
> 	error = copyin(uap->jail, &j, sizeof(j));
> 	if (error)
> 		return (error);
> 	if (j.version < XPRISON_VERSION)
> 	{
> 		struct in_addr tmpv4;
> 
> 		error = jail_createjail(td, j.u.v1.hostname, j.u.v1.path, &pr);
> 		if (error) {
> 			return error;
> 		}
> 		MALLOC(pr_new, void *, sizeof(struct in_addr)*1, M_PRISON_IP4, M_WAITOK | M_ZERO);
> 		tmpv4.s_addr = htonl(j.u.v1.ip_number);		
> 		mtx_lock(&pr->pr_mtx);
> 		error = prison_add_ip4(&tmpv4, pr, pr_new, &pr_old);
> 		mtx_unlock(&pr->pr_mtx);
> 		if (error) {
> 			jail_dropvnref(pr);
> 		}
> 	}
> 	else
> 	{
> 		if (j.u.v2.function == CREATEJAIL) {
> 			error = jail_createjail(td, j.u.v2.u.createjail.hostname, j.u.v2.u.createjail.path, &pr);
> 			if (error) {
> 				return error;
> 			}
> 		}
> 		else {
> 			int cnt = 0;
> 			struct malloc_type *alloc_type;
> retry_alloc:
> 			mtx_lock(&allprison_mtx);
> 			pr = prison_find(j.u.v2.u.add_del.id);
> 			if (pr) {
> 				cnt = (j.u.v2.function == ADDIP4 || j.u.v2.function == DELIP4) ? 
> 					pr->pr_ip4s : pr->pr_ip6s;	
> 			}
> 			mtx_unlock(&pr->pr_mtx);
> 			mtx_unlock(&allprison_mtx);
> 			if (pr == NULL) {
> 				return (EINVAL);
> 			}
> 			if (j.u.v2.function == ADDIP4 || j.u.v2.function == DELIP4) {
> 				alloc_type=M_PRISON_IP4;
> 				if (pr->pr_ip4s >= (j.u.v2.function == DELIP4 ? 2 : 0)) {
> 					MALLOC(pr_new, void *, 
> 						sizeof(struct in_addr)*(pr->pr_ip4s+
> 						(j.u.v2.function == DELIP4 ? -1 : +1)),
> 						alloc_type, M_WAITOK | M_ZERO);
> 					/*printf("pr_ip4s:%d\n", pr->pr_ip4s);*/
> 				}
> 			}
> 			else {
> 				alloc_type=M_PRISON_IP6;
> 				if (pr->pr_ip6s >= (j.u.v2.function == DELIP6 ? 2 : 0)) {
> 					MALLOC(pr_new, void *, 
> 						sizeof(struct in6_addr)*(pr->pr_ip6s+
> 						(j.u.v2.function == DELIP6 ? -1 : +1)),
> 						alloc_type, M_WAITOK | M_ZERO);
> 					/*printf("pr_ip4s:%d\n", pr->pr_ip6s);*/
> 				}
> 			}
> 			mtx_lock(&allprison_mtx);
> 			pr = prison_find(j.u.v2.u.add_del.id);
> 			if (pr)
> 			{
> 				if (cnt != ((j.u.v2.function == ADDIP4 || j.u.v2.function == DELIP4) ? 
> 					pr->pr_ip4s : pr->pr_ip6s))	
> 				{
> 					/* should i sleep ? */
> 					mtx_unlock(&pr->pr_mtx);
> 					mtx_unlock(&allprison_mtx);
> 					FREE(pr_new, alloc_type);
> 					/*printf("jail retry alloc\n");*/
> 					goto retry_alloc;
> 				}
> 				mtx_unlock(&allprison_mtx);
> 			}
> 			else
> 			{
> 				mtx_unlock(&allprison_mtx);
> 				return (EINVAL);
> 			}
> 			
> 			switch (j.u.v2.function) {
> 			case ADDIP4:
> 				error = prison_add_ip4(&j.u.v2.u.add_del.v4_6.ip4_num, pr, pr_new, &pr_old);
> 				break;
> 			case ADDIP6:
> 				error = prison_add_ip6(&j.u.v2.u.add_del.v4_6.ip6_num, pr, pr_new, &pr_old);
> 				break;
> 			case DELIP4:
> 				error = prison_del_ip4(&j.u.v2.u.add_del.v4_6.ip4_num, pr, pr_new, &pr_old);
> 				break;
> 			case DELIP6:
> 				error = prison_del_ip6(&j.u.v2.u.add_del.v4_6.ip6_num, pr, pr_new, &pr_old);
> 				break;
> 			default:
> 				mtx_unlock(&pr->pr_mtx);
> 				return EINVAL;
> 			}
> 			mtx_unlock(&pr->pr_mtx);
> 			if (pr_old) {
> 				/*printf("jail free:%p\n", pr_old);*/
> 				FREE(pr_old, alloc_type);
> 			}
> 			return (error);
> 		}
> 	}
> 	/* REST of Create Code */
149c291,292
< 				goto e_dropvnref;
---
> 				jail_dropvnref(pr);
> 				return error;
166a310
> 
172,178c316
< e_dropvnref:
< 	mtx_lock(&Giant);
< 	vrele(pr->pr_root);
< 	mtx_unlock(&Giant);
< e_killmtx:
< 	mtx_destroy(&pr->pr_mtx);
< 	FREE(pr, M_PRISON);
---
> 	jail_dropvnref(pr);
250a389,414
> /* return 0 on not duplicate */
> static int
> prison_check_duplicate(char *hostname, char *path)
> {
> 	struct prison *pr;
> 	mtx_lock(&allprison_mtx);
> 	LIST_FOREACH(pr, &allprison, pr_list) {
> 		if (!strncmp(hostname, pr->pr_host, sizeof(pr->pr_host))) {
> 			mtx_unlock(&allprison_mtx);
> 			return 1;
> 		}
> 		/* this is not perfect remove of trailing / or duplicated //
>                    should be done, who knows the kernel method for this-:)
>                  */
> /*
> 		if (!strncmp(path, pr->pr_path, sizeof(pr->pr_path))) {
> 			mtx_unlock(&allprison_mtx);
> 			return 1;
> 		}
> */
> 	}
> 	mtx_unlock(&allprison_mtx);
> 	return 0;
> }
> 
> 
301a466,469
> 	if (pr->pr_ip4 != NULL)
> 		FREE(pr->pr_ip4, M_PRISON_IP4);
> 	if (pr->pr_ip6 != NULL)
> 		FREE(pr->pr_ip6, M_PRISON_IP6);
316,317c484,485
< u_int32_t
< prison_getip(struct ucred *cred)
---
> int
> prison_first_ip4(struct ucred *cred, struct in_addr *out)
318a487,495
> 	int errno = 0;
> 	mtx_lock(&cred->cr_prison->pr_mtx);
> 	if (cred->cr_prison->pr_ip4s) 
> 		*out = cred->cr_prison->pr_ip4[0];
> 	else
> 		errno = EADDRNOTAVAIL;
> 	mtx_unlock(&cred->cr_prison->pr_mtx);
> 	return errno;
> }
320c497,507
< 	return (cred->cr_prison->pr_ip);
---
> int
> prison_first_ip6(struct ucred *cred, struct in6_addr *out)
> {
> 	int errno = 0;
> 	mtx_lock(&cred->cr_prison->pr_mtx);
> 	if (cred->cr_prison->pr_ip6s)
> 		*out = cred->cr_prison->pr_ip6[0];
> 	else
> 		errno = EADDRNOTAVAIL;
> 	mtx_unlock(&cred->cr_prison->pr_mtx);
> 	return errno;
324c511
< prison_ip(struct ucred *cred, int flag, u_int32_t *ip)
---
> prison_match_ip4(struct ucred *cred, struct in_addr *ip)
330,345c517,537
< 	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);
< 		return (0);
< 	}
< 	if (tmp == INADDR_LOOPBACK) {
< 		if (flag)
< 			*ip = cred->cr_prison->pr_ip;
< 		else
< 			*ip = htonl(cred->cr_prison->pr_ip);
---
> 
> 	for (tmp = 0; tmp < cred->cr_prison->pr_ip4s; ++tmp)
> 	{
> 		if (cred->cr_prison->pr_ip4[tmp].s_addr == ip->s_addr)
> 		{
> 			return 0;
> 		}
> 	}
> 	return (1);
> }
> 
> int
> prison_redirect_ip4(struct ucred *cred, struct in_addr *ip)
> {
> 	if (!jailed(cred))
> 		return (0);
> 	if (cred->cr_prison->pr_ip4s <= 0)
> 		return (0);
> 
> 	if (ip->s_addr == htonl(INADDR_ANY)) {
> 		*ip = cred->cr_prison->pr_ip4[0];
348,350c540,544
< 	if (cred->cr_prison->pr_ip != tmp)
< 		return (1);
< 	return (0);
---
> 	if (ip->s_addr == htonl(INADDR_LOOPBACK)) {
> 		*ip = cred->cr_prison->pr_ip4[0];
> 		return (0);
> 	}
> 	return prison_match_ip4(cred, ip);
353,354c547,548
< void
< prison_remote_ip(struct ucred *cred, int flag, u_int32_t *ip)
---
> int
> prison_match_ip6(struct ucred *cred, struct in6_addr *ip)
358a553,588
> 		return (0);
> 
> 	for (tmp = 0; tmp < cred->cr_prison->pr_ip6s; ++tmp)
> 	{
> 		if (IN6_ARE_ADDR_EQUAL(&(cred->cr_prison->pr_ip6[tmp]), ip))
> 		{
> 			return 0;
> 		}
> 	}
> 	return (1);
> }
> 
> 
> int
> prison_redirect_ip6(struct ucred *cred, struct in6_addr *ip)
> {
> 	if (!jailed(cred))
> 		return (0);
> 	if (cred->cr_prison->pr_ip6s <= 0)
> 		return (0);
> 
> 	if (IN6_ARE_ADDR_EQUAL(ip, &in6addr_any)) {
> 		*ip = cred->cr_prison->pr_ip6[0];
> 		return (0);
> 	}
> 	if (IN6_IS_ADDR_LOOPBACK(ip)) {
> 		*ip = cred->cr_prison->pr_ip6[0];
> 		return (0);
> 	}
> 	return prison_match_ip6(cred, ip);
> }
> 
> void
> prison_remote_ip4(struct ucred *cred, struct in_addr *ip)
> {
> 	if (!jailed(cred))
360,368c590,607
< 	if (flag)
< 		tmp = *ip;
< 	else
< 		tmp = ntohl(*ip);
< 	if (tmp == INADDR_LOOPBACK) {
< 		if (flag)
< 			*ip = cred->cr_prison->pr_ip;
< 		else
< 			*ip = htonl(cred->cr_prison->pr_ip);
---
> 	if (cred->cr_prison->pr_ip4s <= 0)
> 		return;
> 	if (ip->s_addr == INADDR_LOOPBACK) {
> 		*ip = cred->cr_prison->pr_ip4[0];
> 		return;
> 	}
> 	return;
> }
> 
> void
> prison_remote_ip6(struct ucred *cred, struct in6_addr *ip)
> {
> 	if (!jailed(cred))
> 		return;
> 	if (cred->cr_prison->pr_ip6s <= 0)
> 		return;
> 	if (IN6_IS_ADDR_LOOPBACK(ip)) {
> 		*ip = cred->cr_prison->pr_ip6[0];
377,378c616
< 	struct sockaddr_in *sai;
< 	int ok;
---
> 	int ok = 0;
380,381c618,619
< 	sai = (struct sockaddr_in *)sa;
< 	if ((sai->sin_family != AF_INET) && jail_socket_unixiproute_only)
---
> 	if (!(sa->sa_family == AF_INET || sa->sa_family == AF_INET6) 
> 	    && jail_socket_unixiproute_only)
383,388c621,652
< 	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;
---
> 	else 
> 	{
> 		if (sa->sa_family == AF_INET)
> 		{
> 			int tmp;
> 			struct sockaddr_in *sai = (struct sockaddr_in *)sa;
> 			ok = 1;
> 			for (tmp = 0; tmp < cred->cr_prison->pr_ip4s; ++tmp)
> 			{
> 				if (cred->cr_prison->pr_ip4[tmp].s_addr == sai->sin_addr.s_addr)
> 				{
> 					ok = 0;
> 					break;
> 				}
> 			}
> 		}
> 		else if (sa->sa_family == AF_INET6)
> 		{
> 			struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa;
> 			int tmp;
> 			ok = 1;
> 			for (tmp = 0; tmp < cred->cr_prison->pr_ip6s; ++tmp)
> 			{
> 				if (IN6_ARE_ADDR_EQUAL(&(cred->cr_prison->pr_ip6[tmp]), 
> 							&(sa6->sin6_addr)))
> 				{
> 					ok = 0;
> 					break;
> 				}
> 			}
> 		}
> 	}
409a674,805
>  * assumes that mtx_lock (pr->mtx)  is done
>  */
> static int
> prison_add_ip4(struct in_addr *ip, struct prison *pr, void *vpr_new, void **pr_free)
> {
> 	struct in_addr *pr_new = vpr_new;
> 	struct in_addr *wrk_new;
> 
> 	wrk_new = pr_new;
> 	if (pr->pr_ip4s > 0)
> 	{
> 		struct in_addr *pr_old = pr->pr_ip4;
> 		for (;pr_old < &(pr->pr_ip4[pr->pr_ip4s]) ; ++pr_old)
> 		{
> 			if (pr_old->s_addr == ip->s_addr)
> 			{
> 				*pr_free = pr_new;
> 				return 0;
> 			}
> 			*wrk_new++ = *pr_old;
> 		} 
> 	}
> 	*wrk_new = *ip;
> 	++(pr->pr_ip4s);
> 	if (pr->pr_ip4)
> 		*pr_free = pr->pr_ip4;
> 	pr->pr_ip4 = pr_new;
> 	return 0;	
> }
> 
> static int
> prison_add_ip6(struct in6_addr *ip, struct prison *pr, void *vpr_new, void **pr_free)
> {
> 	struct in6_addr *pr_new = vpr_new;
> 	struct in6_addr *wrk_new;
> 
> 	wrk_new = pr_new;
> 	if (pr->pr_ip6s > 0)
> 	{
> 		struct in6_addr *pr_old = pr->pr_ip6;
> 		for (;pr_old < &(pr->pr_ip6[pr->pr_ip6s]) ; ++pr_old)
> 		{
> 			if (IN6_ARE_ADDR_EQUAL(pr_old, ip))
> 			{
> 				*pr_free = pr_new;
> 				return 0;
> 			}
> 			*wrk_new++ = *pr_old;
> 		} 
> 	}
> 	*wrk_new = *ip;
> 	++(pr->pr_ip6s);
> 	if (pr->pr_ip6)
> 		*pr_free = pr->pr_ip6;
> 	pr->pr_ip6 = pr_new;
> 	return 0;	
> }
> 
> static int
> prison_del_ip4(struct in_addr *ip, struct prison *pr, void *vpr_new, void **pr_free)
> {
> 	struct in_addr *pr_new = vpr_new;
> 	struct in_addr *wrk_new;
> 	int errno = ENOENT;
> 
> 	wrk_new = pr_new;
> 	if (pr->pr_ip4s > 0)
> 	{
> 		struct in_addr *pr_old = pr->pr_ip4;
> 		for (;pr_old < &(pr->pr_ip4[pr->pr_ip4s]) ; ++pr_old)
> 		{
> 			if (pr_old->s_addr != ip->s_addr)
> 			{
> 				if (wrk_new) { /* remove only if one or more elements remaining */
> 					*wrk_new++ = *pr_old;
> 				}
> 			}
> 			else
> 			{
> 				errno = 0; /* found element to delete */
> 			}
> 		} 
> 	}
> 	if (errno == 0)
> 	{
> 		--(pr->pr_ip4s);
> 		/* attach new array */
> 		if (pr->pr_ip4)
> 			*pr_free = pr->pr_ip4;
> 		pr->pr_ip4 = pr_new;
> 	}
> 	return errno;	
> }
> 
> static int
> prison_del_ip6(struct in6_addr *ip, struct prison *pr, void *vpr_new, void **pr_free)
> {
> 	struct in6_addr *pr_new = vpr_new;
> 	struct in6_addr *wrk_new;
> 	int errno = ENOENT;
> 
> 	wrk_new = pr_new;
> 	if (pr->pr_ip6s > 0)
> 	{
> 		struct in6_addr *pr_old = pr->pr_ip6;
> 		for (;pr_old < &(pr->pr_ip6[pr->pr_ip6s]) ; ++pr_old)
> 		{
> 			if (!IN6_ARE_ADDR_EQUAL(pr_old, ip))
> 			{
> 				if (wrk_new) { /* remove only if one or more elements remaining */
> 					*wrk_new++ = *pr_old;
> 				}
> 			}
> 			else
> 			{
> 				errno = 0; /* found element to delete */
> 			}
> 		} 
> 	}
> 	if (errno == 0)
> 	{
> 		--(pr->pr_ip6s);
> 		/* attach new array */
> 		if (pr->pr_ip6)
> 			*pr_free = pr->pr_ip6;
> 		pr->pr_ip6 = pr_new;
> 	}
> 	return errno;	
> }
> 
> 
> /*
454a851
> 	int prcount;
461c858,868
< 	count = prisoncount;
---
> 	count = 0;
> 	prcount = 0;
> 	LIST_FOREACH(pr, &allprison, pr_list) {
> 		++prcount;
> 		if (pr->pr_ip4s || pr->pr_ip6s) {
> 			count += max(pr->pr_ip4s, pr->pr_ip6s);
> 		}	
> 		else {
> 			++count;
> 		}
> 	}
466a874
> 	/*printf("jls:count=%d:%d\n", count, prcount);*/
469c877
< 	if (count != prisoncount) {
---
> 	if (prcount != prisoncount) {
476,483c884,911
< 		mtx_lock(&pr->pr_mtx);
< 		xp->pr_version = XPRISON_VERSION;
< 		xp->pr_id = pr->pr_id;
< 		strlcpy(xp->pr_path, pr->pr_path, sizeof(xp->pr_path));
< 		strlcpy(xp->pr_host, pr->pr_host, sizeof(xp->pr_host));
< 		xp->pr_ip = pr->pr_ip;
< 		mtx_unlock(&pr->pr_mtx);
< 		xp++;
---
> 		int id = 0;
> 		int i;
> 		int maxcnt = max(pr->pr_ip4s, pr->pr_ip6s);
> 		/*printf("jls:maxcnt=%d\n", maxcnt);*/
> 		for (i = 0; i < (maxcnt ? maxcnt : 1) ; ++i)
> 		{	
> 			/*printf("jls:-0-:%d:%d\n", i, maxcnt);*/
> 			mtx_lock(&pr->pr_mtx);
> 			xp->pr_version = XPRISON_VERSION;
> 			xp->pr_id = pr->pr_id;
> 			strlcpy(xp->pr_path, pr->pr_path, sizeof(xp->pr_path));
> 			strlcpy(xp->pr_host, pr->pr_host, sizeof(xp->pr_host));
> 			if (i < pr->pr_ip4s) {
> 				xp->pr4_id  = id;
> 				xp->pr4_num = pr->pr_ip4[i];
> 			}
> 			else
> 				xp->pr4_id  = -1;
> 			if (i < pr->pr_ip6s) {
> 				xp->pr6_id  = id;
> 				xp->pr6_num = pr->pr_ip6[i];
> 			}
> 			else
> 				xp->pr6_id  = -1;
> 			++id;
> 			mtx_unlock(&pr->pr_mtx);
> 			xp++;
> 		}
Index: sys/net/rtsock.c
===================================================================
RCS file: /usr/freebsd.cvs/src/sys/net/rtsock.c,v
retrieving revision 1.112
diff -r1.112 rtsock.c
325c325,326
< 	struct sockaddr_in jail;
---
> 	struct sockaddr_in  jail4;
> 	struct sockaddr_in6 jail6;
440,446c441,466
< 						bzero(&jail, sizeof(jail));
< 						jail.sin_family = PF_INET;
< 						jail.sin_len = sizeof(jail);
< 						jail.sin_addr.s_addr =
< 						htonl(prison_getip(so->so_cred));
< 						info.rti_info[RTAX_IFA] =
< 						    (struct sockaddr *)&jail;
---
> 						if (rt->rt_ifa->ifa_addr->sa_family == PF_INET) {
> 							bzero(&jail4, sizeof(jail4));
> 							jail4.sin_family = PF_INET;
> 							jail4.sin_len = sizeof(jail4);
> 							error = prison_first_ip4(so->so_cred, 
> 									&jail4.sin_addr); 
> 							if (error)
> 								senderr(error);
> 							info.rti_info[RTAX_IFA] =
> 							    (struct sockaddr *)&jail4;
> 						}
> 						else if (rt->rt_ifa->ifa_addr->sa_family == PF_INET6) {
> 							bzero(&jail6, sizeof(jail6));
> 							jail6.sin6_family = PF_INET6;
> 							jail6.sin6_len = sizeof(jail6);
> 							error = prison_first_ip6(so->so_cred, 
> 									&jail6.sin6_addr); 
> 							if (error)
> 								senderr(error);
> 							info.rti_info[RTAX_IFA] =
> 							    (struct sockaddr *)&jail6;
> 						}
> 						else {
> 							info.rti_info[RTAX_IFA] =
> 							    rt->rt_ifa->ifa_addr;
> 						}
Index: sys/netinet/in_pcb.c
===================================================================
RCS file: /usr/freebsd.cvs/src/sys/netinet/in_pcb.c,v
retrieving revision 1.150
diff -r1.150 in_pcb.c
293c293
< 			if (prison_ip(cred, 0, &sin->sin_addr.s_addr))
---
> 			if (prison_redirect_ip4(cred, &sin->sin_addr)) 
358c358
< 			if (prison && prison_ip(cred, 0, &sin->sin_addr.s_addr))
---
> 			if (prison && prison_redirect_ip4(cred, &sin->sin_addr)) 
387c387
< 			if (prison_ip(cred, 0, &laddr.s_addr))
---
> 			if (prison_redirect_ip4(cred, &laddr)) 
450c450
< 	if (prison_ip(cred, 0, &laddr.s_addr))
---
> 	if (prison_redirect_ip4(cred, &laddr)) 
557c557,559
< 		sa.sin_addr.s_addr = htonl(prison_getip(socred));
---
> 		error = prison_first_ip4(socred, &sa.sin_addr);
> 		if (error)
> 			return (error);
Index: sys/netinet/raw_ip.c
===================================================================
RCS file: /usr/freebsd.cvs/src/sys/netinet/raw_ip.c,v
retrieving revision 1.135
diff -r1.135 raw_ip.c
215a216
> 		
217,218c218
< 			if (htonl(prison_getip(inp->inp_socket->so_cred)) !=
< 			    ip->ip_dst.s_addr)
---
> 			if (prison_match_ip4(inp->inp_socket->so_cred, &(ip->ip_dst))) 
275,276c275,284
< 			ip->ip_src.s_addr =
< 			    htonl(prison_getip(inp->inp_socket->so_cred));
---
> 		{
> 			/* fallback to first ip */
> 			if (prison_match_ip4(inp->inp_socket->so_cred, &inp->inp_laddr)) {
> 				if ((error = prison_first_ip4(inp->inp_socket->so_cred, 
> 					                     &ip->ip_src)) != 0)
> 					return error;
> 			}
> 			else
> 				ip->ip_src = inp->inp_laddr;
> 		}
289,290c297
< 			if (ip->ip_src.s_addr !=
< 			    htonl(prison_getip(inp->inp_socket->so_cred))) {
---
> 			if (prison_match_ip4(inp->inp_socket->so_cred, &ip->ip_src)) {
660a668
> 		int error;
662,664c670,672
< 			addr->sin_addr.s_addr =
< 			    htonl(prison_getip(td->td_ucred));
< 		if (htonl(prison_getip(td->td_ucred)) != addr->sin_addr.s_addr)
---
> 			if ((error = prison_first_ip4(td->td_ucred, &addr->sin_addr)) != 0)
> 				return error;
> 		if (prison_match_ip4(td->td_ucred, &addr->sin_addr)) 
Index: sys/netinet/tcp_usrreq.c
===================================================================
RCS file: /usr/freebsd.cvs/src/sys/netinet/tcp_usrreq.c,v
retrieving revision 1.103
diff -r1.103 tcp_usrreq.c
359c359
< 		prison_remote_ip(td->td_ucred, 0, &sinp->sin_addr.s_addr);
---
> 		prison_remote_ip4(td->td_ucred, &sinp->sin_addr); 
386a387,389
> 
> 	if (td && jailed(td->td_ucred))
> 		prison_remote_ip6(td->td_ucred, &sin6p->sin6_addr); 
Index: sys/netinet/udp_usrreq.c
===================================================================
RCS file: /usr/freebsd.cvs/src/sys/netinet/udp_usrreq.c,v
retrieving revision 1.156
diff -r1.156 udp_usrreq.c
809c809
< 			prison_remote_ip(td->td_ucred, 0, &sin->sin_addr.s_addr);
---
> 			prison_remote_ip4(td->td_ucred, &sin->sin_addr); 
1005c1005
< 		prison_remote_ip(td->td_ucred, 0, &sin->sin_addr.s_addr);
---
> 		prison_remote_ip4(td->td_ucred, &sin->sin_addr);
Index: sys/netinet6/in6_pcb.c
===================================================================
RCS file: /usr/freebsd.cvs/src/sys/netinet6/in6_pcb.c,v
retrieving revision 1.52
diff -r1.52 in6_pcb.c
130a131
> 	int prison = 0;
148a150,153
> 		if (!IN6_ARE_ADDR_EQUAL(&in6addr_any, &sin6->sin6_addr)) 
> 			if (prison_redirect_ip6(cred, &sin6->sin6_addr)) 
> 				return (EINVAL);
> 
191a197
> 			prison = jailed(cred); 
196c202
< 				    INPLOOKUP_WILDCARD);
---
> 				    prison ? 0 : INPLOOKUP_WILDCARD);
238a245,246
> 			if (prison && prison_redirect_ip6(cred, &sin6->sin6_addr))
> 				return (EADDRNOTAVAIL);
240c248
< 						lport, wild);
---
> 						lport, prison ? 0 : wild);
Index: sys/netinet6/raw_ip6.c
===================================================================
RCS file: /usr/freebsd.cvs/src/sys/netinet6/raw_ip6.c,v
retrieving revision 1.41
diff -r1.41 raw_ip6.c
70a71
> #include <sys/jail.h>
171a173,177
> 
> 		if (jailed(in6p->in6p_socket->so_cred))
> 			if (prison_match_ip6(in6p->in6p_socket->so_cred, &(ip6->ip6_dst)))
> 				continue;
> 
416c422,435
< 	ip6->ip6_src = *in6a;
---
> 	if (jailed(in6p->in6p_socket->so_cred))
> 	{
> 		/* fallback to first ip */
> 		if (prison_match_ip6(in6p->in6p_socket->so_cred, in6a)) {
> 			if ((error = prison_first_ip6(in6p->in6p_socket->so_cred, 
> 				&ip6->ip6_src)) != 0)
> 				return error;
> 		}
> 		else
> 			ip6->ip6_src = *in6a;
> 	}
> 	else
> 		ip6->ip6_src = *in6a;
> 
555a575,578
> 	if (td && jailed(td->td_ucred) && !jail_allow_raw_sockets) {
> 		return (EPERM);
> 	}
> 
620a644,653
> 
> 	if (jailed(td->td_ucred)) {
> 		if (IN6_ARE_ADDR_EQUAL(&(addr->sin6_addr), &in6addr_any)) {
> 			int error;
> 			if ((error = prison_first_ip6(td->td_ucred, &addr->sin6_addr)) != 0)
> 				return error;
> 		}
> 		if (prison_match_ip6(td->td_ucred, &addr->sin6_addr)) 
> 			return (EADDRNOTAVAIL);
> 	}
Index: sys/netinet6/udp6_output.c
===================================================================
RCS file: /usr/freebsd.cvs/src/sys/netinet6/udp6_output.c,v
retrieving revision 1.18
diff -r1.18 udp6_output.c
69a70
> #include <sys/jail.h>
168a170,171
> 		if (td && jailed(td->td_ucred))
> 			prison_remote_ip6(td->td_ucred, &sin6->sin6_addr); 
Index: sys/netinet6/udp6_usrreq.c
===================================================================
RCS file: /usr/freebsd.cvs/src/sys/netinet6/udp6_usrreq.c,v
retrieving revision 1.48
diff -r1.48 udp6_usrreq.c
69a70
> #include <sys/jail.h>
590a592
> 	struct sockaddr_in6 *sin6_p;
597,598d598
< 		struct sockaddr_in6 *sin6_p;
< 
620a621,624
> 	sin6_p = (struct sockaddr_in6 *)nam;
> 	if (td && jailed(td->td_ucred))
> 		prison_remote_ip6(td->td_ucred, &sin6_p->sin6_addr); 
> 
Index: sys/sys/jail.h
===================================================================
RCS file: /usr/freebsd.cvs/src/sys/sys/jail.h,v
retrieving revision 1.21
diff -r1.21 jail.h
9c9
<  * $FreeBSD$
---
>  * $FreeBSD: src/sys/sys/jail.h,v 1.18 2003/04/09 02:55:18 mike Exp $
15a16,27
> #include <netinet/in.h>
> 
> /*
>  * to safe a system call i reuse the jail systemcall to 
>  * to modify a jail. I will enable the ability to add
>  * and remove ip4/6 numbers to a jail.
>  * To get rid of it i playing around with version and 
>  * function numbers.
>  * A jail id is only create on setup path and hostname
>  * these values are inmutable. The function number is
>  * CREATEJAIL
>  */
17,20c29,61
< 	u_int32_t	version;
< 	char		*path;
< 	char		*hostname;
< 	u_int32_t	ip_number;
---
> 	u_int32_t       version;
> 	union {
> 	struct v1_s {
> 		char            *path;
> 		char            *hostname;
> 		u_int32_t       ip_number;
> 	} v1;
> 	struct v2_s {
> 		u_int32_t       function;
> 	#define CREATEJAIL 1
> 	#define ADDIP4 2
> 	#define DELIP4 3
> 	#define ADDIP6 4
> 	#define DELIP6 5
> 		union
> 		{
> 			struct 
> 			{
> 				char		*path;
> 				char		*hostname;
> 			} createjail;
> 			struct 
> 			{
> 				int id;
> 				union 
> 				{
> 					struct in_addr 	ip4_num;
> 					struct in6_addr ip6_num;
> 				} v4_6;
> 			} add_del;
> 		} u;
> 	} v2;
> 	} u;
28c69,72
< 	u_int32_t	 pr_ip;
---
> 	int		 pr4_id;
> 	struct in_addr 	 pr4_num; /* null is empty */
> 	int		 pr6_id;
> 	struct in6_addr  pr6_num; /* null is empty */
30c74
< #define	XPRISON_VERSION	1
---
> #define	XPRISON_VERSION	6
39a84
> #include <sys/_task.h>
42d86
< #include <sys/_task.h>
57a102
>  *   (d) set only during destruction of jail, no mutex needed
60d104
<  *   (d) set only during destruction of jail, no mutex needed
61a106,107
> 
> struct mtx;
69c115,119
< 	u_int32_t	 pr_ip;				/* (c) ip addr host */
---
> 	int		 pr_ip4s; 			/* (p) ipv4 addr count */
> 	struct in_addr	*pr_ip4;			/* (p) ipv4 addr host */
> 	int		 pr_ip6s; 			/* (p) ipv6 addr count */
> 	struct in6_addr *pr_ip6;			/* (p) ipv6 addr host */
>         struct task      pr_task;                       /* (d) destroy task */
72d121
< 	struct task	 pr_task;			/* (d) destroy task */
80a130,131
> extern int      jail_getfsstat_jailrootonly;
> extern int      jail_allow_raw_sockets;
84,85d134
< extern int	jail_getfsstat_jailrootonly;
< extern int	jail_allow_raw_sockets;
94d142
< struct mount;
95a144
> struct mount;
98d146
< int prison_check(struct ucred *cred1, struct ucred *cred2);
99a148
> int prison_check(struct ucred *cred1, struct ucred *cred2);
101c150,153
< u_int32_t prison_getip(struct ucred *cred);
---
> int  prison_first_ip6(struct ucred *cred, struct in6_addr *out); 
> int  prison_first_ip4(struct ucred *cred, struct in_addr *out); 
> int  prison_match_ip4(struct ucred *cred, struct in_addr *in); 
> int  prison_match_ip6(struct ucred *cred, struct in6_addr *in); 
104,105c156,160
< int prison_ip(struct ucred *cred, int flag, u_int32_t *ip);
< void prison_remote_ip(struct ucred *cred, int flags, u_int32_t *ip);
---
> int prison_redirect_ip4(struct ucred *cred, struct in_addr *ip);
> int prison_redirect_ip6(struct ucred *cred, struct in6_addr *ip);
> void prison_remote_ip4(struct ucred *cred, struct in_addr *ip);
> void prison_remote_ip6(struct ucred *cred, struct in6_addr *ip);
> 
Index: usr.sbin/jail/jail.8
===================================================================
RCS file: /usr/freebsd.cvs/src/usr.sbin/jail/jail.8,v
retrieving revision 1.57
diff -r1.57 jail.8
46c46,49
< .Ar path hostname ip-number command ...
---
> .Op Fl j Ar jail identifier
> .Op Fl a Ar ip4 or ip6 address
> .Op Fl d Ar ip4 or ip6 address
> .Ar path hostname [ip4|ip6] command ...
55c58
< Output the jail identifier of the newly created jail.
---
> Output the jail identifier of the newly created jail. Only valid without -j.
61c64,73
< The user name from jailed environment as whom the
---
> The user name from jailed environment as whom the. Only valid without -j.
> .It Fl j Ar jail identifier
> This options set the jail identifier which is modified with -a oder -d.
> The jail identifier could be retrieved with jls.
> .It Fl a Ar ip4 or ip6
> This options add the specified ip number to the jail that is give with -j. You
> can only have one -a per call. 
> .It Fl d Ar ip4 or ip6
> This options deletes the specified ip number from the jail that is give with -j.
> You can only have one -d per call.
69c81
< IP number assigned to the prison.
---
> IP4 or IP6 number assigned to the prison.
Index: usr.sbin/jail/jail.c
===================================================================
RCS file: /usr/freebsd.cvs/src/usr.sbin/jail/jail.c,v
retrieving revision 1.16
diff -r1.16 jail.c
15a16,17
> #include <sys/types.h>
> #include <sys/socket.h>
18a21
> 
53c56
< 	struct in_addr in;
---
> 	int jid = 0;
55a59,62
>         char *address;
>         int add = 0;
>         int del = 0;
> 
60c67
< 	while ((ch = getopt(argc, argv, "iu:U:")) != -1) {
---
> 	while ((ch = getopt(argc, argv, "iu:U:j:a:d:")) != -1) {
72a80,91
>                 case 'j':
>                         jid = atol(optarg);
>                         break;
>                 case 'a':
>                         add = 1;
>                         address = optarg;
>                         break;
>                 case 'd':
>                         del = 1;
>                         address = optarg;
>                         break;
> 
79c98,101
< 	if (argc < 4)
---
> 	if ((jid == 0 && argc < 4) ||
>             (jid < 1 && (add || del)) ||
>             (add && del) ||
>             (jid > 0 && !(add || del)))
80a103,122
>         if (jid > 0) {
> 		int function;
>                 if (inet_pton(AF_INET, address, &j.u.v2.u.add_del.v4_6.ip4_num) > 0) {
>                         function = add ? ADDIP4 : DELIP4;
>                 }
>                 else if (inet_pton(AF_INET6, address, &j.u.v2.u.add_del.v4_6.ip6_num) > 0) {
>                         function = add ? ADDIP6 : DELIP6;
>                 }
>                 else {
>                         err(1, "inet_pton: %s", address);
>                 }
> 		j.version = XPRISON_VERSION;
> 		j.u.v2.function = function;
> 		j.u.v2.u.add_del.id = jid;
> 		i = jail(&j);
> 		if (i == -1)
> 			err(1, "jail(%d)", function);
>                 exit (0);
>         }
> 
90,95c132,148
< 	j.version = 0;
< 	j.path = path;
< 	j.hostname = argv[1];
< 	if (inet_aton(argv[2], &in) == 0)
< 		errx(1, "Could not make sense of ip-number: %s", argv[2]);
< 	j.ip_number = ntohl(in.s_addr);
---
> 	j.version = XPRISON_VERSION;
> 	j.u.v2.function = CREATEJAIL;
> 	j.u.v2.u.createjail.path     = path;
> 	j.u.v2.u.createjail.hostname = argv[1];
> 	jid = i = jail(&j);
> 	if (i == -1)
> 		err(1, "jail(CREATEJAIL)");
> 
> 	j.version = XPRISON_VERSION;
> 	j.u.v2.u.add_del.id = i;
> 	j.u.v2.function = ADDIP4;
> 	if (inet_pton(AF_INET, address, &j.u.v2.u.add_del.v4_6.ip4_num) <= 0) {
> 		j.u.v2.function = ADDIP6;
> 		if (inet_pton(AF_INET6, address, &j.u.v2.u.add_del.v4_6.ip6_num) <= 0) {
> 			errx(1, "Could not make sense of ip-number: %s", argv[2]);
> 		}
> 	}
98c151,152
< 		err(1, "jail");
---
> 		err(1, "jail(%d)", j.u.v2.function);
> 
100c154
< 		printf("%d\n", i);
---
> 		printf("%d\n", jid);
124,127c178,180
< 	(void)fprintf(stderr, "%s%s\n",
< 	     "usage: jail [-i] [-u username | -U username]",
< 	     " path hostname ip-number command ...");
< 	exit(1);
---
>         (void)fprintf(stderr,
>         "usage: jail [-i] [-u username] [-j id] [[-a [ip4|ip6]|[-d [ip4|ip6]] [path hostname [ip4|ip6] command ...]\n");
>         exit(1);
Index: usr.sbin/jls/jls.8
===================================================================
RCS file: /usr/freebsd.cvs/src/usr.sbin/jls/jls.8,v
retrieving revision 1.1
diff -r1.1 jls.8
35a36,37
> .Op Fl a
> .Op Fl 6
39a42,52
> .Pp
> The options are as follows:
> .Bl -tag -width ".Fl a "
> .It Fl a 
> output all ip4 assigments to the jail identifier(JID). Each ip4 gets
> one line in output. If no ip4 address is assigned 0.0.0.0 is the output.
> .It Fl 6 
> output ip6 address also a new column is generated between IP Address 
> and Hostname. If no ip6 address is assigned :: is the output.
> .El
> .Pp
Index: usr.sbin/jls/jls.c
===================================================================
RCS file: /usr/freebsd.cvs/src/usr.sbin/jls/jls.c,v
retrieving revision 1.3
diff -r1.3 jls.c
32a33,35
> #include <sys/types.h>
> #include <sys/socket.h>
> #include <netinet/in.h>
33a37
> 
38a43,53
> #include <unistd.h>
> 
> static int
> usage(void)
> {
> 	fprintf(stderr, "%s\n%s\n%s\n",
> 	     "usage: jls [-a] [-6]",
> 	     " -a output all jail assigned ip addresses",
> 	     " -6 output includes ipv6 addresses");
> 	exit(1);
> }
42c57
< main(void)
---
> main(int argc, char **argv)
45d59
< 	struct in_addr in;
46a61,78
> 	int allflag = 0;
> 	int ip6flag = 0;
> 	int ch;
> 
> 	while ((ch = getopt(argc, argv, "a6")) != -1) {
> 		switch (ch) {
> 		case 'a':
> 			allflag = 1;
> 			break;
> 		case '6':
> 			ip6flag = 1;
> 			break;
> 		default:
> 			usage();
> 		}
> 	}
> 	argc -= optind;
> 	argv += optind;
68c100,103
< 	printf("   JID  IP Address      Hostname                      Path\n");
---
> 	if (ip6flag)
> 		printf("   JID  IP4 Address     IP6 Address            Hostname                      Path\n");
> 	else
> 		printf("   JID  IP Address      Hostname                      Path\n");
70,72c105,119
< 		in.s_addr = ntohl(xp->pr_ip);
< 		printf("%6d  %-15.15s %-29.29s %.74s\n",
< 		    xp->pr_id, inet_ntoa(in), xp->pr_host, xp->pr_path);
---
> 		if (allflag || xp->pr4_id == 0) {
> 			if (ip6flag) {
> 				char buffer[128];
> 				printf("%6d  %-15.15s %-22.22s %-29.29s %.74s\n",
> 				    xp->pr_id, 
> 				    inet_ntoa(xp->pr4_num),
> 				    inet_ntop(AF_INET6, xp->pr6_num.s6_addr, buffer, sizeof(buffer)),
> 				    xp->pr_host, 
>                                     xp->pr_path);
> 			}
> 			else {
> 				printf("%6d  %-15.15s %-29.29s %.74s\n",
> 				    xp->pr_id, inet_ntoa(xp->pr4_num), xp->pr_host, xp->pr_path);
> 			}
> 		}

>Release-Note:
>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20040714192137.A623484040>