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