1ab2043b8SDevin Teskeif [ ! "$_NETWORKING_IPADDR_SUBR" ]; then _NETWORKING_IPADDR_SUBR=1
2ab2043b8SDevin Teske#
37323adacSDevin Teske# Copyright (c) 2006-2013 Devin Teske
4f8ea072aSDevin Teske# All rights reserved.
5ab2043b8SDevin Teske#
6ab2043b8SDevin Teske# Redistribution and use in source and binary forms, with or without
7ab2043b8SDevin Teske# modification, are permitted provided that the following conditions
8ab2043b8SDevin Teske# are met:
9ab2043b8SDevin Teske# 1. Redistributions of source code must retain the above copyright
10ab2043b8SDevin Teske#    notice, this list of conditions and the following disclaimer.
11ab2043b8SDevin Teske# 2. Redistributions in binary form must reproduce the above copyright
12ab2043b8SDevin Teske#    notice, this list of conditions and the following disclaimer in the
13ab2043b8SDevin Teske#    documentation and/or other materials provided with the distribution.
14ab2043b8SDevin Teske#
15ab2043b8SDevin 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
17ab2043b8SDevin Teske# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18ab2043b8SDevin Teske# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19ab2043b8SDevin Teske# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
208e37a7c8SDevin Teske# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21ab2043b8SDevin Teske# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22ab2043b8SDevin Teske# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23ab2043b8SDevin Teske# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24ab2043b8SDevin Teske# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25ab2043b8SDevin Teske# SUCH DAMAGE.
26ab2043b8SDevin Teske#
27ab2043b8SDevin Teske#
28ab2043b8SDevin Teske############################################################ INCLUDES
29ab2043b8SDevin Teske
30ab2043b8SDevin TeskeBSDCFG_SHARE="/usr/share/bsdconfig"
31ab2043b8SDevin Teske. $BSDCFG_SHARE/common.subr || exit 1
3256961fd7SDevin Teskef_dprintf "%s: loading includes..." networking/ipaddr.subr
33ab2043b8SDevin Teskef_include $BSDCFG_SHARE/dialog.subr
34ab2043b8SDevin Teskef_include $BSDCFG_SHARE/networking/common.subr
351de60ff0SDevin Teskef_include $BSDCFG_SHARE/strings.subr
36ab2043b8SDevin Teske
37ab2043b8SDevin TeskeBSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="120.networking"
38ab2043b8SDevin Teskef_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
39ab2043b8SDevin Teske
40ab2043b8SDevin Teske############################################################ FUNCTIONS
41ab2043b8SDevin Teske
4210e8484fSDevin Teske# f_dialog_iperror $error $ipaddr
4310e8484fSDevin Teske#
4410e8484fSDevin Teske# Display a msgbox with the appropriate error message for an error returned by
457323adacSDevin Teske# the f_validate_ipaddr function.
4610e8484fSDevin Teske#
4710e8484fSDevin Teskef_dialog_iperror()
4810e8484fSDevin Teske{
4910e8484fSDevin Teske	local error="$1" ip="$2"
50ab2043b8SDevin Teske
5110e8484fSDevin Teske	[ ${error:-0} -ne 0 ] || return $SUCCESS
5210e8484fSDevin Teske
5310e8484fSDevin Teske	case "$error" in
54fa2e39c8SDevin Teske	1) f_show_msg "$msg_ipv4_addr_octet_contains_invalid_chars" "$ip" ;;
55fa2e39c8SDevin Teske	2) f_show_msg "$msg_ipv4_addr_octet_is_null" "$ip" ;;
56fa2e39c8SDevin Teske	3) f_show_msg "$msg_ipv4_addr_octet_exceeds_max_value" "$ip" ;;
57fa2e39c8SDevin Teske	4) f_show_msg "$msg_ipv4_addr_octet_missing_or_extra" "$ip" ;;
58ab2043b8SDevin Teske	esac
5910e8484fSDevin Teske}
6010e8484fSDevin Teske
6110e8484fSDevin Teske# f_dialog_validate_ipaddr $ipaddr
6210e8484fSDevin Teske#
6310e8484fSDevin Teske# Returns zero if the given argument (an IP address) is of the proper format.
6410e8484fSDevin Teske#
6510e8484fSDevin Teske# If the IP address is determined to be invalid, the appropriate error will be
6610e8484fSDevin Teske# displayed using the f_dialog_iperror function above.
6710e8484fSDevin Teske#
6810e8484fSDevin Teskef_dialog_validate_ipaddr()
6910e8484fSDevin Teske{
7010e8484fSDevin Teske	local ip="$1"
7110e8484fSDevin Teske
7210e8484fSDevin Teske	f_validate_ipaddr "$ip"
7310e8484fSDevin Teske	local retval=$?
7410e8484fSDevin Teske
7510e8484fSDevin Teske	# Produce an appropriate error message if necessary.
7610e8484fSDevin Teske	[ $retval -eq $SUCCESS ] || f_dialog_iperror $retval "$ip"
77ab2043b8SDevin Teske
78ab2043b8SDevin Teske	return $retval
79ab2043b8SDevin Teske}
80ab2043b8SDevin Teske
8110e8484fSDevin Teske# f_dialog_ip6error $error $ipv6_addr
82fdfd7b65SDevin Teske#
8310e8484fSDevin Teske# Display a msgbox with the appropriate error message for an error returned by
8422cfc4a1SDevin Teske# the f_validate_ipaddr6 function above.
85fdfd7b65SDevin Teske#
8610e8484fSDevin Teskef_dialog_ip6error()
8710e8484fSDevin Teske{
8810e8484fSDevin Teske	local error="$1" ip="$2"
8910e8484fSDevin Teske
9010e8484fSDevin Teske	[ ${error:-0} -ne 0 ] || return $SUCCESS
9110e8484fSDevin Teske
9210e8484fSDevin Teske	case "$error" in
93fa2e39c8SDevin Teske	1) f_show_msg "$msg_ipv6_addr_segment_contains_invalid_chars" "$ip" ;;
94fa2e39c8SDevin Teske	2) f_show_msg "$msg_ipv6_addr_too_many_null_segments" "$ip" ;;
95fa2e39c8SDevin Teske	3) f_show_msg "$msg_ipv6_addr_segment_contains_too_many_chars" "$ip" ;;
96fa2e39c8SDevin Teske	4) f_show_msg "$msg_ipv6_addr_too_few_or_extra_segments" "$ip" ;;
9710e8484fSDevin Teske	*)
9810e8484fSDevin Teske		if [ $(( $error & 0xF )) -eq 5 ]; then
9910e8484fSDevin Teske			# IPv4 at the end of IPv6 address is invalid
10010e8484fSDevin Teske			f_dialog_iperror $(( $error >> 4 )) "$ip"
10110e8484fSDevin Teske		fi
102fdfd7b65SDevin Teske	esac
10310e8484fSDevin Teske}
10410e8484fSDevin Teske
10510e8484fSDevin Teske# f_dialog_validate_ipaddr6 $ipv6_addr
10610e8484fSDevin Teske#
10710e8484fSDevin Teske# Returns zero if the given argument (an IPv6 address) is of the proper format.
10810e8484fSDevin Teske#
10910e8484fSDevin Teske# If the IP address is determined to be invalid, the appropriate error will be
11010e8484fSDevin Teske# displayed using the f_dialog_ip6error function above.
11110e8484fSDevin Teske#
11210e8484fSDevin Teskef_dialog_validate_ipaddr6()
11310e8484fSDevin Teske{
11410e8484fSDevin Teske	local ip="$1"
11510e8484fSDevin Teske
11610e8484fSDevin Teske	f_validate_ipaddr6 "$ip"
11710e8484fSDevin Teske	local retval=$?
11810e8484fSDevin Teske
11910e8484fSDevin Teske	# Produce an appropriate error message if necessary.
12010e8484fSDevin Teske	[ $retval -eq $SUCCESS ] || f_dialog_ip6error $retval "$ip"
121fdfd7b65SDevin Teske
122fdfd7b65SDevin Teske	return $retval
123fdfd7b65SDevin Teske}
124fdfd7b65SDevin Teske
125ab2043b8SDevin Teske# f_dialog_input_ipaddr $interface $ipaddr
126ab2043b8SDevin Teske#
127ab2043b8SDevin Teske# Allows the user to edit a given IP address. If the user does not cancel or
128ab2043b8SDevin Teske# press ESC, the $ipaddr environment variable will hold the newly-configured
129ab2043b8SDevin Teske# value upon return.
130ab2043b8SDevin Teske#
131ab2043b8SDevin Teske# Optionally, the user can enter the format "IP_ADDRESS/NBITS" to set the
132ab2043b8SDevin Teske# netmask at the same time as the IP address. If such a format is entered by
133ab2043b8SDevin Teske# the user, the $netmask environment variable will hold the newly-configured
134ab2043b8SDevin Teske# netmask upon return.
135ab2043b8SDevin Teske#
136ab2043b8SDevin Teskef_dialog_input_ipaddr()
137ab2043b8SDevin Teske{
138ab2043b8SDevin Teske	local interface="$1" _ipaddr="$2" _input
139ab2043b8SDevin Teske
140ab2043b8SDevin Teske	#
141ab2043b8SDevin Teske	# Return with-error when there are NFS-mounts currently active. If the
142ab2043b8SDevin Teske	# IP address is changed while NFS-exported directories are mounted, the
143ab2043b8SDevin Teske	# system may hang (if any NFS mounts are using that interface).
144ab2043b8SDevin Teske	#
145ab2043b8SDevin Teske	if f_nfs_mounted && ! f_jailed; then
146d4ae33f0SDevin Teske		local setting
147d4ae33f0SDevin Teske		f_sprintf setting "$msg_current_ipaddr" "$interface" "$_ipaddr"
14839c22926SDevin Teske		f_noyes "$msg_nfs_mounts_may_cause_hang" "$setting" ||
149f677a9e2SDevin Teske			return $DIALOG_CANCEL
150ab2043b8SDevin Teske	fi
151ab2043b8SDevin Teske
152d4ae33f0SDevin Teske	local msg
153d4ae33f0SDevin Teske	f_sprintf msg "$msg_please_enter_new_ip_addr" "$interface"
154ab2043b8SDevin Teske
155ab2043b8SDevin Teske	#
156ab2043b8SDevin Teske	# Loop until the user provides taint-free input.
157ab2043b8SDevin Teske	#
158298cf604SDevin Teske	local retval
159ab2043b8SDevin Teske	while :; do
160ab2043b8SDevin Teske		#
161ab2043b8SDevin Teske		# Return error status if:
162ab2043b8SDevin Teske		# - User has either pressed ESC or chosen Cancel/No
163298cf604SDevin Teske		# - User has not made any changes to the given value
164ab2043b8SDevin Teske		#
165ec7120b5SDevin Teske		f_dialog_input _input "$msg" "$_ipaddr" \
166f677a9e2SDevin Teske		               "$hline_num_punc_tab_enter" || return $?
167f677a9e2SDevin Teske		[ "$_ipaddr" = "$_input" ] && return $DIALOG_CANCEL
168ab2043b8SDevin Teske
169ab2043b8SDevin Teske		# Return success if NULL value was entered
170f677a9e2SDevin Teske		[ "$_input" ] || return $DIALOG_OK
171ab2043b8SDevin Teske
172ab2043b8SDevin Teske		# Take only the first "word" of the user's input
173ab2043b8SDevin Teske		_ipaddr="$_input"
174ab2043b8SDevin Teske		_ipaddr="${_ipaddr%%[$IFS]*}"
175ab2043b8SDevin Teske
176ab2043b8SDevin Teske		# Taint-check the user's input
177ab2043b8SDevin Teske		f_dialog_validate_ipaddr "${_ipaddr%%/*}" && break
178ab2043b8SDevin Teske	done
179ab2043b8SDevin Teske
180ab2043b8SDevin Teske	#
181ab2043b8SDevin Teske	# Support the syntax: IP_ADDRESS/NBITS
182ab2043b8SDevin Teske	#
183ab2043b8SDevin Teske	local _netmask=""
184ab2043b8SDevin Teske	case "$_ipaddr" in
185ab2043b8SDevin Teske	*/*)
186ab2043b8SDevin Teske		local nbits="${_ipaddr#*/}" n=0
187ab2043b8SDevin Teske		_ipaddr="${_ipaddr%%/*}"
188ab2043b8SDevin Teske
189ab2043b8SDevin Teske		#
190ab2043b8SDevin Teske		# Taint-check $nbits to be (a) a positive whole-integer,
191ab2043b8SDevin Teske		# and (b) to be less than or equal to 32. Otherwise, set
192ab2043b8SDevin Teske		# $n so that the below loop never executes.
193ab2043b8SDevin Teske		#
194ab2043b8SDevin Teske		( f_isinteger "$nbits" && [ $nbits -ge 0 -a $nbits -le 32 ] ) \
195ab2043b8SDevin Teske			|| n=4
196ab2043b8SDevin Teske
197ab2043b8SDevin Teske		while [ $n -lt 4 ]; do
198ab2043b8SDevin Teske			_netmask="$_netmask${_netmask:+.}$((
199ab2043b8SDevin Teske				(65280 >> ($nbits - 8 * $n) & 255)
200ab2043b8SDevin Teske				* ((8*$n) < $nbits & $nbits <= (8*($n+1)))
201ab2043b8SDevin Teske				+ 255 * ($nbits > (8*($n+1)))
202ab2043b8SDevin Teske			))"
203ab2043b8SDevin Teske			n=$(( $n + 1 ))
204ab2043b8SDevin Teske		done
205ab2043b8SDevin Teske		;;
206ab2043b8SDevin Teske	esac
207ab2043b8SDevin Teske
208ab2043b8SDevin Teske	ipaddr="$_ipaddr"
209ab2043b8SDevin Teske	[ "$_netmask" ] && netmask="$_netmask"
210ab2043b8SDevin Teske
211f677a9e2SDevin Teske	return $DIALOG_OK
212ab2043b8SDevin Teske}
213ab2043b8SDevin Teske
21456961fd7SDevin Teske############################################################ MAIN
21556961fd7SDevin Teske
21656961fd7SDevin Teskef_dprintf "%s: Successfully loaded." networking/ipaddr.subr
21756961fd7SDevin Teske
218ab2043b8SDevin Teskefi # ! $_NETWORKING_IPADDR_SUBR
219