summaryrefslogtreecommitdiffstats
path: root/etc
diff options
context:
space:
mode:
authorbz <bz@FreeBSD.org>2009-01-26 12:59:11 +0000
committerbz <bz@FreeBSD.org>2009-01-26 12:59:11 +0000
commitd8594296c6acfb8563e755122aceccea14d0ae97 (patch)
tree700cfe8e0ccc7f77d237d2db792afca87287d927 /etc
parent26e902404433f160c478b20ca2adbe5761d8433b (diff)
downloadFreeBSD-src-d8594296c6acfb8563e755122aceccea14d0ae97.zip
FreeBSD-src-d8594296c6acfb8563e755122aceccea14d0ae97.tar.gz
Update jail startup script for multi-IPv4/v6/no-IP jails.
Note: this is only really necessary because of the ifconfig logic to add/remove the jail IPs upon start/stop. Consensus among simon and I is that the logic should really be factored out from the startup script and put into a proper management solution. - We now support starting of no-IP jails. - Remove the global jail_<jname>_netmask option as it is only helpful to set netmasks/prefixes for the right address family and per address. - Implement jail_<jname>_ip options to support both address familes with regard to ifconfig logic. - Implement _multi<n> support suffix to the jail_<jname>_ip option to configure additional addresses to avoid overlong, unreadbale jail_<jname>_ip lines with lots of addresses. Submitted by: initial work from Ruben van Staveren Discussed on: freebsd-jail in Nov 2008. Reviewed by: simon, ru (partial, older version) MFC after: 1 week
Diffstat (limited to 'etc')
-rw-r--r--etc/defaults/rc.conf12
-rwxr-xr-xetc/rc.d/jail224
2 files changed, 215 insertions, 21 deletions
diff --git a/etc/defaults/rc.conf b/etc/defaults/rc.conf
index 99cf2d2..40c35df 100644
--- a/etc/defaults/rc.conf
+++ b/etc/defaults/rc.conf
@@ -617,14 +617,16 @@ jail_sysvipc_allow="NO" # Allow SystemV IPC use from within a jail
# each jail, specified in jail_list, with the following variables.
# NOTES:
# - replace 'example' with the jail's name.
-# - except rootdir, hostname and ip, all of the following variables may be made
-# global jail variables if you don't specify a jail name (ie. jail_interface).
+# - 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_ip="192.0.2.10" # Jail's IP number
-#jail_example_interface="" # Interface to create the IP alias on
-#jail_example_fib="0" # routing table for setfib(1)
+#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
diff --git a/etc/rc.d/jail b/etc/rc.d/jail
index 851bf3c..52b7944 100755
--- a/etc/rc.d/jail
+++ b/etc/rc.d/jail
@@ -39,7 +39,6 @@ init_variables()
_procdir="${_rootdir}/proc"
eval _hostname=\"\$jail_${_j}_hostname\"
eval _ip=\"\$jail_${_j}_ip\"
- eval _netmask=\"\${jail_${_j}_netmask:-255.255.255.255}\"
eval _interface=\"\${jail_${_j}_interface:-${jail_interface}}\"
eval _exec=\"\$jail_${_j}_exec\"
eval _exec_start=\"\${jail_${_j}_exec_start:-${jail_exec_start}}\"
@@ -94,7 +93,7 @@ init_variables()
debug "$_j mount enable: $_mount"
debug "$_j hostname: $_hostname"
debug "$_j ip: $_ip"
- debug "$_j netmask: $_netmask"
+ jail_show_addresses ${_j}
debug "$_j interface: $_interface"
debug "$_j fib: $_fib"
debug "$_j root: $_rootdir"
@@ -128,10 +127,6 @@ init_variables()
if [ -z "${_rootdir}" ]; then
err 3 "$name: No root directory has been defined for ${_j}"
fi
- if [ -z "${_ip}" ]; then
- err 3 "$name: No IP address has been defined for ${_j}"
- fi
-
}
# set_sysctl rc_knob mib msg
@@ -277,6 +272,208 @@ jail_mount_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
+
+ 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
+}
+
+# jail_extract_address argument
+# 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.
+# The function alters the _type, _iface, _addr and _mask variables.
+#
+jail_extract_address()
+{
+ local _i
+ _i=$1
+
+ if [ -z "${_i}" ]; then
+ warn "jail_extract_address: called without input"
+ return
+ fi
+
+ # Check if we have an interface prefix given and split into
+ # iFace and rest.
+ case "${_i}" in
+ *\|*) # ifN|.. prefix there
+ _iface=${_i%%|*}
+ _r=${_i##*|}
+ ;;
+ *) _iface=""
+ _r=${_i}
+ ;;
+ esac
+
+ # In case the IP has no interface given, check if we have a global one.
+ _iface=${_iface:-${_interface}}
+
+ # Set address, cut off any prefix/netmask/prefixlen.
+ _addr=${_r}
+ _addr=${_addr%%[/ ]*}
+
+ # Theoretically we can return here if interface is not set,
+ # as we only care about the _mask if we call ifconfig.
+ # This is not done because we may want to santize IP addresses
+ # based on _type later, and optionally change the type as well.
+
+ # Extract the prefix/netmask/prefixlen part by cutting off the address.
+ _mask=${_r}
+ _mask=`expr "${_mask}" : "${_addr}\(.*\)"`
+
+ # Identify type {inet,inet6}.
+ case "${_addr}" in
+ *\.*\.*\.*) _type="inet" ;;
+ *:*) _type="inet6" ;;
+ *) warn "jail_extract_address: type not identified"
+ ;;
+ esac
+
+ # Handle the special /netmask instead of /prefix or
+ # "netmask xxx" case for legacy IP.
+ # We do NOT support shortend class-full netmasks.
+ if [ "${_type}" = "inet" ]; then
+ case "${_mask}" in
+ /*\.*\.*\.*) _mask=" netmask ${_mask#/}" ;;
+ *) ;;
+ esac
+
+ # In case _mask is still not set use /32.
+ _mask=${_mask:-/32}
+
+ elif [ "${_type}" = "inet6" ]; then
+ # In case _maske is not set for IPv6, use /128.
+ _mask=${_mask:-/128}
+ fi
+}
+
+# jail_handle_ips_option {add,del} input
+# 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
+
+ if [ -z "${_x}" ]; then
+ # No IP given. This can happen for the primary address
+ # of each address family.
+ return
+ fi
+
+ # Loop, in case we find a comma separated list, we need to handle
+ # each argument on its own.
+ while [ ${#_x} -gt 0 ]; do
+ case "${_x}" in
+ *,*) # 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}"
+
+ # make sure we got an address.
+ case "${_addr}" in
+ "") continue ;;
+ *) ;;
+ esac
+
+ # Append address to list of addresses for the jail command.
+ case "${_addrl}" in
+ "") _addrl="${_addr}" ;;
+ *) _addrl="${_addrl},${_addr}" ;;
+ 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) ;;
+ *) 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
+ ;;
+ 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()
+{
+ local _action
+ _action=$1
+
+ case "${_action}" in
+ add) ;;
+ del) ;;
+ *) warn "jail_ips: invalid action '${_action}'"
+ return
+ ;;
+ esac
+
+ # Handle addresses.
+ 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
+ done
+}
+
jail_start()
{
echo -n 'Configuring jails:'
@@ -298,9 +495,8 @@ jail_start()
echo -n " [${_hostname} already running (/var/run/jail_${_jail}.id exists)]"
continue;
fi
- if [ -n "${_interface}" ]; then
- ifconfig ${_interface} alias ${_ip} netmask ${_netmask}
- fi
+ _addrl=""
+ jail_ips "add"
if [ -n "${_fib}" ]; then
_setfib="setfib -F '${_fib}'"
else
@@ -360,7 +556,7 @@ jail_start()
fi
_tmp_jail=${_tmp_dir}/jail.$$
eval ${_setfib} jail ${_flags} -i ${_rootdir} ${_hostname} \
- ${_ip} ${_exec_start} > ${_tmp_jail} 2>&1
+ \"${_addrl}\" ${_exec_start} > ${_tmp_jail} 2>&1
if [ "$?" -eq 0 ] ; then
_jail_id=$(head -1 ${_tmp_jail})
@@ -381,9 +577,7 @@ jail_start()
echo ${_jail_id} > /var/run/jail_${_jail}.id
else
jail_umount_fs
- if [ -n "${_interface}" ]; then
- ifconfig ${_interface} -alias ${_ip}
- fi
+ jail_ips "del"
echo " cannot start jail \"${_jail}\": "
tail +2 ${_tmp_jail}
fi
@@ -412,9 +606,7 @@ jail_stop()
jail_umount_fs
echo -n " $_hostname"
fi
- if [ -n "${_interface}" ]; then
- ifconfig ${_interface} -alias ${_ip}
- fi
+ jail_ips "del"
rm /var/run/jail_${_jail}.id
else
echo " cannot stop jail ${_jail}. No jail id in /var/run"
OpenPOWER on IntegriCloud