xref: /netbsd-src/external/bsd/openresolv/dist/libc.in (revision 59c22029c4938f7f5a598754771a670ab2ba89b8)
1793621c9Sroy#!/bin/sh
2*59c22029Sroy# Copyright (c) 2007-2023 Roy Marples
3793621c9Sroy# All rights reserved
4793621c9Sroy
5793621c9Sroy# libc subscriber for resolvconf
6793621c9Sroy
7793621c9Sroy# Redistribution and use in source and binary forms, with or without
8793621c9Sroy# modification, are permitted provided that the following conditions
9793621c9Sroy# are met:
10793621c9Sroy#     * Redistributions of source code must retain the above copyright
11793621c9Sroy#       notice, this list of conditions and the following disclaimer.
12793621c9Sroy#     * Redistributions in binary form must reproduce the above
13793621c9Sroy#       copyright notice, this list of conditions and the following
14793621c9Sroy#       disclaimer in the documentation and/or other materials provided
15793621c9Sroy#       with the distribution.
16793621c9Sroy#
17793621c9Sroy# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18793621c9Sroy# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19793621c9Sroy# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20793621c9Sroy# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21793621c9Sroy# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22793621c9Sroy# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23793621c9Sroy# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24793621c9Sroy# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25793621c9Sroy# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26793621c9Sroy# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27793621c9Sroy# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28793621c9Sroy
29793621c9SroySYSCONFDIR=@SYSCONFDIR@
30793621c9SroyLIBEXECDIR=@LIBEXECDIR@
31793621c9SroyVARDIR=@VARDIR@
32793621c9SroyIFACEDIR="$VARDIR/interfaces"
33d8775c93SroyNL="
34d8775c93Sroy"
35793621c9Sroy
36793621c9Sroy# sed may not be available, and this is faster on small files
37793621c9Sroykey_get_value()
38793621c9Sroy{
39e37204c6Sroy	key="$1"
40793621c9Sroy	shift
41e37204c6Sroy
42793621c9Sroy	if [ $# -eq 0 ]; then
4302c18234Sroy		while read -r line; do
44793621c9Sroy			case "$line" in
45793621c9Sroy			"$key"*) echo "${line##$key}";;
46793621c9Sroy			esac
47793621c9Sroy		done
48793621c9Sroy	else
4902c18234Sroy		for x do
5002c18234Sroy			while read -r line; do
51793621c9Sroy				case "$line" in
52793621c9Sroy				"$key"*) echo "${line##$key}";;
53793621c9Sroy				esac
54793621c9Sroy			done < "$x"
55793621c9Sroy		done
56793621c9Sroy	fi
57793621c9Sroy}
58793621c9Sroy
5902c18234Sroykeys_remove()
6002c18234Sroy{
6102c18234Sroy	while read -r line; do
6202c18234Sroy		found=false
6302c18234Sroy		for key do
6402c18234Sroy			case "$line" in
6502c18234Sroy			"$key"*|"#"*|" "*|"	"*|"") found=true;;
6602c18234Sroy			esac
6702c18234Sroy			$found && break
6802c18234Sroy		done
6902c18234Sroy		$found || echo "$line"
7002c18234Sroy	done
7102c18234Sroy}
7202c18234Sroy
73075ee3c1Sroylocal_nameservers="127.* 0.0.0.0 255.255.255.255 ::1"
74075ee3c1Sroy
75793621c9Sroy# Support original resolvconf configuration layout
76793621c9Sroy# as well as the openresolv config file
77793621c9Sroyif [ -f "$SYSCONFDIR"/resolvconf.conf ]; then
78793621c9Sroy	. "$SYSCONFDIR"/resolvconf.conf
79793621c9Sroyelif [ -d "$SYSCONFDIR"/resolvconf ]; then
80e37204c6Sroy	SYSCONFDIR="$SYSCONFDIR/resolvconf"
81793621c9Sroy	base="$SYSCONFDIR/resolv.conf.d/base"
82793621c9Sroy	if [ -f "$base" ]; then
83e9917e6eSroy		prepend_nameservers="$(key_get_value "nameserver " "$base")"
8402c18234Sroy		domain="$(key_get_value "domain " "$base")"
85e9917e6eSroy		prepend_search="$(key_get_value "search " "$base")"
86793621c9Sroy		resolv_conf_options="$(key_get_value "options " "$base")"
8702c18234Sroy		resolv_conf_sortlist="$(key_get_value "sortlist " "$base")"
88793621c9Sroy	fi
89793621c9Sroy	if [ -f "$SYSCONFDIR"/resolv.conf.d/head ]; then
90793621c9Sroy		resolv_conf_head="$(cat "${SYSCONFDIR}"/resolv.conf.d/head)"
91793621c9Sroy	fi
92793621c9Sroy	if [ -f "$SYSCONFDIR"/resolv.conf.d/tail ]; then
93793621c9Sroy		resolv_conf_tail="$(cat "$SYSCONFDIR"/resolv.conf.d/tail)"
94793621c9Sroy	fi
95793621c9Sroyfi
96793621c9Sroy: ${resolv_conf:=/etc/resolv.conf}
97*59c22029Sroy: ${resolv_conf_tmp:="$resolv_conf.$$.openresolv"}
98d8775c93Sroy: ${libc_service:=nscd}
99e9917e6eSroy: ${list_resolv:=@SBINDIR@/resolvconf -l}
100d7a1218eSkreif [ "${resolv_conf_head-x}" = x ] && [ -f "$SYSCONFDIR"/resolv.conf.head ]
101d7a1218eSkrethen
102793621c9Sroy	resolv_conf_head="$(cat "${SYSCONFDIR}"/resolv.conf.head)"
103793621c9Sroyfi
104d7a1218eSkreif [ "${resolv_conf_tail-x}" = x ] && [ -f "$SYSCONFDIR"/resolv.conf.tail ]
105d7a1218eSkrethen
106793621c9Sroy	resolv_conf_tail="$(cat "$SYSCONFDIR"/resolv.conf.tail)"
107793621c9Sroyfi
108793621c9Sroy
109548d7cc4Sroybackup=true
110548d7cc4Sroysignature="# Generated by resolvconf"
111548d7cc4Sroy
112793621c9Sroyuniqify()
113793621c9Sroy{
114e37204c6Sroy	result=
115793621c9Sroy	while [ -n "$1" ]; do
116793621c9Sroy		case " $result " in
117793621c9Sroy		*" $1 "*);;
118793621c9Sroy		*) result="$result $1";;
119793621c9Sroy		esac
120793621c9Sroy		shift
121793621c9Sroy	done
122793621c9Sroy	echo "${result# *}"
123793621c9Sroy}
124793621c9Sroy
125793621c9Sroycase "${resolv_conf_passthrough:-NO}" in
126793621c9Sroy[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
127548d7cc4Sroy	backup=false
128793621c9Sroy	newest=
129793621c9Sroy	for conf in "$IFACEDIR"/*; do
130d7a1218eSkre		if [ -z "$newest" ] || [ "$conf" -nt "$newest" ]; then
131793621c9Sroy			newest="$conf"
132793621c9Sroy		fi
133793621c9Sroy	done
134793621c9Sroy	[ -z "$newest" ] && exit 0
135d8775c93Sroy	newconf="$(cat "$newest")$NL"
136793621c9Sroy	;;
137075ee3c1Sroy/dev/null|[Nn][Uu][Ll][Ll])
138075ee3c1Sroy	: ${resolv_conf_local_only:=NO}
139075ee3c1Sroy	if [ "$local_nameservers" = "127.* 0.0.0.0 255.255.255.255 ::1" ]; then
140075ee3c1Sroy		local_nameservers=
141075ee3c1Sroy	fi
142075ee3c1Sroy	# Need to overwrite our variables.
143075ee3c1Sroy	eval "$(@SBINDIR@/resolvconf -V)"
144075ee3c1Sroy	;;
145075ee3c1Sroy
146793621c9Sroy*)
147e9917e6eSroy	[ -z "$RESOLVCONF" ] && eval "$(@SBINDIR@/resolvconf -v)"
148075ee3c1Sroy	;;
149075ee3c1Sroyesac
150075ee3c1Sroycase "${resolv_conf_passthrough:-NO}" in
151075ee3c1Sroy[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1) ;;
152075ee3c1Sroy*)
153075ee3c1Sroy	: ${domain:=$DOMAIN}
154548d7cc4Sroy	newsearch="$(uniqify $prepend_search $SEARCH $append_search)"
155cf0cc01bSroy	NS="$LOCALNAMESERVERS $NAMESERVERS"
156cf0cc01bSroy	newns=
157cf0cc01bSroy	gotlocal=false
158548d7cc4Sroy	for n in $(uniqify $prepend_nameservers $NS $append_nameservers); do
159cf0cc01bSroy		add=true
160075ee3c1Sroy		islocal=false
161075ee3c1Sroy		for l in $local_nameservers; do
162cf0cc01bSroy			case "$n" in
163075ee3c1Sroy			$l) islocal=true; gotlocal=true; break;;
164075ee3c1Sroy			esac
165075ee3c1Sroy		done
166075ee3c1Sroy		if ! $islocal; then
167cf0cc01bSroy			case "${resolv_conf_local_only:-YES}" in
168cf0cc01bSroy			[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
169cf0cc01bSroy				$gotlocal && add=false;;
170333b3001Sroy			esac
171075ee3c1Sroy		fi
172cf0cc01bSroy		$add && newns="$newns $n"
173cf0cc01bSroy	done
174793621c9Sroy
175793621c9Sroy	# Hold our new resolv.conf in a variable to save on temporary files
176548d7cc4Sroy	newconf="$signature$NL"
177793621c9Sroy	if [ -n "$resolv_conf_head" ]; then
178d8775c93Sroy		newconf="$newconf$resolv_conf_head$NL"
179793621c9Sroy	fi
18002c18234Sroy
18102c18234Sroy	[ -n "$domain" ] && newconf="${newconf}domain $domain$NL"
182d7a1218eSkre	if [ -n "$newsearch" ] && [ "$newsearch" != "$domain" ]; then
18302c18234Sroy		newconf="${newconf}search $newsearch$NL"
18402c18234Sroy	fi
185793621c9Sroy	for n in $newns; do
186d8775c93Sroy		newconf="${newconf}nameserver $n$NL"
187793621c9Sroy	done
188793621c9Sroy
18902c18234Sroy	# Now add anything we don't care about such as sortlist and options
19002c18234Sroy	stuff="$($list_resolv | keys_remove nameserver domain search)"
19102c18234Sroy	if [ -n "$stuff" ]; then
19202c18234Sroy		newconf="$newconf$stuff$NL"
19302c18234Sroy	fi
19402c18234Sroy
19502c18234Sroy	# Append any user defined ones
19602c18234Sroy	if [ -n "$resolv_conf_options" ]; then
19702c18234Sroy		newconf="${newconf}options $resolv_conf_options$NL"
19802c18234Sroy	fi
19902c18234Sroy	if [ -n "$resolv_conf_sortlist" ]; then
20002c18234Sroy		newconf="${newconf}sortlist $resolv_conf_sortlist$NL"
201793621c9Sroy	fi
202793621c9Sroy
203793621c9Sroy	if [ -n "$resolv_conf_tail" ]; then
204d8775c93Sroy		newconf="$newconf$resolv_conf_tail$NL"
205793621c9Sroy	fi
206793621c9Sroy	;;
207793621c9Sroyesac
208793621c9Sroy
209793621c9Sroy# Check if the file has actually changed or not
210793621c9Sroyif [ -e "$resolv_conf" ]; then
211d8775c93Sroy	[ "$(cat "$resolv_conf")" = "$(printf %s "$newconf")" ] && exit 0
212793621c9Sroyfi
213793621c9Sroy
214548d7cc4Sroy# Change is good.
215548d7cc4Sroy# If the old file does not have our signature, back it up.
216548d7cc4Sroy# If the new file just has our signature, restore the backup.
217548d7cc4Sroyif $backup; then
218548d7cc4Sroy	if [ "$newconf" = "$signature$NL" ]; then
219548d7cc4Sroy		if [ -e "$resolv_conf.bak" ]; then
220292189d7Sroy			newconf="$(cat "$resolv_conf.bak")$NL"
221548d7cc4Sroy		fi
222548d7cc4Sroy	elif [ -e "$resolv_conf" ]; then
223548d7cc4Sroy		read line <"$resolv_conf"
224548d7cc4Sroy		if [ "$line" != "$signature" ]; then
225548d7cc4Sroy			cp "$resolv_conf" "$resolv_conf.bak"
226548d7cc4Sroy		fi
227548d7cc4Sroy	fi
228548d7cc4Sroyfi
229548d7cc4Sroy
230*59c22029Sroy# There are pros and cons for writing directly to resolv.conf
231*59c22029Sroy# instead of a temporary file and then moving it over.
232*59c22029Sroy# The default is to write to resolv.conf as it has the least
233*59c22029Sroy# issues and has been the long standing default behaviour.
234*59c22029Sroycase "${resolv_conf_mv:-NO}" in
235*59c22029Sroy[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
236*59c22029Sroy	# Protect against symlink attack, ensure new file does not exist
237*59c22029Sroy	rm -f "$resolv_conf_tmp"
238*59c22029Sroy	# Keep original file owner, group and mode
239*59c22029Sroy	[ -r "$resolv_conf" ] && cp -p "$resolv_conf" "$resolv_conf_tmp"
240793621c9Sroy	# Create our resolv.conf now
241*59c22029Sroy	if (umask 022; printf %s "$newconf" >"$resolv_conf_tmp"); then
242*59c22029Sroy		mv "$resolv_conf_tmp" "$resolv_conf"
243*59c22029Sroy	fi
244*59c22029Sroy	;;
245*59c22029Sroy*)
24602c18234Sroy	(umask 022; printf %s "$newconf" >"$resolv_conf")
247*59c22029Sroy	;;
248*59c22029Sroyesac
249*59c22029Sroy
2509d6c0475Sroyif [ -n "$libc_restart" ]; then
251793621c9Sroy	eval $libc_restart
2529d6c0475Sroyelif [ -n "$RESTARTCMD" ]; then
2539d6c0475Sroy	set -- ${libc_service}
2544fa65b6bSkre	eval "$RESTARTCMD"
2559d6c0475Sroyelse
2569d6c0475Sroy	@SBINDIR@/resolvconf -r ${libc_service}
2579d6c0475Sroyfi
258793621c9Sroy
259793621c9Sroyretval=0
260793621c9Sroy# Notify users of the resolver
261793621c9Sroyfor script in "$LIBEXECDIR"/libc.d/*; do
2625bcbb70cSroy	if [ -f "$script" ]; then
2635bcbb70cSroy		if [ -x "$script" ]; then
264793621c9Sroy			"$script" "$@"
2655bcbb70cSroy		else
266d8775c93Sroy			(. "$script")
2675bcbb70cSroy		fi
268793621c9Sroy		retval=$(($retval + $?))
269793621c9Sroy	fi
270793621c9Sroydone
271793621c9Sroyexit $retval
272