Home | History | Annotate | Line # | Download | only in hooks
20-resolv.conf revision 1.1.1.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  roy 		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  roy 	if [ -z "$ltime" -o "$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  roy 	if [ -z "$ltime" -o "$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  roy 	[ -z "$rdnss" -a -z "$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  roy 	if [ -z "$new_domain_name_servers" -a \
    134      1.1  roy 		-z "$new_domain_name" -a \
    135      1.1  roy 		-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  roy 		if valid_domainname_list $new_domain_search; then
    155      1.1  roy 			conf="${conf}search $new_domain_search$NL"
    156      1.1  roy 		elif ! $warn; then
    157      1.1  roy 			syslog err "Invalid domain name in list:" \
    158      1.1  roy 			    "$new_domain_search"
    159      1.1  roy 		fi
    160      1.1  roy 	fi
    161      1.1  roy 	for x in ${new_domain_name_servers}; do
    162      1.1  roy 		conf="${conf}nameserver $x$NL"
    163      1.1  roy 	done
    164      1.1  roy 	if type "$resolvconf" >/dev/null 2>&1; then
    165      1.1  roy 		[ -n "$ifmetric" ] && export IF_METRIC="$ifmetric"
    166      1.1  roy 		printf %s "$conf" | "$resolvconf" -a "$ifname"
    167      1.1  roy 		return $?
    168      1.1  roy 	fi
    169      1.1  roy 
    170      1.1  roy 	if [ -e "$resolv_conf_dir/$ifname" ]; then
    171      1.1  roy 		rm -f "$resolv_conf_dir/$ifname"
    172      1.1  roy 	fi
    173      1.1  roy 	[ -d "$resolv_conf_dir" ] || mkdir -p "$resolv_conf_dir"
    174      1.1  roy 	printf %s "$conf" > "$resolv_conf_dir/$ifname"
    175      1.1  roy 	build_resolv_conf
    176      1.1  roy }
    177      1.1  roy 
    178      1.1  roy remove_resolv_conf()
    179      1.1  roy {
    180      1.1  roy 	if type "$resolvconf" >/dev/null 2>&1; then
    181      1.1  roy 		"$resolvconf" -d "$ifname" -f
    182      1.1  roy 	else
    183      1.1  roy 		if [ -e "$resolv_conf_dir/$ifname" ]; then
    184      1.1  roy 			rm -f "$resolv_conf_dir/$ifname"
    185      1.1  roy 		fi
    186      1.1  roy 		build_resolv_conf
    187      1.1  roy 	fi
    188      1.1  roy }
    189      1.1  roy 
    190      1.1  roy # For ease of use, map DHCP6 names onto our DHCP4 names
    191      1.1  roy case "$reason" in
    192      1.1  roy BOUND6|RENEW6|REBIND6|REBOOT6|INFORM6)
    193      1.1  roy 	new_domain_name_servers="$new_dhcp6_name_servers"
    194      1.1  roy 	new_domain_search="$new_dhcp6_domain_search"
    195      1.1  roy 	;;
    196      1.1  roy esac
    197      1.1  roy 
    198      1.1  roy if $if_up || [ "$reason" = ROUTERADVERT ]; then
    199      1.1  roy 	add_resolv_conf
    200      1.1  roy elif $if_down; then
    201      1.1  roy 	remove_resolv_conf
    202      1.1  roy fi
    203