svn commit: r188287 - in stable/7: etc etc/defaults etc/periodic/weekly etc/rc.d share/man/man5

Bjoern A. Zeeb bz at FreeBSD.org
Sat Feb 7 06:04:36 PST 2009


Author: bz
Date: Sat Feb  7 14:04:35 2009
New Revision: 188287
URL: http://svn.freebsd.org/changeset/base/188287

Log:
  MFC: r187708
  
    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.
    - 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.

Modified:
  stable/7/etc/   (props changed)
  stable/7/etc/defaults/rc.conf
  stable/7/etc/periodic/weekly/   (props changed)
  stable/7/etc/rc.d/jail
  stable/7/share/man/man5/   (props changed)
  stable/7/share/man/man5/rc.conf.5

Modified: stable/7/etc/defaults/rc.conf
==============================================================================
--- stable/7/etc/defaults/rc.conf	Sat Feb  7 13:55:12 2009	(r188286)
+++ stable/7/etc/defaults/rc.conf	Sat Feb  7 14:04:35 2009	(r188287)
@@ -615,14 +615,16 @@ jail_sysvipc_allow="NO"	# Allow SystemV 
 # 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

Modified: stable/7/etc/rc.d/jail
==============================================================================
--- stable/7/etc/rc.d/jail	Sat Feb  7 13:55:12 2009	(r188286)
+++ stable/7/etc/rc.d/jail	Sat Feb  7 14:04:35 2009	(r188287)
@@ -93,6 +93,7 @@ init_variables()
 	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"
@@ -126,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
@@ -275,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:'
@@ -296,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 255.255.255.255
-		fi
+		_addrl=""
+		jail_ips "add"
 		if [ -n "${_fib}" ]; then
 			_setfib="setfib -F '${_fib}'"
 		else
@@ -358,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})
@@ -379,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
@@ -410,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"

Modified: stable/7/share/man/man5/rc.conf.5
==============================================================================
--- stable/7/share/man/man5/rc.conf.5	Sat Feb  7 13:55:12 2009	(r188286)
+++ stable/7/share/man/man5/rc.conf.5	Sat Feb  7 14:04:35 2009	(r188287)
@@ -24,7 +24,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd January 9, 2009
+.Dd January 25, 2009
 .Dt RC.CONF 5
 .Os
 .Sh NAME
@@ -3398,8 +3398,38 @@ Set to the fully qualified domain name (
 .It Va jail_ Ns Ao Ar jname Ac Ns Va _ip
 .Pq Vt str
 Unset by default.
-Set to the IP address assigned to jail
-.Va jname .
+Set to the (primary) IPv4 and/or IPv6 address(es) assigned to the jail.
+The argument can be a sole address or a comma separated list of addresses.
+Additionally each address can be prefixed by the name of an interface
+followed by a pipe to overwrite
+.Va jail_ Ns Ao Ar jname Ac Ns Va _interface
+or
+.Va jail_interface
+and/or suffixed by a netmask, prefixlen or prefix.
+In case no netmask, prefixlen or prefix is given,
+.Sq /32
+will be used for IPv4 and
+.Sq /128
+will be used for an IPv6 address.
+If no address is given for the jail then the jail will be started with
+no networking support.
+.It Va jail_ Ns Ao Ar jname Ac Ns Va _ip_multi Ns Aq Ar n
+.Pq Vt str
+Unset by default.
+Set additional IPv4 and/or IPv6 address(es) assigned to the jail.
+The sequence starts with
+.Dq Li _multi0
+and the numbers have to be strictly ascending.
+These entries follow the same syntax as their primary
+.Va jail_ Ns Ao Ar jname Ac Ns Va _ip
+entry.
+The order of the entries can be important as the first address for
+each address family found will be the primary address of the jail.
+See
+.Va ip-addresses
+option in
+.Xr jail 8
+for more details.
 .It Va jail_ Ns Ao Ar jname Ac Ns Va _flags
 .Pq Vt str
 Set to


More information about the svn-src-all mailing list