From owner-svn-src-all@FreeBSD.ORG Mon Jan 26 12:59:11 2009 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 81771106566B; Mon, 26 Jan 2009 12:59:11 +0000 (UTC) (envelope-from bz@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 6E06F8FC1A; Mon, 26 Jan 2009 12:59:11 +0000 (UTC) (envelope-from bz@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n0QCxBpM050257; Mon, 26 Jan 2009 12:59:11 GMT (envelope-from bz@svn.freebsd.org) Received: (from bz@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n0QCxBMr050254; Mon, 26 Jan 2009 12:59:11 GMT (envelope-from bz@svn.freebsd.org) Message-Id: <200901261259.n0QCxBMr050254@svn.freebsd.org> From: "Bjoern A. Zeeb" Date: Mon, 26 Jan 2009 12:59:11 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r187708 - in head: etc/defaults etc/rc.d share/man/man5 X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 26 Jan 2009 12:59:12 -0000 Author: bz Date: Mon Jan 26 12:59:11 2009 New Revision: 187708 URL: http://svn.freebsd.org/changeset/base/187708 Log: 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__netmask option as it is only helpful to set netmasks/prefixes for the right address family and per address. - Implement jail__ip options to support both address familes with regard to ifconfig logic. - Implement _multi support suffix to the jail__ip option to configure additional addresses to avoid overlong, unreadbale jail__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 Modified: head/etc/defaults/rc.conf head/etc/rc.d/jail head/share/man/man5/rc.conf.5 Modified: head/etc/defaults/rc.conf ============================================================================== --- head/etc/defaults/rc.conf Mon Jan 26 07:31:28 2009 (r187707) +++ head/etc/defaults/rc.conf Mon Jan 26 12:59:11 2009 (r187708) @@ -617,14 +617,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 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: head/etc/rc.d/jail ============================================================================== --- head/etc/rc.d/jail Mon Jan 26 07:31:28 2009 (r187707) +++ head/etc/rc.d/jail Mon Jan 26 12:59:11 2009 (r187708) @@ -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 + 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" Modified: head/share/man/man5/rc.conf.5 ============================================================================== --- head/share/man/man5/rc.conf.5 Mon Jan 26 07:31:28 2009 (r187707) +++ head/share/man/man5/rc.conf.5 Mon Jan 26 12:59:11 2009 (r187708) @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd January 24, 2009 +.Dd January 25, 2009 .Dt RC.CONF 5 .Os .Sh NAME @@ -3426,8 +3426,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 @@ -3440,12 +3470,6 @@ These are flags to pass to Unset by default. When set, sets the interface to use when setting IP address alias. Note that the alias is created at jail startup and removed at jail shutdown. -.It Va jail_ Ns Ao Ar jname Ac Ns Va _netmask -.Pq Vt str -Set to -.Li 255.255.255.255 -by default. -This is the IP netmask to use when setting IP address alias. .It Va jail_ Ns Ao Ar jname Ac Ns Va _fib .Pq Vt str Unset by default.