summaryrefslogtreecommitdiffstats
path: root/dhcpcd/dhcpcd-hooks/20-resolv.conf
diff options
context:
space:
mode:
Diffstat (limited to 'dhcpcd/dhcpcd-hooks/20-resolv.conf')
-rw-r--r--dhcpcd/dhcpcd-hooks/20-resolv.conf165
1 files changed, 165 insertions, 0 deletions
diff --git a/dhcpcd/dhcpcd-hooks/20-resolv.conf b/dhcpcd/dhcpcd-hooks/20-resolv.conf
new file mode 100644
index 00000000..05316c9f
--- /dev/null
+++ b/dhcpcd/dhcpcd-hooks/20-resolv.conf
@@ -0,0 +1,165 @@
+# 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"
+NL="
+"
+
+build_resolv_conf()
+{
+ local cf="$state_dir/resolv.conf.$ifname"
+ 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}
+ domain="$1"
+ [ -n "$2" ] && search="$search $*"
+ [ -n "$search" ] && search="$(uniqify $search)"
+ [ "$domain" = "$search" ] && search=
+ [ -n "$domain" ] && domain="domain $domain$NL"
+ [ -n "$search" ] && search="search $search$NL"
+
+ # Build the nameserver list
+ srvs=$(cd "$resolv_conf_dir"; \
+ key_get_value "nameserver " ${interfaces})
+ for x in $(uniqify ${srvs}); do
+ servers="${servers}nameserver $x$NL"
+ done
+ fi
+ header="$signature_base${header:+ $from }$header"
+
+ # Assemble resolv.conf using our head and tail files
+ [ -f "$cf" ] && rm -f "$cf"
+ [ -d "$resolv_conf_dir" ] || mkdir -p "$resolv_conf_dir"
+ 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 %s "$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
+ if change_file /etc/resolv.conf "$cf"; then
+ chmod 644 /etc/resolv.conf
+ fi
+ rm -f "$cf"
+}
+
+add_resolv_conf()
+{
+ local x= conf="$signature$NL" i=${ra_count:-0} ra=
+
+ while [ $i -ne 0 ]; do
+ eval ra=\$ra${i}_rdnss
+ new_domain_name_servers="$new_domain_name_servers${new_domain_name_servers:+ }$ra"
+ eval ra=\$ra${i}_dnssl
+ new_domain_search="$new_domain_search${new_domain_search:+ }$ra"
+ i=$(($i - 1))
+ done
+
+ # 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
+
+ # Derive a new domain from our various hostname options
+ if [ -z "$new_domain_name" ]; then
+ if [ "$new_dhcp6_fqdn" != "${new_dhcp6_fqdn#*.}" ]; then
+ new_domain_name="${new_dhcp6_fqdn#*.}"
+ elif [ "$new_fqdn" != "${new_fqdn#*.}" ]; then
+ new_domain_name="${new_fqdn#*.}"
+ elif [ "$new_host_name" != "${new_host_name#*.}" ]; then
+ new_domain_name="${new_host_name#*.}"
+ fi
+ fi
+
+ if [ -n "$new_domain_name" ]; then
+ set -- $new_domain_name
+ new_domain_name="$1"
+ if valid_domainname "$new_domain_name"; then
+ conf="${conf}domain $new_domain_name$NL"
+ else
+ syslog err "Invalid domain name: $new_domain_name"
+ fi
+ # 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" -a \
+ "$new_domain_search" != "$new_domain_name" ]
+ then
+ if valid_domainname_list $new_domain_search; then
+ conf="${conf}search $new_domain_search$NL"
+ else
+ syslog err "Invalid domain name in list: $new_domain_search"
+ fi
+ fi
+ for x in ${new_domain_name_servers}; do
+ conf="${conf}nameserver $x$NL"
+ done
+ if type resolvconf >/dev/null 2>&1; then
+ [ -n "$ifmetric" ] && export IF_METRIC="$ifmetric"
+ printf %s "$conf" | resolvconf -a "$ifname"
+ return $?
+ fi
+
+ if [ -e "$resolv_conf_dir/$ifname" ]; then
+ rm -f "$resolv_conf_dir/$ifname"
+ fi
+ [ -d "$resolv_conf_dir" ] || mkdir -p "$resolv_conf_dir"
+ printf %s "$conf" > "$resolv_conf_dir/$ifname"
+ build_resolv_conf
+}
+
+remove_resolv_conf()
+{
+ if type resolvconf >/dev/null 2>&1; then
+ resolvconf -d "$ifname" -f
+ else
+ if [ -e "$resolv_conf_dir/$ifname" ]; then
+ rm -f "$resolv_conf_dir/$ifname"
+ fi
+ build_resolv_conf
+ fi
+}
+
+# For ease of use, map DHCP6 names onto our DHCP4 names
+case "$reason" in
+BOUND6|RENEW6|REBIND6|REBOOT6|INFORM6)
+ new_domain_name_servers="$new_dhcp6_name_servers"
+ new_domain_search="$new_dhcp6_domain_search"
+ ;;
+esac
+
+if $if_up || [ "$reason" = ROUTERADVERT ]; then
+ add_resolv_conf
+elif $if_down; then
+ remove_resolv_conf
+fi