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
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to