Home | History | Annotate | Download | only in net
      1 // Copyright 2015 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 // +build darwin dragonfly freebsd linux netbsd openbsd solaris
      6 
      7 package net
      8 
      9 import (
     10 	"os"
     11 	"strings"
     12 	"testing"
     13 )
     14 
     15 type nssHostTest struct {
     16 	host      string
     17 	localhost string
     18 	want      hostLookupOrder
     19 }
     20 
     21 func nssStr(s string) *nssConf { return parseNSSConf(strings.NewReader(s)) }
     22 
     23 // represents a dnsConfig returned by parsing a nonexistent resolv.conf
     24 var defaultResolvConf = &dnsConfig{
     25 	servers:  defaultNS,
     26 	ndots:    1,
     27 	timeout:  5,
     28 	attempts: 2,
     29 	err:      os.ErrNotExist,
     30 }
     31 
     32 func TestConfHostLookupOrder(t *testing.T) {
     33 	tests := []struct {
     34 		name      string
     35 		c         *conf
     36 		hostTests []nssHostTest
     37 	}{
     38 		{
     39 			name: "force",
     40 			c: &conf{
     41 				forceCgoLookupHost: true,
     42 				nss:                nssStr("foo: bar"),
     43 				resolv:             defaultResolvConf,
     44 			},
     45 			hostTests: []nssHostTest{
     46 				{"foo.local", "myhostname", hostLookupCgo},
     47 				{"google.com", "myhostname", hostLookupCgo},
     48 			},
     49 		},
     50 		{
     51 			name: "netgo_dns_before_files",
     52 			c: &conf{
     53 				netGo:  true,
     54 				nss:    nssStr("hosts: dns files"),
     55 				resolv: defaultResolvConf,
     56 			},
     57 			hostTests: []nssHostTest{
     58 				{"x.com", "myhostname", hostLookupDNSFiles},
     59 			},
     60 		},
     61 		{
     62 			name: "netgo_fallback_on_cgo",
     63 			c: &conf{
     64 				netGo:  true,
     65 				nss:    nssStr("hosts: dns files something_custom"),
     66 				resolv: defaultResolvConf,
     67 			},
     68 			hostTests: []nssHostTest{
     69 				{"x.com", "myhostname", hostLookupFilesDNS},
     70 			},
     71 		},
     72 		{
     73 			name: "ubuntu_trusty_avahi",
     74 			c: &conf{
     75 				nss:    nssStr("hosts: files mdns4_minimal [NOTFOUND=return] dns mdns4"),
     76 				resolv: defaultResolvConf,
     77 			},
     78 			hostTests: []nssHostTest{
     79 				{"foo.local", "myhostname", hostLookupCgo},
     80 				{"foo.local.", "myhostname", hostLookupCgo},
     81 				{"foo.LOCAL", "myhostname", hostLookupCgo},
     82 				{"foo.LOCAL.", "myhostname", hostLookupCgo},
     83 				{"google.com", "myhostname", hostLookupFilesDNS},
     84 			},
     85 		},
     86 		{
     87 			name: "freebsdlinux_no_resolv_conf",
     88 			c: &conf{
     89 				goos:   "freebsd",
     90 				nss:    nssStr("foo: bar"),
     91 				resolv: defaultResolvConf,
     92 			},
     93 			hostTests: []nssHostTest{{"google.com", "myhostname", hostLookupFilesDNS}},
     94 		},
     95 		// On OpenBSD, no resolv.conf means no DNS.
     96 		{
     97 			name: "openbsd_no_resolv_conf",
     98 			c: &conf{
     99 				goos:   "openbsd",
    100 				resolv: defaultResolvConf,
    101 			},
    102 			hostTests: []nssHostTest{{"google.com", "myhostname", hostLookupFiles}},
    103 		},
    104 		{
    105 			name: "solaris_no_nsswitch",
    106 			c: &conf{
    107 				goos:   "solaris",
    108 				nss:    &nssConf{err: os.ErrNotExist},
    109 				resolv: defaultResolvConf,
    110 			},
    111 			hostTests: []nssHostTest{{"google.com", "myhostname", hostLookupCgo}},
    112 		},
    113 		{
    114 			name: "openbsd_lookup_bind_file",
    115 			c: &conf{
    116 				goos:   "openbsd",
    117 				resolv: &dnsConfig{lookup: []string{"bind", "file"}},
    118 			},
    119 			hostTests: []nssHostTest{
    120 				{"google.com", "myhostname", hostLookupDNSFiles},
    121 				{"foo.local", "myhostname", hostLookupDNSFiles},
    122 			},
    123 		},
    124 		{
    125 			name: "openbsd_lookup_file_bind",
    126 			c: &conf{
    127 				goos:   "openbsd",
    128 				resolv: &dnsConfig{lookup: []string{"file", "bind"}},
    129 			},
    130 			hostTests: []nssHostTest{{"google.com", "myhostname", hostLookupFilesDNS}},
    131 		},
    132 		{
    133 			name: "openbsd_lookup_bind",
    134 			c: &conf{
    135 				goos:   "openbsd",
    136 				resolv: &dnsConfig{lookup: []string{"bind"}},
    137 			},
    138 			hostTests: []nssHostTest{{"google.com", "myhostname", hostLookupDNS}},
    139 		},
    140 		{
    141 			name: "openbsd_lookup_file",
    142 			c: &conf{
    143 				goos:   "openbsd",
    144 				resolv: &dnsConfig{lookup: []string{"file"}},
    145 			},
    146 			hostTests: []nssHostTest{{"google.com", "myhostname", hostLookupFiles}},
    147 		},
    148 		{
    149 			name: "openbsd_lookup_yp",
    150 			c: &conf{
    151 				goos:   "openbsd",
    152 				resolv: &dnsConfig{lookup: []string{"file", "bind", "yp"}},
    153 			},
    154 			hostTests: []nssHostTest{{"google.com", "myhostname", hostLookupCgo}},
    155 		},
    156 		{
    157 			name: "openbsd_lookup_two",
    158 			c: &conf{
    159 				goos:   "openbsd",
    160 				resolv: &dnsConfig{lookup: []string{"file", "foo"}},
    161 			},
    162 			hostTests: []nssHostTest{{"google.com", "myhostname", hostLookupCgo}},
    163 		},
    164 		{
    165 			name: "openbsd_lookup_empty",
    166 			c: &conf{
    167 				goos:   "openbsd",
    168 				resolv: &dnsConfig{lookup: nil},
    169 			},
    170 			hostTests: []nssHostTest{{"google.com", "myhostname", hostLookupDNSFiles}},
    171 		},
    172 		// glibc lacking an nsswitch.conf, per
    173 		// http://www.gnu.org/software/libc/manual/html_node/Notes-on-NSS-Configuration-File.html
    174 		{
    175 			name: "linux_no_nsswitch.conf",
    176 			c: &conf{
    177 				goos:   "linux",
    178 				nss:    &nssConf{err: os.ErrNotExist},
    179 				resolv: defaultResolvConf,
    180 			},
    181 			hostTests: []nssHostTest{{"google.com", "myhostname", hostLookupDNSFiles}},
    182 		},
    183 		{
    184 			name: "files_mdns_dns",
    185 			c: &conf{
    186 				nss:    nssStr("hosts: files mdns dns"),
    187 				resolv: defaultResolvConf,
    188 			},
    189 			hostTests: []nssHostTest{
    190 				{"x.com", "myhostname", hostLookupFilesDNS},
    191 				{"x.local", "myhostname", hostLookupCgo},
    192 			},
    193 		},
    194 		{
    195 			name: "dns_special_hostnames",
    196 			c: &conf{
    197 				nss:    nssStr("hosts: dns"),
    198 				resolv: defaultResolvConf,
    199 			},
    200 			hostTests: []nssHostTest{
    201 				{"x.com", "myhostname", hostLookupDNS},
    202 				{"x\\.com", "myhostname", hostLookupCgo},     // punt on weird glibc escape
    203 				{"foo.com%en0", "myhostname", hostLookupCgo}, // and IPv6 zones
    204 			},
    205 		},
    206 		{
    207 			name: "mdns_allow",
    208 			c: &conf{
    209 				nss:          nssStr("hosts: files mdns dns"),
    210 				resolv:       defaultResolvConf,
    211 				hasMDNSAllow: true,
    212 			},
    213 			hostTests: []nssHostTest{
    214 				{"x.com", "myhostname", hostLookupCgo},
    215 				{"x.local", "myhostname", hostLookupCgo},
    216 			},
    217 		},
    218 		{
    219 			name: "files_dns",
    220 			c: &conf{
    221 				nss:    nssStr("hosts: files dns"),
    222 				resolv: defaultResolvConf,
    223 			},
    224 			hostTests: []nssHostTest{
    225 				{"x.com", "myhostname", hostLookupFilesDNS},
    226 				{"x", "myhostname", hostLookupFilesDNS},
    227 				{"x.local", "myhostname", hostLookupCgo},
    228 			},
    229 		},
    230 		{
    231 			name: "dns_files",
    232 			c: &conf{
    233 				nss:    nssStr("hosts: dns files"),
    234 				resolv: defaultResolvConf,
    235 			},
    236 			hostTests: []nssHostTest{
    237 				{"x.com", "myhostname", hostLookupDNSFiles},
    238 				{"x", "myhostname", hostLookupDNSFiles},
    239 				{"x.local", "myhostname", hostLookupCgo},
    240 			},
    241 		},
    242 		{
    243 			name: "something_custom",
    244 			c: &conf{
    245 				nss:    nssStr("hosts: dns files something_custom"),
    246 				resolv: defaultResolvConf,
    247 			},
    248 			hostTests: []nssHostTest{
    249 				{"x.com", "myhostname", hostLookupCgo},
    250 			},
    251 		},
    252 		{
    253 			name: "myhostname",
    254 			c: &conf{
    255 				nss:    nssStr("hosts: files dns myhostname"),
    256 				resolv: defaultResolvConf,
    257 			},
    258 			hostTests: []nssHostTest{
    259 				{"x.com", "myhostname", hostLookupFilesDNS},
    260 				{"myhostname", "myhostname", hostLookupCgo},
    261 				{"myHostname", "myhostname", hostLookupCgo},
    262 				{"myhostname.dot", "myhostname.dot", hostLookupCgo},
    263 				{"myHostname.dot", "myhostname.dot", hostLookupCgo},
    264 				{"gateway", "myhostname", hostLookupCgo},
    265 				{"Gateway", "myhostname", hostLookupCgo},
    266 				{"localhost", "myhostname", hostLookupCgo},
    267 				{"Localhost", "myhostname", hostLookupCgo},
    268 				{"anything.localhost", "myhostname", hostLookupCgo},
    269 				{"Anything.localhost", "myhostname", hostLookupCgo},
    270 				{"localhost.localdomain", "myhostname", hostLookupCgo},
    271 				{"Localhost.Localdomain", "myhostname", hostLookupCgo},
    272 				{"anything.localhost.localdomain", "myhostname", hostLookupCgo},
    273 				{"Anything.Localhost.Localdomain", "myhostname", hostLookupCgo},
    274 				{"somehostname", "myhostname", hostLookupFilesDNS},
    275 				{"", "myhostname", hostLookupFilesDNS}, // Issue 13623
    276 			},
    277 		},
    278 		{
    279 			name: "ubuntu14.04.02",
    280 			c: &conf{
    281 				nss:    nssStr("hosts: files myhostname mdns4_minimal [NOTFOUND=return] dns mdns4"),
    282 				resolv: defaultResolvConf,
    283 			},
    284 			hostTests: []nssHostTest{
    285 				{"x.com", "myhostname", hostLookupFilesDNS},
    286 				{"somehostname", "myhostname", hostLookupFilesDNS},
    287 				{"myhostname", "myhostname", hostLookupCgo},
    288 			},
    289 		},
    290 		// Debian Squeeze is just "dns,files", but lists all
    291 		// the default criteria for dns, but then has a
    292 		// non-standard but redundant notfound=return for the
    293 		// files.
    294 		{
    295 			name: "debian_squeeze",
    296 			c: &conf{
    297 				nss:    nssStr("hosts: dns [success=return notfound=continue unavail=continue tryagain=continue] files [notfound=return]"),
    298 				resolv: defaultResolvConf,
    299 			},
    300 			hostTests: []nssHostTest{
    301 				{"x.com", "myhostname", hostLookupDNSFiles},
    302 				{"somehostname", "myhostname", hostLookupDNSFiles},
    303 			},
    304 		},
    305 		{
    306 			name: "resolv.conf-unknown",
    307 			c: &conf{
    308 				nss:    nssStr("foo: bar"),
    309 				resolv: &dnsConfig{servers: defaultNS, ndots: 1, timeout: 5, attempts: 2, unknownOpt: true},
    310 			},
    311 			hostTests: []nssHostTest{{"google.com", "myhostname", hostLookupCgo}},
    312 		},
    313 		// Android should always use cgo.
    314 		{
    315 			name: "android",
    316 			c: &conf{
    317 				goos:   "android",
    318 				nss:    nssStr(""),
    319 				resolv: defaultResolvConf,
    320 			},
    321 			hostTests: []nssHostTest{
    322 				{"x.com", "myhostname", hostLookupCgo},
    323 			},
    324 		},
    325 	}
    326 
    327 	origGetHostname := getHostname
    328 	defer func() { getHostname = origGetHostname }()
    329 
    330 	for _, tt := range tests {
    331 		for _, ht := range tt.hostTests {
    332 			getHostname = func() (string, error) { return ht.localhost, nil }
    333 
    334 			gotOrder := tt.c.hostLookupOrder(ht.host)
    335 			if gotOrder != ht.want {
    336 				t.Errorf("%s: hostLookupOrder(%q) = %v; want %v", tt.name, ht.host, gotOrder, ht.want)
    337 			}
    338 		}
    339 	}
    340 
    341 }
    342 
    343 func TestSystemConf(t *testing.T) {
    344 	systemConf()
    345 }
    346