Home | History | Annotate | Download | only in dhcpcd-hooks
      1 # Generate /etc/resolv.conf
      2 # Support resolvconf(8) if available
      3 # We can merge other dhcpcd resolv.conf files into one like resolvconf,
      4 # but resolvconf is preferred as other applications like VPN clients
      5 # can readily hook into it.
      6 # Also, resolvconf can configure local nameservers such as bind
      7 # or dnsmasq. This is important as the libc resolver isn't that powerful.
      8 
      9 resolv_conf_dir="$state_dir/resolv.conf"
     10 NL="
     11 "
     12 
     13 build_resolv_conf()
     14 {
     15 	local cf="$state_dir/resolv.conf.$ifname"
     16 	local interfaces= header= search= srvs= servers= x=
     17 
     18 	# Build a list of interfaces
     19 	interfaces=$(list_interfaces "$resolv_conf_dir")
     20 
     21 	# Build the resolv.conf
     22 	if [ -n "$interfaces" ]; then
     23 		# Build the header
     24 		for x in ${interfaces}; do
     25 			header="$header${header:+, }$x"
     26 		done
     27 
     28 		# Build the search list
     29 		domain=$(cd "$resolv_conf_dir"; \
     30 			key_get_value "domain " ${interfaces})
     31 		search=$(cd "$resolv_conf_dir"; \
     32 			key_get_value "search " ${interfaces})
     33 		set -- ${domain}
     34 		domain="$1"
     35 		[ -n "$2" ] && search="$search $*"
     36 		[ -n "$search" ] && search="$(uniqify $search)"
     37 		[ "$domain" = "$search" ] && search=
     38 		[ -n "$domain" ] && domain="domain $domain$NL"
     39 		[ -n "$search" ] && search="search $search$NL"
     40 
     41 		# Build the nameserver list
     42 		srvs=$(cd "$resolv_conf_dir"; \
     43 			key_get_value "nameserver " ${interfaces})
     44 		for x in $(uniqify ${srvs}); do
     45 			servers="${servers}nameserver $x$NL"
     46 		done
     47 	fi
     48 	header="$signature_base${header:+ $from }$header"
     49 
     50 	# Assemble resolv.conf using our head and tail files
     51 	[ -f "$cf" ] && rm -f "$cf"
     52 	[ -d "$resolv_conf_dir" ] || mkdir -p "$resolv_conf_dir"
     53 	echo "$header" > "$cf"
     54 	if [ -f /etc/resolv.conf.head ]; then
     55 		cat /etc/resolv.conf.head >> "$cf"
     56 	else
     57 		echo "# /etc/resolv.conf.head can replace this line" >> "$cf"
     58 	fi
     59 	printf %s "$domain$search$servers" >> "$cf"
     60 	if [ -f /etc/resolv.conf.tail ]; then
     61 		cat /etc/resolv.conf.tail >> "$cf"
     62 	else
     63 		echo "# /etc/resolv.conf.tail can replace this line" >> "$cf"
     64 	fi
     65 	if change_file /etc/resolv.conf "$cf"; then
     66 		chmod 644 /etc/resolv.conf
     67 	fi
     68 	rm -f "$cf"
     69 }
     70 
     71 add_resolv_conf()
     72 {
     73 	local x= conf="$signature$NL" i=${ra_count:-0} ra= warn=true
     74 
     75 	while [ $i -ne 0 ]; do
     76 		eval ra=\$ra${i}_rdnss
     77 		new_domain_name_servers="$new_domain_name_servers${new_domain_name_servers:+ }$ra"
     78 		eval ra=\$ra${i}_dnssl
     79 		new_domain_search="$new_domain_search${new_domain_search:+ }$ra"
     80 		i=$(($i - 1))
     81 	done
     82 
     83 	# If we don't have any configuration, remove it
     84 	if [ -z "$new_domain_name_servers" -a \
     85 		-z "$new_domain_name" -a \
     86 		-z "$new_domain_search" ]; then
     87 		remove_resolv_conf
     88 		return $?
     89 	fi
     90 
     91 	# Derive a new domain from our various hostname options
     92 	if [ -z "$new_domain_name" ]; then
     93 		if [ "$new_dhcp6_fqdn" != "${new_dhcp6_fqdn#*.}" ]; then
     94 			new_domain_name="${new_dhcp6_fqdn#*.}"
     95 		elif [ "$new_fqdn" != "${new_fqdn#*.}" ]; then
     96 			new_domain_name="${new_fqdn#*.}"
     97 		elif [ "$new_host_name" != "${new_host_name#*.}" ]; then
     98 			new_domain_name="${new_host_name#*.}"
     99 		fi
    100 	fi
    101 
    102 	if [ -n "$new_domain_name" ]; then
    103 		set -- $new_domain_name
    104 		if valid_domainname "$1"; then
    105 			conf="${conf}domain $1$NL"
    106 		else
    107 			syslog err "Invalid domain name: $1"
    108 		fi
    109 		# If there is no search this, make this one
    110 		if [ -z "$new_domain_search" ]; then
    111 			new_domain_search="$new_domain_name"
    112 			[ "$new_domain_name" = "$1" ] && warn=true
    113 		fi
    114 	fi
    115 	if [ -n "$new_domain_search" ]; then
    116 		if valid_domainname_list $new_domain_search; then
    117 			conf="${conf}search $new_domain_search$NL"
    118 		elif ! $warn; then
    119 			syslog err "Invalid domain name in list:" \
    120 			    "$new_domain_search"
    121 		fi
    122 	fi
    123 	for x in ${new_domain_name_servers}; do
    124 		conf="${conf}nameserver $x$NL"
    125 	done
    126 	if type resolvconf >/dev/null 2>&1; then
    127 		[ -n "$ifmetric" ] && export IF_METRIC="$ifmetric"
    128 		printf %s "$conf" | resolvconf -a "$ifname"
    129 		return $?
    130 	fi
    131 
    132 	if [ -e "$resolv_conf_dir/$ifname" ]; then
    133 		rm -f "$resolv_conf_dir/$ifname"
    134 	fi
    135 	[ -d "$resolv_conf_dir" ] || mkdir -p "$resolv_conf_dir"
    136 	printf %s "$conf" > "$resolv_conf_dir/$ifname"
    137 	build_resolv_conf
    138 }
    139 
    140 remove_resolv_conf()
    141 {
    142 	if type resolvconf >/dev/null 2>&1; then
    143 		resolvconf -d "$ifname" -f
    144 	else
    145 		if [ -e "$resolv_conf_dir/$ifname" ]; then
    146 			rm -f "$resolv_conf_dir/$ifname"
    147 		fi
    148 		build_resolv_conf
    149 	fi
    150 }
    151 
    152 # For ease of use, map DHCP6 names onto our DHCP4 names
    153 case "$reason" in
    154 BOUND6|RENEW6|REBIND6|REBOOT6|INFORM6)
    155 	new_domain_name_servers="$new_dhcp6_name_servers"
    156 	new_domain_search="$new_dhcp6_domain_search"
    157 	;;
    158 esac
    159 
    160 if $if_up || [ "$reason" = ROUTERADVERT ]; then
    161 	add_resolv_conf
    162 elif $if_down; then
    163 	remove_resolv_conf
    164 fi
    165