Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 24 Nov 2012 06:27:46 +0000 (UTC)
From:      Devin Teske <dteske@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r243475 - in head/usr.sbin/bsdconfig/networking: include share
Message-ID:  <201211240627.qAO6Rk5O084307@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: dteske
Date: Sat Nov 24 06:27:46 2012
New Revision: 243475
URL: http://svnweb.freebsd.org/changeset/base/243475

Log:
  Add IPv6 address-validation routine.
  
  Approved by:	adrian (co-mentor) (implicit)

Modified:
  head/usr.sbin/bsdconfig/networking/include/messages.subr
  head/usr.sbin/bsdconfig/networking/share/ipaddr.subr

Modified: head/usr.sbin/bsdconfig/networking/include/messages.subr
==============================================================================
--- head/usr.sbin/bsdconfig/networking/include/messages.subr	Sat Nov 24 04:15:25 2012	(r243474)
+++ head/usr.sbin/bsdconfig/networking/include/messages.subr	Sat Nov 24 06:27:46 2012	(r243475)
@@ -58,7 +58,11 @@ msg_ipaddr4="ipaddr"
 msg_ipv4_addr_octet_contains_invalid_chars="ERROR! One or more individual octets within the IP address\n(separated by dots) contains one or more invalid characters.\nOctets must contain only the characters 0-9.\n\nInvalid IP Address: %s"
 msg_ipv4_addr_octet_exceeds_max_value="ERROR! One or more individual octets within the IP address\n(separated by dots) exceeds the maximum of 255.\n\nInvalid IP Address: %s"
 msg_ipv4_addr_octet_is_null="ERROR! One or more individual octets within the IP address\n(separated by dots) are null and/or missing.\n\nInvalid IP Address: %s"
-msg_ipv4_addr_octet_missing_or_extra="ERROR! The IP address entered has either too few or too many\noctets.\n\nInvalid IP Address: %s"
+msg_ipv4_addr_octet_missing_or_extra="ERROR! The IP address entered has either too few (less than\nfour) or too many (more than four) octets, separated by dots.\n\nInvalid IP Address: %s"
+msg_ipv6_addr_segment_contains_invalid_chars="ERROR! One or more individual segments within the IP address\n(separated by colons) contains one or more invalid characters.\nSegments must contain only combinations of the characters 0-9,\nA-F, or a-f.\n\nInvalid IPv6 Address: %s"
+msg_ipv6_addr_segment_contains_too_many_chars="ERROR! One or more individual segments within the IP address\n(separated by colons) exceeds the length of 4 hex-digits.\n\nInvalid IPv6 Address: %s"
+msg_ipv6_addr_too_few_or_extra_segments="ERROR! The IP address entered has either too few (less than 3), too\nmany (more than 8), or not enough segments, separated by colons.\n\nInvalid IPv6 Address: %s"
+msg_ipv6_addr_too_many_null_segments="ERROR! Too many/incorrect null segments. A single null\nsegment is allowed within the IP address (separated by\ncolons) but not allowed at the beginning or end (unless\na double-null segment; i.e., \"::*\" or \"*::\").\n\nInvalid IPv6 Address: %s"
 msg_ipv4_mask_field_contains_invalid_chars="ERROR! One or more individual fields within the subnet mask\n(separated by dots) contains one or more invalid characters.\n\nInvalid Subnet Mask: %s"
 msg_ipv4_mask_field_exceeds_max_value="ERROR! One or more individual fields within the subnet mask\n(separated by dots) exceeds the maximum of 255.\n\nInvalid Subnet Mask: %s"
 msg_ipv4_mask_field_invalid_value="ERROR! One or more individual fields within the subnet mask\n(separated by dots) contains one or more invalid integers.\nFields must be one of 0/128/192/224/240/248/252/254/255.\n\nInvalid Subnet Mask: %s"

Modified: head/usr.sbin/bsdconfig/networking/share/ipaddr.subr
==============================================================================
--- head/usr.sbin/bsdconfig/networking/share/ipaddr.subr	Sat Nov 24 04:15:25 2012	(r243474)
+++ head/usr.sbin/bsdconfig/networking/share/ipaddr.subr	Sat Nov 24 06:27:46 2012	(r243475)
@@ -74,7 +74,7 @@ f_ifconfig_inet()
 # 	4	The IP address has either too few or too many octets.
 #
 # If the IP address is determined to be invalid, the appropriate error will be
-# displayed using the above dialog_msgbox function.
+# displayed using the f_dialog_msgbox function.
 #
 f_dialog_validate_ipaddr()
 {
@@ -125,6 +125,157 @@ f_dialog_validate_ipaddr()
 	return $retval
 }
 
+# f_dialog_validate_ipaddr6 $ipv6_addr
+#
+# Returns zero if the given argument (an IPv6 address) is of the proper format.
+#
+# The return status for invalid IP address is one of:
+# 	1	One or more individual segments within the IP address
+# 	 	(separated by colons) contains one or more invalid characters.
+# 	2	More than two segments within the IP address are null or the
+# 	 	the second null segment is not at the end of the address.
+# 	3	One or more individual segments within the IP address exceeds
+# 	 	the word length of 32-bits (segments are always hexadecimal).
+# 	4	The IP address has either too few or too many segments.
+# 	5	The IPv4 address at the end of the IPv6 address is invalid.
+#
+# If the IP address is determined to be invalid, the appropriate error will be
+# displayed using the f_dialog_msgbox function.
+#
+f_dialog_validate_ipaddr6()
+{
+	local ip="$1"
+
+	( # Operate within a sub-shell to protect the parent environment
+
+		oldIFS="$IFS"
+		IFS=":" # Split on `colon'
+		set -- $ip:
+
+		# Return error if too many or too few segments
+		# Using 9 as max in case of leading or trailing null spanner
+		[ $# -gt 9 -o $# -lt 3 ] && exit 4
+
+		h="[0-9A-Fa-f]"
+		nulls=0
+		nsegments=$#
+		contains_ipv4_segment=
+
+		while [ $# -gt 0 ]; do
+
+			segment="${1%:}"
+			shift
+
+			#
+			# Return error if this segment makes one null too-many.
+			# A single null segment is allowed anywhere in the
+			# middle as well as double null segments are allowed at
+			# the beginning or end (but not both).
+			#
+			if [ ! "$segment" ]; then
+				nulls=$(( $nulls + 1 ))
+				if [ $nulls -eq 3 ]; then
+					# Only valid syntax for 3 nulls is `::'
+					[ "$ip" = "::" ] || exit 2
+				elif [ $nulls -eq 2 ]; then
+					# Only valid if begins/ends with `::'
+					case "$ip" in
+					::*|*::) : fall thru ;;
+					*) exit 2
+					esac
+				fi
+				continue
+			fi
+
+			#
+			# Return error if not a valid hexadecimal short
+			#
+			case "$segment" in
+			$h|$h$h|$h$h$h|$h$h$h$h)
+				: valid segment of 1-4 hexadecimal digits
+				;;
+			*[!0-9A-Fa-f]*)
+				# Segment contains at least one invalid char
+
+				# Return error immediately if not last segment
+				[ $# -eq 0 ] || exit 1
+
+				# Otherwise, check for legacy IPv4 notation
+				case "$segment" in
+				*[!0-9.]*)
+					# Segment contains at least one invalid
+					# character even for an IPv4 address
+					exit 1
+				esac
+
+				# Return error if not enough segments
+				if [ $nulls -eq 0 ]; then
+					[ $nsegments -eq 7 ] || exit 4
+				fi
+
+				contains_ipv4_segment=1
+
+				# Validate the IPv4 address
+				IFS="$oldIFS"
+				f_dialog_validate_ipaddr "$segment" || exit 5
+				IFS=":"
+				;;
+			*)
+				# Segment characters are all valid but too many
+				exit 3
+			esac
+
+		done
+
+		if [ $nulls -eq 1 ]; then
+			# Single null segment cannot be at beginning/end
+			case "$ip" in
+			:*|*:) exit 2
+			esac
+		fi
+
+		#
+		# A legacy IPv4 address can span the last two 16-bit segments,
+		# reducing the amount of maximum allowable segments by-one.
+		#
+		maxsegments=8
+		if [ "$contains_ipv4_segment" ]; then
+			maxsegments=7
+		fi
+
+		case $nulls in
+		# Return error if missing segments with no null spanner
+		0) [ $nsegments -eq $maxsegments ] || exit 4 ;;
+		# Return error if null spanner with too many segments
+		1) [ $nsegments -le $maxsegments ] || exit 4 ;;
+		# Return error if leading/trailing `::' with too many segments
+		2) [ $nsegments -le $(( $maxsegments + 1 )) ] || exit 4 ;;
+		esac
+
+		exit $SUCCESS
+	)
+
+	#
+	# Produce an appropriate error message if necessary.
+	#
+	local retval=$?
+	case $retval in
+	1) f_dialog_msgbox "$( printf \
+		"$msg_ipv6_addr_segment_contains_invalid_chars" "$ip" )";;
+	2) f_dialog_msgbox "$( printf \
+		"$msg_ipv6_addr_too_many_null_segments" "$ip" )";;
+	3) f_dialog_msgbox "$( printf \
+		"$msg_ipv6_addr_segment_contains_too_many_chars" "$ip" )";;
+	4) f_dialog_msgbox "$( printf \
+		"$msg_ipv6_addr_too_few_or_extra_segments" "$ip" )";;
+	5) : IPv4 at the end of IPv6 address is invalid ;;
+		# Don't display an error because f_dialog_validate_ipaddr
+		# already displayed one for the particular issue encountered.
+	esac
+
+	return $retval
+}
+
 # f_dialog_input_ipaddr $interface $ipaddr
 #
 # Allows the user to edit a given IP address. If the user does not cancel or



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201211240627.qAO6Rk5O084307>