xref: /freebsd/usr.sbin/bsdconfig/share/media/tcpip.subr (revision d4ae33f0721c1b170fe37d97e395228ffcfb3f80)
17323adacSDevin Teskeif [ ! "$_MEDIA_TCPIP_SUBR" ]; then _MEDIA_TCPIP_SUBR=1
27323adacSDevin Teske#
37323adacSDevin Teske# Copyright (c) 2012-2013 Devin Teske
4f8ea072aSDevin Teske# All rights reserved.
57323adacSDevin Teske#
67323adacSDevin Teske# Redistribution and use in source and binary forms, with or without
77323adacSDevin Teske# modification, are permitted provided that the following conditions
87323adacSDevin Teske# are met:
97323adacSDevin Teske# 1. Redistributions of source code must retain the above copyright
107323adacSDevin Teske#    notice, this list of conditions and the following disclaimer.
117323adacSDevin Teske# 2. Redistributions in binary form must reproduce the above copyright
127323adacSDevin Teske#    notice, this list of conditions and the following disclaimer in the
137323adacSDevin Teske#    documentation and/or other materials provided with the distribution.
147323adacSDevin Teske#
157323adacSDevin Teske# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
168e37a7c8SDevin Teske# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
177323adacSDevin Teske# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
187323adacSDevin Teske# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
197323adacSDevin Teske# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
208e37a7c8SDevin Teske# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
217323adacSDevin Teske# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
227323adacSDevin Teske# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
237323adacSDevin Teske# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
247323adacSDevin Teske# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
257323adacSDevin Teske# SUCH DAMAGE.
267323adacSDevin Teske#
277323adacSDevin Teske# $FreeBSD$
287323adacSDevin Teske#
297323adacSDevin Teske############################################################ INCLUDES
307323adacSDevin Teske
317323adacSDevin TeskeBSDCFG_SHARE="/usr/share/bsdconfig"
327323adacSDevin Teske. $BSDCFG_SHARE/common.subr || exit 1
337323adacSDevin Teskef_dprintf "%s: loading includes..." media/tcpip.subr
347323adacSDevin Teskef_include $BSDCFG_SHARE/device.subr
357323adacSDevin Teskef_include $BSDCFG_SHARE/dialog.subr
36*d4ae33f0SDevin Teskef_include $BSDCFG_SHARE/strings.subr
371de60ff0SDevin Teskef_include $BSDCFG_SHARE/struct.subr
387323adacSDevin Teskef_include $BSDCFG_SHARE/variable.subr
397323adacSDevin Teske
407323adacSDevin TeskeBSDCFG_LIBE="/usr/libexec/bsdconfig"
417323adacSDevin Teskef_include_lang $BSDCFG_LIBE/include/messages.subr
427323adacSDevin Teske
437323adacSDevin TeskeTCP_HELPFILE=$BSDCFG_LIBE/include/tcp.hlp
447323adacSDevin TeskeNETWORK_DEVICE_HELPFILE=$BSDCFG_LIBE/include/network_device.hlp
457323adacSDevin Teske
467323adacSDevin Teske############################################################ GLOBALS
477323adacSDevin Teske
487323adacSDevin Teske#
497323adacSDevin Teske# Path to resolv.conf(5).
507323adacSDevin Teske#
517323adacSDevin Teske: ${RESOLV_CONF:="/etc/resolv.conf"}
527323adacSDevin Teske
537323adacSDevin Teske#
547323adacSDevin Teske# Path to nsswitch.conf(5).
557323adacSDevin Teske#
567323adacSDevin Teske: ${NSSWITCH_CONF:="/etc/nsswitch.conf"}
577323adacSDevin Teske
587323adacSDevin Teske#
597323adacSDevin Teske# Path to hosts(5)
607323adacSDevin Teske#
617323adacSDevin Teske: ${ETC_HOSTS:="/etc/hosts"}
627323adacSDevin Teske
637323adacSDevin Teske#
647323adacSDevin Teske# Structure of dhclient.leases(5) lease { ... } entry
657323adacSDevin Teske#
667323adacSDevin Teskef_struct_define DHCP_LEASE \
677323adacSDevin Teske	interface		\
687323adacSDevin Teske	fixed_address		\
697323adacSDevin Teske	filename		\
707323adacSDevin Teske	server_name		\
717323adacSDevin Teske	script			\
727323adacSDevin Teske	medium			\
737323adacSDevin Teske	host_name		\
747323adacSDevin Teske	subnet_mask		\
757323adacSDevin Teske	routers			\
767323adacSDevin Teske	domain_name_servers	\
777323adacSDevin Teske	domain_name		\
787323adacSDevin Teske	broadcast_address	\
797323adacSDevin Teske	dhcp_lease_time		\
807323adacSDevin Teske	dhcp_message_type	\
817323adacSDevin Teske	dhcp_server_identifier	\
827323adacSDevin Teske	dhcp_renewal_time	\
837323adacSDevin Teske	dhcp_rebinding_time	\
847323adacSDevin Teske	renew			\
857323adacSDevin Teske	rebind			\
867323adacSDevin Teske	expire
877323adacSDevin Teske
887323adacSDevin Teske############################################################ FUNCTIONS
897323adacSDevin Teske
907323adacSDevin Teske# f_validate_hostname $hostname
917323adacSDevin Teske#
927323adacSDevin Teske# Returns zero if the given argument (a fully-qualified hostname) is compliant
937323adacSDevin Teske# with standards set-forth in RFC's 952 and 1123 of the Network Working Group:
947323adacSDevin Teske#
957323adacSDevin Teske# RFC 952 - DoD Internet host table specification
967323adacSDevin Teske# http://tools.ietf.org/html/rfc952
977323adacSDevin Teske#
987323adacSDevin Teske# RFC 1123 - Requirements for Internet Hosts - Application and Support
997323adacSDevin Teske# http://tools.ietf.org/html/rfc1123
1007323adacSDevin Teske#
1017323adacSDevin Teske# See http://en.wikipedia.org/wiki/Hostname for a brief overview.
1027323adacSDevin Teske#
1037323adacSDevin Teske# The return status for invalid hostnames is one of:
1047323adacSDevin Teske# 	255	Entire hostname exceeds the maximum length of 255 characters.
1057323adacSDevin Teske# 	 63	One or more individual labels within the hostname (separated by
1067323adacSDevin Teske# 	   	dots) exceeds the maximum of 63 characters.
1077323adacSDevin Teske# 	  1	One or more individual labels within the hostname contains one
1087323adacSDevin Teske# 	   	or more invalid characters.
1097323adacSDevin Teske# 	  2	One or more individual labels within the hostname starts or
1107323adacSDevin Teske# 	   	ends with a hyphen (hyphens are allowed, but a label cannot
1117323adacSDevin Teske# 	   	begin or end with a hyphen).
1127323adacSDevin Teske# 	  3	One or more individual labels within the hostname are null.
1137323adacSDevin Teske#
114c5f2a20eSDevin Teske# To call this function and display an appropriate error message to the user
115c5f2a20eSDevin Teske# based on the above error codes, use the following function defined in
116c5f2a20eSDevin Teske# dialog.subr:
1177323adacSDevin Teske#
118c5f2a20eSDevin Teske# 	f_dialog_validate_hostname $hostname
1197323adacSDevin Teske#
1207323adacSDevin Teskef_validate_hostname()
1217323adacSDevin Teske{
1227323adacSDevin Teske	local fqhn="$1"
1237323adacSDevin Teske
1247323adacSDevin Teske	# Return error if the hostname exceeds 255 characters
1257323adacSDevin Teske	[ ${#fqhn} -gt 255 ] && return 255
1267323adacSDevin Teske
1277323adacSDevin Teske	local IFS="." # Split on `dot'
1287323adacSDevin Teske	for label in $fqhn; do
1297323adacSDevin Teske		# Return error if the label exceeds 63 characters
1307323adacSDevin Teske		[ ${#label} -gt 63 ] && return 63
1317323adacSDevin Teske
1327323adacSDevin Teske		# Return error if the label is null
1337323adacSDevin Teske		[ "$label" ] || return 3
1347323adacSDevin Teske
1357323adacSDevin Teske		# Return error if label begins/ends with dash
1367323adacSDevin Teske		case "$label" in -*|*-) return 2; esac
1377323adacSDevin Teske
1387323adacSDevin Teske		# Return error if the label contains any invalid chars
1397323adacSDevin Teske		case "$label" in *[!0-9a-zA-Z-]*) return 1; esac
1407323adacSDevin Teske	done
1417323adacSDevin Teske
1427323adacSDevin Teske	return $SUCCESS
1437323adacSDevin Teske}
1447323adacSDevin Teske
1457323adacSDevin Teske# f_inet_atoi $ipv4_address [$var_to_set]
1467323adacSDevin Teske#
1477323adacSDevin Teske# Convert an IPv4 address or mask from dotted-quad notation (e.g., `127.0.0.1'
1487323adacSDevin Teske# or `255.255.255.0') to a 32-bit unsigned integer for the purpose of network
1497323adacSDevin Teske# and broadcast calculations. For example, one can validate that two addresses
1507323adacSDevin Teske# are on the same network:
1517323adacSDevin Teske#
1527323adacSDevin Teske# 	f_inet_atoi 1.2.3.4 ip1num
1537323adacSDevin Teske# 	f_inet_atoi 1.2.4.5 ip2num
1547323adacSDevin Teske# 	f_inet_atoi 255.255.0.0 masknum
1557323adacSDevin Teske# 	if [ $(( $ip1num & $masknum )) -eq \
1567323adacSDevin Teske# 	     $(( $ip2num & $masknum )) ]
1577323adacSDevin Teske# 	then
1587323adacSDevin Teske# 		: IP addresses are on same network
1597323adacSDevin Teske# 	fi
1607323adacSDevin Teske#
1617323adacSDevin Teske# See f_validate_ipaddr() below for an additional example usage, on calculating
1627323adacSDevin Teske# network and broadcast addresses.
1637323adacSDevin Teske#
1647323adacSDevin Teske# If $var_to_set is missing or NULL, the converted IP address is printed to
1657323adacSDevin Teske# standard output for capturing in a sub-shell (which is less-recommended
1667323adacSDevin Teske# because of performance degredation; for example, when called in a loop).
1677323adacSDevin Teske#
1687323adacSDevin Teskef_inet_atoi()
1697323adacSDevin Teske{
1707323adacSDevin Teske	local __addr="$1" __var_to_set="$2" __num=0
1717323adacSDevin Teske	if f_validate_ipaddr "$__addr"; then
172*d4ae33f0SDevin Teske		IFS=.
173*d4ae33f0SDevin Teske		set -- $__addr
174*d4ae33f0SDevin Teske		__num=$(( ($1 << 24) + ($2 << 16) + ($3 << 8) + $4 ))
1757323adacSDevin Teske	fi
1767323adacSDevin Teske	if [ "$__var_to_set" ]; then
1777323adacSDevin Teske		setvar "$__var_to_set" $__num
1787323adacSDevin Teske	else
1797323adacSDevin Teske		echo $__num
1807323adacSDevin Teske	fi
1817323adacSDevin Teske}
1827323adacSDevin Teske
1837323adacSDevin Teske# f_validate_ipaddr $ipaddr [$netmask]
1847323adacSDevin Teske#
1857323adacSDevin Teske# Returns zero if the given argument (an IP address) is of the proper format.
1867323adacSDevin Teske#
1877323adacSDevin Teske# The return status for invalid IP address is one of:
1887323adacSDevin Teske# 	1	One or more individual octets within the IP address (separated
1897323adacSDevin Teske# 	 	by dots) contains one or more invalid characters.
1907323adacSDevin Teske# 	2	One or more individual octets within the IP address are null
1917323adacSDevin Teske# 	 	and/or missing.
1927323adacSDevin Teske# 	3	One or more individual octets within the IP address exceeds the
1937323adacSDevin Teske# 	 	maximum of 255 (or 2^8, being an octet comprised of 8 bits).
1947323adacSDevin Teske# 	4	The IP address has either too few or too many octets.
1957323adacSDevin Teske#
1967323adacSDevin Teske# If a netmask is provided, the IP address is checked further:
1977323adacSDevin Teske#
1987323adacSDevin Teske# 	5	The IP address must not be the network or broadcast address.
1997323adacSDevin Teske#
2007323adacSDevin Teskef_validate_ipaddr()
2017323adacSDevin Teske{
2027323adacSDevin Teske	local ip="$1" mask="$2"
2037323adacSDevin Teske
2047323adacSDevin Teske	# Track number of octets for error checking
2057323adacSDevin Teske	local noctets=0
2067323adacSDevin Teske
2077323adacSDevin Teske	local oldIFS="$IFS"
2087323adacSDevin Teske	local IFS="." # Split on `dot'
2097323adacSDevin Teske	for octet in $ip; do
2107323adacSDevin Teske		# Return error if the octet is null
2117323adacSDevin Teske		[ "$octet" ] || return 2
2127323adacSDevin Teske
2137323adacSDevin Teske		# Return error if not a whole integer
2147323adacSDevin Teske		f_isinteger "$octet" || return 1
2157323adacSDevin Teske
2167323adacSDevin Teske		# Return error if not a positive integer
2177323adacSDevin Teske		[ $octet -ge 0 ] || return 1
2187323adacSDevin Teske
2197323adacSDevin Teske		# Return error if the octet exceeds 255
2207323adacSDevin Teske		[ $octet -gt 255 ] && return 3
2217323adacSDevin Teske
2227323adacSDevin Teske		noctets=$(( $noctets + 1 ))
2237323adacSDevin Teske	done
2247323adacSDevin Teske	IFS="$oldIFS"
2257323adacSDevin Teske
2267323adacSDevin Teske	[ $noctets -eq 4 ] || return 4
2277323adacSDevin Teske
2287323adacSDevin Teske	#
2297323adacSDevin Teske	# The IP address must not be network or broadcast address.
2307323adacSDevin Teske	#
2317323adacSDevin Teske	if [ "$mask" ]; then
2327323adacSDevin Teske		local ipnum masknum netnum bcastnum
2337323adacSDevin Teske		local max_addr=4294967295 # 255.255.255.255
2347323adacSDevin Teske
2357323adacSDevin Teske		f_inet_atoi $ip ipnum
2367323adacSDevin Teske		f_inet_atoi $mask masknum
2377323adacSDevin Teske
2387323adacSDevin Teske		netnum=$(( $ipnum & $masknum ))
2397323adacSDevin Teske		bcastnum=$(( ($ipnum & $masknum)+$max_addr-$masknum ))
2407323adacSDevin Teske
2417323adacSDevin Teske		if [ "$masknum" ] &&
2427323adacSDevin Teske		   [ $ipnum -eq $netnum -o $ipnum -eq $bcastnum ]
2437323adacSDevin Teske		then
2447323adacSDevin Teske			return 5
2457323adacSDevin Teske		fi
2467323adacSDevin Teske	fi
2477323adacSDevin Teske
2487323adacSDevin Teske	return $SUCCESS
2497323adacSDevin Teske}
2507323adacSDevin Teske
2517323adacSDevin Teske# f_validate_ipaddr6 $ipv6_addr
2527323adacSDevin Teske#
2537323adacSDevin Teske# Returns zero if the given argument (an IPv6 address) is of the proper format.
2547323adacSDevin Teske#
2557323adacSDevin Teske# The return status for invalid IP address is one of:
2567323adacSDevin Teske# 	1	One or more individual segments within the IP address
2577323adacSDevin Teske# 	 	(separated by colons) contains one or more invalid characters.
2587323adacSDevin Teske# 	 	Segments must contain only combinations of the characters 0-9,
2597323adacSDevin Teske# 	 	A-F, or a-f.
2607323adacSDevin Teske# 	2	Too many/incorrect null segments. A single null segment is
2617323adacSDevin Teske# 	 	allowed within the IP address (separated by colons) but not
2627323adacSDevin Teske# 	 	allowed at the beginning or end (unless a double-null segment;
2637323adacSDevin Teske# 	 	i.e., "::*" or "*::").
2647323adacSDevin Teske# 	3	One or more individual segments within the IP address
2657323adacSDevin Teske# 	 	(separated by colons) exceeds the length of 4 hex-digits.
2667323adacSDevin Teske# 	4	The IP address entered has either too few (less than 3), too
2677323adacSDevin Teske# 	 	many (more than 8), or not enough segments, separated by
2687323adacSDevin Teske# 	 	colons.
2697323adacSDevin Teske# 	5*	The IPv4 address at the end of the IPv6 address is invalid.
2707323adacSDevin Teske# 	*	When there is an error with the dotted-quad IPv4 address at the
2717323adacSDevin Teske# 	 	end of the IPv6 address, the return value of 5 is OR'd with a
2727323adacSDevin Teske# 	 	bit-shifted (<< 4) return of f_validate_ipaddr.
2737323adacSDevin Teske#
2747323adacSDevin Teskef_validate_ipaddr6()
2757323adacSDevin Teske{
2767323adacSDevin Teske	local ip="${1%\%*}" # removing the interface specification if-present
2777323adacSDevin Teske
2787323adacSDevin Teske	local IFS=":" # Split on `colon'
2797323adacSDevin Teske	set -- $ip:
2807323adacSDevin Teske
2817323adacSDevin Teske	# Return error if too many or too few segments
2827323adacSDevin Teske	# Using 9 as max in case of leading or trailing null spanner
2837323adacSDevin Teske	[ $# -gt 9 -o $# -lt 3 ] && return 4
2847323adacSDevin Teske
2857323adacSDevin Teske	local h="[0-9A-Fa-f]"
2867323adacSDevin Teske	local nulls=0 nsegments=$# contains_ipv4_segment=
2877323adacSDevin Teske
2887323adacSDevin Teske	while [ $# -gt 0 ]; do
2897323adacSDevin Teske
2907323adacSDevin Teske		segment="${1%:}"
2917323adacSDevin Teske		shift
2927323adacSDevin Teske
2937323adacSDevin Teske		#
2947323adacSDevin Teske		# Return error if this segment makes one null too-many. A
2957323adacSDevin Teske		# single null segment is allowed anywhere in the middle as well
2967323adacSDevin Teske		# as double null segments are allowed at the beginning or end
2977323adacSDevin Teske		# (but not both).
2987323adacSDevin Teske		#
2997323adacSDevin Teske		if [ ! "$segment" ]; then
3007323adacSDevin Teske			nulls=$(( $nulls + 1 ))
3017323adacSDevin Teske			if [ $nulls -eq 3 ]; then
3027323adacSDevin Teske				# Only valid syntax for 3 nulls is `::'
3037323adacSDevin Teske				[ "$ip" = "::" ] || return 2
3047323adacSDevin Teske			elif [ $nulls -eq 2 ]; then
3057323adacSDevin Teske				# Only valid if begins/ends with `::'
3067323adacSDevin Teske				case "$ip" in
3077323adacSDevin Teske				::*|*::) : fall thru ;;
3087323adacSDevin Teske				*) return 2
3097323adacSDevin Teske				esac
3107323adacSDevin Teske			fi
3117323adacSDevin Teske			continue
3127323adacSDevin Teske		fi
3137323adacSDevin Teske
3147323adacSDevin Teske		#
3157323adacSDevin Teske		# Return error if not a valid hexadecimal short
3167323adacSDevin Teske		#
3177323adacSDevin Teske		case "$segment" in
3187323adacSDevin Teske		$h|$h$h|$h$h$h|$h$h$h$h)
3197323adacSDevin Teske			: valid segment of 1-4 hexadecimal digits
3207323adacSDevin Teske			;;
3217323adacSDevin Teske		*[!0-9A-Fa-f]*)
3227323adacSDevin Teske			# Segment contains at least one invalid char
3237323adacSDevin Teske
3247323adacSDevin Teske			# Return error immediately if not last segment
3257323adacSDevin Teske			[ $# -eq 0 ] || return 1
3267323adacSDevin Teske
3277323adacSDevin Teske			# Otherwise, check for legacy IPv4 notation
3287323adacSDevin Teske			case "$segment" in
3297323adacSDevin Teske			*[!0-9.]*)
3307323adacSDevin Teske				# Segment contains at least one invalid
3317323adacSDevin Teske				# character even for an IPv4 address
3327323adacSDevin Teske				return 1
3337323adacSDevin Teske			esac
3347323adacSDevin Teske
3357323adacSDevin Teske			# Return error if not enough segments
3367323adacSDevin Teske			if [ $nulls -eq 0 ]; then
3377323adacSDevin Teske				[ $nsegments -eq 7 ] || return 4
3387323adacSDevin Teske			fi
3397323adacSDevin Teske
3407323adacSDevin Teske			contains_ipv4_segment=1
3417323adacSDevin Teske
3427323adacSDevin Teske			# Validate the IPv4 address
3437323adacSDevin Teske			f_validate_ipaddr "$segment" ||
3447323adacSDevin Teske				return $(( 5 | $? << 4 ))
3457323adacSDevin Teske			;;
3467323adacSDevin Teske		*)
3477323adacSDevin Teske			# Segment characters are all valid but too many
3487323adacSDevin Teske			return 3
3497323adacSDevin Teske		esac
3507323adacSDevin Teske
3517323adacSDevin Teske	done
3527323adacSDevin Teske
3537323adacSDevin Teske	if [ $nulls -eq 1 ]; then
3547323adacSDevin Teske		# Single null segment cannot be at beginning/end
3557323adacSDevin Teske		case "$ip" in
3567323adacSDevin Teske		:*|*:) return 2
3577323adacSDevin Teske		esac
3587323adacSDevin Teske	fi
3597323adacSDevin Teske
3607323adacSDevin Teske	#
3617323adacSDevin Teske	# A legacy IPv4 address can span the last two 16-bit segments,
3627323adacSDevin Teske	# reducing the amount of maximum allowable segments by-one.
3637323adacSDevin Teske	#
3647323adacSDevin Teske	maxsegments=8
3657323adacSDevin Teske	if [ "$contains_ipv4_segment" ]; then
3667323adacSDevin Teske		maxsegments=7
3677323adacSDevin Teske	fi
3687323adacSDevin Teske
3697323adacSDevin Teske	case $nulls in
3707323adacSDevin Teske	# Return error if missing segments with no null spanner
3717323adacSDevin Teske	0) [ $nsegments -eq $maxsegments ] || return 4 ;;
3727323adacSDevin Teske	# Return error if null spanner with too many segments
3737323adacSDevin Teske	1) [ $nsegments -le $maxsegments ] || return 4 ;;
3747323adacSDevin Teske	# Return error if leading/trailing `::' with too many segments
3757323adacSDevin Teske	2) [ $nsegments -le $(( $maxsegments + 1 )) ] || return 4 ;;
3767323adacSDevin Teske	esac
3777323adacSDevin Teske
3787323adacSDevin Teske	return $SUCCESS
3797323adacSDevin Teske}
3807323adacSDevin Teske
3817323adacSDevin Teske# f_validate_netmask $netmask
3827323adacSDevin Teske#
3837323adacSDevin Teske# Returns zero if the given argument (a subnet mask) is of the proper format.
3847323adacSDevin Teske#
3857323adacSDevin Teske# The return status for invalid netmask is one of:
3867323adacSDevin Teske# 	1	One or more individual fields within the subnet mask (separated
3877323adacSDevin Teske# 	 	by dots) contains one or more invalid characters.
3887323adacSDevin Teske# 	2	One or more individual fields within the subnet mask are null
3897323adacSDevin Teske# 	 	and/or missing.
3907323adacSDevin Teske# 	3	One or more individual fields within the subnet mask exceeds
3917323adacSDevin Teske# 	 	the maximum of 255 (a full 8-bit register).
3927323adacSDevin Teske# 	4	The subnet mask has either too few or too many fields.
3937323adacSDevin Teske# 	5	One or more individual fields within the subnet mask is an
3947323adacSDevin Teske# 	 	invalid integer (only 0,128,192,224,240,248,252,254,255 are
3957323adacSDevin Teske# 	 	valid integers).
3967323adacSDevin Teske#
3977323adacSDevin Teskef_validate_netmask()
3987323adacSDevin Teske{
3997323adacSDevin Teske	local mask="$1"
4007323adacSDevin Teske
4017323adacSDevin Teske	# Track number of fields for error checking
4027323adacSDevin Teske	local nfields=0
4037323adacSDevin Teske
4047323adacSDevin Teske	local IFS="." # Split on `dot'
4057323adacSDevin Teske	for field in $mask; do
4067323adacSDevin Teske		# Return error if the field is null
4077323adacSDevin Teske		[ "$field" ] || return 2
4087323adacSDevin Teske
4097323adacSDevin Teske		# Return error if not a whole positive integer
4107323adacSDevin Teske		f_isinteger "$field" || return 1
4117323adacSDevin Teske
4127323adacSDevin Teske		# Return error if the field exceeds 255
4137323adacSDevin Teske		[ $field -gt 255 ] && return 3
4147323adacSDevin Teske
4157323adacSDevin Teske		# Return error if the field is an invalid integer
4167323adacSDevin Teske		case "$field" in
4177323adacSDevin Teske		0|128|192|224|240|248|252|254|255) : ;;
4187323adacSDevin Teske		*) return 5 ;;
4197323adacSDevin Teske		esac
4207323adacSDevin Teske
4217323adacSDevin Teske		nfields=$(( $nfields + 1 ))
4227323adacSDevin Teske	done
4237323adacSDevin Teske
4247323adacSDevin Teske	[ $nfields -eq 4 ] || return 4
4257323adacSDevin Teske}
4267323adacSDevin Teske
4277323adacSDevin Teske# f_validate_gateway $gateway $ipaddr $netmask
4287323adacSDevin Teske#
4297323adacSDevin Teske# Validate an IPv4 default gateway (aka router) address for a given IP address
4307323adacSDevin Teske# making sure the two are in the same network (able to ``talk'' to each other).
4317323adacSDevin Teske# Returns success if $ipaddr and $gateway are in the same network given subnet
4327323adacSDevin Teske# mask $netmask.
4337323adacSDevin Teske#
4347323adacSDevin Teskef_validate_gateway()
4357323adacSDevin Teske{
4367323adacSDevin Teske	local gateway="$1" ipaddr="$2" netmask="$3"
4377323adacSDevin Teske	local gwnum ipnum masknum
4387323adacSDevin Teske
4397323adacSDevin Teske	f_validate_ipaddr "$gateway" "$netmask" || return $FAILURE
4407323adacSDevin Teske
4417323adacSDevin Teske	f_inet_atoi "$netmask" masknum
4427323adacSDevin Teske	f_inet_atoi "$ipaddr"  ipnum
4437323adacSDevin Teske	f_inet_atoi "$gateway" gwnum
4447323adacSDevin Teske
4457323adacSDevin Teske	# Gateway must be within set of IPs reachable through interface
4467323adacSDevin Teske	[ $(( $ipnum & $masknum )) -eq \
4477323adacSDevin Teske	  $(( $gwnum & $masknum )) ] # Return status
4487323adacSDevin Teske}
4497323adacSDevin Teske
4507323adacSDevin Teske# f_dialog_validate_tcpip $hostname $gateway $nameserver $ipaddr $netmask
4517323adacSDevin Teske#
4527323adacSDevin Teske# Returns success if the arguments provided are valid for accessing a TCP/IP
4537323adacSDevin Teske# network, otherwise returns failure.
4547323adacSDevin Teske#
4557323adacSDevin Teskef_dialog_validate_tcpip()
4567323adacSDevin Teske{
4577323adacSDevin Teske	local hostname="$1" gateway="$2" nameserver="$3"
4587323adacSDevin Teske	local ipaddr="$4" netmask="$5"
4597323adacSDevin Teske	local ipnum masknum
4607323adacSDevin Teske
4617323adacSDevin Teske	if [ ! "$hostname" ]; then
4627079fc4eSDevin Teske		f_show_msg "$msg_must_specify_a_host_name_of_some_sort"
4637323adacSDevin Teske	elif ! f_validate_hostname "$hostname"; then
4647079fc4eSDevin Teske		f_show_msg "$msg_invalid_hostname_value"
4657323adacSDevin Teske	elif [ "$netmask" ] && ! f_validate_netmask "$netmask"; then
4667079fc4eSDevin Teske		f_show_msg "$msg_invalid_netmask_value"
4677323adacSDevin Teske	elif [ "$nameserver" ] &&
4687323adacSDevin Teske	     ! f_validate_ipaddr "$nameserver" &&
4697323adacSDevin Teske	     ! f_validate_ipaddr6 "$nameserver"; then
4707079fc4eSDevin Teske		f_show_msg "$msg_invalid_name_server_ip_address_specified"
4717323adacSDevin Teske	elif [ "$ipaddr" ] && ! f_validate_ipaddr "$ipaddr" "$netmask"; then
4727079fc4eSDevin Teske		f_show_msg "$msg_invalid_ipv4_address"
4737323adacSDevin Teske	elif [ "$gateway" -a "$gateway" != "NO" ] &&
4747323adacSDevin Teske	     ! f_validate_gateway "$gateway" "$ipaddr" "$netmask"; then
4757079fc4eSDevin Teske		f_show_msg "$msg_invalid_gateway_ipv4_address_specified"
4767323adacSDevin Teske	else
477f677a9e2SDevin Teske		return $DIALOG_OK
4787323adacSDevin Teske	fi
4797323adacSDevin Teske
480f677a9e2SDevin Teske	return $DIALOG_CANCEL
4817323adacSDevin Teske}
4827323adacSDevin Teske
4837323adacSDevin Teske# f_ifconfig_inet $interface [$var_to_set]
4847323adacSDevin Teske#
4857323adacSDevin Teske# Returns the IPv4 address associated with $interface. If $var_to_set is
4867323adacSDevin Teske# missing or NULL, the IP address is printed to standard output for capturing
4877323adacSDevin Teske# in a sub-shell (which is less-recommended because of performance degredation;
4887323adacSDevin Teske# for example, when called in a loop).
4897323adacSDevin Teske#
4907323adacSDevin Teske# This function is a two-parter. Below is the awk(1) portion of the function,
4917323adacSDevin Teske# afterward is the sh(1) function which utilizes the below awk script.
4927323adacSDevin Teske#
4937323adacSDevin Teskef_ifconfig_inet_awk='
4947323adacSDevin TeskeBEGIN { found = 0 }
4957323adacSDevin Teske( $1 == "inet" ) \
4967323adacSDevin Teske{
4977323adacSDevin Teske	print $2
4987323adacSDevin Teske	found = 1
4997323adacSDevin Teske	exit
5007323adacSDevin Teske}
5017323adacSDevin TeskeEND { exit ! found }
5027323adacSDevin Teske'
5037323adacSDevin Teskef_ifconfig_inet()
5047323adacSDevin Teske{
5057323adacSDevin Teske	local __interface="$1" __var_to_set="$2"
5067323adacSDevin Teske	if [ "$__var_to_set" ]; then
5077323adacSDevin Teske		local __ip
5087323adacSDevin Teske		__ip=$( ifconfig "$__interface" 2> /dev/null |
5097323adacSDevin Teske			awk "$f_ifconfig_inet_awk" )
5107323adacSDevin Teske		setvar "$__var_to_set" "$__ip"
5117323adacSDevin Teske	else
5127323adacSDevin Teske		ifconfig "$__interface" 2> /dev/null |
5137323adacSDevin Teske			awk "$f_ifconfig_inet_awk"
5147323adacSDevin Teske	fi
5157323adacSDevin Teske}
5167323adacSDevin Teske
5177323adacSDevin Teske# f_ifconfig_inet6 $interface [$var_to_set]
5187323adacSDevin Teske#
5197323adacSDevin Teske# Returns the IPv6 address associated with $interface. If $var_to_set is
5207323adacSDevin Teske# missing or NULL, the IP address is printed to standard output for capturing
5217323adacSDevin Teske# in a sub-shell (which is less-recommended because of performance degredation;
5227323adacSDevin Teske# for example, when called in a loop).
5237323adacSDevin Teske#
5247323adacSDevin Teske# This function is a two-parter. Below is the awk(1) portion of the function,
5257323adacSDevin Teske# afterward is the sh(1) function which utilizes the below awk script.
5267323adacSDevin Teske#
5277323adacSDevin Teskef_ifconfig_inet6_awk='
5287323adacSDevin TeskeBEGIN { found = 0 }
5297323adacSDevin Teske( $1 == "inet6" ) \
5307323adacSDevin Teske{
5317323adacSDevin Teske	print $2
5327323adacSDevin Teske	found = 1
5337323adacSDevin Teske	exit
5347323adacSDevin Teske}
5357323adacSDevin TeskeEND { exit ! found }
5367323adacSDevin Teske'
5377323adacSDevin Teskef_ifconfig_inet6()
5387323adacSDevin Teske{
5397323adacSDevin Teske	local __interface="$1" __var_to_set="$2"
5407323adacSDevin Teske	if [ "$__var_to_set" ]; then
5417323adacSDevin Teske		local __ip6
5427323adacSDevin Teske		__ip6=$( ifconfig "$__interface" 2> /dev/null |
5437323adacSDevin Teske			awk "$f_ifconfig_inet6_awk" )
5447323adacSDevin Teske		setvar "$__var_to_set" "$__ip6"
5457323adacSDevin Teske	else
5467323adacSDevin Teske		ifconfig "$__interface" 2> /dev/null |
5477323adacSDevin Teske			awk "$f_ifconfig_inet6_awk"
5487323adacSDevin Teske	fi
5497323adacSDevin Teske}
5507323adacSDevin Teske
5517323adacSDevin Teske# f_ifconfig_netmask $interface [$var_to_set]
5527323adacSDevin Teske#
5537323adacSDevin Teske# Returns the IPv4 subnet mask associated with $interface. If $var_to_set is
5547323adacSDevin Teske# missing or NULL, the netmask is printed to standard output for capturing in a
5557323adacSDevin Teske# sub-shell (which is less-recommended because of performance degredation; for
5567323adacSDevin Teske# example, when called in a loop).
5577323adacSDevin Teske#
5587323adacSDevin Teskef_ifconfig_netmask()
5597323adacSDevin Teske{
5607323adacSDevin Teske	local __interface="$1" __var_to_set="$2" __octets
5617323adacSDevin Teske	__octets=$( ifconfig "$__interface" 2> /dev/null | awk \
5627323adacSDevin Teske	'
5637323adacSDevin Teske		BEGIN { found = 0 }
5647323adacSDevin Teske		( $1 == "inet" ) \
5657323adacSDevin Teske		{
5667323adacSDevin Teske			printf "%s %s %s %s\n",
5677323adacSDevin Teske				substr($4,3,2),
5687323adacSDevin Teske				substr($4,5,2),
5697323adacSDevin Teske				substr($4,7,2),
5707323adacSDevin Teske				substr($4,9,2)
5717323adacSDevin Teske			found = 1
5727323adacSDevin Teske			exit
5737323adacSDevin Teske		}
5747323adacSDevin Teske		END { exit ! found }
5757323adacSDevin Teske	' ) || return $FAILURE
5767323adacSDevin Teske
5777323adacSDevin Teske	local __octet __netmask=
5787323adacSDevin Teske	for __octet in $__octets; do
579*d4ae33f0SDevin Teske		f_sprintf __netmask "%s.%u" "$__netmask" "0x$__octet"
5807323adacSDevin Teske	done
5817323adacSDevin Teske	__netmask="${__netmask#.}"
5827323adacSDevin Teske	if [ "$__var_to_set" ]; then
5837323adacSDevin Teske		setvar "$__var_to_set" "$__netmask"
5847323adacSDevin Teske	else
5857323adacSDevin Teske		echo $__netmask
5867323adacSDevin Teske	fi
5877323adacSDevin Teske}
5887323adacSDevin Teske
5897323adacSDevin Teske# f_route_get_default [$var_to_set]
5907323adacSDevin Teske#
5917323adacSDevin Teske# Returns the IP address of the currently active default router. If $var_to_set
5927323adacSDevin Teske# is missing or NULL, the IP address is printed to standard output for
5937323adacSDevin Teske# capturing in a sub-shell (which is less-recommended because of performance
5947323adacSDevin Teske# degredation; for example, when called in a loop).
5957323adacSDevin Teske#
5967323adacSDevin Teske# This function is a two-parter. Below is the awk(1) portion of the function,
5977323adacSDevin Teske# afterward is the sh(1) function which utilizes the below awk script.
5987323adacSDevin Teske#
599a7408e5cSDevin Teskef_route_get_default_awk='
6007323adacSDevin TeskeBEGIN { found = 0 }
6017323adacSDevin Teske( $1 == "gateway:" ) \
6027323adacSDevin Teske{
6037323adacSDevin Teske	print $2
6047323adacSDevin Teske	found = 1
6057323adacSDevin Teske	exit
6067323adacSDevin Teske}
6077323adacSDevin TeskeEND { exit ! found }
6087323adacSDevin Teske'
6097323adacSDevin Teskef_route_get_default()
6107323adacSDevin Teske{
6117323adacSDevin Teske	local __var_to_set="$1"
6127323adacSDevin Teske	if [ "$__var_to_set" ]; then
6137323adacSDevin Teske		local __ip
6147323adacSDevin Teske		__ip=$( route -n get default 2> /dev/null |
6157323adacSDevin Teske			awk "$f_route_get_default_awk" )
6167323adacSDevin Teske		setvar "$__var_to_set" "$__ip"
6177323adacSDevin Teske	else
6187323adacSDevin Teske		route -n get default 2> /dev/null |
6197323adacSDevin Teske			awk "$f_route_get_default_awk"
6207323adacSDevin Teske	fi
6217323adacSDevin Teske}
6227323adacSDevin Teske
6237323adacSDevin Teske# f_resolv_conf_nameservers [$var_to_set]
6247323adacSDevin Teske#
6257323adacSDevin Teske# Returns nameserver(s) configured in resolv.conf(5). If $var_to_set is missing
6267323adacSDevin Teske# or NULL, the list of nameservers is printed to standard output for capturing
6277323adacSDevin Teske# in a sub-shell (which is less-recommended because of performance degredation;
6287323adacSDevin Teske# for example, when called in a loop).
6297323adacSDevin Teske#
6307323adacSDevin Teske# This function is a two-parter. Below is the awk(1) portion of the function,
6317323adacSDevin Teske# afterward is the sh(1) function which utilizes the below awk script.
6327323adacSDevin Teske#
6337323adacSDevin Teskef_resolv_conf_nameservers_awk='
6347323adacSDevin TeskeBEGIN { found = 0 }
6357323adacSDevin Teske( $1 == "nameserver" ) \
6367323adacSDevin Teske{
6377323adacSDevin Teske	print $2
6387323adacSDevin Teske	found = 1
6397323adacSDevin Teske}
6407323adacSDevin TeskeEND { exit ! found }
6417323adacSDevin Teske'
6427323adacSDevin Teskef_resolv_conf_nameservers()
6437323adacSDevin Teske{
6447323adacSDevin Teske	local __var_to_set="$1"
6457323adacSDevin Teske	if [ "$__var_to_set" ]; then
6467323adacSDevin Teske		local __ns
6477323adacSDevin Teske		__ns=$( awk "$f_resolv_conf_nameservers_awk" "$RESOLV_CONF" \
6487323adacSDevin Teske			2> /dev/null )
6497323adacSDevin Teske		setvar "$__var_to_set" "$__ns"
6507323adacSDevin Teske	else
6517323adacSDevin Teske		awk "$f_resolv_conf_nameservers_awk" "$RESOLV_CONF" \
6527323adacSDevin Teske			2> /dev/null
6537323adacSDevin Teske	fi
6547323adacSDevin Teske}
6557323adacSDevin Teske
6567323adacSDevin Teske# f_config_resolv
6577323adacSDevin Teske#
6587323adacSDevin Teske# Attempts to configure resolv.conf(5) and ilk. Returns success if able to
6597323adacSDevin Teske# write the file(s), otherwise returns error status.
6607323adacSDevin Teske#
6617323adacSDevin Teske# Variables from variable.subr that are used in configuring resolv.conf(5) are
6627323adacSDevin Teske# as follows (all of which can be configured automatically through functions
6637323adacSDevin Teske# like f_dhcp_get_info() or manually):
6647323adacSDevin Teske#
6657323adacSDevin Teske# 	VAR_NAMESERVER
6667323adacSDevin Teske#		The nameserver to add in resolv.conf(5).
6677323adacSDevin Teske# 	VAR_DOMAINNAME
6687323adacSDevin Teske# 		The domain to configure in resolv.conf(5). Also used in the
6697323adacSDevin Teske# 		configuration of hosts(5).
6707323adacSDevin Teske# 	VAR_IPADDR
6717323adacSDevin Teske# 		The IPv4 address to configure in hosts(5).
6727323adacSDevin Teske# 	VAR_IPV6ADDR
6737323adacSDevin Teske# 		The IPv6 address to configure in hosts(5).
6747323adacSDevin Teske# 	VAR_HOSTNAME
6757323adacSDevin Teske# 		The hostname to associate with the IPv4 and/or IPv6 address in
6767323adacSDevin Teske# 		hosts(5).
6777323adacSDevin Teske#
6787323adacSDevin Teskef_config_resolv()
6797323adacSDevin Teske{
6807323adacSDevin Teske	local cp c6p dp hp
6817323adacSDevin Teske
6827323adacSDevin Teske	f_getvar $VAR_NAMESERVER cp
6837323adacSDevin Teske	if [ "$cp" ]; then
6847323adacSDevin Teske		case "$RESOLV_CONF" in
6857323adacSDevin Teske		*/*) f_quietly mkdir -p "${RESOLV_CONF%/*}" ;;
6867323adacSDevin Teske		esac
6877323adacSDevin Teske
6887323adacSDevin Teske		# Attempt to create/truncate the file
6897323adacSDevin Teske		( :> "$RESOLV_CONF" ) 2> /dev/null || return $FAILURE
6907323adacSDevin Teske
6917323adacSDevin Teske		f_getvar $VAR_DOMAINNAME dp &&
6927323adacSDevin Teske			printf "domain\t%s\n" "$dp" >> "$RESOLV_CONF"
6937323adacSDevin Teske		printf "nameserver\t%s\n" "$cp" >> "$RESOLV_CONF"
6947323adacSDevin Teske
6957323adacSDevin Teske		f_dprintf "Wrote out %s" "$RESOLV_CONF"
6967323adacSDevin Teske	fi
6977323adacSDevin Teske
6987323adacSDevin Teske	f_getvar $VAR_DOMAINNAME dp
6997323adacSDevin Teske	f_getvar $VAR_IPADDR cp
7007323adacSDevin Teske	f_getvar $VAR_IPV6ADDR c6p
7017323adacSDevin Teske	f_getvar $VAR_HOSTNAME hp
7027323adacSDevin Teske
7037323adacSDevin Teske	# Attempt to create the file if it doesn't already exist
7047323adacSDevin Teske	if [ ! -e "$ETC_HOSTS" ]; then
7057323adacSDevin Teske		case "$ETC_HOSTS" in
7067323adacSDevin Teske		*/*) f_quietly mkdir -p "${ETC_HOSTS%/*}" ;;
7077323adacSDevin Teske		esac
7087323adacSDevin Teske
7097323adacSDevin Teske		( :> "$ETC_HOSTS" ) 2> /dev/null || return $FAILURE
7107323adacSDevin Teske	fi
7117323adacSDevin Teske
7127323adacSDevin Teske	# Scan the file and add ourselves if not already configured
7137323adacSDevin Teske	awk -v dn="$dp" -v ip4="$cp" -v ip6="$c6p" -v hn="$hp" '
7147323adacSDevin Teske		BEGIN {
7157323adacSDevin Teske			local4found = local6found = 0
7167323adacSDevin Teske			hn4found = hn6found = h4found = h6found = 0
7177323adacSDevin Teske			h = ( match(hn, /\./) ? substr(hn, 0, RSTART-1) : "" )
7187323adacSDevin Teske		}
7197323adacSDevin Teske		($1 == "127.0.0.1") { local4found = 1 }
7207323adacSDevin Teske		($1 == "::1") { local6found = 1 }
7217323adacSDevin Teske		{
7227323adacSDevin Teske			for (n = 2; n <= NF; n++)
7237323adacSDevin Teske			{
7247323adacSDevin Teske				if ( $1 == ip4 ) {
7257323adacSDevin Teske					if ( $n == h ) h4found = 1
7267323adacSDevin Teske					if ( $n == hn ) hn4found = 1
7277323adacSDevin Teske					if ( $n == hn "." ) hn4found = 1
7287323adacSDevin Teske				}
7297323adacSDevin Teske				if ( $1 == ip6 ) {
7307323adacSDevin Teske					if ( $n == h ) h6found = 1
7317323adacSDevin Teske					if ( $n == hn ) hn6found = 1
7327323adacSDevin Teske					if ( $n == hn "." ) hn6found = 1
7337323adacSDevin Teske				}
7347323adacSDevin Teske			}
7357323adacSDevin Teske		}
7367323adacSDevin Teske		END {
7377323adacSDevin Teske			hosts = FILENAME
7387323adacSDevin Teske
7397323adacSDevin Teske			if ( ! local6found )
7407323adacSDevin Teske				printf "::1\t\t\tlocalhost%s\n",
7417323adacSDevin Teske				       ( dn ? " localhost." dn : "" ) >> hosts
7427323adacSDevin Teske			if ( ! local4found )
7437323adacSDevin Teske				printf "127.0.0.1\t\tlocalhost%s\n",
7447323adacSDevin Teske				       ( dn ? " localhost." dn : "" ) >> hosts
7457323adacSDevin Teske
7467323adacSDevin Teske			if ( ip6 && ! (h6found && hn6found))
7477323adacSDevin Teske			{
7487323adacSDevin Teske				printf "%s\t%s %s\n", ip6, hn, h >> hosts
7497323adacSDevin Teske				printf "%s\t%s.\n", ip6, hn >> hosts
7507323adacSDevin Teske			}
7517323adacSDevin Teske			else if ( ip6 )
7527323adacSDevin Teske			{
7537323adacSDevin Teske				if ( ! h6found )
7547323adacSDevin Teske					printf "%s\t%s.\n", ip6, h >> hosts
7557323adacSDevin Teske				if ( ! hn6found )
7567323adacSDevin Teske					printf "%s\t%s\n", ip6, hn >> hosts
7577323adacSDevin Teske			}
7587323adacSDevin Teske
7597323adacSDevin Teske			if ( ip4 && ! (h4found && hn4found))
7607323adacSDevin Teske			{
7617323adacSDevin Teske				printf "%s\t\t%s %s\n", ip4, hn, h >> hosts
7627323adacSDevin Teske				printf "%s\t\t%s.\n", ip4, hn >> hosts
7637323adacSDevin Teske			}
7647323adacSDevin Teske			else if ( ip4 )
7657323adacSDevin Teske			{
7667323adacSDevin Teske				if ( ! h4found )
7677323adacSDevin Teske					printf "%s\t\t%s.\n", ip4, h >> hosts
7687323adacSDevin Teske				if ( ! hn4found )
7697323adacSDevin Teske					printf "%s\t\t%s\n", ip4, hn >> hosts
7707323adacSDevin Teske			}
7717323adacSDevin Teske		}
7727323adacSDevin Teske	' "$ETC_HOSTS" 2> /dev/null || return $FAILURE
7737323adacSDevin Teske
7747323adacSDevin Teske	f_dprintf "Wrote out %s" "$ETC_HOSTS"
7757323adacSDevin Teske	return $SUCCESS
7767323adacSDevin Teske}
7777323adacSDevin Teske
7787323adacSDevin Teske# f_dhcp_parse_leases $leasefile struct_name
7797323adacSDevin Teske#
7807323adacSDevin Teske# Parse $leasefile and store the information for the most recent lease in a
7817323adacSDevin Teske# struct (see struct.subr for additional details) named `struct_name'. See
7827323adacSDevin Teske# DHCP_LEASE struct definition in the GLOBALS section above.
7837323adacSDevin Teske#
7847323adacSDevin Teskef_dhcp_parse_leases()
7857323adacSDevin Teske{
7867323adacSDevin Teske	local leasefile="$1" struct_name="$2"
7877323adacSDevin Teske
7887323adacSDevin Teske	[ "$struct_name" ] || return $FAILURE
7897323adacSDevin Teske
7907323adacSDevin Teske	if [ ! -e "$leasefile" ]; then
7917323adacSDevin Teske		f_dprintf "%s: No such file or directory" "$leasefile"
7927323adacSDevin Teske		return $FAILURE
7937323adacSDevin Teske	fi
7947323adacSDevin Teske
7957323adacSDevin Teske	f_struct "$struct_name" && f_struct_free "$struct_name"
7967323adacSDevin Teske	f_struct_new DHCP_LEASE "$struct_name"
7977323adacSDevin Teske
7987323adacSDevin Teske	eval "$( awk -v struct="$struct_name" '
7997323adacSDevin Teske		BEGIN {
8007323adacSDevin Teske			lease_found = 0
8017323adacSDevin Teske			keyword_list = " \
8027323adacSDevin Teske				interface	\
8037323adacSDevin Teske				fixed-address	\
8047323adacSDevin Teske				filename	\
8057323adacSDevin Teske				server-name	\
8067323adacSDevin Teske				script		\
8077323adacSDevin Teske				medium		\
8087323adacSDevin Teske			"
8097323adacSDevin Teske			split(keyword_list, keywords, FS)
8107323adacSDevin Teske
8117323adacSDevin Teske			time_list = "renew rebind expire"
8127323adacSDevin Teske			split(time_list, times, FS)
8137323adacSDevin Teske
8147323adacSDevin Teske			option_list = " \
8157323adacSDevin Teske				host-name		\
8167323adacSDevin Teske				subnet-mask		\
8177323adacSDevin Teske				routers			\
8187323adacSDevin Teske				domain-name-servers	\
8197323adacSDevin Teske				domain-name		\
8207323adacSDevin Teske				broadcast-address	\
8217323adacSDevin Teske				dhcp-lease-time		\
8227323adacSDevin Teske				dhcp-message-type	\
8237323adacSDevin Teske				dhcp-server-identifier	\
8247323adacSDevin Teske				dhcp-renewal-time	\
8257323adacSDevin Teske				dhcp-rebinding-time	\
8267323adacSDevin Teske			"
8277323adacSDevin Teske			split(option_list, options, FS)
8287323adacSDevin Teske		}
8297323adacSDevin Teske		function set_value(prop,value)
8307323adacSDevin Teske		{
8317323adacSDevin Teske			lease_found = 1
8327323adacSDevin Teske			gsub(/[^[:alnum:]_]/, "_", prop)
8337323adacSDevin Teske			sub(/;$/, "", value)
8347323adacSDevin Teske			sub(/^"/, "", value)
8357323adacSDevin Teske			sub(/"$/, "", value)
8367323adacSDevin Teske			sub(/,.*/, "", value)
8377323adacSDevin Teske			printf "%s set %s \"%s\"\n", struct, prop, value
8387323adacSDevin Teske		}
8397323adacSDevin Teske		/^lease {$/, /^}$/ \
8407323adacSDevin Teske		{
8417323adacSDevin Teske			if ( $0 ~ /^lease {$/ ) next
8427323adacSDevin Teske			if ( $0 ~ /^}$/ ) exit
8437323adacSDevin Teske
8447323adacSDevin Teske			for (k in keywords)
8457323adacSDevin Teske			{
8467323adacSDevin Teske				keyword = keywords[k]
8477323adacSDevin Teske				if ( $1 == keyword )
8487323adacSDevin Teske				{
8497323adacSDevin Teske					set_value(keyword, $2)
8507323adacSDevin Teske					next
8517323adacSDevin Teske				}
8527323adacSDevin Teske			}
8537323adacSDevin Teske
8547323adacSDevin Teske			for (t in times)
8557323adacSDevin Teske			{
8567323adacSDevin Teske				time = times[t]
8577323adacSDevin Teske				if ( $1 == time )
8587323adacSDevin Teske				{
8597323adacSDevin Teske					set_value(time, $2 " " $3 " " $4)
8607323adacSDevin Teske					next
8617323adacSDevin Teske				}
8627323adacSDevin Teske			}
8637323adacSDevin Teske
8647323adacSDevin Teske			if ( $1 != "option" ) next
8657323adacSDevin Teske			for (o in options)
8667323adacSDevin Teske			{
8677323adacSDevin Teske				option = options[o]
8687323adacSDevin Teske				if ( $2 == option )
8697323adacSDevin Teske				{
8707323adacSDevin Teske					set_value(option, $3)
8717323adacSDevin Teske					next
8727323adacSDevin Teske				}
8737323adacSDevin Teske			}
8747323adacSDevin Teske		}
8757323adacSDevin Teske		EXIT {
8767323adacSDevin Teske			if ( ! lease_found )
8777323adacSDevin Teske			{
8787323adacSDevin Teske				printf "f_struct_free \"%s\"\n", struct
8797323adacSDevin Teske				print "return $FAILURE"
8807323adacSDevin Teske			}
8817323adacSDevin Teske		}
8827323adacSDevin Teske	' "$leasefile" )"
8837323adacSDevin Teske}
8847323adacSDevin Teske
8857323adacSDevin Teske# f_dhcp_get_info $interface
8867323adacSDevin Teske#
8877323adacSDevin Teske# Parse the dhclient(8) lease database for $interface to obtain all the
8887323adacSDevin Teske# necessary IPv4 details necessary to communicate on the network. The retrieved
8897323adacSDevin Teske# information is stored in VAR_IPADDR, VAR_NETMASK, VAR_GATEWAY, and
8907323adacSDevin Teske# VAR_NAMESERVER.
8917323adacSDevin Teske#
8927323adacSDevin Teske# If reading the lease database fails, values are obtained from ifconfig(8) and
8937323adacSDevin Teske# route(8). If the DHCP lease did not provide a nameserver (or likewise, we
8947323adacSDevin Teske# were unable to parse the lease database), fall-back to resolv.conf(5) for
8957323adacSDevin Teske# obtaining the nameserver. Always returns success.
8967323adacSDevin Teske#
8977323adacSDevin Teskef_dhcp_get_info()
8987323adacSDevin Teske{
8997323adacSDevin Teske	local interface="$1" cp
9007323adacSDevin Teske	local leasefile="/var/db/dhclient.leases.$interface"
9017323adacSDevin Teske
9027323adacSDevin Teske	# If it fails, do it the old-fashioned way
9037323adacSDevin Teske	if f_dhcp_parse_leases "$leasefile" lease; then
9047323adacSDevin Teske		lease get fixed_address $VAR_IPADDR
9057323adacSDevin Teske		lease get subnet_mask $VAR_NETMASK
9067323adacSDevin Teske		lease get routers cp
9077323adacSDevin Teske		setvar $VAR_GATEWAY "${cp%%,*}"
9087323adacSDevin Teske		lease get domain_name_servers cp
9097323adacSDevin Teske		setvar $VAR_NAMESERVER "${cp%%,*}"
9107323adacSDevin Teske		lease get host_name cp &&
9117323adacSDevin Teske			setvar $VAR_HOSTNAME "$cp"
9127323adacSDevin Teske		f_struct_free lease
9137323adacSDevin Teske	else
9147323adacSDevin Teske		# Bah, now we have to get the information from ifconfig
9157323adacSDevin Teske		if f_debugging; then
9167323adacSDevin Teske			f_dprintf "DHCP configured interface returns %s" \
9177323adacSDevin Teske			          "$( ifconfig "$interface" )"
9187323adacSDevin Teske		fi
9197323adacSDevin Teske		f_ifconfig_inet "$interface" $VAR_IPADDR
9207323adacSDevin Teske		f_ifconfig_netmask "$interface" $VAR_NETMASK
9217323adacSDevin Teske		f_route_get_default $VAR_GATEWAY
9227323adacSDevin Teske	fi
9237323adacSDevin Teske
9247323adacSDevin Teske	# If we didn't get a name server value, hunt for it in resolv.conf
9257323adacSDevin Teske	local ns
9267323adacSDevin Teske	if [ -r "$RESOLV_CONF" ] && ! {
9277323adacSDevin Teske		f_getvar $VAR_NAMESERVER ns || [ "$ns" ]
9287323adacSDevin Teske	}; then
9297323adacSDevin Teske		f_resolv_conf_nameservers cp &&
9307323adacSDevin Teske			setvar $VAR_NAMESERVER ${cp%%[$IFS]*}
9317323adacSDevin Teske	fi
9327323adacSDevin Teske
9337323adacSDevin Teske	return $SUCCESS
9347323adacSDevin Teske}
9357323adacSDevin Teske
9367323adacSDevin Teske# f_rtsol_get_info $interface
9377323adacSDevin Teske#
9387323adacSDevin Teske# Returns the rtsol-provided IPv6 address associated with $interface. The
9397323adacSDevin Teske# retrieved IP address is stored in VAR_IPV6ADDR. Always returns success.
9407323adacSDevin Teske#
9417323adacSDevin Teskef_rtsol_get_info()
9427323adacSDevin Teske{
9437323adacSDevin Teske	local interface="$1" cp
9447323adacSDevin Teske	cp=$( ifconfig "$interface" 2> /dev/null | awk \
9457323adacSDevin Teske	'
9467323adacSDevin Teske		BEGIN { found = 0 }
9477323adacSDevin Teske		( $1 == "inet6" ) && ( $2 ~ /^fe80:/ ) \
9487323adacSDevin Teske		{
9497323adacSDevin Teske			print $2
9507323adacSDevin Teske			found = 1
9517323adacSDevin Teske			exit
9527323adacSDevin Teske		}
9537323adacSDevin Teske		END { exit ! found }
9547323adacSDevin Teske	' ) && setvar $VAR_IPV6ADDR "$cp"
9557323adacSDevin Teske}
9567323adacSDevin Teske
9577323adacSDevin Teske# f_host_lookup $host [$var_to_set]
9587323adacSDevin Teske#
9597323adacSDevin Teske# Use host(1) to lookup (or reverse) an Internet number from (or to) a name.
9607323adacSDevin Teske# Multiple answers are returned separated by a single space. If host(1) does
9617323adacSDevin Teske# not exit cleanly, its full output is provided and the return status is 1.
9627323adacSDevin Teske#
9637323adacSDevin Teske# If nsswitch.conf(5) has been configured to query local access first for the
9647323adacSDevin Teske# `hosts' database, we'll manually check hosts(5) first (preventing host(1)
9657323adacSDevin Teske# from hanging in the event that DNS goes awry).
9667323adacSDevin Teske#
9677323adacSDevin Teske# If $var_to_set is missing or NULL, the list of IP addresses is printed to
9687323adacSDevin Teske# standard output for capturing in a sub-shell (which is less-recommended
9697323adacSDevin Teske# because of performance degredation; for example, when called in a loop).
9707323adacSDevin Teske#
9717323adacSDevin Teske# The variables from variable.subr used in looking up the host are as follows
9727323adacSDevin Teske# (which are set manually):
9737323adacSDevin Teske#
9747323adacSDevin Teske# 	VAR_IPV6_ENABLE [Optional]
9757323adacSDevin Teske# 		If set to "YES", enables the lookup of IPv6 addresses and IPv4
9767323adacSDevin Teske# 		address. IPv6 addresses, if any, will come before IPv4. Note
9777323adacSDevin Teske# 		that if nsswitch.conf(5) shows an affinity for "files" for the
9787323adacSDevin Teske# 		"host" database and there is a valid entry in hosts(5) for
9797323adacSDevin Teske# 		$host, this setting currently has no effect (an IPv4 address
9807323adacSDevin Teske# 		can supersede an IPv6 address). By design, hosts(5) overrides
9817323adacSDevin Teske# 		any preferential treatment. Otherwise, if this variable is not
9827323adacSDevin Teske# 		set, IPv6 addresses will not be used (IPv4 addresses will
9837323adacSDevin Teske# 		specifically be requested from DNS).
9847323adacSDevin Teske#
9857323adacSDevin Teske# This function is a two-parter. Below is the awk(1) portion of the function,
9867323adacSDevin Teske# afterward is the sh(1) function which utilizes the below awk script.
9877323adacSDevin Teske#
9887323adacSDevin Teskef_host_lookup_awk='
9897323adacSDevin TeskeBEGIN{ addrs = "" }
9907323adacSDevin Teske!/^[[:space:]]*(#|$)/ \
9917323adacSDevin Teske{
9927323adacSDevin Teske	for (n=1; n++ < NF;) if ($n == name)
9937323adacSDevin Teske		addrs = addrs (addrs ? " " : "") $1
9947323adacSDevin Teske}
9957323adacSDevin TeskeEND {
9967323adacSDevin Teske	if (addrs) print addrs
9977323adacSDevin Teske	exit !addrs
9987323adacSDevin Teske}
9997323adacSDevin Teske'
10007323adacSDevin Teskef_host_lookup()
10017323adacSDevin Teske{
10027323adacSDevin Teske	local __host="$1" __var_to_set="$2"
10037323adacSDevin Teske	f_dprintf "f_host_lookup: host=[%s]" "$__host"
10047323adacSDevin Teske
10057323adacSDevin Teske	# If we're configured to look at local files first, do that
10067323adacSDevin Teske	if awk '/^hosts:/{exit !($2=="files")}' "$NSSWITCH_CONF"; then
10077323adacSDevin Teske		if [ "$__var_to_set" ]; then
10087323adacSDevin Teske			local __cp
10097323adacSDevin Teske			if __cp=$( awk -v name="$__host" \
10107323adacSDevin Teske				"$f_host_lookup_awk" "$ETC_HOSTS" )
10117323adacSDevin Teske			then
10127323adacSDevin Teske				setvar "$__var_to_set" "$__cp"
10137323adacSDevin Teske				return $SUCCESS
10147323adacSDevin Teske			fi
10157323adacSDevin Teske		else
10167323adacSDevin Teske			awk -v name="$__host" \
10177323adacSDevin Teske				"$f_host_lookup_awk" "$ETC_HOSTS" &&
10187323adacSDevin Teske				return $SUCCESS
10197323adacSDevin Teske		fi
10207323adacSDevin Teske	fi
10217323adacSDevin Teske
10227323adacSDevin Teske	#
10237323adacSDevin Teske	# Fall back to host(1) -- which is further governed by nsswitch.conf(5)
10247323adacSDevin Teske	#
10257323adacSDevin Teske
10264b939b11SDevin Teske	local __output __ip6 __addrs=
10277323adacSDevin Teske	f_getvar $VAR_IPV6_ENABLE __ip6
10284b939b11SDevin Teske
10294b939b11SDevin Teske	# If we have a TCP media type configured, check for an SRV record
10304b939b11SDevin Teske	local __srvtypes=
10314b939b11SDevin Teske	{ f_quietly f_getvar $VAR_HTTP_PATH ||
10324b939b11SDevin Teske	  f_quietly f_getvar $VAR_HTTP_PROXY_PATH
10334b939b11SDevin Teske	} && __srvtypes="$__srvtypes _http._tcp"
10344b939b11SDevin Teske	f_quietly f_getvar $VAR_FTP_PATH && __srvtypes="$__srvtypes _ftp._tcp"
10354b939b11SDevin Teske	f_quietly f_getvar $VAR_NFS_PATH &&
10364b939b11SDevin Teske		__srvtypes="$__srvtypes _nfs._tcp _nfs._udp"
10374b939b11SDevin Teske
10384b939b11SDevin Teske	# Calculate wait time as dividend of total time and host(1) invocations
10394b939b11SDevin Teske	local __host_runs __wait
1040*d4ae33f0SDevin Teske	f_count __host_runs $__srvtypes
10414b939b11SDevin Teske	if [ "$__ip6" = "YES" ]; then
1042*d4ae33f0SDevin Teske		__host_runs=$(( $__host_runs + 2 ))
10434b939b11SDevin Teske	else
1044*d4ae33f0SDevin Teske		__host_runs=$(( $__host_runs + 1 ))
10454b939b11SDevin Teske	fi
10464b939b11SDevin Teske	f_getvar $VAR_MEDIA_TIMEOUT __wait
10474b939b11SDevin Teske	[ "$__wait" ] && __wait="-W $(( $__wait / $__host_runs ))"
10484b939b11SDevin Teske
10494b939b11SDevin Teske	# Query SRV types first (1st host response taken as new host to query)
10504b939b11SDevin Teske	for __type in $__srvtypes; do
10514b939b11SDevin Teske		if __output=$(
10524b939b11SDevin Teske			host -t SRV $__wait -- "$__type.$__host" \
10534b939b11SDevin Teske			2> /dev/null
10544b939b11SDevin Teske		); then
10554b939b11SDevin Teske			__host=$( echo "$__output" |
10564b939b11SDevin Teske					awk '/ SRV /{print $NF;exit}' )
10574b939b11SDevin Teske			break
10584b939b11SDevin Teske		fi
10594b939b11SDevin Teske	done
10604b939b11SDevin Teske
10614b939b11SDevin Teske	# Try IPv6 first (if enabled)
10627323adacSDevin Teske	if [ "$__ip6" = "YES" ]; then
10637323adacSDevin Teske		if ! __output=$( host -t AAAA $__wait -- "$__host" 2>&1 ); then
10647323adacSDevin Teske			# An error occurred, display in-full and return error
10657323adacSDevin Teske			[ "$__var_to_set" ] &&
10667323adacSDevin Teske				setvar "$__var_to_set" "$__output"
10677323adacSDevin Teske			return $FAILURE
10687323adacSDevin Teske		fi
10694b939b11SDevin Teske		# Add the IPv6 addresses and fall-through to collect IPv4 too
10707323adacSDevin Teske		__addrs=$( echo "$__output" | awk '/ address /{print $NF}' )
10717323adacSDevin Teske	fi
10724b939b11SDevin Teske
10734b939b11SDevin Teske	# Good ol' IPv4
10747323adacSDevin Teske	if ! __output=$( host -t A $__wait -- "$__host" 2>&1 ); then
10757323adacSDevin Teske		# An error occurred, display it in-full and return error
10767323adacSDevin Teske		[ "$__var_to_set" ] && setvar "$__var_to_set" "$__output"
10777323adacSDevin Teske		return $FAILURE
10787323adacSDevin Teske	fi
10794b939b11SDevin Teske
10807323adacSDevin Teske	__addrs="$__addrs${__addrs:+ }$(
10817323adacSDevin Teske		echo "$__output" | awk '/ address /{print $NF}' )"
10827323adacSDevin Teske	if [ "$__var_to_set" ]; then
10837323adacSDevin Teske		setvar "$__var_to_set" "$__addrs"
10847323adacSDevin Teske	else
10857323adacSDevin Teske		echo $__addrs
10867323adacSDevin Teske	fi
10877323adacSDevin Teske}
10887323adacSDevin Teske
10897323adacSDevin Teske# f_device_dialog_tcp $device
10907323adacSDevin Teske#
10917323adacSDevin Teske# This is it - how to get TCP setup values. Prompt the user to edit/confirm the
10927323adacSDevin Teske# interface, gateway, nameserver, and hostname settings -- all required for
10937323adacSDevin Teske# general TCP/IP access.
10947323adacSDevin Teske#
10957323adacSDevin Teske# Variables from variable.subr that can be used to sript user input:
10967323adacSDevin Teske#
10977323adacSDevin Teske# 	VAR_NO_INET6
10987323adacSDevin Teske# 		If set, prevents asking the user if they would like to use
10997323adacSDevin Teske# 		rtsol(8) to check for an IPv6 router.
11007323adacSDevin Teske# 	VAR_TRY_RTSOL
11017323adacSDevin Teske# 		If set to "YES" (and VAR_NONINTERACTIVE is unset), asks the
11027323adacSDevin Teske# 		user if they would like to try the IPv6 RouTer SOLicitation
11037323adacSDevin Teske# 		utility (rtsol(8)) to get IPv6 information. Ignored if
11047323adacSDevin Teske# 		VAR_NO_INET6 is set.
11057323adacSDevin Teske# 	VAR_TRY_DHCP
11067323adacSDevin Teske# 		If set to "YES" (and VAR_NONINTERACTIVE is unset), asks the
11077323adacSDevin Teske# 		user if they would like to try to acquire IPv4 connection
11087323adacSDevin Teske# 		settings from a DHCP server using dhclient(8).
11097323adacSDevin Teske#
11107323adacSDevin Teske# 	VAR_GATEWAY	Default gateway to use.
11117323adacSDevin Teske# 	VAR_IPADDR	Interface address to assign.
11127323adacSDevin Teske# 	VAR_NETMASK	Interface subnet mask.
11137323adacSDevin Teske# 	VAR_EXTRAS	Extra interface options to ifconfig(8).
11147323adacSDevin Teske# 	VAR_HOSTNAME	Hostname to set.
11157323adacSDevin Teske# 	VAR_DOMAINNAME	Domain name to use.
11167323adacSDevin Teske# 	VAR_NAMESERVER	DNS nameserver to use when making lookups.
11177323adacSDevin Teske# 	VAR_IPV6ADDR	IPv6 interface address.
11187323adacSDevin Teske#
11197323adacSDevin Teske# In addition, the following variables are used in acquiring network settings
11207323adacSDevin Teske# from the user:
11217323adacSDevin Teske#
11227323adacSDevin Teske# 	VAR_NONINTERACTIVE
11237323adacSDevin Teske# 		If set (such as when running in a script), prevents asking the
11247323adacSDevin Teske# 		user questions or displaying the usual prompts, etc.
11257323adacSDevin Teske# 	VAR_NETINTERACTIVE
11267323adacSDevin Teske# 		The one exception to VAR_NONINTERACTIVE is VAR_NETINTERACTIVE,
11277323adacSDevin Teske# 		which if set will prompt the user to try RTSOL (unless
11287323adacSDevin Teske# 		VAR_TRY_RTSOL has been set), try DHCP (unless VAR_TRY_DHCP has
11297323adacSDevin Teske# 		been set), and display the network verification dialog. This
11307323adacSDevin Teske# 		allows you to have a mostly non-interactive script that still
11317323adacSDevin Teske# 		prompts for network setup/confirmation.
11327323adacSDevin Teske#
11337323adacSDevin Teske# After successfull execution, the following variables are set:
11347323adacSDevin Teske#
11357323adacSDevin Teske# 	VAR_IFCONFIG + $device (e.g., `ifconfig_em0')
11367323adacSDevin Teske#               Defines the ifconfig(8) properties specific to $device.
11377323adacSDevin Teske#
11387323adacSDevin Teskef_device_dialog_tcp()
11397323adacSDevin Teske{
11407323adacSDevin Teske	local dev="$1" cp n
11417323adacSDevin Teske	local use_dhcp="" use_rtsol=""
11427323adacSDevin Teske	local _ipaddr _netmask _extras
11437323adacSDevin Teske
1144f677a9e2SDevin Teske	[ "$dev" ] || return $DIALOG_CANCEL
11457323adacSDevin Teske
11467323adacSDevin Teske	# Initialize vars from previous device values
11477323adacSDevin Teske	local private
11487323adacSDevin Teske	device_$dev get private private
11497323adacSDevin Teske	if [ "$private" ] && f_struct "$private"; then
11507323adacSDevin Teske		$private get ipaddr    _ipaddr
11517323adacSDevin Teske		$private get netmask   _netmask
11527323adacSDevin Teske		$private get extras    _extras
11537323adacSDevin Teske		$private get use_dhcp  use_dhcp
11547323adacSDevin Teske		$private get use_rtsol use_rtsol
11557323adacSDevin Teske	else # See if there are any defaults
11567323adacSDevin Teske
11577323adacSDevin Teske		#
11587323adacSDevin Teske		# This is a hack so that the dialogs below are interactive in a
11597323adacSDevin Teske		# script if we have requested interactive behavior.
11607323adacSDevin Teske		#
11617323adacSDevin Teske		local old_interactive=
11627323adacSDevin Teske		if ! f_interactive && f_netinteractive; then
11637323adacSDevin Teske			f_getvar $VAR_NONINTERACTIVE old_interactive
11647323adacSDevin Teske			unset $VAR_NONINTERACTIVE
11657323adacSDevin Teske		fi
11667323adacSDevin Teske
11677323adacSDevin Teske		#
11687323adacSDevin Teske		# Try a RTSOL scan if such behavior is desired.
11697323adacSDevin Teske		# If the variable was configured and is YES, do it.
11707323adacSDevin Teske		# If it was configured to anything else, treat it as NO.
11717323adacSDevin Teske		# Otherwise, ask the question interactively.
11727323adacSDevin Teske		#
11737323adacSDevin Teske		local try6
117480433743SDevin Teske		if ! f_isset $VAR_NO_INET6 && {
11757323adacSDevin Teske		   { f_getvar $VAR_TRY_RTSOL try6 && [ "$try6" = "YES" ]; } ||
11767323adacSDevin Teske		   {
117780433743SDevin Teske			# Only prompt the user when VAR_TRY_RTSOL is unset
117880433743SDevin Teske			! f_isset $VAR_TRY_RTSOL &&
11797323adacSDevin Teske				f_dialog_noyes "$msg_try_ipv6_configuration"
11807323adacSDevin Teske		   }
11817323adacSDevin Teske		}; then
11827323adacSDevin Teske			local i
11837323adacSDevin Teske
11847323adacSDevin Teske			f_quietly sysctl net.inet6.ip6.forwarding=0
11857323adacSDevin Teske			f_quietly sysctl net.inet6.ip6.accept_rtadv=1
11867323adacSDevin Teske			f_quietly ifconfig $dev up
11877323adacSDevin Teske
11887323adacSDevin Teske			i=$( sysctl -n net.inet6.ip6.dad_count )
11897323adacSDevin Teske			sleep $(( $i + 1 ))
11907323adacSDevin Teske
11917323adacSDevin Teske			f_quietly mkdir -p /var/run
11927323adacSDevin Teske			f_dialog_info "$msg_scanning_for_ra_servers"
11937323adacSDevin Teske			if f_quietly rtsol $dev; then
11947323adacSDevin Teske				i=$( sysctl -n net.inet6.ip6.dad_count )
11957323adacSDevin Teske				sleep $(( $i + 1 ))
11967323adacSDevin Teske				f_rtsol_get_info $dev
11977323adacSDevin Teske				use_rtsol=1
11987323adacSDevin Teske			else
11997323adacSDevin Teske				use_rtsol=
12007323adacSDevin Teske			fi
12017323adacSDevin Teske		fi
12027323adacSDevin Teske
12037323adacSDevin Teske		#
12047323adacSDevin Teske		# Try a DHCP scan if such behavior is desired.
12057323adacSDevin Teske		# If the variable was configured and is YES, do it.
12067323adacSDevin Teske		# If it was configured to anything else, treat it as NO.
12077323adacSDevin Teske		# Otherwise, ask the question interactively.
12087323adacSDevin Teske		#
12097323adacSDevin Teske		local try4
12107323adacSDevin Teske		if { f_getvar $VAR_TRY_DHCP try4 && [ "$try4" = "YES" ]; } || {
121180433743SDevin Teske			# Only prompt the user when VAR_TRY_DHCP is unset
121280433743SDevin Teske			! f_isset $VAR_TRY_DHCP &&
12137323adacSDevin Teske				f_dialog_noyes "$msg_try_dhcp_configuration"
12147323adacSDevin Teske		}; then
12157323adacSDevin Teske			f_quietly ifconfig $dev delete
12167323adacSDevin Teske			f_quietly mkdir -p /var/db
12177323adacSDevin Teske			f_quietly mkdir -p /var/run
12187323adacSDevin Teske			f_quietly mkdir -p /tmp
12197323adacSDevin Teske
12207323adacSDevin Teske			local msg="$msg_scanning_for_dhcp_servers"
12217323adacSDevin Teske			trap - SIGINT
12227323adacSDevin Teske			( # Execute in sub-shell to allow/catch Ctrl-C
12237323adacSDevin Teske			  trap 'exit $FAILURE' SIGINT
12247323adacSDevin Teske			  if [ "$USE_XDIALOG" ]; then
12257323adacSDevin Teske			  	f_quietly dhclient $dev |
12267323adacSDevin Teske			  			f_xdialog_info "$msg"
12277323adacSDevin Teske			  else
12287323adacSDevin Teske			  	f_dialog_info "$msg"
12297323adacSDevin Teske			  	f_quietly dhclient $dev
12307323adacSDevin Teske			  fi
12317323adacSDevin Teske			)
12327323adacSDevin Teske			local retval=$?
12337323adacSDevin Teske			trap 'f_interrupt' SIGINT
12347323adacSDevin Teske			if [ $retval -eq $SUCCESS ]; then
12357323adacSDevin Teske				f_dhcp_get_info $dev
12367323adacSDevin Teske				use_dhcp=1
12377323adacSDevin Teske			else
12387323adacSDevin Teske				use_dhcp=
12397323adacSDevin Teske			fi
12407323adacSDevin Teske		fi
12417323adacSDevin Teske
12427323adacSDevin Teske		# Restore old VAR_NONINTERACTIVE if needed.
12437323adacSDevin Teske		[ "$old_interactive" ] &&
12447323adacSDevin Teske			setvar $VAR_NONINTERACTIVE "$old_interactive"
12457323adacSDevin Teske
12467323adacSDevin Teske		# Special hack so it doesn't show up oddly in the menu
12477323adacSDevin Teske		local gw
12487323adacSDevin Teske		if f_getvar $VAR_GATEWAY gw && [ "$gw" = "NO" ]; then
12497323adacSDevin Teske			setvar $VAR_GATEWAY ""
12507323adacSDevin Teske		fi
12517323adacSDevin Teske
12527323adacSDevin Teske		# Get old IP address from variable space, if available
12537323adacSDevin Teske		if [ ! "$_ipaddr" ]; then
12547323adacSDevin Teske			if f_getvar $VAR_IPADDR cp; then
12557323adacSDevin Teske				_ipaddr="$cp"
12567323adacSDevin Teske			elif f_getvar ${dev}_$VAR_IPADDR cp; then
12577323adacSDevin Teske				_ipaddr="$cp"
12587323adacSDevin Teske			fi
12597323adacSDevin Teske		fi
12607323adacSDevin Teske
12617323adacSDevin Teske		# Get old netmask from variable space, if available
12627323adacSDevin Teske		if [ ! "$_netmask" ]; then
12637323adacSDevin Teske			if f_getvar $VAR_NETMASK cp; then
12647323adacSDevin Teske				_netmask="$cp"
12657323adacSDevin Teske			elif f_getvar ${dev}_$VAR_NETMASK cp; then
12667323adacSDevin Teske				_netmask="$cp"
12677323adacSDevin Teske			fi
12687323adacSDevin Teske		fi
12697323adacSDevin Teske
12707323adacSDevin Teske		# Get old extras string from variable space, if available
12717323adacSDevin Teske		if [ ! "$_extras" ]; then
12727323adacSDevin Teske			if f_getvar $VAR_EXTRAS cp; then
12737323adacSDevin Teske				_extras="$cp"
12747323adacSDevin Teske			elif f_getvar ${dev}_$VAR_EXTRAS cp; then
12757323adacSDevin Teske				_extras="$cp"
12767323adacSDevin Teske			fi
12777323adacSDevin Teske		fi
12787323adacSDevin Teske	fi
12797323adacSDevin Teske
12807323adacSDevin Teske	# Look up values already recorded with the system, or blank the string
12817323adacSDevin Teske	# variables ready to accept some new data
12827323adacSDevin Teske	local _hostname _gateway _nameserver
12837323adacSDevin Teske	f_getvar $VAR_HOSTNAME _hostname
12847323adacSDevin Teske	case "$_hostname" in
12857323adacSDevin Teske	*.*) : do nothing ;; # Already fully-qualified
12867323adacSDevin Teske	*)
12877323adacSDevin Teske		f_getvar $VAR_DOMAINNAME cp
12887323adacSDevin Teske		[ "$cp" ] && _hostname="$_hostname.$cp"
12897323adacSDevin Teske	esac
12907323adacSDevin Teske	f_getvar $VAR_GATEWAY _gateway
12917323adacSDevin Teske	f_getvar $VAR_NAMESERVER _nameserver
12927323adacSDevin Teske
12937323adacSDevin Teske	# Re-check variables for initial inheritance before heading into dialog
12947323adacSDevin Teske	[ "$_hostname" ] || _hostname="${HOSTNAME:-$( hostname )}"
12957323adacSDevin Teske	[ "$_gateway" ] || f_route_get_default _gateway
12967323adacSDevin Teske	[ ! "$_nameserver" ] &&
12977323adacSDevin Teske		f_resolv_conf_nameservers cp && _nameserver=${cp%%[$IFS]*}
12987323adacSDevin Teske	[ "$_ipaddr" ] || f_ifconfig_inet $dev _ipaddr
12997323adacSDevin Teske	[ "$_netmask" ] || f_ifconfig_netmask $dev _netmask
13007323adacSDevin Teske
13017323adacSDevin Teske	# If non-interactive, jump over dialog section and into config section
13027323adacSDevin Teske	if f_netinteractive || f_interactive || [ ! "$_hostname" ]
13037323adacSDevin Teske	then
13047323adacSDevin Teske		[ ! "$_hostname" ] && f_interactive &&
13057079fc4eSDevin Teske			f_show_msg "$msg_hostname_variable_not_set"
13067323adacSDevin Teske
13077323adacSDevin Teske		local title=" $msg_network_configuration "
13087323adacSDevin Teske		local hline="$hline_alnum_arrows_punc_tab_enter"
13097323adacSDevin Teske		local extras_help="$tcplayout_extras_help"
13107323adacSDevin Teske
13117323adacSDevin Teske		# Modify the help line for PLIP config
13127323adacSDevin Teske		[ "${dev#plip}" != "$dev" ] &&
13137323adacSDevin Teske			extras_help="$tcplayout_extras_help_for_plip"
13147323adacSDevin Teske
13157323adacSDevin Teske		f_getvar $VAR_IPV6ADDR cp && [ "$cp" ] &&
13167323adacSDevin Teske			title="$title($msg_ipv6_ready) "
13177323adacSDevin Teske
13187323adacSDevin Teske		if [ ! "$USE_XDIALOG" ]; then
13197323adacSDevin Teske			local prompt="$msg_dialog_mixedform_navigation_help"
13207323adacSDevin Teske			# Calculate center position for displaying device label
13217323adacSDevin Teske			local devlabel="$msg_configuration_for_interface $dev"
13227323adacSDevin Teske			local width=54
13237323adacSDevin Teske			local n=$(( $width/2 - (${#devlabel} + 4)/2 - 2 ))
13247323adacSDevin Teske
13257323adacSDevin Teske			while :; do
13267323adacSDevin Teske				cp=$( $DIALOG \
13277323adacSDevin Teske					--title "$title"                     \
13287323adacSDevin Teske					--backtitle "$DIALOG_BACKTITLE"      \
13297323adacSDevin Teske					--hline "$hline"                     \
13307323adacSDevin Teske					--item-help                          \
13317323adacSDevin Teske					--ok-label "$msg_ok"                 \
13327323adacSDevin Teske					--cancel-label "$msg_cancel"         \
13337323adacSDevin Teske					--help-button                        \
13347323adacSDevin Teske					--help-label "$msg_help"             \
13357323adacSDevin Teske					--mixedform "$prompt" 16 $width 9    \
13367323adacSDevin Teske					"$msg_host_name_including_domain:" 1 2 \
13377323adacSDevin Teske						"$_hostname" 2 3 45 255 0    \
13387323adacSDevin Teske						"$tcplayout_hostname_help"   \
13397323adacSDevin Teske					"$msg_ipv4_gateway:" 3 2             \
13407323adacSDevin Teske						"$_gateway" 4 3 16 15 0      \
13417323adacSDevin Teske						"$tcplayout_gateway_help"    \
13427323adacSDevin Teske					"$msg_name_server:" 3 31             \
13437323adacSDevin Teske						"$_nameserver" 4 32 16 15 0  \
13447323adacSDevin Teske						"$tcplayout_nameserver_help" \
13457323adacSDevin Teske					"- $devlabel -" 5 $n "" 0 0 0 0 3 "" \
13467323adacSDevin Teske					"$msg_ipv4_address:" 6 6             \
13477323adacSDevin Teske						"$_ipaddr" 7 7 16 15 0       \
13487323adacSDevin Teske						"$tcplayout_ipaddr_help"     \
13497323adacSDevin Teske					"$msg_netmask:" 6 31                 \
13507323adacSDevin Teske						"$_netmask" 7 32 16 15 0     \
13517323adacSDevin Teske						"$tcplayout_netmask_help"    \
13527323adacSDevin Teske					"$msg_extra_options_to_ifconfig" 8 6 \
13537323adacSDevin Teske						"$_extras" 9 7 41 2048 0     \
13547323adacSDevin Teske						"$extras_help"               \
13557323adacSDevin Teske					2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD )
13567323adacSDevin Teske
13577323adacSDevin Teske				# --mixed-form always returns 0, we have to
13587323adacSDevin Teske				# use the returned data to determine button
13597323adacSDevin Teske				if [ ! "$cp" ]; then
13607323adacSDevin Teske					# User either chose "Cancel", pressed
13617323adacSDevin Teske					# ESC, or blanked every form field
1362f677a9e2SDevin Teske					return $DIALOG_CANCEL
13637323adacSDevin Teske				else
13647323adacSDevin Teske					n=$( echo "$cp" | f_number_of_lines )
13657323adacSDevin Teske					[ $n -eq 1 ] && case "$cp" in HELP*)
13667323adacSDevin Teske						# User chose "Help"
13677323adacSDevin Teske						f_show_help "$TCP_HELPFILE"
13687323adacSDevin Teske						continue
13697323adacSDevin Teske					esac
13707323adacSDevin Teske				fi
13717323adacSDevin Teske
13727323adacSDevin Teske				# Turn mixed-form results into env variables
13737323adacSDevin Teske				eval "$( echo "$cp" | awk '
13747323adacSDevin Teske				BEGIN {
13757323adacSDevin Teske					n = 0
13767323adacSDevin Teske					field[++n] = "_hostname"
13777323adacSDevin Teske					field[++n] = "_gateway"
13787323adacSDevin Teske					field[++n] = "_nameserver"
13797323adacSDevin Teske					field[++n] = "_ipaddr"
13807323adacSDevin Teske					field[++n] = "_netmask"
13817323adacSDevin Teske					field[++n] = "_extras"
13827323adacSDevin Teske					nfields = n
13837323adacSDevin Teske					n = 0
13847323adacSDevin Teske				}
13857323adacSDevin Teske				{
13867323adacSDevin Teske					gsub(/'\''/, "'\'\\\\\'\''")
13877323adacSDevin Teske					sub(/[[:space:]]*$/, "")
13887323adacSDevin Teske					value[field[++n]] = $0
13897323adacSDevin Teske				}
13907323adacSDevin Teske				END {
13917323adacSDevin Teske					for ( n = 1; n <= nfields; n++ )
13927323adacSDevin Teske					{
13937323adacSDevin Teske						printf "%s='\''%s'\'';\n",
13947323adacSDevin Teske						       field[n],
13957323adacSDevin Teske						       value[field[n]]
13967323adacSDevin Teske					}
13977323adacSDevin Teske				}' )"
13987323adacSDevin Teske
13997323adacSDevin Teske				f_dialog_validate_tcpip \
14007323adacSDevin Teske					"$_hostname" \
14017323adacSDevin Teske					"$_gateway" \
14027323adacSDevin Teske					"$_nameserver" \
14037323adacSDevin Teske					"$_ipaddr" \
14047323adacSDevin Teske					"$_netmask" \
14057323adacSDevin Teske					&& break
14067323adacSDevin Teske			done
14077323adacSDevin Teske		else
14087323adacSDevin Teske			# Xdialog(1) does not support --mixed-form
14097323adacSDevin Teske			# Create a persistent menu instead
14107323adacSDevin Teske
14117323adacSDevin Teske			f_dialog_title "$msg_network_configuration"
141251c41087SDevin Teske			local prompt=
14137323adacSDevin Teske
14147323adacSDevin Teske			while :; do
14157323adacSDevin Teske				cp=$( $DIALOG \
14167323adacSDevin Teske					--title "$DIALOG_TITLE"               \
14177323adacSDevin Teske					--backtitle "$DIALOG_BACKTITLE"       \
14187323adacSDevin Teske					--hline "$hline"                      \
14197323adacSDevin Teske					--item-help                           \
14207323adacSDevin Teske					--ok-label "$msg_ok"                  \
14217323adacSDevin Teske					--cancel-label "$msg_cancel"          \
14227323adacSDevin Teske					--help ""                             \
14237323adacSDevin Teske					--menu "$prompt" 21 60 8              \
14247323adacSDevin Teske					"$msg_accept_continue" ""             \
14257323adacSDevin Teske						"$tcplayout_accept_cont_help" \
14267323adacSDevin Teske					"$msg_host_name_including_domain:"    \
14277323adacSDevin Teske						"$_hostname"                  \
14287323adacSDevin Teske						"$tcplayout_hostname_help"    \
14297323adacSDevin Teske					"$msg_ipv4_gateway:" "$_gateway"      \
14307323adacSDevin Teske						"$tcplayout_gateway_help"     \
14317323adacSDevin Teske					"$msg_name_server:" "$_nameserver"    \
14327323adacSDevin Teske						"$tcplayout_nameserver_help"  \
14337323adacSDevin Teske					"$msg_ipv4_address:" "$_ipaddr"       \
14347323adacSDevin Teske						"$tcplayout_ipaddr_help"      \
14357323adacSDevin Teske					"$msg_netmask:" "$_netmask"           \
14367323adacSDevin Teske						"$tcplayout_netmask_help"     \
14377323adacSDevin Teske					"$msg_extra_options_to_ifconfig"      \
14387323adacSDevin Teske						"$_extras" "$extras_help"     \
14397323adacSDevin Teske					2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
14407323adacSDevin Teske				)
14417323adacSDevin Teske				local retval=$?
1442fd962ac6SDevin Teske				f_dialog_data_sanitize cp
14437323adacSDevin Teske				f_dprintf "retval=%u mtag=[%s]" $retval "$cp"
14447323adacSDevin Teske
1445f677a9e2SDevin Teske				if [ $retval -eq $DIALOG_HELP ]; then
14467323adacSDevin Teske					f_show_help "$TCP_HELPFILE"
14477323adacSDevin Teske					continue
1448f677a9e2SDevin Teske				elif [ $retval -ne $DIALOG_OK ]; then
14497323adacSDevin Teske					f_dialog_title_restore
1450f677a9e2SDevin Teske					return $DIALOG_CANCEL
14517323adacSDevin Teske				fi
14527323adacSDevin Teske
14537323adacSDevin Teske				case "$cp" in
14547323adacSDevin Teske				"$msg_accept_continue")
14557323adacSDevin Teske					f_dialog_validate_tcpip \
14567323adacSDevin Teske						"$_hostname" \
14577323adacSDevin Teske						"$_gateway" \
14587323adacSDevin Teske						"$_nameserver" \
14597323adacSDevin Teske						"$_ipaddr" \
14607323adacSDevin Teske						"$_netmask" \
14617323adacSDevin Teske						&& break ;;
14627323adacSDevin Teske				"$msg_host_name_including_domain:")
1463ec7120b5SDevin Teske					f_dialog_input cp "$cp" "$_hostname" \
1464ec7120b5SDevin Teske						&& _hostname="$cp" ;;
14657323adacSDevin Teske				"$msg_ipv4_gateway:")
1466ec7120b5SDevin Teske					f_dialog_input cp "$cp" "$_gateway" \
1467ec7120b5SDevin Teske						&& _gateway="$cp" ;;
14687323adacSDevin Teske				"$msg_name_server:")
1469ec7120b5SDevin Teske					f_dialog_input cp "$cp" "$_nameserver" \
1470ec7120b5SDevin Teske						&& _nameserver="$cp" ;;
14717323adacSDevin Teske				"$msg_ipv4_address:")
1472ec7120b5SDevin Teske					f_dialog_input cp "$cp" "$_ipaddr" \
1473ec7120b5SDevin Teske						&& _ipaddr="$cp" ;;
14747323adacSDevin Teske				"$msg_netmask:")
1475ec7120b5SDevin Teske					f_dialog_input cp "$cp" "$_netmask" \
1476ec7120b5SDevin Teske						&& _netmask="$cp" ;;
14777323adacSDevin Teske				"$msg_extra_options_to_ifconfig")
1478ec7120b5SDevin Teske					f_dialog_input cp "$cp" "$_extras" \
1479ec7120b5SDevin Teske						&& _extras="$cp" ;;
14807323adacSDevin Teske				esac
14817323adacSDevin Teske			done
14827323adacSDevin Teske
14837323adacSDevin Teske			f_dialog_title_restore
14847323adacSDevin Teske
14857323adacSDevin Teske		fi # XDIALOG
14867323adacSDevin Teske
14877323adacSDevin Teske	fi # interactive
14887323adacSDevin Teske
14897323adacSDevin Teske	# We actually need to inform the rest of bsdconfig about this
14907323adacSDevin Teske	# data now if the user hasn't selected cancel.
14917323adacSDevin Teske
14927323adacSDevin Teske	if [ "$_hostname" ]; then
14937323adacSDevin Teske		setvar $VAR_HOSTNAME "$_hostname"
14947323adacSDevin Teske		f_quietly hostname "$_hostname"
14957323adacSDevin Teske		case "$_hostname" in
14967323adacSDevin Teske		*.*) setvar $VAR_DOMAINNAME "${_hostname#*.}" ;;
14977323adacSDevin Teske		esac
14987323adacSDevin Teske	fi
14997323adacSDevin Teske	[ "$_gateway"    ] && setvar $VAR_GATEWAY    "$_gateway"
15007323adacSDevin Teske	[ "$_nameserver" ] && setvar $VAR_NAMESERVER "$_nameserver"
15017323adacSDevin Teske	[ "$_ipaddr"     ] && setvar $VAR_IPADDR     "$_ipaddr"
15027323adacSDevin Teske	[ "$_netmask"    ] && setvar $VAR_NETMASK    "$_netmask"
15037323adacSDevin Teske	[ "$_extras"     ] && setvar $VAR_EXTRAS     "$_extras"
15047323adacSDevin Teske
15057323adacSDevin Teske	f_dprintf "Creating struct DEVICE_INFO devinfo_%s" "$dev"
15067323adacSDevin Teske	f_struct_new DEVICE_INFO devinfo_$dev
15077323adacSDevin Teske	device_$dev set private devinfo_$dev
15087323adacSDevin Teske
15097323adacSDevin Teske	devinfo_$dev set ipaddr    $_ipaddr
15107323adacSDevin Teske	devinfo_$dev set netmask   $_netmask
15117323adacSDevin Teske	devinfo_$dev set extras    $_extras
15127323adacSDevin Teske	devinfo_$dev set use_rtsol $use_rtsol
15137323adacSDevin Teske	devinfo_$dev set use_dhcp  $use_dhcp
15147323adacSDevin Teske
15157323adacSDevin Teske	if [ "$use_dhcp" -o "$_ipaddr" ]; then
15167323adacSDevin Teske		if [ "$use_dhcp" ]; then
15177323adacSDevin Teske			cp="DHCP${extras:+ $extras}"
15187323adacSDevin Teske		else
15197323adacSDevin Teske			cp="inet $_ipaddr netmask $_netmask${extras:+ $extras}"
15207323adacSDevin Teske		fi
15217323adacSDevin Teske		setvar $VAR_IFCONFIG$dev "$cp"
15227323adacSDevin Teske	fi
15237323adacSDevin Teske	[ "$use_rtsol" ] &&
15247323adacSDevin Teske		setvar $VAR_IPV6_ENABLE "YES"
15257323adacSDevin Teske
15267323adacSDevin Teske	[ "$use_dhcp" ] ||
15277323adacSDevin Teske		f_config_resolv # XXX this will do it on the MFS copy
15287323adacSDevin Teske
1529f677a9e2SDevin Teske	return $DIALOG_OK
15307323adacSDevin Teske}
15317323adacSDevin Teske
15327323adacSDevin Teske# f_device_scan_tcp [$var_to_set]
15337323adacSDevin Teske#
15347323adacSDevin Teske# Scan for the first active/configured TCP/IP device. The name of the interface
15357323adacSDevin Teske# is printed to stderr like other dialog(1)-based functions (stdout is reserved
15367323adacSDevin Teske# for dialog(1) interaction) if $var_to_set is missing or NULL. Returns failure
15377323adacSDevin Teske# if no active/configured interface
15387323adacSDevin Teske#
15397323adacSDevin Teskef_device_scan_tcp()
15407323adacSDevin Teske{
15417323adacSDevin Teske	local __var_to_set="$1" __iface
15427323adacSDevin Teske	for __iface in $( ifconfig -l ); do
15437323adacSDevin Teske		if ifconfig $__iface | awk '
15447323adacSDevin Teske		BEGIN {
15457323adacSDevin Teske			has_inet = has_inet6 = is_ethernet = 0
15467323adacSDevin Teske			is_usable = 1
15477323adacSDevin Teske		}
15487323adacSDevin Teske		( $1 == "status:" && $2 != "active" ) { is_usable = 0; exit }
15497323adacSDevin Teske		( $1 == "inet" ) {
15507323adacSDevin Teske			if ($2 == "0.0.0.0") { is_usable = 0; exit }
15517323adacSDevin Teske			has_inet++
15527323adacSDevin Teske		}
15537323adacSDevin Teske		( $1 == "inet6") { has_inet6++ }
15547323adacSDevin Teske		( $1 == "media:" ) {
15557323adacSDevin Teske			if ($2 != "Ethernet") { is_usable = 0; exit }
15567323adacSDevin Teske			is_ethernet = 1
15577323adacSDevin Teske		}
15587323adacSDevin Teske		END {
15597323adacSDevin Teske			if (!(is_ethernet && (has_inet || has_inet6)))
15607323adacSDevin Teske				is_usable = 0
15617323adacSDevin Teske			exit ! is_usable
15627323adacSDevin Teske		}'; then
15637323adacSDevin Teske			f_interactive &&
15647323adacSDevin Teske				f_show_msg "$msg_using_interface" "$__iface"
15657323adacSDevin Teske			f_dprintf "f_device_scan_tcp found %s" "$__iface"
15667323adacSDevin Teske			if [ "$__var_to_set" ]; then
15677323adacSDevin Teske				setvar "$__var_to_set" "$__iface"
15687323adacSDevin Teske			else
15697323adacSDevin Teske				echo "$__iface" >&2
15707323adacSDevin Teske			fi
15717323adacSDevin Teske			return $SUCCESS
15727323adacSDevin Teske		fi
15737323adacSDevin Teske	done
15747323adacSDevin Teske
15757323adacSDevin Teske	return $FAILURE
15767323adacSDevin Teske}
15777323adacSDevin Teske
15787323adacSDevin Teske# f_device_select_tcp
15797323adacSDevin Teske#
15807323adacSDevin Teske# Prompt the user to select network interface to use for TCP/IP access.
15817323adacSDevin Teske# Variables from variable.subr that can be used to script user input:
15827323adacSDevin Teske#
15837323adacSDevin Teske# 	VAR_NETWORK_DEVICE [Optional]
15847323adacSDevin Teske# 		Either a comma-separated list of network interfaces to try when
15857323adacSDevin Teske# 		setting up network access (e.g., "fxp0,em0") or "ANY" (case-
15867323adacSDevin Teske# 		sensitive) to indicate that the first active and configured
15877323adacSDevin Teske# 		interface is acceptable. If unset, the user is presented with a
15887323adacSDevin Teske# 		menu of all available network interfaces.
15897323adacSDevin Teske#
15907323adacSDevin Teske# Returns success if a valid network interface has been selected.
15917323adacSDevin Teske#
15927323adacSDevin Teskef_device_select_tcp()
15937323adacSDevin Teske{
15947323adacSDevin Teske	local devs dev cnt network_dev
15957323adacSDevin Teske	f_getvar $VAR_NETWORK_DEVICE network_dev
15967323adacSDevin Teske
15977323adacSDevin Teske	f_dprintf "f_device_select_tcp: %s=[%s]" \
15987323adacSDevin Teske	          VAR_NETWORK_DEVICE "$network_dev"
15997323adacSDevin Teske
16007323adacSDevin Teske	if [ "$network_dev" ]; then
16017323adacSDevin Teske		#
16027323adacSDevin Teske		# This can be set to several types of values. If set to ANY,
16037323adacSDevin Teske		# scan all network devices looking for a valid link, and go
16047323adacSDevin Teske		# with the first device found. Can also be specified as a
16057323adacSDevin Teske		# comma delimited list, with each network device tried in
16067323adacSDevin Teske		# order. Can also be set to a single network device.
16077323adacSDevin Teske		#
16087323adacSDevin Teske		[ "$network_dev" = "ANY" ] && f_device_scan_tcp network_dev
16097323adacSDevin Teske
16107323adacSDevin Teske		while [ "$network_dev" ]; do
16117323adacSDevin Teske			case "$network_dev" in
16127323adacSDevin Teske			*,*) dev="${network_dev%%,*}"
16137323adacSDevin Teske			     network_dev="${network_dev#*,}"
16147323adacSDevin Teske			     ;;
16157323adacSDevin Teske			  *) dev="$network_dev"
16167323adacSDevin Teske			     network_dev=
16177323adacSDevin Teske			esac
16187323adacSDevin Teske
16197323adacSDevin Teske			f_device_find "$dev" $DEVICE_TYPE_NETWORK devs
1620*d4ae33f0SDevin Teske			f_count cnt $devs
16217323adacSDevin Teske
16227323adacSDevin Teske			if [ ${cnt:=0} -gt 0 ]; then
16237323adacSDevin Teske				dev="${devs%%[$IFS]*}"
16247323adacSDevin Teske				f_device_dialog_tcp $dev
1625f677a9e2SDevin Teske				if [ $? -eq $DIALOG_OK ]; then
16267323adacSDevin Teske					setvar $VAR_NETWORK_DEVICE $dev
1627f677a9e2SDevin Teske					return $DIALOG_OK
16287323adacSDevin Teske				fi
16297323adacSDevin Teske			fi
16307323adacSDevin Teske		done
16317323adacSDevin Teske
16327079fc4eSDevin Teske		f_interactive && f_show_msg "$msg_no_network_devices"
1633f677a9e2SDevin Teske		return $DIALOG_CANCEL
16347323adacSDevin Teske
16357323adacSDevin Teske	fi # $network_dev
16367323adacSDevin Teske
16377323adacSDevin Teske	f_device_find "" $DEVICE_TYPE_NETWORK devs
1638*d4ae33f0SDevin Teske	f_count cnt $devs
16397323adacSDevin Teske	dev="${devs%%[$IFS]*}"
16407323adacSDevin Teske
16417323adacSDevin Teske	f_quietly f_getvar NETWORK_CONFIGURED # for debugging info
16427323adacSDevin Teske	if ! f_running_as_init &&
16437323adacSDevin Teske	   ! [ "${NETWORK_CONFIGURED+set}" -a "$NETWORK_CONFIGURED" = "NO" ]
16447323adacSDevin Teske	then
16457323adacSDevin Teske		trap 'f_interrupt' SIGINT
16467323adacSDevin Teske		if f_dialog_yesno "$msg_assume_network_is_already_configured"
16477323adacSDevin Teske		then
16487323adacSDevin Teske			setvar $VAR_NETWORK_DEVICE $dev
1649f677a9e2SDevin Teske			return $DIALOG_OK
16507323adacSDevin Teske		fi
16517323adacSDevin Teske	fi
16527323adacSDevin Teske
16537323adacSDevin Teske	local retval=$SUCCESS
16547323adacSDevin Teske	if [ ${cnt:=0} -eq 0 ]; then
16557079fc4eSDevin Teske		f_show_msg "$msg_no_network_devices"
1656f677a9e2SDevin Teske		retval=$DIALOG_CANCEL
16577323adacSDevin Teske	elif [ $cnt -eq 1 ]; then
16587323adacSDevin Teske		f_device_dialog_tcp $dev
16597323adacSDevin Teske		retval=$?
1660f677a9e2SDevin Teske		[ $retval -eq $DIALOG_OK ] && setvar $VAR_NETWORK_DEVICE $dev
16617323adacSDevin Teske	else
16627323adacSDevin Teske		local title="$msg_network_interface_information_required"
16637323adacSDevin Teske		local prompt="$msg_please_select_ethernet_device_to_configure"
16647323adacSDevin Teske		local hline="$hline_arrows_tab_enter"
16657323adacSDevin Teske
16667323adacSDevin Teske		dev=$( f_device_menu \
16677323adacSDevin Teske			"$title" "$prompt" "$hline" $DEVICE_TYPE_NETWORK \
16687323adacSDevin Teske			"$NETWORK_DEVICE_HELPFILE" \
16697323adacSDevin Teske			2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD )
16707323adacSDevin Teske		retval=$?
1671f677a9e2SDevin Teske		[ "$dev" ] || return $DIALOG_CANCEL
16727323adacSDevin Teske
16737323adacSDevin Teske		f_device_find "$dev" $DEVICE_TYPE_NETWORK devs
1674f677a9e2SDevin Teske		[ "$devs" ] || return $DIALOG_CANCEL
16757323adacSDevin Teske		dev="${devs%%[$IFS]*}"
16767323adacSDevin Teske
16777323adacSDevin Teske		f_device_dialog_tcp $dev
16787323adacSDevin Teske		retval=$?
1679f677a9e2SDevin Teske		if [ $retval -eq $DIALOG_OK ]; then
16807323adacSDevin Teske			f_struct_copy device_$dev device_network
16817323adacSDevin Teske			setvar $VAR_NETWORK_DEVICE network
16827323adacSDevin Teske		else
16837323adacSDevin Teske			f_struct_free device_network
16847323adacSDevin Teske		fi
16857323adacSDevin Teske	fi
16867323adacSDevin Teske
16877323adacSDevin Teske	return $retval
16887323adacSDevin Teske}
16897323adacSDevin Teske
16907323adacSDevin Teske# f_dialog_menu_select_tcp
16917323adacSDevin Teske#
16927323adacSDevin Teske# Like f_dialog_select_tcp() above, but do it from a menu that doesn't care
16937323adacSDevin Teske# about status. In other words, where f_dialog_select_tcp() will not display a
16947323adacSDevin Teske# menu if scripted, this function will always display the menu of available
16957323adacSDevin Teske# network interfaces.
16967323adacSDevin Teske#
16977323adacSDevin Teskef_dialog_menu_select_tcp()
16987323adacSDevin Teske{
16997323adacSDevin Teske	local private use_dhcp name
17007323adacSDevin Teske	NETWORK_CONFIGURED=NO f_device_select_tcp
17017323adacSDevin Teske	if f_struct device_network &&
17027323adacSDevin Teske	   device_network get private private &&
17037323adacSDevin Teske	   f_struct_copy "$private" di &&
17047323adacSDevin Teske	   di get use_dhcp use_dhcp &&
17057323adacSDevin Teske	   [ ! "$use_dhcp" ] &&
17067323adacSDevin Teske	   device_network get name name &&
17077323adacSDevin Teske	   f_yesno "$msg_would_you_like_to_bring_interface_up" "$name"
17087323adacSDevin Teske	then
17097323adacSDevin Teske		if ! f_device_init network; then
17107323adacSDevin Teske			f_show_msg "$msg_initialization_of_device_failed" \
17117323adacSDevin Teske			           "$name"
17127323adacSDevin Teske		fi
17137323adacSDevin Teske	fi
1714f677a9e2SDevin Teske	return $DIALOG_OK
17157323adacSDevin Teske}
17167323adacSDevin Teske
17177323adacSDevin Teske############################################################ MAIN
17187323adacSDevin Teske
17197323adacSDevin Teskef_dprintf "%s: Successfully loaded." media/tcpip.subr
17207323adacSDevin Teske
17217323adacSDevin Teskefi # ! $_MEDIA_TCPIP_SUBR
1722