Proposal ipv6_addrs_common

Dirk Engling erdgeist at erdgeist.org
Mon Feb 6 00:36:54 UTC 2012


On 01.02.12 05:04, Dirk Engling wrote:

> The attached network6.subr is a shell script demonstrating the
> ipv6_addrs_common function inside, for playing around one can use some
> of the values the supplied get_if_var dummy function returns.

Following up my shell script I patched my /etc/network.subr to properly
work with the ipv6_addrs_IF variables while also removing some bugs in
the interface configuration code. ipv4_addrs_common also has been
patched to handle ranges in all octets.

The patch at

http://erdgeist.org/arts/software/network.subr_9.0.diff

has been tested on my FreeBSD 9.0, fixing some bugs introduced in the
rewrite of ifalias_up/ifalias_down for 9.0, as well.

I also have back ported the code to work under FreeBSD 8.2, the patch
against my 8.2-RELEASE's /etc/network.subr can be found here:

http://erdgeist.org/arts/software/network.subr_8.2.diff

Regards,

  erdgeist
-------------- next part --------------
--- FreeBSD_8.2/network.subr	2012-01-21 12:52:45.000000000 +0000
+++ network.subr	2012-01-21 12:54:06.000000000 +0000
@@ -45,6 +45,7 @@
 	ifscript_up ${ifn} && cfg=0
 	ifconfig_up ${ifn} && cfg=0
 	ipv4_up ${ifn} && cfg=0
+	ipv6_up ${ifn} && cfg=0
 	ipx_up ${ifn} && cfg=0
 	childif_create ${ifn}
 
@@ -64,6 +65,7 @@
 	[ -z "$ifn" ] && return 1
 
 	ipx_down ${ifn} && cfg=0
+	ipv6_down ${ifn} && cfg=0
 	ipv4_down ${ifn} && cfg=0
 	ifconfig_down ${ifn} && cfg=0
 	ifscript_down ${ifn} && cfg=0
@@ -307,6 +309,32 @@
 	ifconfig -n $1 > /dev/null 2>&1
 }
 
+# ipv6_up if
+#  add IPv6 addresses to the interface $if
+ipv6_up()
+{
+	local _ret _if
+	_ret=1
+	_if=$1
+	ipv6if ${_if} || return 1 
+	
+	ipv6_addrs_common ${_if} alias && _ret=0
+	return _ret
+}
+
+# ifv6_down if
+#  remove IPv6 addresses from the interface $if
+ifp6_down()
+{
+	local _ret _if
+	_ret=1
+	_if=$1
+	ipv6if ${_if} || return 1 
+	
+	ipv6_addrs_common ${_if} -alias && _ret=0
+	return _ret
+}
+
 # ipv4_up if
 #  add IPv4 addresses to the interface $if 
 ipv4_up()
@@ -326,6 +354,9 @@
 
 	ifexists ${_if} || return 1
 
+	ifalias_down ${_if} && _ret=0
+	ipv4_addrs_common ${_if} -alias && _ret=0
+
 	inetList="`ifconfig ${_if} | grep 'inet ' | tr "\n" "$_ifs"`"
 
 	oldifs="$IFS"
@@ -343,49 +374,150 @@
 	done
 	IFS="$oldifs"
 
-	ifalias_down ${_if} && _ret=0
-	ipv4_addrs_common ${_if} -alias && _ret=0
-
 	return $_ret
 }
 
 # ipv4_addrs_common if action
-#   Evaluate the ifconfig_if_ipv4 arguments for interface $if
-#   and use $action to add or remove IPv4 addresses from $if.
+#	Evaluate the ipv4_addrs_IF arguments for interface $if and
+#	use $action to add or remove IPv4 addresses from $if.
 ipv4_addrs_common()
-{  
+{
+	local _ret _if _action _cidr _cidr_addr
+	local _ipaddr _netmask _ipleft _ipright _iplow _iphigh
 	_ret=1
 	_if=$1
 	_action=$2
-    
+
 	# get ipv4-addresses
-	cidr_addr=`get_if_var $_if ipv4_addrs_IF`
-    
-	for _cidr in ${cidr_addr}; do
-		_ipaddr=${_cidr%%/*}
-		_netmask="/"${_cidr##*/}
-		_range=${_ipaddr##*.}
-		_ipnet=${_ipaddr%.*}
-		_iplow=${_range%-*}
-		_iphigh=${_range#*-}
-
-		# clear netmask when removing aliases
-		if [ "${_action}" = "-alias" ]; then
-			_netmask=""
-		fi
-        
-		_ipcount=${_iplow}
-		while [ "${_ipcount}" -le "${_iphigh}" ]; do
-			eval "ifconfig ${_if} ${_action} ${_ipnet}.${_ipcount}${_netmask}"
-			_ipcount=$((${_ipcount}+1))
-			_ret=0
+	_cidr_addr=`get_if_var $_if ipv4_addrs_IF`
+
+	for _cidr in ${_cidr_addr}; do
+		_ipaddr="${_cidr%%/*}"
+
+		if [ "${_ipaddr}" = "${_cidr}" -o "$_action" = "-alias" ]; then
+			unset _netmask
+		else
+			_netmask="/"${_cidr##*/}
+		fi
+
+		_ipleft=${_ipaddr%-*}
+		_ipright=${_ipaddr#*-}
 
-			# only the first ipaddr in a subnet need the real netmask
-			if [ "${_action}" != "-alias" ]; then
-				_netmask="/32"
+		_iplow=${_ipleft##*.}
+		_iphigh=${_ipright%%.*}
+		_ipleft=${_ipleft%.*}
+		_ipright=${_ipright#*.}
+
+		if [ "${_iphigh}" = "${_ipright}" ]; then
+			 unset _ipright
+		else
+			_ipright=.$_ipright
+		fi
+
+		if [ -n "${_iplow}" -a -n "${_iphigh}" ]; then
+			while [ ${_iplow} -le ${_iphigh} ]; do
+				ifconfig ${_if} ${_ipleft}.${_iplow}${_ipright}${_netmask} \
+				    ${_action} && _ret=0
+				_iplow=$(( ${_iplow} + 1 ))
+
+				# only the first ipaddr in a subnet need the real netmask
+				if [ "${_action}" != "-alias" ]; then
+					_netmask="/32"
+				fi
+			done
+		else
+			# no range or parse error, just pass to ifconfig
+			ifconfig ${_if} ${_ipaddr}${_netmask} ${_action} && _ret=0
+		fi
+	done
+
+	return $_ret
+}
+
+# ipv6_addrs_common if action
+#	Evaluate the ipv6_addrs_IF arguments for interface $if and
+#	use $action to add or remove IPv6 addresses from $if.
+ipv6_addrs_common()
+{
+	local _ret _if _action _cidr _cidr_addr
+	local _ipaddr _netmask _ipleft _ipright _iplow _iphigh
+	local _ipv6part _ipv4part
+	_ret=1
+	_if=$1
+	_action=$2
+
+	# get ipv6-addresses
+	_cidr_addr=`get_if_var $_if ipv6_addrs_IF`
+
+	for _cidr in ${_cidr_addr}; do
+		_ipaddr="${_cidr%%/*}"
+
+		if [ "${_ipaddr}" = "${_cidr}" -o "$_action" = "-alias" ]; then
+			unset _netmask
+		else
+			_netmask="/"${_cidr##*/}
+		fi
+
+		# Handle v6 mapped v4 addresses below
+		if [ "${_ipaddr%:*.*.*.*}" = "${_ipaddr}" ]; then
+			_ipleft=${_ipaddr%-*}
+			_ipright=${_ipaddr#*-}
+			_iplow=${_ipleft##*:}
+			_iphigh=${_ipright%%:*}
+			_ipleft=${_ipleft%:*}
+			_ipright=${_ipright#*:}
+
+			if [ "${_iphigh}" = "${_ipright}" ]; then
+				unset _ipright
+			else
+				_ipright=:$_ipright
 			fi
-		done
+
+			if [ -n "${_iplow}" -a -n "${_iphigh}" ]; then
+				while [ $(( 0x$_iplow )) -le $(( 0x$_iphigh )) ]; do
+					ifconfig ${_if} inet6 ${_ipleft}:${_iplow}${_ipright}\
+${_netmask} ${_action} && _ret=0
+
+					# Advance counter - in hex
+					_iplow=`printf %04x $(( 0x$_iplow + 1 ))`
+				done
+			else
+				# no range or parse error, just pass to ifconfig
+				ifconfig ${_if} inet6 ${_ipaddr}${_netmask} ${_action} && _ret=0
+			fi
+		else
+			# v6 mapped v4 range
+			_ipv6part=${_ipaddr%:*}
+			_ipv4part=${_ipaddr##*:}
+			_ipleft=${_ipv4part%-*}
+			_ipright=${_ipv4part#*-}
+
+			_iplow=${_ipleft##*.}
+			_iphigh=${_ipright%%.*}
+			_ipleft=${_ipv6part}:${_ipleft%.*}
+			_ipright=${_ipright#*.}
+
+			if [ "${_iphigh}" = "${_ipright}" ]; then
+				unset _ipright
+			else
+				_ipright=.$_ipright
+			fi
+
+			if [ -n "${_iplow}" -a -n "${_iphigh}" ]; then
+				while [ ${_iplow} -le ${_iphigh} ]; do
+					ifconfig ${_if} inet6 ${_ipleft}.${_iplow}${_ipright}\
+${_netmask} ${_action} && _ret=0
+
+					# Advance counter - in dec
+					_iplow=$(( ${_iplow} + 1 ))
+				done
+			else
+				# no range or parse error, just pass to ifconfig
+				ifconfig ${_if} inet6 ${_ipaddr}${_netmask} ${_action} && _ret=0
+			fi
+		fi
 	done
+
 	return $_ret
 }
 
-------------- next part --------------
--- /usr/share/examples/etc/network.subr	2011-12-04 10:11:10.000000000 +0100
+++ network.subr	2012-01-30 11:49:39.000000000 +0100
@@ -444,6 +444,12 @@
 			return 0
 		fi
 
+		# True if ipv6_addrs_IF is defined.
+		_tmpargs=`get_if_var $_if ipv6_addrs_IF`
+		if [ -n "${_tmpargs}" ]; then
+			return 0
+		fi
+
 		# backward compatibility: True if $ipv6_ifconfig_IF is defined.
 		_tmpargs=`get_if_var $_if ipv6_ifconfig_IF`
 		if [ -n "${_tmpargs}" ]; then
@@ -538,7 +544,6 @@
 		fi
 	fi
 	ifalias_up ${_if} inet && _ret=0
-	ipv4_addrs_common ${_if} alias && _ret=0
 
 	return $_ret
 }
@@ -575,6 +580,10 @@
 	_ifs="^"
 	_ret=1
 
+	# remove all ip addresses configured by network.subr
+	ifalias_down ${_if} inet && _ret=0
+
+	# remove the rest
 	inetList="`ifconfig ${_if} | grep 'inet ' | tr "\n" "$_ifs"`"
 
 	oldifs="$IFS"
@@ -586,15 +595,12 @@
 		_inet=`expr "$_inet" : '.*\(inet \([0-9]\{1,3\}\.\)\{3\}[0-9]\{1,3\}\).*'`
 
 		IFS="$oldifs"
-		ifconfig ${_if} ${_inet} delete
+		ifconfig ${_if} ${_inet} delete && _ret=0
 		IFS="$_ifs"
 		_ret=0
 	done
 	IFS="$oldifs"
 
-	ifalias_down ${_if} inet && _ret=0
-	ipv4_addrs_common ${_if} -alias && _ret=0
-
 	return $_ret
 }
 
@@ -636,43 +642,144 @@
 }
 
 # ipv4_addrs_common if action
-#	Evaluate the ifconfig_if_ipv4 arguments for interface $if and
+#	Evaluate the ipv4_addrs_IF arguments for interface $if and
 #	use $action to add or remove IPv4 addresses from $if.
 ipv4_addrs_common()
 {
 	local _ret _if _action _cidr _cidr_addr
-	local _ipaddr _netmask _range _ipnet _iplow _iphigh _ipcount
+	local _ipaddr _netmask _ipleft _ipright _iplow _iphigh
 	_ret=1
 	_if=$1
 	_action=$2
 
 	# get ipv4-addresses
-	cidr_addr=`get_if_var $_if ipv4_addrs_IF`
+	_cidr_addr=`get_if_var $_if ipv4_addrs_IF`
+
+	for _cidr in ${_cidr_addr}; do
+		_ipaddr="${_cidr%%/*}"
+
+		if [ "${_ipaddr}" = "${_cidr}" -o "$_action" = "-alias" ]; then
+			unset _netmask
+		else
+			_netmask="/"${_cidr##*/}
+		fi
+
+		_ipleft=${_ipaddr%-*}
+		_ipright=${_ipaddr#*-}
 
-	for _cidr in ${cidr_addr}; do
-		_ipaddr=${_cidr%%/*}
-		_netmask="/"${_cidr##*/}
-		_range=${_ipaddr##*.}
-		_ipnet=${_ipaddr%.*}
-		_iplow=${_range%-*}
-		_iphigh=${_range#*-}
-
-		# clear netmask when removing aliases
-		if [ "${_action}" = "-alias" ]; then
-			_netmask=""
-		fi
-
-		_ipcount=${_iplow}
-		while [ "${_ipcount}" -le "${_iphigh}" ]; do
-			eval "ifconfig ${_if} ${_action} ${_ipnet}.${_ipcount}${_netmask}"
-			_ipcount=$((${_ipcount}+1))
-			_ret=0
-
-			# only the first ipaddr in a subnet need the real netmask
-			if [ "${_action}" != "-alias" ]; then
-				_netmask="/32"
+		_iplow=${_ipleft##*.}
+		_iphigh=${_ipright%%.*}
+		_ipleft=${_ipleft%.*}
+		_ipright=${_ipright#*.}
+
+		if [ "${_iphigh}" = "${_ipright}" ]; then
+			 unset _ipright
+		else
+			_ipright=.$_ipright
+		fi
+
+		if [ -n "${_iplow}" -a -n "${_iphigh}" ]; then
+			while [ ${_iplow} -le ${_iphigh} ]; do
+				ifconfig ${_if} ${_ipleft}.${_iplow}${_ipright}${_netmask} \
+				    ${_action} && _ret=0
+				_iplow=$(( ${_iplow} + 1 ))
+
+				# only the first ipaddr in a subnet need the real netmask
+				if [ "${_action}" != "-alias" ]; then
+					_netmask="/32"
+				fi
+			done
+		else
+			# no range or parse error, just pass to ifconfig
+			ifconfig ${_if} ${_ipaddr}${_netmask} ${_action} && _ret=0
+		fi
+	done
+
+	return $_ret
+}
+
+# ipv6_addrs_common if action
+#	Evaluate the ipv6_addrs_IF arguments for interface $if and
+#	use $action to add or remove IPv6 addresses from $if.
+ipv6_addrs_common()
+{
+	local _ret _if _action _cidr _cidr_addr
+	local _ipaddr _netmask _ipleft _ipright _iplow _iphigh
+	local _ipv6part _ipv4part
+	_ret=1
+	_if=$1
+	_action=$2
+
+	# get ipv6-addresses
+	_cidr_addr=`get_if_var $_if ipv6_addrs_IF`
+
+	for _cidr in ${_cidr_addr}; do
+		_ipaddr="${_cidr%%/*}"
+
+		if [ "${_ipaddr}" = "${_cidr}" -o "$_action" = "-alias" ]; then
+			unset _netmask
+		else
+			_netmask="/"${_cidr##*/}
+		fi
+
+		# Handle v6 mapped v4 addresses below
+		if [ "${_ipaddr%:*.*.*.*}" = "${_ipaddr}" ]; then
+			_ipleft=${_ipaddr%-*}
+			_ipright=${_ipaddr#*-}
+			_iplow=${_ipleft##*:}
+			_iphigh=${_ipright%%:*}
+			_ipleft=${_ipleft%:*}
+			_ipright=${_ipright#*:}
+
+			if [ "${_iphigh}" = "${_ipright}" ]; then
+				unset _ipright
+			else
+				_ipright=:$_ipright
 			fi
-		done
+
+			if [ -n "${_iplow}" -a -n "${_iphigh}" ]; then
+				while [ $(( 0x$_iplow )) -le $(( 0x$_iphigh )) ]; do
+					ifconfig ${_if} inet6 ${_ipleft}:${_iplow}${_ipright}\
+${_netmask} ${_action} && _ret=0
+
+					# Advance counter - in hex
+					_iplow=`printf %04x $(( 0x$_iplow + 1 ))`
+				done
+			else
+				# no range or parse error, just pass to ifconfig
+				ifconfig ${_if} inet6 ${_ipaddr}${_netmask} ${_action} && _ret=0
+			fi
+		else
+			# v6 mapped v4 range
+			_ipv6part=${_ipaddr%:*}
+			_ipv4part=${_ipaddr##*:}
+			_ipleft=${_ipv4part%-*}
+			_ipright=${_ipv4part#*-}
+
+			_iplow=${_ipleft##*.}
+			_iphigh=${_ipright%%.*}
+			_ipleft=${_ipv6part}:${_ipleft%.*}
+			_ipright=${_ipright#*.}
+
+			if [ "${_iphigh}" = "${_ipright}" ]; then
+				unset _ipright
+			else
+				_ipright=.$_ipright
+			fi
+
+			if [ -n "${_iplow}" -a -n "${_iphigh}" ]; then
+				while [ ${_iplow} -le ${_iphigh} ]; do
+					ifconfig ${_if} inet6 ${_ipleft}.${_iplow}${_ipright}\
+${_netmask} ${_action} && _ret=0
+
+					# Advance counter - in dec
+					_iplow=$(( ${_iplow} + 1 ))
+				done
+			else
+				# no range or parse error, just pass to ifconfig
+				ifconfig ${_if} inet6 ${_ipaddr}${_netmask} ${_action} && _ret=0
+			fi
+		fi
 	done
 
 	return $_ret
@@ -685,15 +792,18 @@
 #
 ifalias_up()
 {
-	local _ret
+	local _ret _if
 	_ret=1
+	_if=$1
 
 	case "$2" in
 	inet)
-		_ret=`ifalias_ipv4_up "$1"`
+		ifalias_ipv4_up ${_if} && _ret=0
+	    ipv4_addrs_common ${_if} alias && _ret=0
 		;;
 	inet6)
-		_ret=`ifalias_ipv6_up "$1"`
+		ifalias_ipv6_up ${_if} && _ret=0
+	    ipv6_addrs_common ${_if} alias && _ret=0
 		;;
 	esac
 
@@ -776,15 +886,18 @@
 #
 ifalias_down()
 {
-	local _ret
+	local _ret _if
 	_ret=1
+    _if=$1
 
 	case "$2" in
 	inet)
-		_ret=`ifalias_ipv4_down "$1"`
+		ifalias_ipv4_down ${_if} && _ret=0
+	    ipv4_addrs_common ${_if} -alias && _ret=0
 		;;
 	inet6)
-		_ret=`ifalias_ipv6_down "$1"`
+		ifalias_ipv6_down ${_if} && _ret=0
+	    ipv6_addrs_common ${_if} -alias && _ret=0
 		;;
 	esac
 


More information about the freebsd-rc mailing list