Home | History | Annotate | Line # | Download | only in hooks
20-resolv.conf revision 1.4
      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 : ${resolvconf:=resolvconf}
     13 
     14 build_resolv_conf()
     15 {
     16 	cf="$state_dir/resolv.conf.$ifname"
     17 
     18 	# Build a list of interfaces
     19 	interfaces=$(list_interfaces "$resolv_conf_dir")
     20 
     21 	# Build the resolv.conf
     22 	header=
     23 	if [ -n "$interfaces" ]; then
     24 		# Build the header
     25 		for x in ${interfaces}; do
     26 			header="$header${header:+, }$x"
     27 		done
     28 
     29 		# Build the search list
     30 		domain=$(cd "$resolv_conf_dir"; \
     31 			key_get_value "domain " ${interfaces})
     32 		search=$(cd "$resolv_conf_dir"; \
     33 			key_get_value "search " ${interfaces})
     34 		set -- ${domain}
     35 		domain="$1"
     36 		[ -n "$2" ] && search="$search $*"
     37 		[ -n "$search" ] && search="$(uniqify $search)"
     38 		[ "$domain" = "$search" ] && search=
     39 		[ -n "$domain" ] && domain="domain $domain$NL"
     40 		[ -n "$search" ] && search="search $search$NL"
     41 
     42 		# Build the nameserver list
     43 		srvs=$(cd "$resolv_conf_dir"; \
     44 			key_get_value "nameserver " ${interfaces})
     45 		for x in $(uniqify $srvs); do
     46 			servers="${servers}nameserver $x$NL"
     47 		done
     48 	fi
     49 	header="$signature_base${header:+ $from }$header"
     50 
     51 	# Assemble resolv.conf using our head and tail files
     52 	[ -f "$cf" ] && rm -f "$cf"
     53 	[ -d "$resolv_conf_dir" ] || mkdir -p "$resolv_conf_dir"
     54 	echo "$header" > "$cf"
     55 	if [ -f /etc/resolv.conf.head ]; then
     56 		cat /etc/resolv.conf.head >> "$cf"
     57 	else
     58 		echo "# /etc/resolv.conf.head can replace this line" >> "$cf"
     59 	fi
     60 	printf %s "$domain$search$servers" >> "$cf"
     61 	if [ -f /etc/resolv.conf.tail ]; then
     62 		cat /etc/resolv.conf.tail >> "$cf"
     63 	else
     64 		echo "# /etc/resolv.conf.tail can replace this line" >> "$cf"
     65 	fi
     66 	if change_file /etc/resolv.conf "$cf"; then
     67 		chmod 644 /etc/resolv.conf
     68 	fi
     69 	rm -f "$cf"
     70 }
     71 
     72 # Extract any ND DNS options from the RA
     73 # Obey the lifetimes
     74 eval_nd_dns()
     75 {
     76 
     77 	eval rdnsstime=\$nd${i}_rdnss${j}_lifetime
     78 	[ -z "$rdnsstime" ] && return 1
     79 	ltime=$(($rdnsstime - $offset))
     80 	if [ "$ltime" -gt 0 ]; then
     81 		eval rdnss=\$nd${i}_rdnss${j}_servers
     82 		[ -n "$rdnss" ] && new_rdnss="$new_rdnss${new_rdnss:+ }$rdnss"
     83 	fi
     84 
     85 	eval dnssltime=\$nd${i}_dnssl${j}_lifetime
     86 	[ -z "$dnssltime" ] && return 1
     87 	ltime=$(($dnssltime - $offset))
     88 	if [ "$ltime" -gt 0 ]; then
     89 		eval dnssl=\$nd${i}_dnssl${j}_search
     90 		[ -n "$dnssl" ] && new_dnssl="$new_dnssl${new_dnssl:+ }$dnssl"
     91 	fi
     92 
     93 	j=$(($j + 1))
     94 	return 0
     95 }
     96 
     97 add_resolv_conf()
     98 {
     99 	conf="$signature$NL"
    100 	warn=true
    101 
    102 	# Loop to extract the ND DNS options using our indexed shell values
    103 	i=1
    104 	j=1
    105 	while true; do
    106 		eval acquired=\$nd${i}_acquired
    107 		[ -z "$acquired" ] && break
    108 		eval now=\$nd${i}_now
    109 		[ -z "$now" ] && break
    110 		offset=$(($now - $acquired))
    111 		while true; do
    112 			eval_nd_dns || break
    113 		done
    114 		i=$(($i + 1))
    115 		j=1
    116 	done
    117 	[ -n "$new_rdnss" ] && \
    118 	    new_domain_name_servers="$new_domain_name_servers${new_domain_name_servers:+ }$new_rdnss"
    119 	[ -n "$new_dnssl" ] && \
    120 	    new_domain_search="$new_domain_search${new_domain_search:+ }$new_dnssl"
    121 
    122 	# Derive a new domain from our various hostname options
    123 	if [ -z "$new_domain_name" ]; then
    124 		if [ "$new_dhcp6_fqdn" != "${new_dhcp6_fqdn#*.}" ]; then
    125 			new_domain_name="${new_dhcp6_fqdn#*.}"
    126 		elif [ "$new_fqdn" != "${new_fqdn#*.}" ]; then
    127 			new_domain_name="${new_fqdn#*.}"
    128 		elif [ "$new_host_name" != "${new_host_name#*.}" ]; then
    129 			new_domain_name="${new_host_name#*.}"
    130 		fi
    131 	fi
    132 
    133 	# If we don't have any configuration, remove it
    134 	if [ -z "$new_domain_name_servers" ] &&
    135 	   [ -z "$new_domain_name" ] &&
    136 	   [ -z "$new_domain_search" ]; then
    137 		remove_resolv_conf
    138 		return $?
    139 	fi
    140 
    141 	if [ -n "$new_domain_name" ]; then
    142 		set -- $new_domain_name
    143 		if valid_domainname "$1"; then
    144 			conf="${conf}domain $1$NL"
    145 		else
    146 			syslog err "Invalid domain name: $1"
    147 		fi
    148 		# If there is no search this, make this one
    149 		if [ -z "$new_domain_search" ]; then
    150 			new_domain_search="$new_domain_name"
    151 			[ "$new_domain_name" = "$1" ] && warn=true
    152 		fi
    153 	fi
    154 	if [ -n "$new_domain_search" ]; then
    155 		new_domain_search=$(uniqify $new_domain_search)
    156 		if valid_domainname_list $new_domain_search; then
    157 			conf="${conf}search $new_domain_search$NL"
    158 		elif ! $warn; then
    159 			syslog err "Invalid domain name in list:" \
    160 			    "$new_domain_search"
    161 		fi
    162 	fi
    163 	new_domain_name_servers=$(uniqify $new_domain_name_servers)
    164 	for x in ${new_domain_name_servers}; do
    165 		conf="${conf}nameserver $x$NL"
    166 	done
    167 	if type "$resolvconf" >/dev/null 2>&1; then
    168 		[ -n "$ifmetric" ] && export IF_METRIC="$ifmetric"
    169 		printf %s "$conf" | "$resolvconf" -a "$ifname"
    170 		return $?
    171 	fi
    172 
    173 	if [ -e "$resolv_conf_dir/$ifname" ]; then
    174 		rm -f "$resolv_conf_dir/$ifname"
    175 	fi
    176 	[ -d "$resolv_conf_dir" ] || mkdir -p "$resolv_conf_dir"
    177 	printf %s "$conf" > "$resolv_conf_dir/$ifname"
    178 	build_resolv_conf
    179 }
    180 
    181 remove_resolv_conf()
    182 {
    183 	if type "$resolvconf" >/dev/null 2>&1; then
    184 		"$resolvconf" -d "$ifname" -f
    185 	else
    186 		if [ -e "$resolv_conf_dir/$ifname" ]; then
    187 			rm -f "$resolv_conf_dir/$ifname"
    188 		fi
    189 		build_resolv_conf
    190 	fi
    191 }
    192 
    193 # For ease of use, map DHCP6 names onto our DHCP4 names
    194 case "$reason" in
    195 BOUND6|RENEW6|REBIND6|REBOOT6|INFORM6)
    196 	new_domain_name_servers="$new_dhcp6_name_servers"
    197 	new_domain_search="$new_dhcp6_domain_search"
    198 	;;
    199 esac
    200 
    201 if $if_up || [ "$reason" = ROUTERADVERT ]; then
    202 	add_resolv_conf
    203 elif $if_down; then
    204 	remove_resolv_conf
    205 fi
    206