net/dns/resolvconffile: unify three /etc/resolv.conf parsers into new package

Change-Id: I2120893ca802d12f1bd0407d49077d3672627d33
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
Brad Fitzpatrick
2022-02-14 20:17:51 -08:00
committed by Brad Fitzpatrick
parent 1dc4151f8b
commit c988bd6ed1
6 changed files with 227 additions and 126 deletions

View File

@@ -5,7 +5,6 @@
package dns
import (
"bufio"
"bytes"
"context"
"crypto/rand"
@@ -20,6 +19,7 @@ import (
"time"
"inet.af/netaddr"
"tailscale.com/net/dns/resolvconffile"
"tailscale.com/types/logger"
"tailscale.com/util/dnsname"
)
@@ -30,64 +30,23 @@ const (
)
// writeResolvConf writes DNS configuration in resolv.conf format to the given writer.
func writeResolvConf(w io.Writer, servers []netaddr.IP, domains []dnsname.FQDN) {
io.WriteString(w, "# resolv.conf(5) file generated by tailscale\n")
io.WriteString(w, "# DO NOT EDIT THIS FILE BY HAND -- CHANGES WILL BE OVERWRITTEN\n\n")
for _, ns := range servers {
io.WriteString(w, "nameserver ")
io.WriteString(w, ns.String())
io.WriteString(w, "\n")
}
if len(domains) > 0 {
io.WriteString(w, "search")
for _, domain := range domains {
io.WriteString(w, " ")
io.WriteString(w, domain.WithoutTrailingDot())
}
io.WriteString(w, "\n")
func writeResolvConf(w io.Writer, servers []netaddr.IP, domains []dnsname.FQDN) error {
c := &resolvconffile.Config{
Nameservers: servers,
SearchDomains: domains,
}
return c.Write(w)
}
func readResolv(r io.Reader) (config OSConfig, err error) {
scanner := bufio.NewScanner(r)
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
i := strings.IndexByte(line, '#')
if i >= 0 {
line = line[:i]
}
if strings.HasPrefix(line, "nameserver") {
s := strings.TrimPrefix(line, "nameserver")
nameserver := strings.TrimSpace(s)
if len(nameserver) == len(s) {
return OSConfig{}, fmt.Errorf("missing space after \"nameserver\" in %q", line)
}
ip, err := netaddr.ParseIP(nameserver)
if err != nil {
return OSConfig{}, err
}
config.Nameservers = append(config.Nameservers, ip)
continue
}
if strings.HasPrefix(line, "search") {
s := strings.TrimPrefix(line, "search")
domain := strings.TrimSpace(s)
if len(domain) == len(s) {
// No leading space?!
return OSConfig{}, fmt.Errorf("missing space after \"domain\" in %q", line)
}
fqdn, err := dnsname.ToFQDN(domain)
if err != nil {
return OSConfig{}, fmt.Errorf("parsing search domains %q: %w", line, err)
}
config.SearchDomains = append(config.SearchDomains, fqdn)
continue
}
func readResolv(r io.Reader) (OSConfig, error) {
c, err := resolvconffile.Parse(r)
if err != nil {
return OSConfig{}, err
}
return config, nil
return OSConfig{
Nameservers: c.Nameservers,
SearchDomains: c.SearchDomains,
}, nil
}
// resolvOwner returns the apparent owner of the resolv.conf