2024-01-24 16:47:26 +01:00
|
|
|
//go:build !android
|
|
|
|
|
|
|
|
package dns
|
|
|
|
|
|
|
|
import (
|
|
|
|
"os"
|
2024-02-02 17:54:33 +01:00
|
|
|
"path/filepath"
|
2024-01-24 16:47:26 +01:00
|
|
|
"testing"
|
|
|
|
)
|
|
|
|
|
|
|
|
func Test_parseResolvConf(t *testing.T) {
|
|
|
|
testCases := []struct {
|
|
|
|
input string
|
|
|
|
expectedSearch []string
|
|
|
|
expectedNS []string
|
|
|
|
expectedOther []string
|
|
|
|
}{
|
|
|
|
{
|
2024-01-29 17:10:47 +01:00
|
|
|
input: `domain example.org
|
|
|
|
search example.org
|
2024-01-24 16:47:26 +01:00
|
|
|
nameserver 192.168.0.1
|
|
|
|
`,
|
2024-01-29 17:10:47 +01:00
|
|
|
expectedSearch: []string{"example.org"},
|
2024-01-24 16:47:26 +01:00
|
|
|
expectedNS: []string{"192.168.0.1"},
|
|
|
|
expectedOther: []string{},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
input: `# This is /run/systemd/resolve/resolv.conf managed by man:systemd-resolved(8).
|
|
|
|
# Do not edit.
|
|
|
|
#
|
|
|
|
# This file might be symlinked as /etc/resolv.conf. If you're looking at
|
|
|
|
# /etc/resolv.conf and seeing this text, you have followed the symlink.
|
|
|
|
#
|
|
|
|
# This is a dynamic resolv.conf file for connecting local clients directly to
|
|
|
|
# all known uplink DNS servers. This file lists all configured search domains.
|
|
|
|
#
|
|
|
|
# Third party programs should typically not access this file directly, but only
|
|
|
|
# through the symlink at /etc/resolv.conf. To manage man:resolv.conf(5) in a
|
|
|
|
# different way, replace this symlink by a static file or a different symlink.
|
|
|
|
#
|
|
|
|
# See man:systemd-resolved.service(8) for details about the supported modes of
|
|
|
|
# operation for /etc/resolv.conf.
|
|
|
|
|
|
|
|
nameserver 192.168.2.1
|
|
|
|
nameserver 100.81.99.197
|
|
|
|
search netbird.cloud
|
|
|
|
`,
|
|
|
|
expectedSearch: []string{"netbird.cloud"},
|
|
|
|
expectedNS: []string{"192.168.2.1", "100.81.99.197"},
|
|
|
|
expectedOther: []string{},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
input: `# This is /run/systemd/resolve/resolv.conf managed by man:systemd-resolved(8).
|
|
|
|
# Do not edit.
|
|
|
|
#
|
|
|
|
# This file might be symlinked as /etc/resolv.conf. If you're looking at
|
|
|
|
# /etc/resolv.conf and seeing this text, you have followed the symlink.
|
|
|
|
#
|
|
|
|
# This is a dynamic resolv.conf file for connecting local clients directly to
|
|
|
|
# all known uplink DNS servers. This file lists all configured search domains.
|
|
|
|
#
|
|
|
|
# Third party programs should typically not access this file directly, but only
|
|
|
|
# through the symlink at /etc/resolv.conf. To manage man:resolv.conf(5) in a
|
|
|
|
# different way, replace this symlink by a static file or a different symlink.
|
|
|
|
#
|
|
|
|
# See man:systemd-resolved.service(8) for details about the supported modes of
|
|
|
|
# operation for /etc/resolv.conf.
|
|
|
|
|
|
|
|
nameserver 192.168.2.1
|
|
|
|
nameserver 100.81.99.197
|
|
|
|
search netbird.cloud
|
|
|
|
options debug
|
|
|
|
`,
|
|
|
|
expectedSearch: []string{"netbird.cloud"},
|
|
|
|
expectedNS: []string{"192.168.2.1", "100.81.99.197"},
|
|
|
|
expectedOther: []string{"options debug"},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, testCase := range testCases {
|
|
|
|
testCase := testCase
|
|
|
|
t.Run("test", func(t *testing.T) {
|
|
|
|
t.Parallel()
|
2024-02-02 17:54:33 +01:00
|
|
|
tmpResolvConf := filepath.Join(t.TempDir(), "resolv.conf")
|
2024-01-24 16:47:26 +01:00
|
|
|
err := os.WriteFile(tmpResolvConf, []byte(testCase.input), 0644)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
cfg, err := parseResolvConfFile(tmpResolvConf)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
ok := compareLists(cfg.searchDomains, testCase.expectedSearch)
|
|
|
|
if !ok {
|
|
|
|
t.Errorf("invalid parse result for search domains, expected: %v, got: %v", testCase.expectedSearch, cfg.searchDomains)
|
|
|
|
}
|
|
|
|
|
|
|
|
ok = compareLists(cfg.nameServers, testCase.expectedNS)
|
|
|
|
if !ok {
|
|
|
|
t.Errorf("invalid parse result for ns domains, expected: %v, got: %v", testCase.expectedNS, cfg.nameServers)
|
|
|
|
}
|
|
|
|
|
|
|
|
ok = compareLists(cfg.others, testCase.expectedOther)
|
|
|
|
if !ok {
|
|
|
|
t.Errorf("invalid parse result for others, expected: %v, got: %v", testCase.expectedOther, cfg.others)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
func compareLists(search []string, search2 []string) bool {
|
|
|
|
if len(search) != len(search2) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
for i, v := range search {
|
|
|
|
if v != search2[i] {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
2024-02-02 17:54:33 +01:00
|
|
|
|
|
|
|
func Test_emptyFile(t *testing.T) {
|
|
|
|
cfg, err := parseResolvConfFile("/tmp/nothing")
|
|
|
|
if err == nil {
|
|
|
|
t.Errorf("expected error, got nil")
|
|
|
|
}
|
|
|
|
if len(cfg.others) != 0 || len(cfg.searchDomains) != 0 || len(cfg.nameServers) != 0 {
|
|
|
|
t.Errorf("expected empty config, got %v", cfg)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func Test_symlink(t *testing.T) {
|
|
|
|
input := `# This is /run/systemd/resolve/resolv.conf managed by man:systemd-resolved(8).
|
|
|
|
# Do not edit.
|
|
|
|
#
|
|
|
|
# This file might be symlinked as /etc/resolv.conf. If you're looking at
|
|
|
|
# /etc/resolv.conf and seeing this text, you have followed the symlink.
|
|
|
|
#
|
|
|
|
# This is a dynamic resolv.conf file for connecting local clients directly to
|
|
|
|
# all known uplink DNS servers. This file lists all configured search domains.
|
|
|
|
#
|
|
|
|
# Third party programs should typically not access this file directly, but only
|
|
|
|
# through the symlink at /etc/resolv.conf. To manage man:resolv.conf(5) in a
|
|
|
|
# different way, replace this symlink by a static file or a different symlink.
|
|
|
|
#
|
|
|
|
# See man:systemd-resolved.service(8) for details about the supported modes of
|
|
|
|
# operation for /etc/resolv.conf.
|
|
|
|
|
|
|
|
nameserver 192.168.0.1
|
|
|
|
`
|
|
|
|
|
|
|
|
tmpResolvConf := filepath.Join(t.TempDir(), "resolv.conf")
|
|
|
|
err := os.WriteFile(tmpResolvConf, []byte(input), 0644)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
tmpLink := filepath.Join(t.TempDir(), "symlink")
|
|
|
|
err = os.Symlink(tmpResolvConf, tmpLink)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
cfg, err := parseResolvConfFile(tmpLink)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(cfg.nameServers) != 1 {
|
|
|
|
t.Errorf("unexpected resolv.conf content: %v", cfg)
|
|
|
|
}
|
|
|
|
}
|