|  | // Copyright 2015 The Go Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style | 
|  | // license that can be found in the LICENSE file. | 
|  |  | 
|  | // +build darwin dragonfly freebsd linux netbsd openbsd solaris | 
|  |  | 
|  | package net | 
|  |  | 
|  | import ( | 
|  | "io/fs" | 
|  | "strings" | 
|  | "testing" | 
|  | ) | 
|  |  | 
|  | type nssHostTest struct { | 
|  | host      string | 
|  | localhost string | 
|  | want      hostLookupOrder | 
|  | } | 
|  |  | 
|  | func nssStr(s string) *nssConf { return parseNSSConf(strings.NewReader(s)) } | 
|  |  | 
|  | // represents a dnsConfig returned by parsing a nonexistent resolv.conf | 
|  | var defaultResolvConf = &dnsConfig{ | 
|  | servers:  defaultNS, | 
|  | ndots:    1, | 
|  | timeout:  5, | 
|  | attempts: 2, | 
|  | err:      fs.ErrNotExist, | 
|  | } | 
|  |  | 
|  | func TestConfHostLookupOrder(t *testing.T) { | 
|  | tests := []struct { | 
|  | name      string | 
|  | c         *conf | 
|  | resolver  *Resolver | 
|  | hostTests []nssHostTest | 
|  | }{ | 
|  | { | 
|  | name: "force", | 
|  | c: &conf{ | 
|  | forceCgoLookupHost: true, | 
|  | nss:                nssStr("foo: bar"), | 
|  | resolv:             defaultResolvConf, | 
|  | }, | 
|  | hostTests: []nssHostTest{ | 
|  | {"foo.local", "myhostname", hostLookupCgo}, | 
|  | {"google.com", "myhostname", hostLookupCgo}, | 
|  | }, | 
|  | }, | 
|  | { | 
|  | name: "netgo_dns_before_files", | 
|  | c: &conf{ | 
|  | netGo:  true, | 
|  | nss:    nssStr("hosts: dns files"), | 
|  | resolv: defaultResolvConf, | 
|  | }, | 
|  | hostTests: []nssHostTest{ | 
|  | {"x.com", "myhostname", hostLookupDNSFiles}, | 
|  | }, | 
|  | }, | 
|  | { | 
|  | name: "netgo_fallback_on_cgo", | 
|  | c: &conf{ | 
|  | netGo:  true, | 
|  | nss:    nssStr("hosts: dns files something_custom"), | 
|  | resolv: defaultResolvConf, | 
|  | }, | 
|  | hostTests: []nssHostTest{ | 
|  | {"x.com", "myhostname", hostLookupFilesDNS}, | 
|  | }, | 
|  | }, | 
|  | { | 
|  | name: "ubuntu_trusty_avahi", | 
|  | c: &conf{ | 
|  | nss:    nssStr("hosts: files mdns4_minimal [NOTFOUND=return] dns mdns4"), | 
|  | resolv: defaultResolvConf, | 
|  | }, | 
|  | hostTests: []nssHostTest{ | 
|  | {"foo.local", "myhostname", hostLookupCgo}, | 
|  | {"foo.local.", "myhostname", hostLookupCgo}, | 
|  | {"foo.LOCAL", "myhostname", hostLookupCgo}, | 
|  | {"foo.LOCAL.", "myhostname", hostLookupCgo}, | 
|  | {"google.com", "myhostname", hostLookupFilesDNS}, | 
|  | }, | 
|  | }, | 
|  | { | 
|  | name: "freebsdlinux_no_resolv_conf", | 
|  | c: &conf{ | 
|  | goos:   "freebsd", | 
|  | nss:    nssStr("foo: bar"), | 
|  | resolv: defaultResolvConf, | 
|  | }, | 
|  | hostTests: []nssHostTest{{"google.com", "myhostname", hostLookupFilesDNS}}, | 
|  | }, | 
|  | // On OpenBSD, no resolv.conf means no DNS. | 
|  | { | 
|  | name: "openbsd_no_resolv_conf", | 
|  | c: &conf{ | 
|  | goos:   "openbsd", | 
|  | resolv: defaultResolvConf, | 
|  | }, | 
|  | hostTests: []nssHostTest{{"google.com", "myhostname", hostLookupFiles}}, | 
|  | }, | 
|  | { | 
|  | name: "solaris_no_nsswitch", | 
|  | c: &conf{ | 
|  | goos:   "solaris", | 
|  | nss:    &nssConf{err: fs.ErrNotExist}, | 
|  | resolv: defaultResolvConf, | 
|  | }, | 
|  | hostTests: []nssHostTest{{"google.com", "myhostname", hostLookupCgo}}, | 
|  | }, | 
|  | { | 
|  | name: "openbsd_lookup_bind_file", | 
|  | c: &conf{ | 
|  | goos:   "openbsd", | 
|  | resolv: &dnsConfig{lookup: []string{"bind", "file"}}, | 
|  | }, | 
|  | hostTests: []nssHostTest{ | 
|  | {"google.com", "myhostname", hostLookupDNSFiles}, | 
|  | {"foo.local", "myhostname", hostLookupDNSFiles}, | 
|  | }, | 
|  | }, | 
|  | { | 
|  | name: "openbsd_lookup_file_bind", | 
|  | c: &conf{ | 
|  | goos:   "openbsd", | 
|  | resolv: &dnsConfig{lookup: []string{"file", "bind"}}, | 
|  | }, | 
|  | hostTests: []nssHostTest{{"google.com", "myhostname", hostLookupFilesDNS}}, | 
|  | }, | 
|  | { | 
|  | name: "openbsd_lookup_bind", | 
|  | c: &conf{ | 
|  | goos:   "openbsd", | 
|  | resolv: &dnsConfig{lookup: []string{"bind"}}, | 
|  | }, | 
|  | hostTests: []nssHostTest{{"google.com", "myhostname", hostLookupDNS}}, | 
|  | }, | 
|  | { | 
|  | name: "openbsd_lookup_file", | 
|  | c: &conf{ | 
|  | goos:   "openbsd", | 
|  | resolv: &dnsConfig{lookup: []string{"file"}}, | 
|  | }, | 
|  | hostTests: []nssHostTest{{"google.com", "myhostname", hostLookupFiles}}, | 
|  | }, | 
|  | { | 
|  | name: "openbsd_lookup_yp", | 
|  | c: &conf{ | 
|  | goos:   "openbsd", | 
|  | resolv: &dnsConfig{lookup: []string{"file", "bind", "yp"}}, | 
|  | }, | 
|  | hostTests: []nssHostTest{{"google.com", "myhostname", hostLookupCgo}}, | 
|  | }, | 
|  | { | 
|  | name: "openbsd_lookup_two", | 
|  | c: &conf{ | 
|  | goos:   "openbsd", | 
|  | resolv: &dnsConfig{lookup: []string{"file", "foo"}}, | 
|  | }, | 
|  | hostTests: []nssHostTest{{"google.com", "myhostname", hostLookupCgo}}, | 
|  | }, | 
|  | { | 
|  | name: "openbsd_lookup_empty", | 
|  | c: &conf{ | 
|  | goos:   "openbsd", | 
|  | resolv: &dnsConfig{lookup: nil}, | 
|  | }, | 
|  | hostTests: []nssHostTest{{"google.com", "myhostname", hostLookupDNSFiles}}, | 
|  | }, | 
|  | { | 
|  | name: "linux_no_nsswitch.conf", | 
|  | c: &conf{ | 
|  | goos:   "linux", | 
|  | nss:    &nssConf{err: fs.ErrNotExist}, | 
|  | resolv: defaultResolvConf, | 
|  | }, | 
|  | hostTests: []nssHostTest{{"google.com", "myhostname", hostLookupFilesDNS}}, | 
|  | }, | 
|  | { | 
|  | name: "linux_empty_nsswitch.conf", | 
|  | c: &conf{ | 
|  | goos:   "linux", | 
|  | nss:    nssStr(""), | 
|  | resolv: defaultResolvConf, | 
|  | }, | 
|  | hostTests: []nssHostTest{{"google.com", "myhostname", hostLookupFilesDNS}}, | 
|  | }, | 
|  | { | 
|  | name: "files_mdns_dns", | 
|  | c: &conf{ | 
|  | nss:    nssStr("hosts: files mdns dns"), | 
|  | resolv: defaultResolvConf, | 
|  | }, | 
|  | hostTests: []nssHostTest{ | 
|  | {"x.com", "myhostname", hostLookupFilesDNS}, | 
|  | {"x.local", "myhostname", hostLookupCgo}, | 
|  | }, | 
|  | }, | 
|  | { | 
|  | name: "dns_special_hostnames", | 
|  | c: &conf{ | 
|  | nss:    nssStr("hosts: dns"), | 
|  | resolv: defaultResolvConf, | 
|  | }, | 
|  | hostTests: []nssHostTest{ | 
|  | {"x.com", "myhostname", hostLookupDNS}, | 
|  | {"x\\.com", "myhostname", hostLookupCgo},     // punt on weird glibc escape | 
|  | {"foo.com%en0", "myhostname", hostLookupCgo}, // and IPv6 zones | 
|  | }, | 
|  | }, | 
|  | { | 
|  | name: "mdns_allow", | 
|  | c: &conf{ | 
|  | nss:          nssStr("hosts: files mdns dns"), | 
|  | resolv:       defaultResolvConf, | 
|  | hasMDNSAllow: true, | 
|  | }, | 
|  | hostTests: []nssHostTest{ | 
|  | {"x.com", "myhostname", hostLookupCgo}, | 
|  | {"x.local", "myhostname", hostLookupCgo}, | 
|  | }, | 
|  | }, | 
|  | { | 
|  | name: "files_dns", | 
|  | c: &conf{ | 
|  | nss:    nssStr("hosts: files dns"), | 
|  | resolv: defaultResolvConf, | 
|  | }, | 
|  | hostTests: []nssHostTest{ | 
|  | {"x.com", "myhostname", hostLookupFilesDNS}, | 
|  | {"x", "myhostname", hostLookupFilesDNS}, | 
|  | {"x.local", "myhostname", hostLookupCgo}, | 
|  | }, | 
|  | }, | 
|  | { | 
|  | name: "dns_files", | 
|  | c: &conf{ | 
|  | nss:    nssStr("hosts: dns files"), | 
|  | resolv: defaultResolvConf, | 
|  | }, | 
|  | hostTests: []nssHostTest{ | 
|  | {"x.com", "myhostname", hostLookupDNSFiles}, | 
|  | {"x", "myhostname", hostLookupDNSFiles}, | 
|  | {"x.local", "myhostname", hostLookupCgo}, | 
|  | }, | 
|  | }, | 
|  | { | 
|  | name: "something_custom", | 
|  | c: &conf{ | 
|  | nss:    nssStr("hosts: dns files something_custom"), | 
|  | resolv: defaultResolvConf, | 
|  | }, | 
|  | hostTests: []nssHostTest{ | 
|  | {"x.com", "myhostname", hostLookupCgo}, | 
|  | }, | 
|  | }, | 
|  | { | 
|  | name: "myhostname", | 
|  | c: &conf{ | 
|  | nss:    nssStr("hosts: files dns myhostname"), | 
|  | resolv: defaultResolvConf, | 
|  | }, | 
|  | hostTests: []nssHostTest{ | 
|  | {"x.com", "myhostname", hostLookupFilesDNS}, | 
|  | {"myhostname", "myhostname", hostLookupCgo}, | 
|  | {"myHostname", "myhostname", hostLookupCgo}, | 
|  | {"myhostname.dot", "myhostname.dot", hostLookupCgo}, | 
|  | {"myHostname.dot", "myhostname.dot", hostLookupCgo}, | 
|  | {"gateway", "myhostname", hostLookupCgo}, | 
|  | {"Gateway", "myhostname", hostLookupCgo}, | 
|  | {"localhost", "myhostname", hostLookupCgo}, | 
|  | {"Localhost", "myhostname", hostLookupCgo}, | 
|  | {"anything.localhost", "myhostname", hostLookupCgo}, | 
|  | {"Anything.localhost", "myhostname", hostLookupCgo}, | 
|  | {"localhost.localdomain", "myhostname", hostLookupCgo}, | 
|  | {"Localhost.Localdomain", "myhostname", hostLookupCgo}, | 
|  | {"anything.localhost.localdomain", "myhostname", hostLookupCgo}, | 
|  | {"Anything.Localhost.Localdomain", "myhostname", hostLookupCgo}, | 
|  | {"somehostname", "myhostname", hostLookupFilesDNS}, | 
|  | {"", "myhostname", hostLookupFilesDNS}, // Issue 13623 | 
|  | }, | 
|  | }, | 
|  | { | 
|  | name: "ubuntu14.04.02", | 
|  | c: &conf{ | 
|  | nss:    nssStr("hosts: files myhostname mdns4_minimal [NOTFOUND=return] dns mdns4"), | 
|  | resolv: defaultResolvConf, | 
|  | }, | 
|  | hostTests: []nssHostTest{ | 
|  | {"x.com", "myhostname", hostLookupFilesDNS}, | 
|  | {"somehostname", "myhostname", hostLookupFilesDNS}, | 
|  | {"myhostname", "myhostname", hostLookupCgo}, | 
|  | }, | 
|  | }, | 
|  | // Debian Squeeze is just "dns,files", but lists all | 
|  | // the default criteria for dns, but then has a | 
|  | // non-standard but redundant notfound=return for the | 
|  | // files. | 
|  | { | 
|  | name: "debian_squeeze", | 
|  | c: &conf{ | 
|  | nss:    nssStr("hosts: dns [success=return notfound=continue unavail=continue tryagain=continue] files [notfound=return]"), | 
|  | resolv: defaultResolvConf, | 
|  | }, | 
|  | hostTests: []nssHostTest{ | 
|  | {"x.com", "myhostname", hostLookupDNSFiles}, | 
|  | {"somehostname", "myhostname", hostLookupDNSFiles}, | 
|  | }, | 
|  | }, | 
|  | { | 
|  | name: "resolv.conf-unknown", | 
|  | c: &conf{ | 
|  | nss:    nssStr("foo: bar"), | 
|  | resolv: &dnsConfig{servers: defaultNS, ndots: 1, timeout: 5, attempts: 2, unknownOpt: true}, | 
|  | }, | 
|  | hostTests: []nssHostTest{{"google.com", "myhostname", hostLookupCgo}}, | 
|  | }, | 
|  | // Android should always use cgo. | 
|  | { | 
|  | name: "android", | 
|  | c: &conf{ | 
|  | goos:   "android", | 
|  | nss:    nssStr(""), | 
|  | resolv: defaultResolvConf, | 
|  | }, | 
|  | hostTests: []nssHostTest{ | 
|  | {"x.com", "myhostname", hostLookupCgo}, | 
|  | }, | 
|  | }, | 
|  | // Issue 24393: make sure "Resolver.PreferGo = true" acts like netgo. | 
|  | { | 
|  | name:     "resolver-prefergo", | 
|  | resolver: &Resolver{PreferGo: true}, | 
|  | c: &conf{ | 
|  | goos:               "darwin", | 
|  | forceCgoLookupHost: true, // always true for darwin | 
|  | resolv:             defaultResolvConf, | 
|  | nss:                nssStr(""), | 
|  | netCgo:             true, | 
|  | }, | 
|  | hostTests: []nssHostTest{ | 
|  | {"localhost", "myhostname", hostLookupFilesDNS}, | 
|  | }, | 
|  | }, | 
|  | } | 
|  |  | 
|  | origGetHostname := getHostname | 
|  | defer func() { getHostname = origGetHostname }() | 
|  |  | 
|  | for _, tt := range tests { | 
|  | for _, ht := range tt.hostTests { | 
|  | getHostname = func() (string, error) { return ht.localhost, nil } | 
|  |  | 
|  | gotOrder := tt.c.hostLookupOrder(tt.resolver, ht.host) | 
|  | if gotOrder != ht.want { | 
|  | t.Errorf("%s: hostLookupOrder(%q) = %v; want %v", tt.name, ht.host, gotOrder, ht.want) | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | } | 
|  |  | 
|  | func TestSystemConf(t *testing.T) { | 
|  | systemConf() | 
|  | } |