Deleted Added
full compact
resolv.subr (251242) resolv.subr (251264)
1if [ ! "$_NETWORKING_RESOLV_SUBR" ]; then _NETWORKING_RESOLV_SUBR=1
2#
3# Copyright (c) 2006-2013 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_RESOLV_SUBR" ]; then _NETWORKING_RESOLV_SUBR=1
2#
3# Copyright (c) 2006-2013 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/resolv.subr 251242 2013-06-02 05:45:25Z dteske $
27# $FreeBSD: head/usr.sbin/bsdconfig/networking/share/resolv.subr 251264 2013-06-02 20:02:50Z dteske $
28#
29############################################################ INCLUDES
30
31BSDCFG_SHARE="/usr/share/bsdconfig"
32. $BSDCFG_SHARE/common.subr || exit 1
33f_dprintf "%s: loading includes..." networking/resolv.subr
34f_include $BSDCFG_SHARE/dialog.subr
35f_include $BSDCFG_SHARE/strings.subr
36f_include $BSDCFG_SHARE/media/tcpip.subr
37f_include $BSDCFG_SHARE/networking/common.subr
38f_include $BSDCFG_SHARE/networking/ipaddr.subr
39
40BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="120.networking"
41f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
42
43############################################################ CONFIGURATION
44
45#
46# When updating resolv.conf(5), should we populate the `search' directive with
47# all possible sub-domains? In example, if the domain is "sub.domain.com", when
48# the below option is set to 1, include both "sub.domain.com" and "domain.com"
49# in the `search' directive, otherwise use only "sub.domain.com".
50#
51# When enabled (set to 1), specify the minimum number of dots required for each
52# `search' domain by setting the second option below, `RESOLVER_SEARCH_NDOTS'.
53#
54: ${RESOLVER_SEARCH_DOMAINS_ALL:=1}
55: ${RESOLVER_SEARCH_NDOTS:=1}
56
57############################################################ FUNCTIONS
58
59# f_resolv_conf_domain
60#
61# Returns the domain configured in resolv.conf(5).
62#
63f_resolv_conf_domain()
64{
65 tail -r "$RESOLV_CONF" 2> /dev/null | awk \
66 '
67 BEGIN { found = 0 }
68 ( tolower($1) == "domain" ) \
69 {
70 print $2
71 found = 1
72 exit
73 }
74 END { exit ! found }
75 '
76}
77
78# f_resolv_conf_search
79#
80# Returns the search configured in resolv.conf(5).
81#
82f_resolv_conf_search()
83{
84 tail -r "$RESOLV_CONF" 2> /dev/null | awk \
85 '
86 BEGIN { found = 0 }
87 {
88 tl0 = tolower($0)
89 if ( match(tl0, /^[[:space:]]*search[[:space:]]+/) ) {
90 search = substr($0, RLENGTH + 1)
91 sub(/[[:space:]]*#.*$/, "", search)
92 gsub(/[[:space:]]+/, " ", search)
93 print search
94 found = 1
95 exit
96 }
97 }
98 END { exit ! found }
99 '
100}
101
102# f_dialog_resolv_conf_update $hostname
103#
104# Updates the search/domain directives in resolv.conf(5) given a valid fully-
105# qualified hostname.
106#
107# This function is a two-parter. Below is the awk(1) portion of the function,
108# afterward is the sh(1) function which utilizes the below awk script.
109#
110f_dialog_resolv_conf_update_awk='
111# Variables that should be defined on the invocation line:
112# -v domain="domain"
113# -v search_all="0|1"
114# -v search_ndots="1+"
115#
116BEGIN {
117 domain_found = search_found = 0
118
119 if ( search_all ) {
120 search = ""
121 subdomain = domain
122 if ( search_ndots < 1 )
123 search_ndots = 1
124
125 ndots = split(subdomain, labels, ".") - 1
126 while ( ndots-- >= search_ndots ) {
127 if ( length(search) ) search = search " "
128 search = search subdomain
129 sub(/[^.]*\./, "", subdomain)
130 }
131 }
132 else search = domain
133}
134{
135 if ( domain_found && search_found ) { print; next }
136
137 tl0 = tolower($0)
138 if ( ! domain_found && \
139 match(tl0, /^[[:space:]]*domain[[:space:]]+/) ) \
140 {
141 if ( length(domain) ) {
142 printf "%s%s\n", substr($0, 0, RLENGTH), domain
143 domain_found = 1
144 }
145 }
146 else if ( ! search_found && \
147 match(tl0, /^[[:space:]]*search[[:space:]]+/) ) \
148 {
149 if ( length(search) ) {
150 printf "%s%s\n", substr($0, 0, RLENGTH), search
151 search_found = 1
152 }
153 }
154 else print
155}
156END {
157 if ( ! search_found && length(search) )
158 printf "search\t%s\n", search
159 if ( ! domain_found && length(domain) )
160 printf "domain\t%s\n", domain
161}
162'
163f_dialog_resolv_conf_update()
164{
165 local hostname="$1"
166
167 #
168 # Extrapolate the desired domain search parameter for resolv.conf(5)
169 #
170 local search ndots domain="${hostname#*.}"
171 if [ "$RESOLVER_SEARCH_DOMAINS_ALL" = "1" ]; then
172 search=""
173 ndots=$( IFS=.; set -- $domain; echo $(( $# - 1 )) )
174 while [ $ndots -ge ${RESOLVER_SEARCH_NDOTS:-1} ]; do
175 search="$search${search:+ }$domain"
176 domain="${domain#*.}"
177 ndots=$(( $ndots - 1 ))
178 done
179 domain="${hostname#*.}"
180 else
181 search="$domain"
182 fi
183
184 #
185 # Save domain/search information only if different from resolv.conf(5)
186 #
187 if [ "$domain" != "$( f_resolv_conf_domain )" -o \
188 "$search" != "$( f_resolv_conf_search )" ]
189 then
190 f_dialog_info "Saving new domain/search settings" \
191 "to resolv.conf(5)..."
192
193 #
194 # Create a new temporary file to write our resolv.conf(5)
195 # update with our new `domain' and `search' directives.
196 #
197 local tmpfile="$( mktemp -t "$pgm" )"
198 [ "$tmpfile" ] || return $FAILURE
199
200 #
201 # Fixup permissions and ownership (mktemp(1) creates the
202 # temporary file with 0600 permissions -- change the
203 # permissions and ownership to match resolv.conf(5) before
204 # we write it out and mv(1) it into place).
205 #
206 local mode="$( stat -f '%#Lp' "$RESOLV_CONF" 2> /dev/null )"
207 local owner="$( stat -f '%u:%g' "$RESOLV_CONF" 2> /dev/null )"
208 f_quietly chmod "${mode:-0644}" "$tmpfile"
209 f_quietly chown "${owner:-root:wheel}" "$tmpfile"
210
211 #
212 # Operate on resolv.conf(5), replacing only the last
213 # occurrences of `domain' and `search' directives (or add
214 # them to the top if not found), in strict-adherence to the
215 # following entry in resolver(5):
216 #
217 # The domain and search keywords are mutually exclusive.
218 # If more than one instance of these keywords is present,
219 # the last instance will override.
220 #
221 # NOTE: If RESOLVER_SEARCH_DOMAINS_ALL is set to `1' in the
222 # environment, all sub-domains will be added to the `search'
223 # directive, not just the FQDN.
224 #
225 local domain="${hostname#*.}" new_contents
226 [ "$domain" = "$hostname" ] && domain=
227 new_contents=$( tail -r "$RESOLV_CONF" 2> /dev/null )
228 new_contents=$( echo "$new_contents" | awk \
229 -v domain="$domain" \
230 -v search_all="${RESOLVER_SEARCH_DOMAINS_ALL:-1}" \
231 -v search_ndots="${RESOLVER_SEARCH_NDOTS:-1}" \
232 "$f_dialog_resolv_conf_update_awk" )
233
234 #
235 # Write the temporary file contents and move the temporary
236 # file into place.
237 #
238 echo "$new_contents" | tail -r > "$tmpfile" || return $FAILURE
239 f_quietly mv "$tmpfile" "$RESOLV_CONF"
240
241 fi
242}
243
244# f_dialog_input_nameserver [ $n $nameserver ]
245#
246# Allows the user to edit a given nameserver. The first argument is the
247# resolv.conf(5) nameserver ``instance'' integer. For example, this will be one
248# if editing the first nameserver instance, two if editing the second, three if
249# the third, ad nauseum. If this argument is zero, null, or missing, the value
250# entered by the user (if non-null) will be added to resolv.conf(5) as a new
251# `nameserver' entry. The second argument is the IPv4 address of the nameserver
252# to be edited -- this will be displayed as the initial value during the edit.
253#
254# Taint-checking is performed when editing an existing entry (when the second
255# argument is one or higher) in that the first argument must match the current
256# value of the Nth `nameserver' instance in resolv.conf(5) else an error is
257# generated discarding any/all changes.
258#
259# This function is a two-parter. Below is the awk(1) portion of the function,
260# afterward is the sh(1) function which utilizes the below awk script.
261#
262f_dialog_input_nameserver_edit_awk='
263# Variables that should be defined on the invocation line:
264# -v nsindex="1+"
265# -v old_value="..."
266# -v new_value="..."
267#
268BEGIN {
269 if ( nsindex < 1 ) exit 1
270 found = n = 0
271}
272{
273 if ( found ) { print; next }
274
275 if ( match(tolower($0), /^[[:space:]]*nameserver[[:space:]]+/)) {
276 if ( ++n == nsindex ) {
277 if ( $2 != old_value ) exit 2
278 if ( new_value != "" ) printf "%s%s\n", \
279 substr($0, 0, RLENGTH), new_value
280 found = 1
281 }
282 else print
283 }
284 else print
285}
286END { if ( ! found ) exit 3 }
287'
288f_dialog_input_nameserver()
289{
290 local index="${1:-0}" old_ns="$2" new_ns
291 local ns="$old_ns"
292
293 #
294 # Perform sanity checks
295 #
296 f_isinteger "$index" || return $FAILURE
297 [ $index -ge 0 ] || return $FAILURE
298
299 local msg
300 if [ $index -gt 0 ]; then
301 if [ "$USE_XDIALOG" ]; then
302 msg="$xmsg_please_enter_nameserver_existing"
303 else
304 msg="$msg_please_enter_nameserver_existing"
305 fi
306 else
307 msg="$msg_please_enter_nameserver"
308 fi
309
310 #
311 # Loop until the user provides taint-free input.
312 #
313 while :; do
314 f_dialog_input new_ns "$msg" "$ns" \
315 "$hline_num_punc_tab_enter" || return
316
317 # Take only the first "word" of the user's input
318 new_ns="${new_ns%%[$IFS]*}"
319
320 # Taint-check the user's input
321 [ "$new_ns" ] || break
322 f_dialog_validate_ipaddr "$new_ns" && break
323
324 # Update prompt to allow user to re-edit previous entry
325 ns="$new_ns"
326 done
327
328 #
329 # Save only if the user changed the nameserver.
330 #
331 if [ $index -eq "0" -a "$new_ns" ]; then
332 f_dialog_info "$msg_saving_nameserver"
333 printf "nameserver\t%s\n" "$new_ns" >> "$RESOLV_CONF"
334 return $SUCCESS
335 elif [ $index -gt 0 -a "$old_ns" != "$new_ns" ]; then
336 if [ "$new_ns" ]; then
337 msg="$msg_saving_nameserver_existing"
338 else
339 msg="$msg_removing_nameserver"
340 fi
341 f_dialog_info "$msg"
342
343 #
344 # Create a new temporary file to write our new resolv.conf(5)
345 #
346 local tmpfile="$( mktemp -t "$pgm" )"
347 [ "$tmpfile" ] || return $FAILURE
348
349 #
350 # Quietly fixup permissions and ownership
351 #
352 local mode owner
353 mode=$( stat -f '%#Lp' "$RESOLV_CONF" 2> /dev/null )
354 owner=$( stat -f '%u:%g' "$RESOLV_CONF" 2> /dev/null )
355 f_quietly chmod "${mode:-0644}" "$tmpfile"
356 f_quietly chown "${owner:-root:wheel}" "$tmpfile"
357
358 #
359 # Operate on resolv.conf(5)
360 #
361 local new_contents
362 new_contents=$( awk -v nsindex="$index" \
363 -v old_value="$old_ns" \
364 -v new_value="$new_ns" \
365 "$f_dialog_input_nameserver_edit_awk" \
366 "$RESOLV_CONF" )
367
368 #
369 # Produce an appropriate error message if necessary.
370 #
371 local retval=$?
372 case $retval in
373 1) f_die 1 "$msg_internal_error_nsindex_value" "$nsindex";;
374 2) f_dialog_msgbox "$msg_resolv_conf_changed_while_editing"
375 return $retval;;
376 3) f_dialog_msgbox "$msg_resolv_conf_entry_no_longer_exists"
377 return $retval;;
378 esac
379
380 #
381 # Write the temporary file contents and move the temporary
382 # file into place.
383 #
384 echo "$new_contents" > "$tmpfile" || return $FAILURE
385 f_quietly mv "$tmpfile" "$RESOLV_CONF"
386 fi
387}
388
389# f_dialog_menu_nameservers
390#
391# Edit the nameservers in resolv.conf(5).
392#
393f_dialog_menu_nameservers()
394{
28#
29############################################################ INCLUDES
30
31BSDCFG_SHARE="/usr/share/bsdconfig"
32. $BSDCFG_SHARE/common.subr || exit 1
33f_dprintf "%s: loading includes..." networking/resolv.subr
34f_include $BSDCFG_SHARE/dialog.subr
35f_include $BSDCFG_SHARE/strings.subr
36f_include $BSDCFG_SHARE/media/tcpip.subr
37f_include $BSDCFG_SHARE/networking/common.subr
38f_include $BSDCFG_SHARE/networking/ipaddr.subr
39
40BSDCFG_LIBE="/usr/libexec/bsdconfig" APP_DIR="120.networking"
41f_include_lang $BSDCFG_LIBE/$APP_DIR/include/messages.subr
42
43############################################################ CONFIGURATION
44
45#
46# When updating resolv.conf(5), should we populate the `search' directive with
47# all possible sub-domains? In example, if the domain is "sub.domain.com", when
48# the below option is set to 1, include both "sub.domain.com" and "domain.com"
49# in the `search' directive, otherwise use only "sub.domain.com".
50#
51# When enabled (set to 1), specify the minimum number of dots required for each
52# `search' domain by setting the second option below, `RESOLVER_SEARCH_NDOTS'.
53#
54: ${RESOLVER_SEARCH_DOMAINS_ALL:=1}
55: ${RESOLVER_SEARCH_NDOTS:=1}
56
57############################################################ FUNCTIONS
58
59# f_resolv_conf_domain
60#
61# Returns the domain configured in resolv.conf(5).
62#
63f_resolv_conf_domain()
64{
65 tail -r "$RESOLV_CONF" 2> /dev/null | awk \
66 '
67 BEGIN { found = 0 }
68 ( tolower($1) == "domain" ) \
69 {
70 print $2
71 found = 1
72 exit
73 }
74 END { exit ! found }
75 '
76}
77
78# f_resolv_conf_search
79#
80# Returns the search configured in resolv.conf(5).
81#
82f_resolv_conf_search()
83{
84 tail -r "$RESOLV_CONF" 2> /dev/null | awk \
85 '
86 BEGIN { found = 0 }
87 {
88 tl0 = tolower($0)
89 if ( match(tl0, /^[[:space:]]*search[[:space:]]+/) ) {
90 search = substr($0, RLENGTH + 1)
91 sub(/[[:space:]]*#.*$/, "", search)
92 gsub(/[[:space:]]+/, " ", search)
93 print search
94 found = 1
95 exit
96 }
97 }
98 END { exit ! found }
99 '
100}
101
102# f_dialog_resolv_conf_update $hostname
103#
104# Updates the search/domain directives in resolv.conf(5) given a valid fully-
105# qualified hostname.
106#
107# This function is a two-parter. Below is the awk(1) portion of the function,
108# afterward is the sh(1) function which utilizes the below awk script.
109#
110f_dialog_resolv_conf_update_awk='
111# Variables that should be defined on the invocation line:
112# -v domain="domain"
113# -v search_all="0|1"
114# -v search_ndots="1+"
115#
116BEGIN {
117 domain_found = search_found = 0
118
119 if ( search_all ) {
120 search = ""
121 subdomain = domain
122 if ( search_ndots < 1 )
123 search_ndots = 1
124
125 ndots = split(subdomain, labels, ".") - 1
126 while ( ndots-- >= search_ndots ) {
127 if ( length(search) ) search = search " "
128 search = search subdomain
129 sub(/[^.]*\./, "", subdomain)
130 }
131 }
132 else search = domain
133}
134{
135 if ( domain_found && search_found ) { print; next }
136
137 tl0 = tolower($0)
138 if ( ! domain_found && \
139 match(tl0, /^[[:space:]]*domain[[:space:]]+/) ) \
140 {
141 if ( length(domain) ) {
142 printf "%s%s\n", substr($0, 0, RLENGTH), domain
143 domain_found = 1
144 }
145 }
146 else if ( ! search_found && \
147 match(tl0, /^[[:space:]]*search[[:space:]]+/) ) \
148 {
149 if ( length(search) ) {
150 printf "%s%s\n", substr($0, 0, RLENGTH), search
151 search_found = 1
152 }
153 }
154 else print
155}
156END {
157 if ( ! search_found && length(search) )
158 printf "search\t%s\n", search
159 if ( ! domain_found && length(domain) )
160 printf "domain\t%s\n", domain
161}
162'
163f_dialog_resolv_conf_update()
164{
165 local hostname="$1"
166
167 #
168 # Extrapolate the desired domain search parameter for resolv.conf(5)
169 #
170 local search ndots domain="${hostname#*.}"
171 if [ "$RESOLVER_SEARCH_DOMAINS_ALL" = "1" ]; then
172 search=""
173 ndots=$( IFS=.; set -- $domain; echo $(( $# - 1 )) )
174 while [ $ndots -ge ${RESOLVER_SEARCH_NDOTS:-1} ]; do
175 search="$search${search:+ }$domain"
176 domain="${domain#*.}"
177 ndots=$(( $ndots - 1 ))
178 done
179 domain="${hostname#*.}"
180 else
181 search="$domain"
182 fi
183
184 #
185 # Save domain/search information only if different from resolv.conf(5)
186 #
187 if [ "$domain" != "$( f_resolv_conf_domain )" -o \
188 "$search" != "$( f_resolv_conf_search )" ]
189 then
190 f_dialog_info "Saving new domain/search settings" \
191 "to resolv.conf(5)..."
192
193 #
194 # Create a new temporary file to write our resolv.conf(5)
195 # update with our new `domain' and `search' directives.
196 #
197 local tmpfile="$( mktemp -t "$pgm" )"
198 [ "$tmpfile" ] || return $FAILURE
199
200 #
201 # Fixup permissions and ownership (mktemp(1) creates the
202 # temporary file with 0600 permissions -- change the
203 # permissions and ownership to match resolv.conf(5) before
204 # we write it out and mv(1) it into place).
205 #
206 local mode="$( stat -f '%#Lp' "$RESOLV_CONF" 2> /dev/null )"
207 local owner="$( stat -f '%u:%g' "$RESOLV_CONF" 2> /dev/null )"
208 f_quietly chmod "${mode:-0644}" "$tmpfile"
209 f_quietly chown "${owner:-root:wheel}" "$tmpfile"
210
211 #
212 # Operate on resolv.conf(5), replacing only the last
213 # occurrences of `domain' and `search' directives (or add
214 # them to the top if not found), in strict-adherence to the
215 # following entry in resolver(5):
216 #
217 # The domain and search keywords are mutually exclusive.
218 # If more than one instance of these keywords is present,
219 # the last instance will override.
220 #
221 # NOTE: If RESOLVER_SEARCH_DOMAINS_ALL is set to `1' in the
222 # environment, all sub-domains will be added to the `search'
223 # directive, not just the FQDN.
224 #
225 local domain="${hostname#*.}" new_contents
226 [ "$domain" = "$hostname" ] && domain=
227 new_contents=$( tail -r "$RESOLV_CONF" 2> /dev/null )
228 new_contents=$( echo "$new_contents" | awk \
229 -v domain="$domain" \
230 -v search_all="${RESOLVER_SEARCH_DOMAINS_ALL:-1}" \
231 -v search_ndots="${RESOLVER_SEARCH_NDOTS:-1}" \
232 "$f_dialog_resolv_conf_update_awk" )
233
234 #
235 # Write the temporary file contents and move the temporary
236 # file into place.
237 #
238 echo "$new_contents" | tail -r > "$tmpfile" || return $FAILURE
239 f_quietly mv "$tmpfile" "$RESOLV_CONF"
240
241 fi
242}
243
244# f_dialog_input_nameserver [ $n $nameserver ]
245#
246# Allows the user to edit a given nameserver. The first argument is the
247# resolv.conf(5) nameserver ``instance'' integer. For example, this will be one
248# if editing the first nameserver instance, two if editing the second, three if
249# the third, ad nauseum. If this argument is zero, null, or missing, the value
250# entered by the user (if non-null) will be added to resolv.conf(5) as a new
251# `nameserver' entry. The second argument is the IPv4 address of the nameserver
252# to be edited -- this will be displayed as the initial value during the edit.
253#
254# Taint-checking is performed when editing an existing entry (when the second
255# argument is one or higher) in that the first argument must match the current
256# value of the Nth `nameserver' instance in resolv.conf(5) else an error is
257# generated discarding any/all changes.
258#
259# This function is a two-parter. Below is the awk(1) portion of the function,
260# afterward is the sh(1) function which utilizes the below awk script.
261#
262f_dialog_input_nameserver_edit_awk='
263# Variables that should be defined on the invocation line:
264# -v nsindex="1+"
265# -v old_value="..."
266# -v new_value="..."
267#
268BEGIN {
269 if ( nsindex < 1 ) exit 1
270 found = n = 0
271}
272{
273 if ( found ) { print; next }
274
275 if ( match(tolower($0), /^[[:space:]]*nameserver[[:space:]]+/)) {
276 if ( ++n == nsindex ) {
277 if ( $2 != old_value ) exit 2
278 if ( new_value != "" ) printf "%s%s\n", \
279 substr($0, 0, RLENGTH), new_value
280 found = 1
281 }
282 else print
283 }
284 else print
285}
286END { if ( ! found ) exit 3 }
287'
288f_dialog_input_nameserver()
289{
290 local index="${1:-0}" old_ns="$2" new_ns
291 local ns="$old_ns"
292
293 #
294 # Perform sanity checks
295 #
296 f_isinteger "$index" || return $FAILURE
297 [ $index -ge 0 ] || return $FAILURE
298
299 local msg
300 if [ $index -gt 0 ]; then
301 if [ "$USE_XDIALOG" ]; then
302 msg="$xmsg_please_enter_nameserver_existing"
303 else
304 msg="$msg_please_enter_nameserver_existing"
305 fi
306 else
307 msg="$msg_please_enter_nameserver"
308 fi
309
310 #
311 # Loop until the user provides taint-free input.
312 #
313 while :; do
314 f_dialog_input new_ns "$msg" "$ns" \
315 "$hline_num_punc_tab_enter" || return
316
317 # Take only the first "word" of the user's input
318 new_ns="${new_ns%%[$IFS]*}"
319
320 # Taint-check the user's input
321 [ "$new_ns" ] || break
322 f_dialog_validate_ipaddr "$new_ns" && break
323
324 # Update prompt to allow user to re-edit previous entry
325 ns="$new_ns"
326 done
327
328 #
329 # Save only if the user changed the nameserver.
330 #
331 if [ $index -eq "0" -a "$new_ns" ]; then
332 f_dialog_info "$msg_saving_nameserver"
333 printf "nameserver\t%s\n" "$new_ns" >> "$RESOLV_CONF"
334 return $SUCCESS
335 elif [ $index -gt 0 -a "$old_ns" != "$new_ns" ]; then
336 if [ "$new_ns" ]; then
337 msg="$msg_saving_nameserver_existing"
338 else
339 msg="$msg_removing_nameserver"
340 fi
341 f_dialog_info "$msg"
342
343 #
344 # Create a new temporary file to write our new resolv.conf(5)
345 #
346 local tmpfile="$( mktemp -t "$pgm" )"
347 [ "$tmpfile" ] || return $FAILURE
348
349 #
350 # Quietly fixup permissions and ownership
351 #
352 local mode owner
353 mode=$( stat -f '%#Lp' "$RESOLV_CONF" 2> /dev/null )
354 owner=$( stat -f '%u:%g' "$RESOLV_CONF" 2> /dev/null )
355 f_quietly chmod "${mode:-0644}" "$tmpfile"
356 f_quietly chown "${owner:-root:wheel}" "$tmpfile"
357
358 #
359 # Operate on resolv.conf(5)
360 #
361 local new_contents
362 new_contents=$( awk -v nsindex="$index" \
363 -v old_value="$old_ns" \
364 -v new_value="$new_ns" \
365 "$f_dialog_input_nameserver_edit_awk" \
366 "$RESOLV_CONF" )
367
368 #
369 # Produce an appropriate error message if necessary.
370 #
371 local retval=$?
372 case $retval in
373 1) f_die 1 "$msg_internal_error_nsindex_value" "$nsindex";;
374 2) f_dialog_msgbox "$msg_resolv_conf_changed_while_editing"
375 return $retval;;
376 3) f_dialog_msgbox "$msg_resolv_conf_entry_no_longer_exists"
377 return $retval;;
378 esac
379
380 #
381 # Write the temporary file contents and move the temporary
382 # file into place.
383 #
384 echo "$new_contents" > "$tmpfile" || return $FAILURE
385 f_quietly mv "$tmpfile" "$RESOLV_CONF"
386 fi
387}
388
389# f_dialog_menu_nameservers
390#
391# Edit the nameservers in resolv.conf(5).
392#
393f_dialog_menu_nameservers()
394{
395 local prompt="$msg_dns_configuration"
396 local menu_list # Calculated below
397 local hline="$hline_arrows_tab_enter"
398 local defaultitem=
395
396 local height width rows
397 local opt_exit="$msg_return_to_previous_menu"
398 local opt_add="$msg_add_nameserver"
399
400 local height width rows
401 local opt_exit="$msg_return_to_previous_menu"
402 local opt_add="$msg_add_nameserver"
399 local hline="$hline_arrows_tab_enter"
400 local prompt defaultitem=
401
402 #
403 # Loop forever until the user has finished configuring nameservers
404 #
403
404 #
405 # Loop forever until the user has finished configuring nameservers
406 #
405 prompt="$msg_dns_configuration"
406 while :; do
407 #
408 # Re/Build list of nameservers
409 #
410 local nameservers="$( f_resolv_conf_nameservers )"
407 while :; do
408 #
409 # Re/Build list of nameservers
410 #
411 local nameservers="$( f_resolv_conf_nameservers )"
411 local menu_list="$(
412 menu_list=$(
412 index=1
413
414 echo "'X $msg_exit' '$opt_exit'"
415 index=$(( $index + 1 ))
416
417 echo "'A $msg_add' '$opt_add'"
418 index=$(( $index + 1 ))
419
420 for ns in $nameservers; do
421 [ $index -lt ${#DIALOG_MENU_TAGS} ] || break
422 tag=$( f_substr "$DIALOG_MENU_TAGS" $index 1 )
423 echo "'$tag nameserver' '$ns'"
424 index=$(( $index + 1 ))
425 done
413 index=1
414
415 echo "'X $msg_exit' '$opt_exit'"
416 index=$(( $index + 1 ))
417
418 echo "'A $msg_add' '$opt_add'"
419 index=$(( $index + 1 ))
420
421 for ns in $nameservers; do
422 [ $index -lt ${#DIALOG_MENU_TAGS} ] || break
423 tag=$( f_substr "$DIALOG_MENU_TAGS" $index 1 )
424 echo "'$tag nameserver' '$ns'"
425 index=$(( $index + 1 ))
426 done
426 )"
427 )
427
428 #
429 # Display configuration-edit menu
430 #
431 eval f_dialog_menu_size height width rows \
432 \"\$DIALOG_TITLE\" \
433 \"\$DIALOG_BACKTITLE\" \
434 \"\$prompt\" \
435 \"\$hline\" \
436 $menu_list
437 local tag
438 tag=$( eval $DIALOG \
439 --title \"\$DIALOG_TITLE\" \
440 --backtitle \"\$DIALOG_BACKTITLE\" \
441 --hline \"\$hline\" \
442 --ok-label \"\$msg_ok\" \
443 --cancel-label \"\$msg_cancel\" \
444 --default-item \"\$defaultitem\" \
445 --menu \"\$prompt\" \
446 $height $width $rows \
447 $menu_list \
448 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
449 )
450 local retval=$?
451 f_dialog_data_sanitize tag
452
453 # Return if "Cancel" was chosen (-1) or ESC was pressed (255)
454 if [ $retval -ne $SUCCESS ]; then
455 return $retval
456 else
457 # Only update default-item on success
458 defaultitem="$tag"
459 fi
460
461 case "$tag" in
462 "X $msg_exit") break;;
463 "A $msg_add")
464 f_dialog_input_nameserver
465 ;;
466 *)
467 local n ns
468 n=$( eval f_dialog_menutag2index \"\$tag\" $menu_list )
469 ns=$( eval f_dialog_menutag2item \"\$tag\" $menu_list )
470 f_dialog_input_nameserver $(( $n - 2 )) "$ns"
471 ;;
472 esac
473 done
474}
475
476############################################################ MAIN
477
478f_dprintf "%s: Successfully loaded." networking/resolv.subr
479
480fi # ! $_NETWORKING_RESOLV_SUBR
428
429 #
430 # Display configuration-edit menu
431 #
432 eval f_dialog_menu_size height width rows \
433 \"\$DIALOG_TITLE\" \
434 \"\$DIALOG_BACKTITLE\" \
435 \"\$prompt\" \
436 \"\$hline\" \
437 $menu_list
438 local tag
439 tag=$( eval $DIALOG \
440 --title \"\$DIALOG_TITLE\" \
441 --backtitle \"\$DIALOG_BACKTITLE\" \
442 --hline \"\$hline\" \
443 --ok-label \"\$msg_ok\" \
444 --cancel-label \"\$msg_cancel\" \
445 --default-item \"\$defaultitem\" \
446 --menu \"\$prompt\" \
447 $height $width $rows \
448 $menu_list \
449 2>&1 >&$DIALOG_TERMINAL_PASSTHRU_FD
450 )
451 local retval=$?
452 f_dialog_data_sanitize tag
453
454 # Return if "Cancel" was chosen (-1) or ESC was pressed (255)
455 if [ $retval -ne $SUCCESS ]; then
456 return $retval
457 else
458 # Only update default-item on success
459 defaultitem="$tag"
460 fi
461
462 case "$tag" in
463 "X $msg_exit") break;;
464 "A $msg_add")
465 f_dialog_input_nameserver
466 ;;
467 *)
468 local n ns
469 n=$( eval f_dialog_menutag2index \"\$tag\" $menu_list )
470 ns=$( eval f_dialog_menutag2item \"\$tag\" $menu_list )
471 f_dialog_input_nameserver $(( $n - 2 )) "$ns"
472 ;;
473 esac
474 done
475}
476
477############################################################ MAIN
478
479f_dprintf "%s: Successfully loaded." networking/resolv.subr
480
481fi # ! $_NETWORKING_RESOLV_SUBR