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