xref: /freebsd/usr.sbin/bsdconfig/networking/share/netmask.subr (revision 34f9b7199d70df0ff5616621c43998eb09d9dea5)
1if [ ! "$_NETWORKING_NETMASK_SUBR" ]; then _NETWORKING_NETMASK_SUBR=1
2#
3# Copyright (c) 2006-2012 Devin Teske
4# All Rights Reserved.
5#
6# Redistribution and use in source and binary forms, with or without
7# modification, are permitted provided that the following conditions
8# are met:
9# 1. Redistributions of source code must retain the above copyright
10#    notice, this list of conditions and the following disclaimer.
11# 2. Redistributions in binary form must reproduce the above copyright
12#    notice, this list of conditions and the following disclaimer in the
13#    documentation and/or other materials provided with the distribution.
14#
15# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, THE
17# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20# DAMAGES (INLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25# SUCH DAMAGE.
26#
27# $FreeBSD$
28#
29############################################################ INCLUDES
30
31BSDCFG_SHARE="/usr/share/bsdconfig"
32. $BSDCFG_SHARE/common.subr || exit 1
33f_include $BSDCFG_SHARE/dialog.subr
34f_include $BSDCFG_SHARE/strings.subr
35f_include $BSDCFG_SHARE/networking/common.subr
36
37BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="120.networking"
38f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
39
40############################################################ FUNCTIONS
41
42# f_ifconfig_netmask $interface
43#
44# Returns the IPv4 subnet mask associated with $interface.
45#
46f_ifconfig_netmask()
47{
48	local interface="$1" octets
49	octets=$( ifconfig "$interface" 2> /dev/null | awk \
50	'
51		BEGIN { found = 0 }
52		( $1 == "inet" ) \
53		{
54			printf "%s %s %s %s\n",
55				substr($4,3,2),
56				substr($4,5,2),
57				substr($4,7,2),
58				substr($4,9,2)
59			found = 1
60			exit
61		}
62		END { exit ! found }
63	' ) || return $FAILURE
64
65	local octet netmask=
66	for octet in $octets; do
67		netmask="$netmask${netmask:+.}$( printf "%u" "0x$octet" )"
68	done
69	echo $netmask
70}
71
72# f_dialog_validate_netmask $netmask
73#
74# Returns zero if the given argument (a subnet mask) is of the proper format.
75#
76# The return status for invalid IP address is one of:
77# 	1	One or more individual fields within the subnet mask (separated
78# 	 	by dots) contains one or more invalid characters.
79# 	2	One or more individual fields within the subnet mask are null
80# 	 	and/or missing.
81# 	3	One or more individual fields within the subnet mask exceeds
82# 	 	the maximum of 255 (a full 8-bit register).
83# 	4	The subnet mask has either too few or too many fields.
84# 	5	One or more individual fields within the subnet mask is an
85# 	 	invalid integer (only 0,128,192,224,240,248,252,254,255 are
86# 	 	valid integers).
87#
88# If the subnet mask is determined to be invalid, the appropriate error will be
89# displayed using the f_dialog_msgbox function.
90#
91f_dialog_validate_netmask()
92{
93	local mask="$1"
94
95	( # Operate within a sub-shell to protect the parent environment
96
97		# Track number of fields for error checking
98		nfields=0
99
100		IFS="." # Split on `dot'
101		for field in $mask; do
102
103			# Return error if the field is null
104			[ "$field" ] || exit 2
105
106			# Return error if not a whole positive integer
107			f_isinteger "$field" || exit 1
108
109			# Return error if the field exceeds 255
110			[ $field -gt 255 ] && exit 3
111
112			# Return error if the field is an invalid integer
113			case "$field" in
114			0|128|192|224|240|248|252|254|255) :;;
115			*) exit 5;;
116			esac
117
118			nfields=$(( $nfields + 1 ))
119
120		done
121
122		[ $nfields -eq 4 ] || exit 4
123	)
124
125	#
126	# Produce an appropriate error message if necessary.
127	#
128	local retval=$?
129	case $retval in
130	1) f_show_msg "$msg_ipv4_mask_field_contains_invalid_chars" "$mask";;
131	2) f_show_msg "$msg_ipv4_mask_field_is_null" "$mask";;
132	3) f_show_msg "$msg_ipv4_mask_field_exceeds_max_value" "$mask";;
133	4) f_show_msg "$msg_ipv4_mask_field_missing_or_extra" "$mask";;
134	5) f_show_msg "$msg_ipv4_mask_field_invalid_value" "$mask";;
135	esac
136
137	return $retval
138}
139
140# f_dialog_input_netmask $interface $netmask
141#
142# Edits the IP netmask of the given interface.
143#
144f_dialog_input_netmask()
145{
146	local interface="$1" _netmask="$2" _input
147
148	#
149	# Return with-error when there are NFS-mounts currently active. If the
150	# subnet mask is changed while NFS-exported directories are mounted,
151	# the system may hang (if any NFS mounts are using that interface).
152	#
153	if f_nfs_mounted && ! f_jailed; then
154		local setting="$( printf "$msg_current_subnet" \
155		                         "$interface" "$_netmask" )"
156		f_show_msg "$msg_nfs_mounts_may_cause_hang" "$setting"
157		return $FAILURE
158	fi
159
160	#
161	# Loop until the user provides taint-free input.
162	#
163	local msg="$( printf "$msg_please_enter_subnet_mask" "$interface" )"
164	while :; do
165		#
166		# Return error status if:
167		# - User has either pressed ESC or chosen Cancel/No
168		# - User has not made any changes to the given value
169		#
170		_input=$( f_dialog_input "$msg" "$_netmask" \
171		                         "$hline_num_punc_tab_enter"
172		        ) || return
173		[ "$_netmask" = "$_input" ] && return $FAILURE
174
175		# Return success if NULL value was entered
176		[ "$_input" ] || return $SUCCESS
177
178		# Take only the first "word" of the user's input
179		_netmask="$_input"
180		_netmask="${_netmask%%[$IFS]*}"
181
182		# Taint-check the user's input
183		f_dialog_validate_netmask "$_netmask" && break
184	done
185
186	netmask="$_netmask"
187}
188
189fi # ! $_NETWORKING_NETMASK_SUBR
190