diff options
author | bz <bz@FreeBSD.org> | 2009-01-26 12:59:11 +0000 |
---|---|---|
committer | bz <bz@FreeBSD.org> | 2009-01-26 12:59:11 +0000 |
commit | d8594296c6acfb8563e755122aceccea14d0ae97 (patch) | |
tree | 700cfe8e0ccc7f77d237d2db792afca87287d927 /etc | |
parent | 26e902404433f160c478b20ca2adbe5761d8433b (diff) | |
download | FreeBSD-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.conf | 12 | ||||
-rwxr-xr-x | etc/rc.d/jail | 224 |
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" |