17827cba2SAaron LI# Generate /etc/resolv.conf 27827cba2SAaron LI# Support resolvconf(8) if available 37827cba2SAaron LI# We can merge other dhcpcd resolv.conf files into one like resolvconf, 47827cba2SAaron LI# but resolvconf is preferred as other applications like VPN clients 57827cba2SAaron LI# can readily hook into it. 67827cba2SAaron LI# Also, resolvconf can configure local nameservers such as bind 77827cba2SAaron LI# or dnsmasq. This is important as the libc resolver isn't that powerful. 87827cba2SAaron LI 97827cba2SAaron LIresolv_conf_dir="$state_dir/resolv.conf" 107827cba2SAaron LINL=" 117827cba2SAaron LI" 127827cba2SAaron LI: ${resolvconf:=resolvconf} 137827cba2SAaron LI 147827cba2SAaron LIbuild_resolv_conf() 157827cba2SAaron LI{ 167827cba2SAaron LI cf="$state_dir/resolv.conf.$ifname" 177827cba2SAaron LI 187827cba2SAaron LI # Build a list of interfaces 197827cba2SAaron LI interfaces=$(list_interfaces "$resolv_conf_dir") 207827cba2SAaron LI 217827cba2SAaron LI # Build the resolv.conf 228d36e1dfSRoy Marples header= 237827cba2SAaron LI if [ -n "$interfaces" ]; then 247827cba2SAaron LI # Build the header 257827cba2SAaron LI for x in ${interfaces}; do 267827cba2SAaron LI header="$header${header:+, }$x" 277827cba2SAaron LI done 287827cba2SAaron LI 297827cba2SAaron LI # Build the search list 307827cba2SAaron LI domain=$(cd "$resolv_conf_dir"; \ 317827cba2SAaron LI key_get_value "domain " ${interfaces}) 327827cba2SAaron LI search=$(cd "$resolv_conf_dir"; \ 337827cba2SAaron LI key_get_value "search " ${interfaces}) 347827cba2SAaron LI set -- ${domain} 357827cba2SAaron LI domain="$1" 367827cba2SAaron LI [ -n "$2" ] && search="$search $*" 377827cba2SAaron LI [ -n "$search" ] && search="$(uniqify $search)" 387827cba2SAaron LI [ "$domain" = "$search" ] && search= 397827cba2SAaron LI [ -n "$domain" ] && domain="domain $domain$NL" 407827cba2SAaron LI [ -n "$search" ] && search="search $search$NL" 417827cba2SAaron LI 427827cba2SAaron LI # Build the nameserver list 437827cba2SAaron LI srvs=$(cd "$resolv_conf_dir"; \ 447827cba2SAaron LI key_get_value "nameserver " ${interfaces}) 456e63cc1fSRoy Marples for x in $(uniqify $srvs); do 467827cba2SAaron LI servers="${servers}nameserver $x$NL" 477827cba2SAaron LI done 487827cba2SAaron LI fi 497827cba2SAaron LI header="$signature_base${header:+ $from }$header" 507827cba2SAaron LI 517827cba2SAaron LI # Assemble resolv.conf using our head and tail files 527827cba2SAaron LI [ -f "$cf" ] && rm -f "$cf" 537827cba2SAaron LI [ -d "$resolv_conf_dir" ] || mkdir -p "$resolv_conf_dir" 547827cba2SAaron LI echo "$header" > "$cf" 557827cba2SAaron LI if [ -f /etc/resolv.conf.head ]; then 567827cba2SAaron LI cat /etc/resolv.conf.head >> "$cf" 577827cba2SAaron LI else 587827cba2SAaron LI echo "# /etc/resolv.conf.head can replace this line" >> "$cf" 597827cba2SAaron LI fi 607827cba2SAaron LI printf %s "$domain$search$servers" >> "$cf" 617827cba2SAaron LI if [ -f /etc/resolv.conf.tail ]; then 627827cba2SAaron LI cat /etc/resolv.conf.tail >> "$cf" 637827cba2SAaron LI else 647827cba2SAaron LI echo "# /etc/resolv.conf.tail can replace this line" >> "$cf" 657827cba2SAaron LI fi 667827cba2SAaron LI if change_file /etc/resolv.conf "$cf"; then 677827cba2SAaron LI chmod 644 /etc/resolv.conf 687827cba2SAaron LI fi 697827cba2SAaron LI rm -f "$cf" 707827cba2SAaron LI} 717827cba2SAaron LI 727827cba2SAaron LI# Extract any ND DNS options from the RA 738d36e1dfSRoy Marples# Obey the lifetimes 747827cba2SAaron LIeval_nd_dns() 757827cba2SAaron LI{ 768d36e1dfSRoy Marples 778d36e1dfSRoy Marples eval rdnsstime=\$nd${i}_rdnss${j}_lifetime 788d36e1dfSRoy Marples [ -z "$rdnsstime" ] && return 1 798d36e1dfSRoy Marples ltime=$(($rdnsstime - $offset)) 808d36e1dfSRoy Marples if [ "$ltime" -gt 0 ]; then 817827cba2SAaron LI eval rdnss=\$nd${i}_rdnss${j}_servers 827827cba2SAaron LI [ -n "$rdnss" ] && new_rdnss="$new_rdnss${new_rdnss:+ }$rdnss" 838d36e1dfSRoy Marples fi 848d36e1dfSRoy Marples 858d36e1dfSRoy Marples eval dnssltime=\$nd${i}_dnssl${j}_lifetime 868d36e1dfSRoy Marples [ -z "$dnssltime" ] && return 1 878d36e1dfSRoy Marples ltime=$(($dnssltime - $offset)) 888d36e1dfSRoy Marples if [ "$ltime" -gt 0 ]; then 898d36e1dfSRoy Marples eval dnssl=\$nd${i}_dnssl${j}_search 907827cba2SAaron LI [ -n "$dnssl" ] && new_dnssl="$new_dnssl${new_dnssl:+ }$dnssl" 918d36e1dfSRoy Marples fi 928d36e1dfSRoy Marples 937827cba2SAaron LI j=$(($j + 1)) 947827cba2SAaron LI return 0 957827cba2SAaron LI} 967827cba2SAaron LI 977827cba2SAaron LIadd_resolv_conf() 987827cba2SAaron LI{ 997827cba2SAaron LI conf="$signature$NL" 1007827cba2SAaron LI warn=true 1017827cba2SAaron LI 1027827cba2SAaron LI # Loop to extract the ND DNS options using our indexed shell values 1037827cba2SAaron LI i=1 1047827cba2SAaron LI j=1 1057827cba2SAaron LI while true; do 1068d36e1dfSRoy Marples eval acquired=\$nd${i}_acquired 1078d36e1dfSRoy Marples [ -z "$acquired" ] && break 1088d36e1dfSRoy Marples eval now=\$nd${i}_now 1098d36e1dfSRoy Marples [ -z "$now" ] && break 1108d36e1dfSRoy Marples offset=$(($now - $acquired)) 1117827cba2SAaron LI while true; do 1127827cba2SAaron LI eval_nd_dns || break 1137827cba2SAaron LI done 1147827cba2SAaron LI i=$(($i + 1)) 1157827cba2SAaron LI j=1 1167827cba2SAaron LI done 1177827cba2SAaron LI [ -n "$new_rdnss" ] && \ 1187827cba2SAaron LI new_domain_name_servers="$new_domain_name_servers${new_domain_name_servers:+ }$new_rdnss" 1197827cba2SAaron LI [ -n "$new_dnssl" ] && \ 1207827cba2SAaron LI new_domain_search="$new_domain_search${new_domain_search:+ }$new_dnssl" 1217827cba2SAaron LI 1227827cba2SAaron LI # Derive a new domain from our various hostname options 1237827cba2SAaron LI if [ -z "$new_domain_name" ]; then 1247827cba2SAaron LI if [ "$new_dhcp6_fqdn" != "${new_dhcp6_fqdn#*.}" ]; then 1257827cba2SAaron LI new_domain_name="${new_dhcp6_fqdn#*.}" 1267827cba2SAaron LI elif [ "$new_fqdn" != "${new_fqdn#*.}" ]; then 1277827cba2SAaron LI new_domain_name="${new_fqdn#*.}" 1287827cba2SAaron LI elif [ "$new_host_name" != "${new_host_name#*.}" ]; then 1297827cba2SAaron LI new_domain_name="${new_host_name#*.}" 1307827cba2SAaron LI fi 1317827cba2SAaron LI fi 1327827cba2SAaron LI 1337827cba2SAaron LI # If we don't have any configuration, remove it 1348d36e1dfSRoy Marples if [ -z "$new_domain_name_servers" ] && 1358d36e1dfSRoy Marples [ -z "$new_domain_name" ] && 1368d36e1dfSRoy Marples [ -z "$new_domain_search" ]; then 1377827cba2SAaron LI remove_resolv_conf 1387827cba2SAaron LI return $? 1397827cba2SAaron LI fi 1407827cba2SAaron LI 1417827cba2SAaron LI if [ -n "$new_domain_name" ]; then 1427827cba2SAaron LI set -- $new_domain_name 1437827cba2SAaron LI if valid_domainname "$1"; then 1447827cba2SAaron LI conf="${conf}domain $1$NL" 1457827cba2SAaron LI else 1467827cba2SAaron LI syslog err "Invalid domain name: $1" 1477827cba2SAaron LI fi 1487827cba2SAaron LI # If there is no search this, make this one 1497827cba2SAaron LI if [ -z "$new_domain_search" ]; then 1507827cba2SAaron LI new_domain_search="$new_domain_name" 1517827cba2SAaron LI [ "$new_domain_name" = "$1" ] && warn=true 1527827cba2SAaron LI fi 1537827cba2SAaron LI fi 1547827cba2SAaron LI if [ -n "$new_domain_search" ]; then 1556e63cc1fSRoy Marples new_domain_search=$(uniqify $new_domain_search) 1567827cba2SAaron LI if valid_domainname_list $new_domain_search; then 1577827cba2SAaron LI conf="${conf}search $new_domain_search$NL" 1587827cba2SAaron LI elif ! $warn; then 1597827cba2SAaron LI syslog err "Invalid domain name in list:" \ 1607827cba2SAaron LI "$new_domain_search" 1617827cba2SAaron LI fi 1627827cba2SAaron LI fi 1636e63cc1fSRoy Marples new_domain_name_servers=$(uniqify $new_domain_name_servers) 1647827cba2SAaron LI for x in ${new_domain_name_servers}; do 1657827cba2SAaron LI conf="${conf}nameserver $x$NL" 1667827cba2SAaron LI done 1677827cba2SAaron LI if type "$resolvconf" >/dev/null 2>&1; then 1687827cba2SAaron LI [ -n "$ifmetric" ] && export IF_METRIC="$ifmetric" 1697827cba2SAaron LI printf %s "$conf" | "$resolvconf" -a "$ifname" 1707827cba2SAaron LI return $? 1717827cba2SAaron LI fi 1727827cba2SAaron LI 1737827cba2SAaron LI if [ -e "$resolv_conf_dir/$ifname" ]; then 1747827cba2SAaron LI rm -f "$resolv_conf_dir/$ifname" 1757827cba2SAaron LI fi 1767827cba2SAaron LI [ -d "$resolv_conf_dir" ] || mkdir -p "$resolv_conf_dir" 1777827cba2SAaron LI printf %s "$conf" > "$resolv_conf_dir/$ifname" 1787827cba2SAaron LI build_resolv_conf 1797827cba2SAaron LI} 1807827cba2SAaron LI 1817827cba2SAaron LIremove_resolv_conf() 1827827cba2SAaron LI{ 1837827cba2SAaron LI if type "$resolvconf" >/dev/null 2>&1; then 1847827cba2SAaron LI "$resolvconf" -d "$ifname" -f 1857827cba2SAaron LI else 1867827cba2SAaron LI if [ -e "$resolv_conf_dir/$ifname" ]; then 1877827cba2SAaron LI rm -f "$resolv_conf_dir/$ifname" 1887827cba2SAaron LI fi 1897827cba2SAaron LI build_resolv_conf 1907827cba2SAaron LI fi 1917827cba2SAaron LI} 1927827cba2SAaron LI 1937827cba2SAaron LI# For ease of use, map DHCP6 names onto our DHCP4 names 1947827cba2SAaron LIcase "$reason" in 1957827cba2SAaron LIBOUND6|RENEW6|REBIND6|REBOOT6|INFORM6) 1967827cba2SAaron LI new_domain_name_servers="$new_dhcp6_name_servers" 1977827cba2SAaron LI new_domain_search="$new_dhcp6_domain_search" 1987827cba2SAaron LI ;; 1997827cba2SAaron LIesac 2007827cba2SAaron LI 2017827cba2SAaron LIif $if_up || [ "$reason" = ROUTERADVERT ]; then 2027827cba2SAaron LI add_resolv_conf 2037827cba2SAaron LIelif $if_down; then 2047827cba2SAaron LI remove_resolv_conf 2057827cba2SAaron LIfi 206