summaryrefslogtreecommitdiffstats
path: root/dhcpcd-hooks/20-resolv.conf
blob: 7f69d4c295765a11d649ffb86da2e5fadb4e8243 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# Generate /etc/resolv.conf
# Support resolvconf(8) if available
# We can merge other dhcpcd resolv.conf files into one like resolvconf,
# but resolvconf is preferred as other applications like VPN clients
# can readily hook into it.
# Also, resolvconf can configure local nameservers such as bind
# or dnsmasq. This is important as the libc resolver isn't that powerful.

resolv_conf_dir="${state_dir}/resolv.conf"

build_resolv_conf()
{
	local cf="${state_dir}/resolv.conf.${interface}"
	local interfaces= header= search= srvs= servers= x=

	# Build a list of interfaces
	interfaces=$(list_interfaces "${resolv_conf_dir}")

	# Build the resolv.conf
	if [ -n "${interfaces}" ]; then
		# Build the header
		for x in ${interfaces}; do
			header="${header}${header:+, }${x}"
		done

		# Build the search list
		domain=$(cd "${resolv_conf_dir}"; \
			key_get_value "domain " ${interfaces})
		search=$(cd "${resolv_conf_dir}"; \
			key_get_value "search " ${interfaces})
		set -- ${domain}
		unset domain
		if [ -n "$2" ]; then
			search="${search} $@"
		elif [ -n "$1" ]; then
			domain="domain $1\n"
		fi
		[ -n "${search}" ] && search="search $(uniqify ${search})\n"

		# Build the nameserver list
		srvs=$(cd "${resolv_conf_dir}"; \
			key_get_value "nameserver " ${interfaces})
		for x in $(uniqify ${srvs}); do
			servers="${servers}nameserver ${x}\n"
		done
	fi
	header="${signature_base}${header:+ ${from} }${header}"

	# Assemble resolv.conf using our head and tail files
	[ -f "${cf}" ] && rm -f "${cf}"
	echo "${header}" > "${cf}"
	if [ -f /etc/resolv.conf.head ]; then
		cat /etc/resolv.conf.head >> "${cf}"
	else
		echo "# /etc/resolv.conf.head can replace this line" >> "${cf}"
	fi
	printf "${domain}${search}${servers}" >> "${cf}"
	if [ -f /etc/resolv.conf.tail ]; then
		cat /etc/resolv.conf.tail >> "${cf}"
	else
		echo "# /etc/resolv.conf.tail can replace this line" >> "${cf}"
	fi
	cat "${cf}" > /etc/resolv.conf
	chmod 644 /etc/resolv.conf
	rm -f "${cf}"
}

add_resolv_conf()
{
	local x= conf="${signature}\n"

	# If we don't have any configuration, remove it
	if [ -z "${new_domain_name_servers}" -a \
		-z "${new_domain_name}" -a \
		-z "${new_domain_search}" ]; then
		remove_resolv_conf
		return $?
	fi

	if [ -n "${new_domain_name}" ]; then
		set -- ${new_domain_name}
		new_domain_name="$1"
		conf="${conf}domain ${new_domain_name}\n"
		# Support RFC violating search in domain
		if [ -z "${new_domain_search}" -a -n "$2" ]; then
			new_domain_search="$@"
		fi
	fi
	if [ -n "${new_domain_search}" ]; then
		conf="${conf}search ${new_domain_search}\n"
	fi
	for x in ${new_domain_name_servers}; do
		conf="${conf}nameserver ${x}\n"
	done
	if type resolvconf >/dev/null 2>&1; then
		[ -n "${metric}" ] && export IF_METRIC="${metric}"
		printf "${conf}" | resolvconf -a "${interface}"
		return $?
	fi

	if [ -e "${resolv_conf_dir}/${interface}" ]; then
		rm -f "${resolv_conf_dir}/${interface}"
	fi
	if [ ! -d "${resolv_conf_dir}" ]; then
		mkdir -p "${resolv_conf_dir}"
	fi
	printf "${conf}" > "${resolv_conf_dir}/${interface}"
	build_resolv_conf
}

remove_resolv_conf()
{
	if type resolvconf >/dev/null 2>&1; then
		resolvconf -d "${interface}" -f
	else
		if [ -e "${resolv_conf_dir}/${interface}" ]; then
			rm -f "${resolv_conf_dir}/${interface}"
		fi
		build_resolv_conf
	fi
}

case "${reason}" in
BOUND|INFORM|REBIND|REBOOT|RENEW|TIMEOUT|STATIC)	add_resolv_conf;;
PREINIT|EXPIRE|FAIL|IPV4LL|NAK|NOCARRIER|RELEASE|STOP)	remove_resolv_conf;;
esac