Deleted Added
full compact
ipaddr.subr (243475) ipaddr.subr (243504)
1if [ ! "$_NETWORKING_IPADDR_SUBR" ]; then _NETWORKING_IPADDR_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#
1if [ ! "$_NETWORKING_IPADDR_SUBR" ]; then _NETWORKING_IPADDR_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: head/usr.sbin/bsdconfig/networking/share/ipaddr.subr 243475 2012-11-24 06:27:46Z dteske $
27# $FreeBSD: head/usr.sbin/bsdconfig/networking/share/ipaddr.subr 243504 2012-11-25 10:37:10Z dteske $
28#
29############################################################ INCLUDES
30
31BSDCFG_SHARE="/usr/share/bsdconfig"
32. $BSDCFG_SHARE/common.subr || exit 1
33f_include $BSDCFG_SHARE/sysrc.subr
34f_include $BSDCFG_SHARE/dialog.subr
35f_include $BSDCFG_SHARE/strings.subr
36f_include $BSDCFG_SHARE/networking/common.subr
37
38BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="120.networking"
39f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
40
41############################################################ FUNCTIONS
42
43# f_ifconfig_inet $interface
44#
45# Returns the IPv4 address associated with $interface.
46#
47f_ifconfig_inet()
48{
49 local interface="$1"
50 ifconfig "$interface" 2> /dev/null | awk \
51 '
52 BEGIN { found = 0 }
53 ( $1 == "inet" ) \
54 {
55 print $2
56 found = 1
57 exit
58 }
59 END { exit ! found }
60 '
61}
62
28#
29############################################################ INCLUDES
30
31BSDCFG_SHARE="/usr/share/bsdconfig"
32. $BSDCFG_SHARE/common.subr || exit 1
33f_include $BSDCFG_SHARE/sysrc.subr
34f_include $BSDCFG_SHARE/dialog.subr
35f_include $BSDCFG_SHARE/strings.subr
36f_include $BSDCFG_SHARE/networking/common.subr
37
38BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="120.networking"
39f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
40
41############################################################ FUNCTIONS
42
43# f_ifconfig_inet $interface
44#
45# Returns the IPv4 address associated with $interface.
46#
47f_ifconfig_inet()
48{
49 local interface="$1"
50 ifconfig "$interface" 2> /dev/null | awk \
51 '
52 BEGIN { found = 0 }
53 ( $1 == "inet" ) \
54 {
55 print $2
56 found = 1
57 exit
58 }
59 END { exit ! found }
60 '
61}
62
63# f_dialog_validate_ipaddr $ipaddr
63# f_validate_ipaddr $ipaddr
64#
65# Returns zero if the given argument (an IP address) is of the proper format.
66#
67# The return status for invalid IP address is one of:
68# 1 One or more individual octets within the IP address (separated
69# by dots) contains one or more invalid characters.
70# 2 One or more individual octets within the IP address are null
71# and/or missing.
72# 3 One or more individual octets within the IP address exceeds the
73# maximum of 255 (or 2^8, being an octet comprised of 8 bits).
74# 4 The IP address has either too few or too many octets.
75#
64#
65# Returns zero if the given argument (an IP address) is of the proper format.
66#
67# The return status for invalid IP address is one of:
68# 1 One or more individual octets within the IP address (separated
69# by dots) contains one or more invalid characters.
70# 2 One or more individual octets within the IP address are null
71# and/or missing.
72# 3 One or more individual octets within the IP address exceeds the
73# maximum of 255 (or 2^8, being an octet comprised of 8 bits).
74# 4 The IP address has either too few or too many octets.
75#
76# If the IP address is determined to be invalid, the appropriate error will be
77# displayed using the f_dialog_msgbox function.
78#
79f_dialog_validate_ipaddr()
76f_validate_ipaddr()
80{
81 local ip="$1"
82
83 ( # Operate within a sub-shell to protect the parent environment
84
85 # Track number of octets for error checking
86 noctets=0
87
88 IFS="." # Split on `dot'
89 for octet in $ip; do
90
91 # Return error if the octet is null
92 [ "$octet" ] || exit 2
93
94 # Return error if not a whole integer
95 f_isinteger "$octet" || exit 1
96
97 # Return error if not a positive integer
98 [ $octet -ge 0 ] || exit 1
99
100 # Return error if the octet exceeds 255
101 [ $octet -gt 255 ] && exit 3
102
103 noctets=$(( $noctets + 1 ))
104
105 done
106
107 [ $noctets -eq 4 ] || exit 4
108 )
77{
78 local ip="$1"
79
80 ( # Operate within a sub-shell to protect the parent environment
81
82 # Track number of octets for error checking
83 noctets=0
84
85 IFS="." # Split on `dot'
86 for octet in $ip; do
87
88 # Return error if the octet is null
89 [ "$octet" ] || exit 2
90
91 # Return error if not a whole integer
92 f_isinteger "$octet" || exit 1
93
94 # Return error if not a positive integer
95 [ $octet -ge 0 ] || exit 1
96
97 # Return error if the octet exceeds 255
98 [ $octet -gt 255 ] && exit 3
99
100 noctets=$(( $noctets + 1 ))
101
102 done
103
104 [ $noctets -eq 4 ] || exit 4
105 )
106}
107# f_dialog_iperror $error $ipaddr
108#
109# Display a msgbox with the appropriate error message for an error returned by
110# f_validate_ipaddr above.
111#
112f_dialog_iperror()
113{
114 local error="$1" ip="$2"
109
115
110 #
111 # Produce an appropriate error message if necessary.
112 #
113 local retval=$?
114 case $retval in
116 [ ${error:-0} -ne 0 ] || return $SUCCESS
117
118 case "$error" in
115 1) f_dialog_msgbox "$( printf \
116 "$msg_ipv4_addr_octet_contains_invalid_chars" "$ip" )";;
117 2) f_dialog_msgbox "$( printf \
118 "$msg_ipv4_addr_octet_is_null" "$ip" )";;
119 3) f_dialog_msgbox "$( printf \
120 "$msg_ipv4_addr_octet_exceeds_max_value" "$ip" )";;
121 4) f_dialog_msgbox "$( printf \
122 "$msg_ipv4_addr_octet_missing_or_extra" "$ip" )";;
123 esac
119 1) f_dialog_msgbox "$( printf \
120 "$msg_ipv4_addr_octet_contains_invalid_chars" "$ip" )";;
121 2) f_dialog_msgbox "$( printf \
122 "$msg_ipv4_addr_octet_is_null" "$ip" )";;
123 3) f_dialog_msgbox "$( printf \
124 "$msg_ipv4_addr_octet_exceeds_max_value" "$ip" )";;
125 4) f_dialog_msgbox "$( printf \
126 "$msg_ipv4_addr_octet_missing_or_extra" "$ip" )";;
127 esac
128}
124
129
130# f_dialog_validate_ipaddr $ipaddr
131#
132# Returns zero if the given argument (an IP address) is of the proper format.
133#
134# If the IP address is determined to be invalid, the appropriate error will be
135# displayed using the f_dialog_iperror function above.
136#
137f_dialog_validate_ipaddr()
138{
139 local ip="$1"
140
141 f_validate_ipaddr "$ip"
142 local retval=$?
143
144 # Produce an appropriate error message if necessary.
145 [ $retval -eq $SUCCESS ] || f_dialog_iperror $retval "$ip"
146
125 return $retval
126}
127
147 return $retval
148}
149
128# f_dialog_validate_ipaddr6 $ipv6_addr
150# f_validate_ipaddr6 $ipv6_addr
129#
130# Returns zero if the given argument (an IPv6 address) is of the proper format.
131#
132# The return status for invalid IP address is one of:
133# 1 One or more individual segments within the IP address
134# (separated by colons) contains one or more invalid characters.
151#
152# Returns zero if the given argument (an IPv6 address) is of the proper format.
153#
154# The return status for invalid IP address is one of:
155# 1 One or more individual segments within the IP address
156# (separated by colons) contains one or more invalid characters.
135# 2 More than two segments within the IP address are null or the
136# the second null segment is not at the end of the address.
137# 3 One or more individual segments within the IP address exceeds
138# the word length of 32-bits (segments are always hexadecimal).
139# 4 The IP address has either too few or too many segments.
140# 5 The IPv4 address at the end of the IPv6 address is invalid.
157# Segments must contain only combinations of the characters 0-9,
158# A-F, or a-f.
159# 2 Too many/incorrect null segments. A single null segment is
160# allowed within the IP address (separated by colons) but not
161# allowed at the beginning or end (unless a double-null segment;
162# i.e., "::*" or "*::").
163# 3 One or more individual segments within the IP address
164# (separated by colons) exceeds the length of 4 hex-digits.
165# 4 The IP address entered has either too few (less than 3), too
166# many (more than 8), or not enough segments, separated by
167# colons.
168# 5* The IPv4 address at the end of the IPv6 address is invalid.
169# * When there is an error with the dotted-quad IPv4 address at the
170# end of the IPv6 address, the return value of 5 is OR'd with a
171# bit-shifted (<< 4) return of f_validate_ipaddr.
141#
172#
142# If the IP address is determined to be invalid, the appropriate error will be
143# displayed using the f_dialog_msgbox function.
144#
145f_dialog_validate_ipaddr6()
173f_validate_ipaddr6()
146{
147 local ip="$1"
148
149 ( # Operate within a sub-shell to protect the parent environment
150
174{
175 local ip="$1"
176
177 ( # Operate within a sub-shell to protect the parent environment
178
151 oldIFS="$IFS"
152 IFS=":" # Split on `colon'
153 set -- $ip:
154
155 # Return error if too many or too few segments
156 # Using 9 as max in case of leading or trailing null spanner
157 [ $# -gt 9 -o $# -lt 3 ] && exit 4
158
159 h="[0-9A-Fa-f]"
160 nulls=0
161 nsegments=$#
162 contains_ipv4_segment=
163
164 while [ $# -gt 0 ]; do
165
166 segment="${1%:}"
167 shift
168
169 #
170 # Return error if this segment makes one null too-many.
171 # A single null segment is allowed anywhere in the
172 # middle as well as double null segments are allowed at
173 # the beginning or end (but not both).
174 #
175 if [ ! "$segment" ]; then
176 nulls=$(( $nulls + 1 ))
177 if [ $nulls -eq 3 ]; then
178 # Only valid syntax for 3 nulls is `::'
179 [ "$ip" = "::" ] || exit 2
180 elif [ $nulls -eq 2 ]; then
181 # Only valid if begins/ends with `::'
182 case "$ip" in
183 ::*|*::) : fall thru ;;
184 *) exit 2
185 esac
186 fi
187 continue
188 fi
189
190 #
191 # Return error if not a valid hexadecimal short
192 #
193 case "$segment" in
194 $h|$h$h|$h$h$h|$h$h$h$h)
195 : valid segment of 1-4 hexadecimal digits
196 ;;
197 *[!0-9A-Fa-f]*)
198 # Segment contains at least one invalid char
199
200 # Return error immediately if not last segment
201 [ $# -eq 0 ] || exit 1
202
203 # Otherwise, check for legacy IPv4 notation
204 case "$segment" in
205 *[!0-9.]*)
206 # Segment contains at least one invalid
207 # character even for an IPv4 address
208 exit 1
209 esac
210
211 # Return error if not enough segments
212 if [ $nulls -eq 0 ]; then
213 [ $nsegments -eq 7 ] || exit 4
214 fi
215
216 contains_ipv4_segment=1
217
218 # Validate the IPv4 address
179 IFS=":" # Split on `colon'
180 set -- $ip:
181
182 # Return error if too many or too few segments
183 # Using 9 as max in case of leading or trailing null spanner
184 [ $# -gt 9 -o $# -lt 3 ] && exit 4
185
186 h="[0-9A-Fa-f]"
187 nulls=0
188 nsegments=$#
189 contains_ipv4_segment=
190
191 while [ $# -gt 0 ]; do
192
193 segment="${1%:}"
194 shift
195
196 #
197 # Return error if this segment makes one null too-many.
198 # A single null segment is allowed anywhere in the
199 # middle as well as double null segments are allowed at
200 # the beginning or end (but not both).
201 #
202 if [ ! "$segment" ]; then
203 nulls=$(( $nulls + 1 ))
204 if [ $nulls -eq 3 ]; then
205 # Only valid syntax for 3 nulls is `::'
206 [ "$ip" = "::" ] || exit 2
207 elif [ $nulls -eq 2 ]; then
208 # Only valid if begins/ends with `::'
209 case "$ip" in
210 ::*|*::) : fall thru ;;
211 *) exit 2
212 esac
213 fi
214 continue
215 fi
216
217 #
218 # Return error if not a valid hexadecimal short
219 #
220 case "$segment" in
221 $h|$h$h|$h$h$h|$h$h$h$h)
222 : valid segment of 1-4 hexadecimal digits
223 ;;
224 *[!0-9A-Fa-f]*)
225 # Segment contains at least one invalid char
226
227 # Return error immediately if not last segment
228 [ $# -eq 0 ] || exit 1
229
230 # Otherwise, check for legacy IPv4 notation
231 case "$segment" in
232 *[!0-9.]*)
233 # Segment contains at least one invalid
234 # character even for an IPv4 address
235 exit 1
236 esac
237
238 # Return error if not enough segments
239 if [ $nulls -eq 0 ]; then
240 [ $nsegments -eq 7 ] || exit 4
241 fi
242
243 contains_ipv4_segment=1
244
245 # Validate the IPv4 address
219 IFS="$oldIFS"
220 f_dialog_validate_ipaddr "$segment" || exit 5
221 IFS=":"
246 f_validate_ipaddr "$segment" ||
247 exit $(( 5 | $? << 4 ))
222 ;;
223 *)
224 # Segment characters are all valid but too many
225 exit 3
226 esac
227
228 done
229
230 if [ $nulls -eq 1 ]; then
231 # Single null segment cannot be at beginning/end
232 case "$ip" in
233 :*|*:) exit 2
234 esac
235 fi
236
237 #
238 # A legacy IPv4 address can span the last two 16-bit segments,
239 # reducing the amount of maximum allowable segments by-one.
240 #
241 maxsegments=8
242 if [ "$contains_ipv4_segment" ]; then
243 maxsegments=7
244 fi
245
246 case $nulls in
247 # Return error if missing segments with no null spanner
248 0) [ $nsegments -eq $maxsegments ] || exit 4 ;;
249 # Return error if null spanner with too many segments
250 1) [ $nsegments -le $maxsegments ] || exit 4 ;;
251 # Return error if leading/trailing `::' with too many segments
252 2) [ $nsegments -le $(( $maxsegments + 1 )) ] || exit 4 ;;
253 esac
254
255 exit $SUCCESS
256 )
248 ;;
249 *)
250 # Segment characters are all valid but too many
251 exit 3
252 esac
253
254 done
255
256 if [ $nulls -eq 1 ]; then
257 # Single null segment cannot be at beginning/end
258 case "$ip" in
259 :*|*:) exit 2
260 esac
261 fi
262
263 #
264 # A legacy IPv4 address can span the last two 16-bit segments,
265 # reducing the amount of maximum allowable segments by-one.
266 #
267 maxsegments=8
268 if [ "$contains_ipv4_segment" ]; then
269 maxsegments=7
270 fi
271
272 case $nulls in
273 # Return error if missing segments with no null spanner
274 0) [ $nsegments -eq $maxsegments ] || exit 4 ;;
275 # Return error if null spanner with too many segments
276 1) [ $nsegments -le $maxsegments ] || exit 4 ;;
277 # Return error if leading/trailing `::' with too many segments
278 2) [ $nsegments -le $(( $maxsegments + 1 )) ] || exit 4 ;;
279 esac
280
281 exit $SUCCESS
282 )
283}
257
284
258 #
259 # Produce an appropriate error message if necessary.
260 #
261 local retval=$?
262 case $retval in
285# f_dialog_ip6error $error $ipv6_addr
286#
287# Display a msgbox with the appropriate error message for an error returned by
288# f_validate_ipaddr6 above.
289#
290f_dialog_ip6error()
291{
292 local error="$1" ip="$2"
293
294 [ ${error:-0} -ne 0 ] || return $SUCCESS
295
296 case "$error" in
263 1) f_dialog_msgbox "$( printf \
264 "$msg_ipv6_addr_segment_contains_invalid_chars" "$ip" )";;
265 2) f_dialog_msgbox "$( printf \
266 "$msg_ipv6_addr_too_many_null_segments" "$ip" )";;
267 3) f_dialog_msgbox "$( printf \
268 "$msg_ipv6_addr_segment_contains_too_many_chars" "$ip" )";;
269 4) f_dialog_msgbox "$( printf \
270 "$msg_ipv6_addr_too_few_or_extra_segments" "$ip" )";;
297 1) f_dialog_msgbox "$( printf \
298 "$msg_ipv6_addr_segment_contains_invalid_chars" "$ip" )";;
299 2) f_dialog_msgbox "$( printf \
300 "$msg_ipv6_addr_too_many_null_segments" "$ip" )";;
301 3) f_dialog_msgbox "$( printf \
302 "$msg_ipv6_addr_segment_contains_too_many_chars" "$ip" )";;
303 4) f_dialog_msgbox "$( printf \
304 "$msg_ipv6_addr_too_few_or_extra_segments" "$ip" )";;
271 5) : IPv4 at the end of IPv6 address is invalid ;;
272 # Don't display an error because f_dialog_validate_ipaddr
273 # already displayed one for the particular issue encountered.
305 *)
306 if [ $(( $error & 0xF )) -eq 5 ]; then
307 # IPv4 at the end of IPv6 address is invalid
308 f_dialog_iperror $(( $error >> 4 )) "$ip"
309 fi
274 esac
310 esac
311}
275
312
313# f_dialog_validate_ipaddr6 $ipv6_addr
314#
315# Returns zero if the given argument (an IPv6 address) is of the proper format.
316#
317# If the IP address is determined to be invalid, the appropriate error will be
318# displayed using the f_dialog_ip6error function above.
319#
320f_dialog_validate_ipaddr6()
321{
322 local ip="$1"
323
324 f_validate_ipaddr6 "$ip"
325 local retval=$?
326
327 # Produce an appropriate error message if necessary.
328 [ $retval -eq $SUCCESS ] || f_dialog_ip6error $retval "$ip"
329
276 return $retval
277}
278
279# f_dialog_input_ipaddr $interface $ipaddr
280#
281# Allows the user to edit a given IP address. If the user does not cancel or
282# press ESC, the $ipaddr environment variable will hold the newly-configured
283# value upon return.
284#
285# Optionally, the user can enter the format "IP_ADDRESS/NBITS" to set the
286# netmask at the same time as the IP address. If such a format is entered by
287# the user, the $netmask environment variable will hold the newly-configured
288# netmask upon return.
289#
290f_dialog_input_ipaddr()
291{
292 local interface="$1" _ipaddr="$2" _input
293
294 #
295 # Return with-error when there are NFS-mounts currently active. If the
296 # IP address is changed while NFS-exported directories are mounted, the
297 # system may hang (if any NFS mounts are using that interface).
298 #
299 if f_nfs_mounted && ! f_jailed; then
300 local setting="$( printf "$msg_current_ipaddr" \
301 "$interface" "$_ipaddr" )"
302 local message="$( printf "$msg_nfs_mounts_may_cause_hang" \
303 "$setting" )"
304 f_dialog_msgbox "$message"
305 return $FAILURE
306 fi
307
308 local msg="$( printf "$msg_please_enter_new_ip_addr" "$interface" )"
309 local hline="$hline_num_punc_tab_enter"
310 local size="$( f_dialog_inputbox_size \
311 "$DIALOG_TITLE" \
312 "$DIALOG_BACKTITLE" \
313 "$msg" \
314 "$_ipaddr" \
315 "$hline" )"
316
317 #
318 # Loop until the user provides taint-free input.
319 #
320 while :; do
321 local dialog_inputbox
322 dialog_inputbox=$( eval $DIALOG \
323 --title \"\$DIALOG_TITLE\" \
324 --backtitle \"\$DIALOG_BACKTITLE\" \
325 --hline \"\$hline\" \
326 --ok-label \"\$msg_ok\" \
327 --cancel-label \"\$msg_cancel\" \
328 --inputbox \"\$msg\" $size \
329 \"\$_ipaddr\" \
330 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
331 )
332
333 local retval=$?
334 setvar DIALOG_INPUTBOX_$$ "$dialog_inputbox"
335 _input=$( f_dialog_inputstr )
336
337 #
338 # Return error status if:
339 # - User has not made any changes to the given value
340 # - User has either pressed ESC or chosen Cancel/No
341 #
342 [ "$_ipaddr" = "$_input" ] && return $FAILURE
343 [ $retval -eq $SUCCESS ] || return $retval
344
345 # Return success if NULL value was entered
346 [ "$_input" ] || return $SUCCESS
347
348 # Take only the first "word" of the user's input
349 _ipaddr="$_input"
350 _ipaddr="${_ipaddr%%[$IFS]*}"
351
352 # Taint-check the user's input
353 f_dialog_validate_ipaddr "${_ipaddr%%/*}" && break
354 done
355
356 #
357 # Support the syntax: IP_ADDRESS/NBITS
358 #
359 local _netmask=""
360 case "$_ipaddr" in
361 */*)
362 local nbits="${_ipaddr#*/}" n=0
363 _ipaddr="${_ipaddr%%/*}"
364
365 #
366 # Taint-check $nbits to be (a) a positive whole-integer,
367 # and (b) to be less than or equal to 32. Otherwise, set
368 # $n so that the below loop never executes.
369 #
370 ( f_isinteger "$nbits" && [ $nbits -ge 0 -a $nbits -le 32 ] ) \
371 || n=4
372
373 while [ $n -lt 4 ]; do
374 _netmask="$_netmask${_netmask:+.}$((
375 (65280 >> ($nbits - 8 * $n) & 255)
376 * ((8*$n) < $nbits & $nbits <= (8*($n+1)))
377 + 255 * ($nbits > (8*($n+1)))
378 ))"
379 n=$(( $n + 1 ))
380 done
381 ;;
382 esac
383
384 ipaddr="$_ipaddr"
385 [ "$_netmask" ] && netmask="$_netmask"
386
387 return $SUCCESS
388}
389
390fi # ! $_NETWORKING_IPADDR_SUBR
330 return $retval
331}
332
333# f_dialog_input_ipaddr $interface $ipaddr
334#
335# Allows the user to edit a given IP address. If the user does not cancel or
336# press ESC, the $ipaddr environment variable will hold the newly-configured
337# value upon return.
338#
339# Optionally, the user can enter the format "IP_ADDRESS/NBITS" to set the
340# netmask at the same time as the IP address. If such a format is entered by
341# the user, the $netmask environment variable will hold the newly-configured
342# netmask upon return.
343#
344f_dialog_input_ipaddr()
345{
346 local interface="$1" _ipaddr="$2" _input
347
348 #
349 # Return with-error when there are NFS-mounts currently active. If the
350 # IP address is changed while NFS-exported directories are mounted, the
351 # system may hang (if any NFS mounts are using that interface).
352 #
353 if f_nfs_mounted && ! f_jailed; then
354 local setting="$( printf "$msg_current_ipaddr" \
355 "$interface" "$_ipaddr" )"
356 local message="$( printf "$msg_nfs_mounts_may_cause_hang" \
357 "$setting" )"
358 f_dialog_msgbox "$message"
359 return $FAILURE
360 fi
361
362 local msg="$( printf "$msg_please_enter_new_ip_addr" "$interface" )"
363 local hline="$hline_num_punc_tab_enter"
364 local size="$( f_dialog_inputbox_size \
365 "$DIALOG_TITLE" \
366 "$DIALOG_BACKTITLE" \
367 "$msg" \
368 "$_ipaddr" \
369 "$hline" )"
370
371 #
372 # Loop until the user provides taint-free input.
373 #
374 while :; do
375 local dialog_inputbox
376 dialog_inputbox=$( eval $DIALOG \
377 --title \"\$DIALOG_TITLE\" \
378 --backtitle \"\$DIALOG_BACKTITLE\" \
379 --hline \"\$hline\" \
380 --ok-label \"\$msg_ok\" \
381 --cancel-label \"\$msg_cancel\" \
382 --inputbox \"\$msg\" $size \
383 \"\$_ipaddr\" \
384 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
385 )
386
387 local retval=$?
388 setvar DIALOG_INPUTBOX_$$ "$dialog_inputbox"
389 _input=$( f_dialog_inputstr )
390
391 #
392 # Return error status if:
393 # - User has not made any changes to the given value
394 # - User has either pressed ESC or chosen Cancel/No
395 #
396 [ "$_ipaddr" = "$_input" ] && return $FAILURE
397 [ $retval -eq $SUCCESS ] || return $retval
398
399 # Return success if NULL value was entered
400 [ "$_input" ] || return $SUCCESS
401
402 # Take only the first "word" of the user's input
403 _ipaddr="$_input"
404 _ipaddr="${_ipaddr%%[$IFS]*}"
405
406 # Taint-check the user's input
407 f_dialog_validate_ipaddr "${_ipaddr%%/*}" && break
408 done
409
410 #
411 # Support the syntax: IP_ADDRESS/NBITS
412 #
413 local _netmask=""
414 case "$_ipaddr" in
415 */*)
416 local nbits="${_ipaddr#*/}" n=0
417 _ipaddr="${_ipaddr%%/*}"
418
419 #
420 # Taint-check $nbits to be (a) a positive whole-integer,
421 # and (b) to be less than or equal to 32. Otherwise, set
422 # $n so that the below loop never executes.
423 #
424 ( f_isinteger "$nbits" && [ $nbits -ge 0 -a $nbits -le 32 ] ) \
425 || n=4
426
427 while [ $n -lt 4 ]; do
428 _netmask="$_netmask${_netmask:+.}$((
429 (65280 >> ($nbits - 8 * $n) & 255)
430 * ((8*$n) < $nbits & $nbits <= (8*($n+1)))
431 + 255 * ($nbits > (8*($n+1)))
432 ))"
433 n=$(( $n + 1 ))
434 done
435 ;;
436 esac
437
438 ipaddr="$_ipaddr"
439 [ "$_netmask" ] && netmask="$_netmask"
440
441 return $SUCCESS
442}
443
444fi # ! $_NETWORKING_IPADDR_SUBR