Home | History | Annotate | Line # | Download | only in hooks
20-resolv.conf revision 1.1.1.1.4.2
      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 	local cf="$state_dir/resolv.conf.$ifname"
     17 	local interfaces= header= search= srvs= servers= x=
     18 
     19 	# Build a list of interfaces
     20 	interfaces=$(list_interfaces "$resolv_conf_dir")
     21 
     22 	# Build the resolv.conf
     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 # For now, we ignore the lifetime of the DNS options unless they
     74 # are absent or zero.
     75 # In this case they are removed from consideration.
     76 # See draft-gont-6man-slaac-dns-config-issues-01 for issues
     77 # regarding DNS option lifetime in ND messages.
     78 eval_nd_dns()
     79 {
     80 
     81 	eval ltime=\$nd${i}_rdnss${j}_lifetime
     82 	if [ -z "$ltime" -o "$ltime" = 0 ]; then
     83 		rdnss=
     84 	else
     85 		eval rdnss=\$nd${i}_rdnss${j}_servers
     86 	fi
     87 	eval ltime=\$nd${i}_dnssl${j}_lifetime
     88 	if [ -z "$ltime" -o "$ltime" = 0 ]; then
     89 		dnssl=
     90 	else
     91 		eval dnssl=\$nd${i}_dnssl${j}_search
     92 	fi
     93 
     94 	[ -z "$rdnss" -a -z "$dnssl" ] && return 1
     95 
     96 	[ -n "$rdnss" ] && new_rdnss="$new_rdnss${new_rdnss:+ }$rdnss"
     97 	[ -n "$dnssl" ] && new_dnssl="$new_dnssl${new_dnssl:+ }$dnssl"
     98 	j=$(($j + 1))
     99 	return 0
    100 }
    101 
    102 add_resolv_conf()
    103 {
    104 	local x= conf="$signature$NL" warn=true
    105 	local i j ltime rdnss dnssl new_rdnss new_dnssl
    106 
    107 	# Loop to extract the ND DNS options using our indexed shell values
    108 	i=1
    109 	j=1
    110 	while true; do
    111 		while true; do
    112 			eval_nd_dns || break
    113 		done
    114 		i=$(($i + 1))
    115 		j=1
    116 		eval_nd_dns || break
    117 	done
    118 	[ -n "$new_rdnss" ] && \
    119 	    new_domain_name_servers="$new_domain_name_servers${new_domain_name_servers:+ }$new_rdnss"
    120 	[ -n "$new_dnssl" ] && \
    121 	    new_domain_search="$new_domain_search${new_domain_search:+ }$new_dnssl"
    122 
    123 	# Derive a new domain from our various hostname options
    124 	if [ -z "$new_domain_name" ]; then
    125 		if [ "$new_dhcp6_fqdn" != "${new_dhcp6_fqdn#*.}" ]; then
    126 			new_domain_name="${new_dhcp6_fqdn#*.}"
    127 		elif [ "$new_fqdn" != "${new_fqdn#*.}" ]; then
    128 			new_domain_name="${new_fqdn#*.}"
    129 		elif [ "$new_host_name" != "${new_host_name#*.}" ]; then
    130 			new_domain_name="${new_host_name#*.}"
    131 		fi
    132 	fi
    133 
    134 	# If we don't have any configuration, remove it
    135 	if [ -z "$new_domain_name_servers" -a \
    136 		-z "$new_domain_name" -a \
    137 		-z "$new_domain_search" ]; then
    138 		remove_resolv_conf
    139 		return $?
    140 	fi
    141 
    142 	if [ -n "$new_domain_name" ]; then
    143 		set -- $new_domain_name
    144 		if valid_domainname "$1"; then
    145 			conf="${conf}domain $1$NL"
    146 		else
    147 			syslog err "Invalid domain name: $1"
    148 		fi
    149 		# If there is no search this, make this one
    150 		if [ -z "$new_domain_search" ]; then
    151 			new_domain_search="$new_domain_name"
    152 			[ "$new_domain_name" = "$1" ] && warn=true
    153 		fi
    154 	fi
    155 	if [ -n "$new_domain_search" ]; then
    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 	for x in ${new_domain_name_servers}; do
    164 		conf="${conf}nameserver $x$NL"
    165 	done
    166 	if type "$resolvconf" >/dev/null 2>&1; then
    167 		[ -n "$ifmetric" ] && export IF_METRIC="$ifmetric"
    168 		printf %s "$conf" | "$resolvconf" -a "$ifname"
    169 		return $?
    170 	fi
    171 
    172 	if [ -e "$resolv_conf_dir/$ifname" ]; then
    173 		rm -f "$resolv_conf_dir/$ifname"
    174 	fi
    175 	[ -d "$resolv_conf_dir" ] || mkdir -p "$resolv_conf_dir"
    176 	printf %s "$conf" > "$resolv_conf_dir/$ifname"
    177 	build_resolv_conf
    178 }
    179 
    180 remove_resolv_conf()
    181 {
    182 	if type "$resolvconf" >/dev/null 2>&1; then
    183 		"$resolvconf" -d "$ifname" -f
    184 	else
    185 		if [ -e "$resolv_conf_dir/$ifname" ]; then
    186 			rm -f "$resolv_conf_dir/$ifname"
    187 		fi
    188 		build_resolv_conf
    189 	fi
    190 }
    191 
    192 # For ease of use, map DHCP6 names onto our DHCP4 names
    193 case "$reason" in
    194 BOUND6|RENEW6|REBIND6|REBOOT6|INFORM6)
    195 	new_domain_name_servers="$new_dhcp6_name_servers"
    196 	new_domain_search="$new_dhcp6_domain_search"
    197 	;;
    198 esac
    199 
    200 if $if_up || [ "$reason" = ROUTERADVERT ]; then
    201 	add_resolv_conf
    202 elif $if_down; then
    203 	remove_resolv_conf
    204 fi
    205