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