xref: /freebsd/usr.sbin/bsdconfig/networking/share/ipaddr.subr (revision 7323adac99d399e58bdec71236a0db9ee6bfb6d2)
1ab2043b8SDevin Teskeif [ ! "$_NETWORKING_IPADDR_SUBR" ]; then _NETWORKING_IPADDR_SUBR=1
2ab2043b8SDevin Teske#
3*7323adacSDevin Teske# Copyright (c) 2006-2013 Devin Teske
4ab2043b8SDevin 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
16ab2043b8SDevin 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
20ab2043b8SDevin Teske# DAMAGES (INLUDING, 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# $FreeBSD$
28ab2043b8SDevin Teske#
29ab2043b8SDevin Teske############################################################ INCLUDES
30ab2043b8SDevin Teske
31ab2043b8SDevin TeskeBSDCFG_SHARE="/usr/share/bsdconfig"
32ab2043b8SDevin Teske. $BSDCFG_SHARE/common.subr || exit 1
3356961fd7SDevin Teskef_dprintf "%s: loading includes..." networking/ipaddr.subr
34ab2043b8SDevin Teskef_include $BSDCFG_SHARE/dialog.subr
35ab2043b8SDevin Teskef_include $BSDCFG_SHARE/strings.subr
36ab2043b8SDevin Teskef_include $BSDCFG_SHARE/networking/common.subr
37ab2043b8SDevin Teske
38ab2043b8SDevin TeskeBSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="120.networking"
39ab2043b8SDevin Teskef_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
40ab2043b8SDevin Teske
41ab2043b8SDevin Teske############################################################ FUNCTIONS
42ab2043b8SDevin Teske
4310e8484fSDevin Teske# f_dialog_iperror $error $ipaddr
4410e8484fSDevin Teske#
4510e8484fSDevin Teske# Display a msgbox with the appropriate error message for an error returned by
46*7323adacSDevin Teske# the f_validate_ipaddr function.
4710e8484fSDevin Teske#
4810e8484fSDevin Teskef_dialog_iperror()
4910e8484fSDevin Teske{
5010e8484fSDevin Teske	local error="$1" ip="$2"
51ab2043b8SDevin Teske
5210e8484fSDevin Teske	[ ${error:-0} -ne 0 ] || return $SUCCESS
5310e8484fSDevin Teske
5410e8484fSDevin Teske	case "$error" in
55fa2e39c8SDevin Teske	1) f_show_msg "$msg_ipv4_addr_octet_contains_invalid_chars" "$ip";;
56fa2e39c8SDevin Teske	2) f_show_msg "$msg_ipv4_addr_octet_is_null" "$ip";;
57fa2e39c8SDevin Teske	3) f_show_msg "$msg_ipv4_addr_octet_exceeds_max_value" "$ip";;
58fa2e39c8SDevin Teske	4) f_show_msg "$msg_ipv4_addr_octet_missing_or_extra" "$ip";;
59ab2043b8SDevin Teske	esac
6010e8484fSDevin Teske}
6110e8484fSDevin Teske
6210e8484fSDevin Teske# f_dialog_validate_ipaddr $ipaddr
6310e8484fSDevin Teske#
6410e8484fSDevin Teske# Returns zero if the given argument (an IP address) is of the proper format.
6510e8484fSDevin Teske#
6610e8484fSDevin Teske# If the IP address is determined to be invalid, the appropriate error will be
6710e8484fSDevin Teske# displayed using the f_dialog_iperror function above.
6810e8484fSDevin Teske#
6910e8484fSDevin Teskef_dialog_validate_ipaddr()
7010e8484fSDevin Teske{
7110e8484fSDevin Teske	local ip="$1"
7210e8484fSDevin Teske
7310e8484fSDevin Teske	f_validate_ipaddr "$ip"
7410e8484fSDevin Teske	local retval=$?
7510e8484fSDevin Teske
7610e8484fSDevin Teske	# Produce an appropriate error message if necessary.
7710e8484fSDevin Teske	[ $retval -eq $SUCCESS ] || f_dialog_iperror $retval "$ip"
78ab2043b8SDevin Teske
79ab2043b8SDevin Teske	return $retval
80ab2043b8SDevin Teske}
81ab2043b8SDevin Teske
8210e8484fSDevin Teske# f_dialog_ip6error $error $ipv6_addr
83fdfd7b65SDevin Teske#
8410e8484fSDevin Teske# Display a msgbox with the appropriate error message for an error returned by
8522cfc4a1SDevin Teske# the f_validate_ipaddr6 function above.
86fdfd7b65SDevin Teske#
8710e8484fSDevin Teskef_dialog_ip6error()
8810e8484fSDevin Teske{
8910e8484fSDevin Teske	local error="$1" ip="$2"
9010e8484fSDevin Teske
9110e8484fSDevin Teske	[ ${error:-0} -ne 0 ] || return $SUCCESS
9210e8484fSDevin Teske
9310e8484fSDevin Teske	case "$error" in
94fa2e39c8SDevin Teske	1) f_show_msg "$msg_ipv6_addr_segment_contains_invalid_chars" "$ip";;
95fa2e39c8SDevin Teske	2) f_show_msg "$msg_ipv6_addr_too_many_null_segments" "$ip";;
96fa2e39c8SDevin Teske	3) f_show_msg "$msg_ipv6_addr_segment_contains_too_many_chars" "$ip";;
97fa2e39c8SDevin Teske	4) f_show_msg "$msg_ipv6_addr_too_few_or_extra_segments" "$ip";;
9810e8484fSDevin Teske	*)
9910e8484fSDevin Teske		if [ $(( $error & 0xF )) -eq 5 ]; then
10010e8484fSDevin Teske			# IPv4 at the end of IPv6 address is invalid
10110e8484fSDevin Teske			f_dialog_iperror $(( $error >> 4 )) "$ip"
10210e8484fSDevin Teske		fi
103fdfd7b65SDevin Teske	esac
10410e8484fSDevin Teske}
10510e8484fSDevin Teske
10610e8484fSDevin Teske# f_dialog_validate_ipaddr6 $ipv6_addr
10710e8484fSDevin Teske#
10810e8484fSDevin Teske# Returns zero if the given argument (an IPv6 address) is of the proper format.
10910e8484fSDevin Teske#
11010e8484fSDevin Teske# If the IP address is determined to be invalid, the appropriate error will be
11110e8484fSDevin Teske# displayed using the f_dialog_ip6error function above.
11210e8484fSDevin Teske#
11310e8484fSDevin Teskef_dialog_validate_ipaddr6()
11410e8484fSDevin Teske{
11510e8484fSDevin Teske	local ip="$1"
11610e8484fSDevin Teske
11710e8484fSDevin Teske	f_validate_ipaddr6 "$ip"
11810e8484fSDevin Teske	local retval=$?
11910e8484fSDevin Teske
12010e8484fSDevin Teske	# Produce an appropriate error message if necessary.
12110e8484fSDevin Teske	[ $retval -eq $SUCCESS ] || f_dialog_ip6error $retval "$ip"
122fdfd7b65SDevin Teske
123fdfd7b65SDevin Teske	return $retval
124fdfd7b65SDevin Teske}
125fdfd7b65SDevin Teske
126ab2043b8SDevin Teske# f_dialog_input_ipaddr $interface $ipaddr
127ab2043b8SDevin Teske#
128ab2043b8SDevin Teske# Allows the user to edit a given IP address. If the user does not cancel or
129ab2043b8SDevin Teske# press ESC, the $ipaddr environment variable will hold the newly-configured
130ab2043b8SDevin Teske# value upon return.
131ab2043b8SDevin Teske#
132ab2043b8SDevin Teske# Optionally, the user can enter the format "IP_ADDRESS/NBITS" to set the
133ab2043b8SDevin Teske# netmask at the same time as the IP address. If such a format is entered by
134ab2043b8SDevin Teske# the user, the $netmask environment variable will hold the newly-configured
135ab2043b8SDevin Teske# netmask upon return.
136ab2043b8SDevin Teske#
137ab2043b8SDevin Teskef_dialog_input_ipaddr()
138ab2043b8SDevin Teske{
139ab2043b8SDevin Teske	local interface="$1" _ipaddr="$2" _input
140ab2043b8SDevin Teske
141ab2043b8SDevin Teske	#
142ab2043b8SDevin Teske	# Return with-error when there are NFS-mounts currently active. If the
143ab2043b8SDevin Teske	# IP address is changed while NFS-exported directories are mounted, the
144ab2043b8SDevin Teske	# system may hang (if any NFS mounts are using that interface).
145ab2043b8SDevin Teske	#
146ab2043b8SDevin Teske	if f_nfs_mounted && ! f_jailed; then
147ab2043b8SDevin Teske		local setting="$( printf "$msg_current_ipaddr" \
148ab2043b8SDevin Teske		                         "$interface" "$_ipaddr" )"
149fa2e39c8SDevin Teske		f_show_msg "$msg_nfs_mounts_may_cause_hang" "$setting"
150ab2043b8SDevin Teske		return $FAILURE
151ab2043b8SDevin Teske	fi
152ab2043b8SDevin Teske
153ab2043b8SDevin Teske	local msg="$( printf "$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		#
165298cf604SDevin Teske		_input=$( f_dialog_input "$msg" "$_ipaddr" \
166298cf604SDevin Teske		                         "$hline_num_punc_tab_enter"
167298cf604SDevin Teske		        ) || return
168ab2043b8SDevin Teske		[ "$_ipaddr" = "$_input" ] && return $FAILURE
169ab2043b8SDevin Teske
170ab2043b8SDevin Teske		# Return success if NULL value was entered
171ab2043b8SDevin Teske		[ "$_input" ] || return $SUCCESS
172ab2043b8SDevin Teske
173ab2043b8SDevin Teske		# Take only the first "word" of the user's input
174ab2043b8SDevin Teske		_ipaddr="$_input"
175ab2043b8SDevin Teske		_ipaddr="${_ipaddr%%[$IFS]*}"
176ab2043b8SDevin Teske
177ab2043b8SDevin Teske		# Taint-check the user's input
178ab2043b8SDevin Teske		f_dialog_validate_ipaddr "${_ipaddr%%/*}" && break
179ab2043b8SDevin Teske	done
180ab2043b8SDevin Teske
181ab2043b8SDevin Teske	#
182ab2043b8SDevin Teske	# Support the syntax: IP_ADDRESS/NBITS
183ab2043b8SDevin Teske	#
184ab2043b8SDevin Teske	local _netmask=""
185ab2043b8SDevin Teske	case "$_ipaddr" in
186ab2043b8SDevin Teske	*/*)
187ab2043b8SDevin Teske		local nbits="${_ipaddr#*/}" n=0
188ab2043b8SDevin Teske		_ipaddr="${_ipaddr%%/*}"
189ab2043b8SDevin Teske
190ab2043b8SDevin Teske		#
191ab2043b8SDevin Teske		# Taint-check $nbits to be (a) a positive whole-integer,
192ab2043b8SDevin Teske		# and (b) to be less than or equal to 32. Otherwise, set
193ab2043b8SDevin Teske		# $n so that the below loop never executes.
194ab2043b8SDevin Teske		#
195ab2043b8SDevin Teske		( f_isinteger "$nbits" && [ $nbits -ge 0 -a $nbits -le 32 ] ) \
196ab2043b8SDevin Teske			|| n=4
197ab2043b8SDevin Teske
198ab2043b8SDevin Teske		while [ $n -lt 4 ]; do
199ab2043b8SDevin Teske			_netmask="$_netmask${_netmask:+.}$((
200ab2043b8SDevin Teske				(65280 >> ($nbits - 8 * $n) & 255)
201ab2043b8SDevin Teske				* ((8*$n) < $nbits & $nbits <= (8*($n+1)))
202ab2043b8SDevin Teske				+ 255 * ($nbits > (8*($n+1)))
203ab2043b8SDevin Teske			))"
204ab2043b8SDevin Teske			n=$(( $n + 1 ))
205ab2043b8SDevin Teske		done
206ab2043b8SDevin Teske		;;
207ab2043b8SDevin Teske	esac
208ab2043b8SDevin Teske
209ab2043b8SDevin Teske	ipaddr="$_ipaddr"
210ab2043b8SDevin Teske	[ "$_netmask" ] && netmask="$_netmask"
211ab2043b8SDevin Teske
212ab2043b8SDevin Teske	return $SUCCESS
213ab2043b8SDevin Teske}
214ab2043b8SDevin Teske
21556961fd7SDevin Teske############################################################ MAIN
21656961fd7SDevin Teske
21756961fd7SDevin Teskef_dprintf "%s: Successfully loaded." networking/ipaddr.subr
21856961fd7SDevin Teske
219ab2043b8SDevin Teskefi # ! $_NETWORKING_IPADDR_SUBR
220