Author: hrs
Date: Thu Oct 10 09:32:27 2013
New Revision: 256256
URL: http://svnweb.freebsd.org/changeset/base/256256

Log:
  - Update rc.d/jail to use a jail(8) configuration file instead of
    command line options.  The "jail_<jname>_*" rc.conf(5) variables for
    per-jail configuration are automatically converted to
    /var/run/jail.<jname>.conf before the jail(8) utility is invoked.
    This is transparently backward compatible.
  
  - Fix a minor bug in jail(8) which prevented it from returning false
    when jail -r failed.
  
  Approved by:  re (glebius)

Modified:
  head/UPDATING
  head/etc/defaults/rc.conf
  head/etc/rc.d/jail
  head/etc/rc.subr
  head/share/man/man5/rc.conf.5
  head/usr.sbin/jail/jail.c

Modified: head/UPDATING
==============================================================================
--- head/UPDATING       Thu Oct 10 07:41:11 2013        (r256255)
+++ head/UPDATING       Thu Oct 10 09:32:27 2013        (r256256)
@@ -31,6 +31,25 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 10
        disable the most expensive debugging functionality run
        "ln -s 'abort:false,junk:false' /etc/malloc.conf".)
 
+20131010:
+       The rc.d/jail script has been updated to support jail(8)
+       configuration file.  The "jail_<jname>_*" rc.conf(5) variables
+       for per-jail configuration are automatically converted to
+       /var/run/jail.<jname>.conf before the jail(8) utility is invoked.
+       This is transparently backward compatible.  See below about some
+       incompatibilities and rc.conf(5) manual page for more details.
+
+       These variables are now deprecated in favor of jail(8) configuration
+       file.  One can use "rc.d/jail config <jname>" command to generate
+       a jail(8) configuration file in /var/run/jail.<jname>.conf without
+       running the jail(8) utility.   The default pathname of the
+       configuration file is /etc/jail.conf and can be specified by
+       using $jail_conf or $jail_<jname>_conf variables.
+
+       Please note that jail_devfs_ruleset accepts an integer at
+       this moment.  Please consider to rewrite the ruleset name
+       with an integer.
+
 20130930:
        BIND has been removed from the base system.  If all you need
        is a local resolver, simply enable and start the local_unbound

Modified: head/etc/defaults/rc.conf
==============================================================================
--- head/etc/defaults/rc.conf   Thu Oct 10 07:41:11 2013        (r256255)
+++ head/etc/defaults/rc.conf   Thu Oct 10 09:32:27 2013        (r256256)
@@ -674,44 +674,11 @@ mixer_enable="YES"        # Run the sound mixer
 opensm_enable="NO"     # Opensm(8) for infiniband devices defaults to off
 
 ##############################################################
-### Jail Configuration #######################################
+### Jail Configuration (see rc.conf(5) manual page) ##########
 ##############################################################
 jail_enable="NO"       # Set to NO to disable starting of any jails
 jail_parallel_start="NO"       # Start jails in the background
 jail_list=""           # Space separated list of names of jails
-jail_set_hostname_allow="YES" # Allow root user in a jail to change its 
hostname
-jail_socket_unixiproute_only="YES" # Route only TCP/IP within a jail
-jail_sysvipc_allow="NO"        # Allow SystemV IPC use from within a jail
-
-#
-# To use rc's built-in jail infrastructure create entries for
-# each jail, specified in jail_list, with the following variables.
-# NOTES:
-# - replace 'example' with the jail's name.
-# - except rootdir, hostname, ip and the _multi<n> addresses,
-#   all of the following variables may be made global jail variables
-#   if you don't specify a jail name (ie. jail_interface, jail_devfs_ruleset).
-#
-#jail_example_rootdir="/usr/jail/default"      # Jail's root directory
-#jail_example_hostname="default.domain.com"    # Jail's hostname
-#jail_example_interface=""                     # Jail's interface variable to 
create IP aliases on
-#jail_example_fib="0"                          # Routing table for setfib(1)
-#jail_example_ip="192.0.2.10,2001:db8::17"     # Jail's primary IPv4 and IPv6 
address
-#jail_example_ip_multi0="2001:db8::10"         #  and another IPv6 address
-#jail_example_exec_start="/bin/sh /etc/rc"             # command to execute in 
jail for starting
-#jail_example_exec_afterstart0="/bin/sh command"       # command to execute 
after the one for
-                                                       # starting the jail. 
More than one can be
-                                                       # specified using a 
trailing number
-#jail_example_exec_stop="/bin/sh /etc/rc.shutdown"     # command to execute in 
jail for stopping
-#jail_example_devfs_enable="NO"                        # mount devfs in the 
jail
-#jail_example_devfs_ruleset="ruleset_name"     # devfs ruleset to apply to 
jail -
-                                               # usually you want 
"devfsrules_jail".
-#jail_example_fdescfs_enable="NO"              # mount fdescfs in the jail
-#jail_example_procfs_enable="NO"               # mount procfs in jail
-#jail_example_mount_enable="NO"                        # mount/umount jail's fs
-#jail_example_fstab=""                         # fstab(5) for mount/umount
-#jail_example_flags="-l -U root"               # flags for jail(8)
-#jail_example_parameters="allow.raw_sockets=1" # extra parameters for this jail
 
 ##############################################################
 ### Define source_rc_confs, the mechanism used by /etc/rc.* ##

Modified: head/etc/rc.d/jail
==============================================================================
--- head/etc/rc.d/jail  Thu Oct 10 07:41:11 2013        (r256255)
+++ head/etc/rc.d/jail  Thu Oct 10 09:32:27 2013        (r256256)
@@ -8,81 +8,138 @@
 # BEFORE: securelevel
 # KEYWORD: nojail shutdown
 
-# WARNING: This script deals with untrusted data (the data and
-# processes inside the jails) and care must be taken when changing the
-# code related to this!  If you have any doubt whether a change is
-# correct and have security impact, please get the patch reviewed by
-# the FreeBSD Security Team prior to commit.
-
 . /etc/rc.subr
 
 name="jail"
 rcvar="jail_enable"
 
-start_precmd="jail_prestart"
 start_cmd="jail_start"
+start_postcmd="jail_warn"
 stop_cmd="jail_stop"
+config_cmd="jail_config"
+console_cmd="jail_console"
+status_cmd="jail_status"
+extra_commands="config console status"
+: ${jail_conf:=/etc/jail.conf}
+: ${jail_program:=/usr/sbin/jail}
+: ${jail_consolecmd:=/bin/sh}
+: ${jail_jexec:=/usr/sbin/jexec}
+: ${jail_jls:=/usr/sbin/jls}
+
+need_dad_wait=
+
+# extact_var jail name param num defval
+#      Extract value from ${jail_$jail_$name} or ${jail_$name} and
+#      set it to $param.  If not defined, $defval is used.
+#      When $num is [0-9]*, ${jail_$jail_$name$num} are looked up and
+#      $param is set by using +=.
+#      When $num is YN or NY, the value is interpret as boolean.
+extract_var()
+{
+       local i _j _name _param _num _def _name1 _name2
+       _j=$1
+       _name=$2
+       _param=$3
+       _num=$4
+       _def=$5
+
+       case $_num in
+       YN)
+               _name1=jail_${_j}_${_name}
+               _name2=jail_${_name}
+               eval $_name1=\"\${$_name1:-\${$_name2:-$_def}}\"
+               if checkyesno $_name1; then
+                       echo "  $_param = 1;"
+               else
+                       echo "  $_param = 0;"
+               fi
+       ;;
+       NY)
+               _name1=jail_${_j}_${_name}
+               _name2=jail_${_name}
+               eval $_name1=\"\${$_name1:-\${$_name2:-$_def}}\"
+               if checkyesno $_name1; then
+                       echo "  $_param = 0;"
+               else
+                       echo "  $_param = 1;"
+               fi
+       ;;
+       [0-9]*)
+               i=$_num
+               while : ; do
+                       _name1=jail_${_j}_${_name}${i}
+                       _name2=jail_${_name}${i}
+                       eval _tmpargs=\"\${$_name1:-\${$_name2:-$_def}}\"
+                       if [ -n "$_tmpargs" ]; then 
+                               echo "  $_param += \"$_tmpargs\";"
+                       else
+                               break;
+                       fi
+                       i=$(($i + 1))
+               done
+       ;;
+       *)
+               _name1=jail_${_j}_${_name}
+               _name2=jail_${_name}
+               eval _tmpargs=\"\${$_name1:-\${$_name2:-$_def}}\"
+               if [ -n "$_tmpargs" ]; then
+                       echo "  $_param = \"$_tmpargs\";"
+               fi
+       ;;
+       esac
+}
 
-# init_variables _j
-#      Initialize the various jail variables for jail _j.
+# parse_options _j
+#      Parse options and create a temporary configuration file if necessary.
 #
-init_variables()
+parse_options()
 {
-       _j="$1"
+       local _j
+       _j=$1
 
+       _confwarn=0
        if [ -z "$_j" ]; then
-               warn "init_variables: you must specify a jail"
+               warn "parse_options: you must specify a jail"
                return
        fi
-
+       eval _jconf=\"\${jail_${_j}_conf:-/etc/jail.${_j}.conf}\"
        eval _rootdir=\"\$jail_${_j}_rootdir\"
-       _devdir="${_rootdir}/dev"
-       _fdescdir="${_devdir}/fd"
-       _procdir="${_rootdir}/proc"
        eval _hostname=\"\$jail_${_j}_hostname\"
+       if [ -z "$_rootdir" -o \
+            -z "$_hostname" ]; then
+               if [ -r "$_jconf" ]; then
+                       _conf="$_jconf"
+                       return 0
+               elif [ -r "$jail_conf" ]; then
+                       _conf="$jail_conf"
+                       return 0
+               else
+                       warn "Invalid configuration for $_j " \
+                           "(no jail.conf, no hostname, or no path).  " \
+                           "Jail $_j was ignored."
+               fi
+               return 1
+       fi
        eval _ip=\"\$jail_${_j}_ip\"
-       eval _interface=\"\${jail_${_j}_interface:-${jail_interface}}\"
-       eval _exec=\"\$jail_${_j}_exec\"
-
-       i=0
-       while : ; do
-               eval 
_exec_prestart${i}=\"\${jail_${_j}_exec_prestart${i}:-\${jail_exec_prestart${i}}}\"
-               [ -z "$(eval echo \"\$_exec_prestart${i}\")" ] && break
-               i=$((i + 1))
-       done
-
-       eval _exec_start=\"\${jail_${_j}_exec_start:-${jail_exec_start}}\"
-
-       i=1
-       while : ; do
-               eval 
_exec_afterstart${i}=\"\${jail_${_j}_exec_afterstart${i}:-\${jail_exec_afterstart${i}}}\"
-               [ -z "$(eval echo \"\$_exec_afterstart${i}\")" ] &&  break
-               i=$((i + 1))
-       done
-
-       i=0
-       while : ; do
-               eval 
_exec_poststart${i}=\"\${jail_${_j}_exec_poststart${i}:-\${jail_exec_poststart${i}}}\"
-               [ -z "$(eval echo \"\$_exec_poststart${i}\")" ] && break
-               i=$((i + 1))
-       done
-
-       i=0
-       while : ; do
-               eval 
_exec_prestop${i}=\"\${jail_${_j}_exec_prestop${i}:-\${jail_exec_prestop${i}}}\"
-               [ -z "$(eval echo \"\$_exec_prestop${i}\")" ] && break
-               i=$((i + 1))
-       done
-
-       eval _exec_stop=\"\${jail_${_j}_exec_stop:-${jail_exec_stop}}\"
-
-       i=0
-       while : ; do
-               eval 
_exec_poststop${i}=\"\${jail_${_j}_exec_poststop${i}:-\${jail_exec_poststop${i}}}\"
-               [ -z "$(eval echo \"\$_exec_poststop${i}\")" ] && break
-               i=$((i + 1))
-       done
+       if [ -z "$_ip" ] && ! check_kern_features vimage; then
+               warn "no ipaddress specified and no vimage support.  " \
+                   "Jail $_j was ignored."
+               return 1
+       fi
+       _conf=/var/run/jail.${_j}.conf
+       #
+       # To relieve confusion, show a warning message.
+       #
+       _confwarn=1
+       if [ -r "$jail_conf" -o -r "$_jconf" ]; then
+               warn "$_conf is created and used for jail $_j."
+       fi
+       /usr/bin/install -m 0644 -o root -g wheel /dev/null $_conf || return 1
 
+       eval : \${jail_${_j}_flags:=${jail_flags}}
+       eval _exec=\"\$jail_${_j}_exec\"
+       eval _exec_start=\"\$jail_${_j}_exec_start\"
+       eval _exec_stop=\"\$jail_${_j}_exec_stop\"
        if [ -n "${_exec}" ]; then
                #   simple/backward-compatible execution
                _exec_start="${_exec}"
@@ -96,285 +153,104 @@ init_variables()
                        fi
                fi
        fi
-
-       # The default jail ruleset will be used by rc.subr if none is specified.
-       eval _ruleset=\"\${jail_${_j}_devfs_ruleset:-${jail_devfs_ruleset}}\"
-       eval _devfs=\"\${jail_${_j}_devfs_enable:-${jail_devfs_enable}}\"
-       [ -z "${_devfs}" ] && _devfs="NO"
-       eval _fdescfs=\"\${jail_${_j}_fdescfs_enable:-${jail_fdescfs_enable}}\"
-       [ -z "${_fdescfs}" ] && _fdescfs="NO"
-       eval _procfs=\"\${jail_${_j}_procfs_enable:-${jail_procfs_enable}}\"
-       [ -z "${_procfs}" ] && _procfs="NO"
-
-       eval _mount=\"\${jail_${_j}_mount_enable:-${jail_mount_enable}}\"
-       [ -z "${_mount}" ] && _mount="NO"
-       # "/etc/fstab.${_j}" will be used for {,u}mount(8) if none is specified.
-       eval _fstab=\"\${jail_${_j}_fstab:-${jail_fstab}}\"
-       [ -z "${_fstab}" ] && _fstab="/etc/fstab.${_j}"
-       eval _flags=\"\${jail_${_j}_flags:-${jail_flags}}\"
-       [ -z "${_flags}" ] && _flags="-l -U root"
-       eval _consolelog=\"\${jail_${_j}_consolelog:-${jail_consolelog}}\"
-       [ -z "${_consolelog}" ] && _consolelog="/var/log/jail_${_j}_console.log"
+       eval _interface=\"\${jail_${_j}_interface:-${jail_interface}}\"
        eval _parameters=\"\${jail_${_j}_parameters:-${jail_parameters}}\"
-       [ -z "${_parameters}" ] && _parameters=""
-       eval _fib=\"\${jail_${_j}_fib:-${jail_fib}}\"
-
-       # Debugging aid
-       #
-       debug "$_j devfs enable: $_devfs"
-       debug "$_j fdescfs enable: $_fdescfs"
-       debug "$_j procfs enable: $_procfs"
-       debug "$_j mount enable: $_mount"
-       debug "$_j hostname: $_hostname"
-       debug "$_j ip: $_ip"
-       jail_show_addresses ${_j}
-       debug "$_j interface: $_interface"
-       debug "$_j fib: $_fib"
-       debug "$_j root: $_rootdir"
-       debug "$_j devdir: $_devdir"
-       debug "$_j fdescdir: $_fdescdir"
-       debug "$_j procdir: $_procdir"
-       debug "$_j ruleset: $_ruleset"
-       debug "$_j fstab: $_fstab"
-
-       i=0
-       while : ; do
-               eval out=\"\${_exec_prestart${i}:-''}\"
-               if [ -z "$out" ]; then
-                       break
-               fi
-               debug "$_j exec pre-start #${i}: ${out}"
-               i=$((i + 1))
-       done
-
-       debug "$_j exec start: $_exec_start"
-
-       i=1
-       while : ; do
-               eval out=\"\${_exec_afterstart${i}:-''}\"
-
-               if [ -z "$out" ]; then
-                       break;
-               fi
-
-               debug "$_j exec after start #${i}: ${out}"
-               i=$((i + 1))
-       done
-
-       i=0
-       while : ; do
-               eval out=\"\${_exec_poststart${i}:-''}\"
-               if [ -z "$out" ]; then
-                       break
-               fi
-               debug "$_j exec post-start #${i}: ${out}"
-               i=$((i + 1))
-       done
-
-       i=0
-       while : ; do
-               eval out=\"\${_exec_prestop${i}:-''}\"
-               if [ -z "$out" ]; then
-                       break
-               fi
-               debug "$_j exec pre-stop #${i}: ${out}"
-               i=$((i + 1))
-       done
-
-       debug "$_j exec stop: $_exec_stop"
+       eval _fstab=\"\${jail_${_j}_fstab:-${jail_fstab:-/etc/fstab.$_j}}\"
+       (
+               date +"# Generated by rc.d/jail at %Y-%m-%d %H:%M:%S"
+               echo "$_j {"
+               extract_var $_j hostname host.hostname - ""
+               extract_var $_j rootdir path - ""
+               if [ -n "$_ip" ]; then
+                       extract_var $_j interface interface - ""
+                       jail_handle_ips_option $_ip $_interface
+                       alias=0
+                       while : ; do
+                               eval _x=\"\$jail_${_jail}_ip_multi${alias}\"
+                               [ -z "$_x" ] && break
 
-       i=0
-       while : ; do
-               eval out=\"\${_exec_poststop${i}:-''}\"
-               if [ -z "$out" ]; then
-                       break
+                               jail_handle_ips_option $_x $_interface
+                               alias=$(($alias + 1))
+                       done
+                       case $need_dad_wait in
+                       1)
+                               # Sleep to let DAD complete before
+                               # starting services.
+                               echo "  exec.start += \"sleep " \
+                               $(($(${SYSCTL_N} net.inet6.ip6.dad_count) + 1)) 
\
+                               "\";"
+                       ;;
+                       esac
+                       # These are applicable only to non-vimage jails. 
+                       extract_var $_j fib exec.fib - ""
+                       extract_var $_j socket_unixiproute_only \
+                           allow.raw_sockets NY YES
+               else
+                       echo "  vnet;"
+                       extract_var $_j vnet_interface vnet.interface - ""
                fi
-               debug "$_j exec post-stop #${i}: ${out}"
-               i=$((i + 1))
-       done
-
-       debug "$_j flags: $_flags"
-       debug "$_j consolelog: $_consolelog"
-       debug "$_j parameters: $_parameters"
 
-       if [ -z "${_hostname}" ]; then
-               err 3 "$name: No hostname has been defined for ${_j}"
-       fi
-       if [ -z "${_rootdir}" ]; then
-               err 3 "$name: No root directory has been defined for ${_j}"
-       fi
-}
-
-# set_sysctl rc_knob mib msg
-#      If the mib sysctl is set according to what rc_knob
-#      specifies, this function does nothing. However if
-#      rc_knob is set differently than mib, then the mib
-#      is set accordingly and msg is displayed followed by
-#      an '=" sign and the word 'YES' or 'NO'.
-#
-set_sysctl()
-{
-       _knob="$1"
-       _mib="$2"
-       _msg="$3"
-
-       _current=`${SYSCTL} -n $_mib 2>/dev/null`
-       if checkyesno $_knob ; then
-               if [ "$_current" -ne 1 ]; then
-                       echo -n " ${_msg}=YES"
-                       ${SYSCTL} 1>/dev/null ${_mib}=1
-               fi
-       else
-               if [ "$_current" -ne 0 ]; then
-                       echo -n " ${_msg}=NO"
-                       ${SYSCTL} 1>/dev/null ${_mib}=0
+               echo "  exec.clean;"
+               echo "  exec.system_user = \"root\";"
+               echo "  exec.jail_user = \"root\";"
+               extract_var $_j exec_prestart exec.prestart 0 ""
+               extract_var $_j exec_poststart exec.poststart 0 ""
+               extract_var $_j exec_prestop exec.prestop 0 ""
+               extract_var $_j exec_poststop exec.poststop 0 ""
+
+               echo "  exec.start += \"$_exec_start\";"
+               extract_var $_j exec_afterstart exec.start 1 ""
+               echo "  exec.stop = \"$_exec_stop\";"
+
+               extract_var $_j consolelog exec.consolelog - \
+                   /var/log/jail_${_j}_console.log
+
+               eval : \${jail_${_j}_devfs_enable:=${jail_devfs_enable:-NO}}
+               if checkyesno jail_${_j}_devfs_enable; then
+                       echo "  mount.devfs;"
+                       case $_ruleset in
+                       "")     ;;
+                       [0-9]*) echo "  devfs_ruleset = \"$_ruleset\";" ;;
+                       devfsrules_jail)
+                               # XXX: This is the default value,
+                               # Let jail(8) to use the default because
+                               # mount(8) only accepts an integer. 
+                               # This should accept a ruleset name.
+                       ;;
+                       *)      warn "devfs_ruleset must be integer." ;;
+                       esac
+                       if [ -r $_fstab ]; then
+                               echo "  mount.fstab = \"$_fstab\";"
+                       fi
                fi
-       fi
-}
-
-# is_current_mountpoint()
-#      Is the directory mount point for a currently mounted file
-#      system?
-#
-is_current_mountpoint()
-{
-       local _dir _dir2
-
-       _dir=$1
-
-       _dir=`echo $_dir | sed -Ee 's#//+#/#g' -e 's#/$##'`
-       [ ! -d "${_dir}" ] && return 1
-       _dir2=`df ${_dir} | tail +2 | awk '{ print $6 }'`
-       [ "${_dir}" = "${_dir2}" ]
-       return $?
-}
-
-# is_symlinked_mountpoint()
-#      Is a mount point, or any of its parent directories, a symlink?
-#
-is_symlinked_mountpoint()
-{
-       local _dir
-
-       _dir=$1
-
-       [ -L "$_dir" ] && return 0
-       [ "$_dir" = "/" ] && return 1
-       is_symlinked_mountpoint `dirname $_dir`
-       return $?
-}
-
-# secure_umount
-#      Try to unmount a mount point without being vulnerable to
-#      symlink attacks.
-#
-secure_umount()
-{
-       local _dir
-
-       _dir=$1
-
-       if is_current_mountpoint ${_dir}; then
-               umount -f ${_dir} >/dev/null 2>&1
-       else
-               debug "Nothing mounted on ${_dir} - not unmounting"
-       fi
-}
-
-
-# jail_umount_fs
-#      This function unmounts certain special filesystems in the
-#      currently selected jail. The caller must call the init_variables()
-#      routine before calling this one.
-#
-jail_umount_fs()
-{
-       local _device _mountpt _rest
 
-       if checkyesno _fdescfs; then
-               if [ -d "${_fdescdir}" ] ; then
-                       secure_umount ${_fdescdir}
-               fi
-       fi
-       if checkyesno _devfs; then
-               if [ -d "${_devdir}" ] ; then
-                       secure_umount ${_devdir}
+               eval : \${jail_${_j}_fdescfs_enable:=${jail_fdescfs_enable:-NO}}
+               if checkyesno jail_${_j}_fdescfs_enable; then
+                       echo "  mount += " \
+                           "\"fdescfs ${_rootdir%/}/dev/fd fdescfs rw 0 0\";"
                fi
-       fi
-       if checkyesno _procfs; then
-               if [ -d "${_procdir}" ] ; then
-                       secure_umount ${_procdir}
+               eval : \${jail_${_j}_procfs_enable:=${jail_procfs_enable:-NO}}
+               if checkyesno jail_${_j}_procfs_enable; then
+                       echo "  mount += " \
+                           "\"procfs ${_rootdir%/}/proc procfs rw 0 0\";"
                fi
-       fi
-       if checkyesno _mount; then
-               [ -f "${_fstab}" ] || warn "${_fstab} does not exist"
-               tail -r ${_fstab} | while read _device _mountpt _rest; do
-                       case ":${_device}" in
-                       :#* | :)
-                               continue
-                               ;;
-                       esac
-                       secure_umount ${_mountpt}
-               done
-       fi
-}
 
-# jail_mount_fstab()
-#      Mount file systems from a per jail fstab while trying to
-#      secure against symlink attacks at the mount points.
-#
-#      If we are certain we cannot secure against symlink attacks we
-#      do not mount all of the file systems (since we cannot just not
-#      mount the file system with the problematic mount point).
-#
-#      The caller must call the init_variables() routine before
-#      calling this one.
-#
-jail_mount_fstab()
-{
-       local _device _mountpt _rest
+               echo "  ${_parameters};"
 
-       while read _device _mountpt _rest; do
-               case ":${_device}" in
-               :#* | :)
-                       continue
-                       ;;
-               esac
-               if is_symlinked_mountpoint ${_mountpt}; then
-                       warn "${_mountpt} has symlink as parent - not mounting 
from ${_fstab}"
-                       return
+               eval : \${jail_${_j}_mount_enable:=${jail_mount_enable:-NO}}
+               if checkyesno jail_${_j}_mount_enable; then
+                       echo "  allow.mount;" >> $_conf
                fi
-       done <${_fstab}
-       mount -a -F "${_fstab}"
-}
-
-# jail_show_addresses jail
-#      Debug print the input for the given _multi aliases
-#      for a jail for init_variables().
-#
-jail_show_addresses()
-{
-       local _j _type alias
-       _j="$1"
-       alias=0
 
-       if [ -z "${_j}" ]; then
-               warn "jail_show_addresses: you must specify a jail"
-               return
-       fi
+               extract_var $_j set_hostname_allow allow.set_hostname YN NO
+               extract_var $_j sysvipc_allow allow.sysvipc YN NO
+               echo "}"
+       ) >> $_conf
 
-       while : ; do
-               eval _addr=\"\$jail_${_j}_ip_multi${alias}\"
-               if [ -n "${_addr}" ]; then
-                       debug "${_j} ip_multi${alias}: $_addr"
-                       alias=$((${alias} + 1))
-               else
-                       break
-               fi
-       done
+       return 0
 }
 
-# jail_extract_address argument
+# jail_extract_address argument iface
 #      The second argument is the string from one of the _ip
 #      or the _multi variables. In case of a comma separated list
 #      only one argument must be passed in at a time.
@@ -382,8 +258,9 @@ jail_show_addresses()
 #
 jail_extract_address()
 {
-       local _i
+       local _i _interface
        _i=$1
+       _interface=$2
 
        if [ -z "${_i}" ]; then
                warn "jail_extract_address: called without input"
@@ -439,21 +316,21 @@ jail_extract_address()
                _mask=${_mask:-/32}
 
        elif [ "${_type}" = "inet6" ]; then
-               # In case _maske is not set for IPv6, use /128.
-               _mask=${_mask:-/128}
+               # In case _maske is not set for IPv6, use /64.
+               _mask=${_mask:-/64}
        fi
 }
 
-# jail_handle_ips_option {add,del} input
+# jail_handle_ips_option input iface
 #      Handle a single argument imput which can be a comma separated
 #      list of addresses (theoretically with an option interface and
 #      prefix/netmask/prefixlen).
 #
 jail_handle_ips_option()
 {
-       local _x _action _type _i
-       _action=$1
-       _x=$2
+       local _x _type _i _iface
+       _x=$1
+       _iface=$2
 
        if [ -z "${_x}" ]; then
                # No IP given. This can happen for the primary address
@@ -468,294 +345,146 @@ jail_handle_ips_option()
                *,*)    # Extract the first argument and strip it off the list.
                        _i=`expr "${_x}" : '^\([^,]*\)'`
                        _x=`expr "${_x}" : "^[^,]*,\(.*\)"`
-                       ;;
+               ;;
                *)      _i=${_x}
                        _x=""
-                       ;;
+               ;;
                esac
 
                _type=""
-               _iface=""
                _addr=""
                _mask=""
-               jail_extract_address "${_i}"
+               jail_extract_address $_i $_iface
 
                # make sure we got an address.
-               case "${_addr}" in
+               case $_addr in
                "")     continue ;;
                *)      ;;
                esac
 
                # Append address to list of addresses for the jail command.
-               case "${_type}" in
+               case $_type in
                inet)
-                       case "${_addrl}" in
-                       "")     _addrl="${_addr}" ;;
-                       *)      _addrl="${_addrl},${_addr}" ;;
-                       esac
-                       ;;
+                       echo "  ip4.addr += \"${_addr}${_mask}\";"
+               ;;
                inet6)
-                       case "${_addr6l}" in
-                       "")     _addr6l="${_addr}" ;;
-                       *)      _addr6l="${_addr6l},${_addr}" ;;
-                       esac
-                       ;;
-               esac
-
-               # Configure interface alias if requested by a given interface
-               # and if we could correctly parse everything.
-               case "${_iface}" in
-               "")     continue ;;
-               esac
-               case "${_type}" in
-               inet)   ;;
-               inet6)  ipv6_address_count=$((ipv6_address_count + 1)) ;;
-               *)      warn "Could not determine address family.  Not going" \
-                           "to ${_action} address '${_addr}' for ${_jail}."
-                       continue
-                       ;;
-               esac
-               case "${_action}" in
-               add)    ifconfig ${_iface} ${_type} ${_addr}${_mask} alias
-                       ;;
-               del)    # When removing the IP, ignore the _mask.
-                       ifconfig ${_iface} ${_type} ${_addr} -alias
-                       ;;
+                       echo "  ip6.addr += \"${_addr}${_mask}\";"
+                       need_dad_wait=1
+               ;;
                esac
        done
 }
 
-# jail_ips {add,del}
-#      Extract the comma separated list of addresses and return them
-#      for the jail command.
-#      Handle more than one address via the _multi option as well.
-#      If an interface is given also add/remove an alias for the
-#      address with an optional netmask.
-#
-jail_ips()
+jail_config()
 {
-       local _action
-       _action=$1
-
-       case "${_action}" in
-       add)    ;;
-       del)    ;;
-       *)      warn "jail_ips: invalid action '${_action}'"
-               return
-               ;;
+       case $1 in
+       _ALL)   return ;;
        esac
-
-       # Handle addresses.
-       ipv6_address_count=0
-       jail_handle_ips_option ${_action} "${_ip}"
-       # Handle jail_xxx_ip_multi<N>
-       alias=0
-       while : ; do
-               eval _x=\"\$jail_${_jail}_ip_multi${alias}\"
-               case "${_x}" in
-               "")     break ;;
-               *)      jail_handle_ips_option ${_action} "${_x}"
-                       alias=$((${alias} + 1))
-                       ;;
-               esac
+       for _jail in $@; do
+               if parse_options $_jail; then 
+                       echo "$_jail: parameters are in $_conf."
+               fi
        done
-       case ${ipv6_address_count} in
-       0)      ;;
-       *)      # Sleep 1 second to let DAD complete before starting services.
-               sleep 1
-               ;;
+}
+
+jail_console()
+{
+       # One argument that is not _ALL.
+       case $#:$1 in
+       1:_ALL) err 3 "Specify a jail name." ;;
+       1:*)    ;;
+       *)      err 3 "Specify a jail name." ;;
        esac
+       eval _cmd=\${jail_$1_consolecmd:-$jail_consolecmd}
+       $jail_jexec $1 $_cmd
 }
 
-jail_prestart()
+jail_status()
 {
-       if checkyesno jail_parallel_start; then
-               command_args='&'
-       fi
+
+       $jail_jls -N
 }
 
 jail_start()
 {
-       echo -n 'Configuring jails:'
-       set_sysctl jail_set_hostname_allow security.jail.set_hostname_allowed \
-           set_hostname_allow
-       set_sysctl jail_socket_unixiproute_only \
-           security.jail.socket_unixiproute_only unixiproute_only
-       set_sysctl jail_sysvipc_allow security.jail.sysvipc_allowed \
-           sysvipc_allow
-       echo '.'
-
+       if [ $# = 0 ]; then
+               return
+       fi
        echo -n 'Starting jails:'
-       _tmp_dir=`mktemp -d /tmp/jail.XXXXXXXX` || \
-           err 3 "$name: Can't create temp dir, exiting..."
-       for _jail in ${jail_list}
-       do
-               init_variables $_jail
-               if [ -f /var/run/jail_${_jail}.id ]; then
-                       echo -n " [${_hostname} already running 
(/var/run/jail_${_jail}.id exists)]"
-                       continue;
-               fi
-               _addrl=""
-               _addr6l=""
-               jail_ips "add"
-               if [ -n "${_fib}" ]; then
-                       _setfib="setfib -F '${_fib}'"
+       case $1 in
+       _ALL)
+               echo -n ' '
+               command=$jail_program
+               rc_flags=$jail_flags
+               command_args="-f $jail_conf -c"
+               $command $rc_flags $command_args "*"
+               echo '.'
+               return
+       ;;
+       esac
+       _tmp=`mktemp -t jail` || exit 3
+       for _jail in $@; do
+               parse_options $_jail || continue
+
+               eval rc_flags=\${jail_${_j}_flags:-$jail_flags}
+               eval command=\${jail_${_j}_program:-$jail_program}
+               if checkyesno jail_parallel_start; then
+                       command_args="-i -f $_conf -c $_jail &"
                else
-                       _setfib=""
-               fi
-               if checkyesno _mount; then
-                       info "Mounting fstab for jail ${_jail} (${_fstab})"
-                       if [ ! -f "${_fstab}" ]; then
-                               err 3 "$name: ${_fstab} does not exist"
-                       fi
-                       jail_mount_fstab
-               fi
-               if checkyesno _devfs; then
-                       # If devfs is already mounted here, skip it.
-                       df -t devfs "${_devdir}" >/dev/null
-                       if [ $? -ne 0 ]; then
-                               if is_symlinked_mountpoint ${_devdir}; then
-                                       warn "${_devdir} has symlink as parent 
- not starting jail ${_jail}"
-                                       continue
-                               fi
-                               info "Mounting devfs on ${_devdir}"
-                               devfs_mount_jail "${_devdir}" ${_ruleset}
-                               # Transitional symlink for old binaries
-                               if [ ! -L "${_devdir}/log" ]; then
-                                       ln -sf ../var/run/log "${_devdir}/log"
-                               fi
-                       fi
-
-                       # XXX - It seems symlinks don't work when there
-                       #       is a devfs(5) device of the same name.
-                       # Jail console output
-                       #       __pwd="`pwd`"
-                       #       cd "${_devdir}"
-                       #       ln -sf ../var/log/console console
-                       #       cd "$__pwd"
-               fi
-               if checkyesno _fdescfs; then
-                       if is_symlinked_mountpoint ${_fdescdir}; then
-                               warn "${_fdescdir} has symlink as parent, not 
mounting"
-                       else
-                               info "Mounting fdescfs on ${_fdescdir}"
-                               mount -t fdescfs fdesc "${_fdescdir}"
-                       fi
-               fi
-               if checkyesno _procfs; then
-                       if is_symlinked_mountpoint ${_procdir}; then
-                               warn "${_procdir} has symlink as parent, not 
mounting"
-                       else
-                               info "Mounting procfs onto ${_procdir}"
-                               if [ -d "${_procdir}" ] ; then
-                                       mount -t procfs proc "${_procdir}"
-                               fi
-                       fi
+                       command_args="-i -f $_conf -c $_jail"
                fi
-               _tmp_jail=${_tmp_dir}/jail.$$
-
-               i=0
-               while : ; do
-                       eval out=\"\${_exec_prestart${i}:-''}\"
-                       [ -z "$out" ] && break
-                       ${out}
-                       i=$((i + 1))
-               done
-
-               eval ${_setfib} jail -n ${_jail} ${_flags} -i -c 
path=${_rootdir} host.hostname=${_hostname} \
-                       ${_addrl:+ip4.addr=\"${_addrl}\"} 
${_addr6l:+ip6.addr=\"${_addr6l}\"} \
-                       ${_parameters} command=${_exec_start} > ${_tmp_jail} 
2>&1 \
-                       </dev/null
-
-               if [ "$?" -eq 0 ] ; then
-                       _jail_id=$(head -1 ${_tmp_jail})
-                       i=1
-                       while : ; do
-                               eval out=\"\${_exec_afterstart${i}:-''}\"
-
-                               if [ -z "$out" ]; then
-                                       break;
-                               fi
-
-                               jexec "${_jail_id}" ${out}
-                               i=$((i + 1))
-                       done
-
-                       echo -n " $_hostname"
-                       tail +2 ${_tmp_jail} >${_consolelog}
-                       echo ${_jail_id} > /var/run/jail_${_jail}.id
-
-                       i=0
-                       while : ; do
-                               eval out=\"\${_exec_poststart${i}:-''}\"
-                               [ -z "$out" ] && break
-                               ${out}
-                               i=$((i + 1))
-                       done
+               if $command $rc_flags $command_args \
+                   >> $_tmp 2>&1 </dev/null; then
+                       echo -n " ${_hostname:-${_jail}}"
                else
-                       jail_umount_fs
-                       jail_ips "del"
-                       echo " cannot start jail \"${_jail}\": "
-                       tail +2 ${_tmp_jail}
+                       echo " cannot start jail \"${_hostname:-${jail}}\": "
+                       tail +2 $_tmp
                fi
-               rm -f ${_tmp_jail}
+               rm -f $_tmp
        done
-       rmdir ${_tmp_dir}
        echo '.'
 }
 
 jail_stop()
 {
+       if [ $# = 0 ]; then
+               return
+       fi
        echo -n 'Stopping jails:'
-       for _jail in ${jail_list}
-       do
-               if [ -f "/var/run/jail_${_jail}.id" ]; then
-                       _jail_id=$(cat /var/run/jail_${_jail}.id)
-                       if [ ! -z "${_jail_id}" ]; then
-                               init_variables $_jail
-
-                               i=0
-                               while : ; do
-                                       eval out=\"\${_exec_prestop${i}:-''}\"
-                                       [ -z "$out" ] && break
-                                       ${out}

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "[email protected]"

Reply via email to