]> Cypherpunks repositories - gostls13.git/commitdiff
net: ensure dnsConfig search list is rooted
authorMatthew Dempsky <mdempsky@google.com>
Thu, 28 Apr 2016 18:31:59 +0000 (11:31 -0700)
committerMatthew Dempsky <mdempsky@google.com>
Thu, 28 Apr 2016 20:22:21 +0000 (20:22 +0000)
Avoids some extra work and string concatenation at query time.

benchmark                                      old allocs     new allocs     delta
BenchmarkGoLookupIP-32                         154            150            -2.60%
BenchmarkGoLookupIPNoSuchHost-32               446            442            -0.90%
BenchmarkGoLookupIPWithBrokenNameServer-32     564            568            +0.71%

benchmark                                      old bytes     new bytes     delta
BenchmarkGoLookupIP-32                         10824         10704         -1.11%
BenchmarkGoLookupIPNoSuchHost-32               43140         42992         -0.34%
BenchmarkGoLookupIPWithBrokenNameServer-32     46616         46680         +0.14%

BenchmarkGoLookupIPWithBrokenNameServer's regression appears to be
because it's actually only performing 1 LookupIP call, so the extra
work done parsing the DNS config file doesn't amortize as well as for
BenchmarkGoLookupIP or BenchmarkGoLOokupIPNoSuchHost, which perform
2000+ LookupIP calls per run.

Update #15473.

Change-Id: I98c8072f2f39e2f2ccd6c55e9e9bd309f5ad68f8
Reviewed-on: https://go-review.googlesource.com/22571
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
src/net/dnsclient_unix.go
src/net/dnsconfig_unix.go
src/net/dnsconfig_unix_test.go

index 12d12eba9c6168bc86b3ba01457b56feed7b71f2..8f2dff46751b0e31778a1fc1e92d030d630c5f19 100644 (file)
@@ -361,23 +361,23 @@ func (conf *dnsConfig) nameList(name string) []string {
        if rooted {
                return []string{name}
        }
+
+       hasNdots := count(name, '.') >= conf.ndots
+       name += "."
+
        // Build list of search choices.
        names := make([]string, 0, 1+len(conf.search))
        // If name has enough dots, try unsuffixed first.
-       if count(name, '.') >= conf.ndots {
-               names = append(names, name+".")
+       if hasNdots {
+               names = append(names, name)
        }
        // Try suffixes.
        for _, suffix := range conf.search {
-               suffixed := name + "." + suffix
-               if suffixed[len(suffixed)-1] != '.' {
-                       suffixed += "."
-               }
-               names = append(names, suffixed)
+               names = append(names, name+suffix)
        }
        // Try unsuffixed, if not tried first above.
-       if count(name, '.') < conf.ndots {
-               names = append(names, name+".")
+       if !hasNdots {
+               names = append(names, name)
        }
        return names
 }
index 88d168d8d2dbaac2ee4a2e20c60838135927e6fd..aec575e854191067a7c83ae2a8c5bbb8e3ecba70 100644 (file)
@@ -20,7 +20,7 @@ var (
 
 type dnsConfig struct {
        servers    []string      // server addresses (in host:port form) to use
-       search     []string      // suffixes to append to local name
+       search     []string      // rooted suffixes to append to local name
        ndots      int           // number of dots in name to trigger absolute lookup
        timeout    time.Duration // wait before giving up on a query, including retries
        attempts   int           // lost packets before giving up on server
@@ -78,13 +78,13 @@ func dnsReadConfig(filename string) *dnsConfig {
 
                case "domain": // set search path to just this domain
                        if len(f) > 1 {
-                               conf.search = []string{f[1]}
+                               conf.search = []string{ensureRooted(f[1])}
                        }
 
                case "search": // set search path to given servers
                        conf.search = make([]string, len(f)-1)
                        for i := 0; i < len(conf.search); i++ {
-                               conf.search[i] = f[i+1]
+                               conf.search[i] = ensureRooted(f[i+1])
                        }
 
                case "options": // magic options
@@ -141,7 +141,7 @@ func dnsDefaultSearch() []string {
                return nil
        }
        if i := byteIndex(hn, '.'); i >= 0 && i < len(hn)-1 {
-               return []string{hn[i+1:]}
+               return []string{ensureRooted(hn[i+1:])}
        }
        return nil
 }
@@ -149,3 +149,10 @@ func dnsDefaultSearch() []string {
 func hasPrefix(s, prefix string) bool {
        return len(s) >= len(prefix) && s[:len(prefix)] == prefix
 }
+
+func ensureRooted(s string) string {
+       if len(s) > 0 && s[len(s)-1] == '.' {
+               return s
+       }
+       return s + "."
+}
index 7e27a728878dfdbf036ecb1bce941d022bf5d8d8..9fd6dbf982a22305b2118d1f8c3c925cba5f368d 100644 (file)
@@ -22,7 +22,7 @@ var dnsReadConfigTests = []struct {
                name: "testdata/resolv.conf",
                want: &dnsConfig{
                        servers:    []string{"8.8.8.8:53", "[2001:4860:4860::8888]:53", "[fe80::1%lo0]:53"},
-                       search:     []string{"localdomain"},
+                       search:     []string{"localdomain."},
                        ndots:      5,
                        timeout:    10 * time.Second,
                        attempts:   3,
@@ -34,7 +34,7 @@ var dnsReadConfigTests = []struct {
                name: "testdata/domain-resolv.conf",
                want: &dnsConfig{
                        servers:  []string{"8.8.8.8:53"},
-                       search:   []string{"localdomain"},
+                       search:   []string{"localdomain."},
                        ndots:    1,
                        timeout:  5 * time.Second,
                        attempts: 2,
@@ -44,7 +44,7 @@ var dnsReadConfigTests = []struct {
                name: "testdata/search-resolv.conf",
                want: &dnsConfig{
                        servers:  []string{"8.8.8.8:53"},
-                       search:   []string{"test", "invalid"},
+                       search:   []string{"test.", "invalid."},
                        ndots:    1,
                        timeout:  5 * time.Second,
                        attempts: 2,
@@ -57,7 +57,7 @@ var dnsReadConfigTests = []struct {
                        ndots:    1,
                        timeout:  5 * time.Second,
                        attempts: 2,
-                       search:   []string{"domain.local"},
+                       search:   []string{"domain.local."},
                },
        },
        {
@@ -105,7 +105,7 @@ func TestDNSReadMissingFile(t *testing.T) {
                ndots:    1,
                timeout:  5 * time.Second,
                attempts: 2,
-               search:   []string{"domain.local"},
+               search:   []string{"domain.local."},
        }
        if !reflect.DeepEqual(conf, want) {
                t.Errorf("missing resolv.conf:\ngot: %+v\nwant: %+v", conf, want)
@@ -119,11 +119,11 @@ var dnsDefaultSearchTests = []struct {
 }{
        {
                name: "host.long.domain.local",
-               want: []string{"long.domain.local"},
+               want: []string{"long.domain.local."},
        },
        {
                name: "host.local",
-               want: []string{"local"},
+               want: []string{"local."},
        },
        {
                name: "host",