summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordteske <dteske@FreeBSD.org>2012-11-24 06:27:46 +0000
committerdteske <dteske@FreeBSD.org>2012-11-24 06:27:46 +0000
commit4df351052644986d02f4f2b8d7a76bf2e65fbc6d (patch)
treee1be184f94854f3a77882b2965d2c4d5a8189c0b
parentfe5328de4d88c2b21fcede1faefbb88969c774f7 (diff)
downloadFreeBSD-src-4df351052644986d02f4f2b8d7a76bf2e65fbc6d.zip
FreeBSD-src-4df351052644986d02f4f2b8d7a76bf2e65fbc6d.tar.gz
Add IPv6 address-validation routine.
Approved by: adrian (co-mentor) (implicit)
-rw-r--r--usr.sbin/bsdconfig/networking/include/messages.subr6
-rw-r--r--usr.sbin/bsdconfig/networking/share/ipaddr.subr153
2 files changed, 157 insertions, 2 deletions
diff --git a/usr.sbin/bsdconfig/networking/include/messages.subr b/usr.sbin/bsdconfig/networking/include/messages.subr
index dac8e20..d430505 100644
--- a/usr.sbin/bsdconfig/networking/include/messages.subr
+++ b/usr.sbin/bsdconfig/networking/include/messages.subr
@@ -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"
diff --git a/usr.sbin/bsdconfig/networking/share/ipaddr.subr b/usr.sbin/bsdconfig/networking/share/ipaddr.subr
index 7e858dc..c64cfb9 100644
--- a/usr.sbin/bsdconfig/networking/share/ipaddr.subr
+++ b/usr.sbin/bsdconfig/networking/share/ipaddr.subr
@@ -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
OpenPOWER on IntegriCloud