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