diff --git a/pkg/pillar/cmd/nim/controllerdns.go b/pkg/pillar/cmd/nim/controllerdns.go index 62feb73df8..6e30f3dce7 100644 --- a/pkg/pillar/cmd/nim/controllerdns.go +++ b/pkg/pillar/cmd/nim/controllerdns.go @@ -5,12 +5,13 @@ package nim import ( "bytes" + "errors" "fmt" - "net" + "io/fs" "os" "time" - dns "github.com/Focinfi/go-dns-resolver" + "github.com/lf-edge/eve/pkg/pillar/devicenetwork" "github.com/lf-edge/eve/pkg/pillar/types" ) @@ -70,28 +71,104 @@ func (n *nim) queryControllerDNS() { } } -// periodical cache the controller DNS resolution into /etc/hosts file -// it returns the cached ip string, and TTL setting from the server -func (n *nim) controllerDNSCache(etchosts, controllerServer []byte, ipaddrCached string) (string, int) { - if len(etchosts) == 0 || len(controllerServer) == 0 { - return ipaddrCached, maxTTLSec +func (n *nim) resolveWithPorts(domain string) []devicenetwork.DNSResponse { + dnsResponse, errs := devicenetwork.ResolveWithPortsLambda( + domain, + n.dpcManager.GetDNS(), + devicenetwork.ResolveWithSrcIP, + ) + if len(errs) > 0 { + n.Log.Warnf("resolveWithPortsLambda failed: %+v", errs) } + return dnsResponse +} +// periodical cache the controller DNS resolution into /etc/hosts file +// it returns the cached ip string, and TTL setting from the server +func (n *nim) controllerDNSCache( + etchosts, controllerServer []byte, + ipaddrCached string, +) (string, int) { // Check to see if the server domain is already in the /etc/hosts as in eden, // then skip this DNS queries - if ipaddrCached == "" { - hostsEntries := bytes.Split(etchosts, []byte("\n")) - for _, entry := range hostsEntries { - fields := bytes.Fields(entry) - if len(fields) == 2 { - if bytes.Compare(fields[1], controllerServer) == 0 { - n.Log.Tracef("server entry %s already in /etc/hosts, skip", controllerServer) - return ipaddrCached, maxTTLSec - } - } + isCached, ipAddrCached, ttlCached := n.checkCachedEntry( + etchosts, + controllerServer, + ipaddrCached, + ) + if isCached { + return ipAddrCached, ttlCached + } + + err := os.Remove(tmpHostFileName) + if err != nil && !errors.Is(err, fs.ErrNotExist) { + n.Log.Warnf("%s exists but removing failed: %+v", tmpHostFileName, err) + } + + dnsResponses := n.resolveWithPorts(string(controllerServer)) + for _, dnsResponse := range dnsResponses { + if dnsResponse.IP.String() == ipAddrCached { + return ipAddrCached, getTTL(time.Duration(dnsResponse.TTL)) } } + lookupIPaddr := n.writeHostsFile(dnsResponses, etchosts, controllerServer) + if lookupIPaddr != "" { + n.Log.Tracef("append controller IP %s to /etc/hosts", lookupIPaddr) + } + + var ttlSec int + + if len(dnsResponses) > 0 { + ipaddrCached = dnsResponses[0].IP.String() + ttlSec = getTTL(time.Duration(dnsResponses[0].TTL)) + return ipaddrCached, ttlSec + } else { + return "", ttlSec + } +} + +func (n *nim) writeHostsFile( + dnsResponses []devicenetwork.DNSResponse, + etchosts, controllerServer []byte, +) string { + return n.writeHostsFileToDestination(dnsResponses, etchosts, controllerServer, etcHostFileName) +} + +func (n *nim) writeHostsFileToDestination( + dnsResponses []devicenetwork.DNSResponse, + etchosts, controllerServer []byte, + destination string, +) string { + var newhosts []byte + + var lookupIPaddr string + + if len(dnsResponses) == 0 { + newhosts = append(newhosts, etchosts...) + } else { + newhosts = append([]byte{}, etchosts...) + for _, dnsResponse := range dnsResponses { + lookupIPaddr = dnsResponse.IP.String() + serverEntry := fmt.Sprintf("%s %s\n", lookupIPaddr, controllerServer) + newhosts = append(newhosts, []byte(serverEntry)...) + } + } + + err := os.WriteFile(tmpHostFileName, newhosts, 0644) + if err != nil { + n.Log.Errorf("can not write /tmp/etchosts file %v", err) + return "" + } + if err := os.Rename(tmpHostFileName, destination); err != nil { + n.Log.Errorf("can not rename %s file %v", destination, err) + return "" + } + + return lookupIPaddr +} + +func (*nim) readNameservers() []string { var nameServers []string dnsServer, _ := os.ReadFile(resolvFileName) dnsRes := bytes.Split(dnsServer, []byte("\n")) @@ -104,74 +181,31 @@ func (n *nim) controllerDNSCache(etchosts, controllerServer []byte, ipaddrCached if len(nameServers) == 0 { nameServers = append(nameServers, "8.8.8.8") } + return nameServers +} - if _, err := os.Stat(tmpHostFileName); err == nil { - _ = os.Remove(tmpHostFileName) +func (n *nim) checkCachedEntry( + etchosts []byte, + controllerServer []byte, + ipaddrCached string, +) (bool, string, int) { + if len(etchosts) == 0 || len(controllerServer) == 0 { + return true, ipaddrCached, maxTTLSec } - var newhosts []byte - var gotipentry bool - var lookupIPaddr string - var ttlSec int - - domains := []string{string(controllerServer)} - dtypes := []dns.QueryType{dns.TypeA} - for _, nameServer := range nameServers { - resolver := dns.NewResolver(nameServer) - resolver.Targets(domains...).Types(dtypes...) - - res := resolver.Lookup() - for target := range res.ResMap { - for _, r := range res.ResMap[target] { - dIP := net.ParseIP(r.Content) - if dIP == nil { - continue - } - lookupIPaddr = dIP.String() - ttlSec = getTTL(r.Ttl) - if ipaddrCached == lookupIPaddr { - n.Log.Tracef("same IP address %s, return", lookupIPaddr) - return ipaddrCached, ttlSec + if ipaddrCached == "" { + hostsEntries := bytes.Split(etchosts, []byte("\n")) + for _, entry := range hostsEntries { + fields := bytes.Fields(entry) + if len(fields) == 2 { + if bytes.Compare(fields[1], controllerServer) == 0 { + n.Log.Tracef("server entry %s already in /etc/hosts, skip", controllerServer) + return true, ipaddrCached, maxTTLSec } - serverEntry := fmt.Sprintf("%s %s\n", lookupIPaddr, controllerServer) - newhosts = append(etchosts, []byte(serverEntry)...) - gotipentry = true - // a rare event for dns address change, log it - n.Log.Noticef("dnsServer %s, ttl %d, entry add to /etc/hosts: %s", nameServer, ttlSec, serverEntry) - break - } - if gotipentry { - break - } - } - if gotipentry { - break - } - } - - if ipaddrCached == lookupIPaddr { - return ipaddrCached, minTTLSec - } - if !gotipentry { // put original /etc/hosts file back - newhosts = append(newhosts, etchosts...) - } - - ipaddrCached = "" - err := os.WriteFile(tmpHostFileName, newhosts, 0644) - if err == nil { - if err := os.Rename(tmpHostFileName, etcHostFileName); err != nil { - n.Log.Errorf("can not rename /etc/hosts file %v", err) - } else { - if gotipentry { - ipaddrCached = lookupIPaddr } - n.Log.Tracef("append controller IP %s to /etc/hosts", lookupIPaddr) } - } else { - n.Log.Errorf("can not write /tmp/etchosts file %v", err) } - - return ipaddrCached, ttlSec + return false, "", 0 } func getTTL(ttl time.Duration) int { diff --git a/pkg/pillar/cmd/nim/controllerdns_test.go b/pkg/pillar/cmd/nim/controllerdns_test.go new file mode 100644 index 0000000000..75c3e39579 --- /dev/null +++ b/pkg/pillar/cmd/nim/controllerdns_test.go @@ -0,0 +1,79 @@ +package nim + +import ( + "fmt" + "io" + "os" + "strings" + "testing" + + "github.com/lf-edge/eve/pkg/pillar/base" + "github.com/lf-edge/eve/pkg/pillar/devicenetwork" + "github.com/lf-edge/eve/pkg/pillar/dpcmanager" + "github.com/sirupsen/logrus" +) + +func createTestNim() *nim { + var n nim + + dpcManager := dpcmanager.DpcManager{} + n.dpcManager = &dpcManager + logger := logrus.StandardLogger() + log := base.NewSourceLogObject(logger, "zedagent", 1234) + n.Logger = logger + n.Log = log + + return &n +} + +func TestControllerDNSCacheIndexOutOfRange(t *testing.T) { + // Regression test for bug introduced by switching to miekg/dns + n := createTestNim() + + n.controllerDNSCache([]byte(""), []byte("1.1"), "") +} + +func TestWriteHostsFile(t *testing.T) { + n := createTestNim() + + dnsResponses := []devicenetwork.DNSResponse{ + { + IP: []byte{1, 1, 1, 1}, + }, + { + IP: []byte{1, 0, 0, 1}, + }, + } + + dnsName := "one.one.one.one" + + f, err := os.CreateTemp("", "writeHostsFile.*.etchosts") + if err != nil { + panic(err) + } + defer os.Remove(f.Name()) + f.Close() + + n.writeHostsFileToDestination(dnsResponses, []byte{}, []byte(dnsName), f.Name()) + + // reopen the file to be able to read what has been written by writeHostsFileToDestination; f.Seek(0, 0) unfortunately is not enough + f, err = os.Open(f.Name()) + if err != nil { + panic(err) + } + content, err := io.ReadAll(f) + if err != nil { + panic(err) + } + + for _, dnsResponse := range dnsResponses { + expectedContent := fmt.Sprintf("%s %s\n", dnsResponse.IP.String(), dnsName) + if !strings.Contains(string(content), expectedContent) { + t.Fatalf( + "writing to hosts file failed, expected: '%s', got: '%s'", + expectedContent, + content, + ) + } + } +} diff --git a/pkg/pillar/devicenetwork/dns.go b/pkg/pillar/devicenetwork/dns.go index e2877aae9e..9c00e031cf 100644 --- a/pkg/pillar/devicenetwork/dns.go +++ b/pkg/pillar/devicenetwork/dns.go @@ -5,14 +5,33 @@ package devicenetwork import ( "fmt" + "net" "os" "path/filepath" "strings" + "sync" + "time" + + "github.com/lf-edge/eve/pkg/pillar/types" + "github.com/miekg/dns" ) // ResolveConfDirs : directories where resolv.conf for an interface could be found. var ResolveConfDirs = []string{"/run/dhcpcd/resolv.conf", "/run/wwan/resolv.conf"} +const ( + // DNSMaxParallelRequests is the maximum amount of parallel DNS requests + DNSMaxParallelRequests = 5 + maxTTLSec int = 3600 + dnsTimeout = 30 * time.Second +) + +// DNSResponse represents a response from a DNS server (A Record) +type DNSResponse struct { + IP net.IP + TTL uint32 +} + // IfnameToResolvConf : Look for a file created by dhcpcd func IfnameToResolvConf(ifname string) string { for _, d := range ResolveConfDirs { @@ -39,3 +58,121 @@ func ResolvConfToIfname(resolvConf string) string { } return "" } + +// ResolveWithSrcIP resolves a domain with a given dns server and source Ip +func ResolveWithSrcIP(domain string, dnsServerIP net.IP, srcIP net.IP) ([]DNSResponse, error) { + var response []DNSResponse + sourceUDPAddr := net.UDPAddr{IP: srcIP} + dialer := net.Dialer{LocalAddr: &sourceUDPAddr} + dnsClient := dns.Client{Dialer: &dialer} + msg := dns.Msg{} + if domain[len(domain)-1] != '.' { + domain = domain + "." + } + msg.SetQuestion(domain, dns.TypeA) + dnsClient.Timeout = time.Duration(dnsTimeout) + reply, _, err := dnsClient.Exchange(&msg, net.JoinHostPort(dnsServerIP.String(), "53")) + if err != nil { + return response, fmt.Errorf("dns exchange failed: %v", err) + } + for _, answer := range reply.Answer { + if aRecord, ok := answer.(*dns.A); ok { + response = append(response, DNSResponse{ + IP: aRecord.A, + TTL: aRecord.Header().Ttl, + }) + } + } + + return response, nil +} + +// ResolveWithPortsLambda resolves a domain by using source IPs and dns servers from DeviceNetworkStatus +// As a resolver func ResolveWithSrcIP can be used +func ResolveWithPortsLambda(domain string, + dns types.DeviceNetworkStatus, + resolve func(string, net.IP, net.IP) ([]DNSResponse, error)) ([]DNSResponse, []error) { + + quit := make(chan struct{}) + work := make(chan struct{}, DNSMaxParallelRequests) + resolvedIPsChan := make(chan []DNSResponse) + countDNSRequests := 0 + var errs []error + var errsMutex sync.Mutex + var wg sync.WaitGroup + + for _, port := range dns.Ports { + if port.Cost > 0 { + continue + } + + var srcIPs []net.IP + for _, addrInfo := range port.AddrInfoList { + srcIPs = append(srcIPs, addrInfo.Addr) + } + + for _, dnsIP := range port.DNSServers { + for _, srcIP := range srcIPs { + wg.Add(1) + dnsIPCopy := make(net.IP, len(dnsIP)) + copy(dnsIPCopy, dnsIP) + srcIPCopy := make(net.IP, len(srcIP)) + copy(srcIPCopy, srcIP) + countDNSRequests++ + go func(dnsIP, srcIP net.IP) { + select { + case work <- struct{}{}: + // if writable, means less than dnsMaxParallelRequests goroutines are currently running + } + select { + case <-quit: + // will return in case the quit chan has been closed, + // meaning another dns server already resolved the IP + return + default: + // do not wait for receiving a quit + } + response, err := resolve(domain, dnsIP, srcIP) + if err != nil { + errsMutex.Lock() + defer errsMutex.Unlock() + errs = append(errs, err) + } + if response != nil { + resolvedIPsChan <- response + } + <-work + wg.Done() + }(dnsIPCopy, srcIPCopy) + } + } + } + + wgChan := make(chan struct{}) + go func() { + wg.Wait() + close(wgChan) + }() + + select { + case <-wgChan: + var responses []DNSResponse + if countDNSRequests == 0 { + // fallback in case no resolver is configured + ips, err := net.LookupIP(domain) + if err != nil { + return nil, append(errs, fmt.Errorf("fallback resolver failed: %+v", err)) + } + for _, ip := range ips { + responses = append(responses, DNSResponse{ + IP: ip, + TTL: uint32(maxTTLSec), + }) + } + } + return responses, nil + case ip := <-resolvedIPsChan: + close(quit) + return ip, errs + } +} diff --git a/pkg/pillar/devicenetwork/dns_test.go b/pkg/pillar/devicenetwork/dns_test.go new file mode 100644 index 0000000000..af02f43dbd --- /dev/null +++ b/pkg/pillar/devicenetwork/dns_test.go @@ -0,0 +1,201 @@ +// Copyright (c) 2023 Zededa, Inc. +// SPDX-License-Identifier: Apache-2.0 + +package devicenetwork_test + +import ( + "net" + "sync/atomic" + "testing" + "time" + + "github.com/lf-edge/eve/pkg/pillar/devicenetwork" + "github.com/lf-edge/eve/pkg/pillar/netmonitor" + "github.com/lf-edge/eve/pkg/pillar/types" +) + +func createNetmonitorMockInterface() []netmonitor.MockInterface { + mockInterface := []netmonitor.MockInterface{ + { + Attrs: netmonitor.IfAttrs{ + IfIndex: 0, + IfName: "if0", + }, + IPAddrs: []*net.IPNet{ + { + IP: []byte{192, 168, 0, 1}, + Mask: []byte{255, 255, 255, 0}, + }, + { + IP: []byte{192, 168, 0, 2}, + Mask: []byte{255, 255, 255, 0}, + }, + }, + HwAddr: []byte{}, + DNS: netmonitor.DNSInfo{ + ResolvConfPath: "/etc/resolv.conf", + Domains: []string{}, + DNSServers: []net.IP{ + {208, 67, 220, 220}, + {208, 67, 222, 222}, + {141, 1, 1, 1}, + {1, 1, 1, 1}, + {9, 9, 9, 9}, + }, + }, + }, + { + Attrs: netmonitor.IfAttrs{ + IfIndex: 1, + IfName: "if1", + }, + IPAddrs: []*net.IPNet{ + { + IP: []byte{192, 168, 1, 1}, + Mask: []byte{255, 255, 255, 0}, + }, + { + IP: []byte{192, 168, 1, 2}, + Mask: []byte{255, 255, 255, 0}, + }, + }, + HwAddr: []byte{}, + DNS: netmonitor.DNSInfo{ + ResolvConfPath: "/etc/resolv.conf", + Domains: []string{}, + DNSServers: []net.IP{ + {1, 0, 0, 1}, + {8, 8, 8, 8}, + }, + }, + }, + { + Attrs: netmonitor.IfAttrs{ + IfIndex: 2, + IfName: "ExpensiveIf", + }, + IPAddrs: []*net.IPNet{{ + IP: []byte{6, 6, 6, 6}, + Mask: []byte{255, 255, 255, 0}, + }}, + HwAddr: []byte{}, + DNS: netmonitor.DNSInfo{ + ResolvConfPath: "/etc/resolv.conf", + Domains: []string{}, + DNSServers: []net.IP{ + {0, 6, 6, 6}, + {0, 7, 7, 7}, + }, + }, + }, + } + return mockInterface +} + +func createDeviceNetworkStatus() types.DeviceNetworkStatus { + mockInterface := createNetmonitorMockInterface() + deviceNetworkStatusPorts := make([]types.NetworkPortStatus, len(mockInterface)) + for i := range deviceNetworkStatusPorts { + deviceNetworkStatusPorts[i].IfName = mockInterface[i].Attrs.IfName + deviceNetworkStatusPorts[i].DNSServers = mockInterface[i].DNS.DNSServers + addrInfos := make([]types.AddrInfo, len(mockInterface[i].IPAddrs)) + for j := range mockInterface[i].IPAddrs { + addrInfos[j] = types.AddrInfo{ + Addr: mockInterface[i].IPAddrs[j].IP, + } + } + + deviceNetworkStatusPorts[i].AddrInfoList = addrInfos + } + + deviceNetworkStatus := types.DeviceNetworkStatus{ + CurrentIndex: 0, + Ports: deviceNetworkStatusPorts, + } + return deviceNetworkStatus +} + +func TestDnsResolve(t *testing.T) { + t.Parallel() + + testHost := "255.255.255.255.nip.io" + expectedIP := net.IP{255, 255, 255, 255} + if testing.Short() { + t.Skipf( + "Skipping as connecting to the internet would take too much time and short tests are enabled", + ) + } + + res, errs := devicenetwork.ResolveWithSrcIP(testHost, net.IP{1, 1, 1, 1}, net.IP{0, 0, 0, 0}) + if errs != nil { + panic(errs) + } + if res == nil { + t.Skipf( + "could not resolve, skipping as probably the tests don't have internet connection of %s is down", + testHost, + ) + } + if !res[0].IP.Equal(expectedIP) { + t.Fatalf( + "resolving returned wrong IP address %+v, but should have been %+v", + res, + expectedIP, + ) + } +} + +func TestDnsResolveTimeout(t *testing.T) { + t.Parallel() + + if testing.Short() { + t.Skipf("Skipping as timing out would take too much time and short tests are enabled") + } + exampleCom := net.IP{93, 184, 216, 34} // example.com, they drop packets on 53/udp + res, _ := devicenetwork.ResolveWithSrcIP("www.google.com", exampleCom, net.IP{0, 0, 0, 0}) + if res != nil { + t.Fatalf("resolving with dns server %+v should fail, but succeeded: %+v", exampleCom, res) + } +} + +func TestResolveWithPortsLambda(t *testing.T) { + t.Parallel() + + expectedIP := net.IP{1, 2, 3, 4} + + var first atomic.Bool + first.Store(true) + var countCalls atomic.Int32 + resolverFunc := func(domain string, dnsServer net.IP, srcIP net.IP) ([]devicenetwork.DNSResponse, error) { + countCalls.Add(1) + if !first.Swap(false) { + time.Sleep(1 * time.Second) + return []devicenetwork.DNSResponse{}, nil + } + return []devicenetwork.DNSResponse{ + { + IP: expectedIP, + TTL: 3600, + }, + }, nil + } + + deviceNetworkStatus := createDeviceNetworkStatus() + res, err := devicenetwork.ResolveWithPortsLambda( + "example.com", + deviceNetworkStatus, + resolverFunc, + ) + if err != nil { + panic(err) + } + if !res[0].IP.Equal(expectedIP) { + t.Errorf("wrong result, expected IP 1.2.3.4, but got: %+v", res) + } + if countCalls.Load() > devicenetwork.DNSMaxParallelRequests+1 { + // checking for +1 as the first call immediately returns + t.Errorf( + "more calls to resolverFunc than dnsMaxParallelRequests+1, but first call should already succeed", + ) + } +} diff --git a/pkg/pillar/go.mod b/pkg/pillar/go.mod index 43b9d95c09..62ff73a096 100644 --- a/pkg/pillar/go.mod +++ b/pkg/pillar/go.mod @@ -3,7 +3,6 @@ module github.com/lf-edge/eve/pkg/pillar go 1.20 require ( - github.com/Focinfi/go-dns-resolver v1.0.1 github.com/anatol/smart.go v0.0.0-20220615232124-371056cd18c3 github.com/bicomsystems/go-libzfs v0.4.0 github.com/containerd/cgroups v1.0.4 @@ -29,6 +28,7 @@ require ( github.com/lf-edge/eve/api/go v0.0.0-00010101000000-000000000000 github.com/lf-edge/eve/libs v0.0.0-20230303013136-e890ce9ee8a3 github.com/linuxkit/linuxkit/src/cmd/linuxkit v0.0.0-20220913135124-e532e7310810 + github.com/miekg/dns v1.1.41 github.com/moby/sys/mountinfo v0.6.0 github.com/onsi/gomega v1.24.2 github.com/opencontainers/go-digest v1.0.0 @@ -102,7 +102,6 @@ require ( github.com/mdlayher/netlink v1.7.1 // indirect github.com/mdlayher/raw v0.0.0-20191009151244-50f2db8cc065 // indirect github.com/mdlayher/socket v0.4.0 // indirect - github.com/miekg/dns v1.1.41 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/moby/locker v1.0.1 // indirect github.com/moby/sys/signal v0.7.0 // indirect diff --git a/pkg/pillar/go.sum b/pkg/pillar/go.sum index 2396e650fa..e8aa30383b 100644 --- a/pkg/pillar/go.sum +++ b/pkg/pillar/go.sum @@ -155,8 +155,6 @@ github.com/Code-Hex/vz v0.0.4/go.mod h1:UeHKXSv3hP7BzU6IaVE/a7VHSHUHpqbS3oVko4O5 github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/Djarvur/go-err113 v0.0.0-20200410182137-af658d038157/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs= github.com/Djarvur/go-err113 v0.1.0/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs= -github.com/Focinfi/go-dns-resolver v1.0.1 h1:fSNrahh/8Ge06z6HtTEbagPy/WGdV2O1VOEm9+S9vds= -github.com/Focinfi/go-dns-resolver v1.0.1/go.mod h1:DDoAgG4IEfaLksj8/CrTwT1Y/T1tJ2Hg4jznkTL8W0g= github.com/GoogleCloudPlatform/cloudsql-proxy v0.0.0-20191009163259-e802c2cb94ae/go.mod h1:mjwGPas4yKduTyubHvD1Atl9r1rUq8DfVy+gkVvZ+oo= github.com/GoogleCloudPlatform/k8s-cloud-provider v0.0.0-20190822182118-27a4ced34534/go.mod h1:iroGtC8B3tQiqtds1l+mgk/BBOrxbqjH+eUfFQYRc14= github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= @@ -1206,7 +1204,6 @@ github.com/mibk/dupl v1.0.0/go.mod h1:pCr4pNxxIbFGvtyCOi0c7LVjmV6duhKWV+ex5vh38M github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= github.com/miekg/dns v1.1.27/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= -github.com/miekg/dns v1.1.35/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= github.com/miekg/dns v1.1.41 h1:WMszZWJG0XmzbK9FEmzH2TVcqYzFesusSIB41b8KHxY= github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= diff --git a/pkg/pillar/vendor/github.com/Focinfi/go-dns-resolver/.gitignore b/pkg/pillar/vendor/github.com/Focinfi/go-dns-resolver/.gitignore deleted file mode 100644 index 59610b561a..0000000000 --- a/pkg/pillar/vendor/github.com/Focinfi/go-dns-resolver/.gitignore +++ /dev/null @@ -1,26 +0,0 @@ -# Compiled Object files, Static and Dynamic libs (Shared Objects) -*.o -*.a -*.so - -# Folders -_obj -_test - -# Architecture specific extensions/prefixes -*.[568vq] -[568vq].out - -*.cgo1.go -*.cgo2.c -_cgo_defun.c -_cgo_gotypes.go -_cgo_export.* - -_testmain.go - -*.exe -*.test -*.prof - -.idea \ No newline at end of file diff --git a/pkg/pillar/vendor/github.com/Focinfi/go-dns-resolver/LICENSE b/pkg/pillar/vendor/github.com/Focinfi/go-dns-resolver/LICENSE deleted file mode 100644 index 55f12ab777..0000000000 --- a/pkg/pillar/vendor/github.com/Focinfi/go-dns-resolver/LICENSE +++ /dev/null @@ -1,30 +0,0 @@ -Copyright (c) 2009 The Go Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -As this is fork of the official Go code the same license applies. -Extensions of the original work are copyright (c) 2011 Miek Gieben diff --git a/pkg/pillar/vendor/github.com/Focinfi/go-dns-resolver/README.md b/pkg/pillar/vendor/github.com/Focinfi/go-dns-resolver/README.md deleted file mode 100644 index b38a7dd78b..0000000000 --- a/pkg/pillar/vendor/github.com/Focinfi/go-dns-resolver/README.md +++ /dev/null @@ -1,89 +0,0 @@ -# go-dns-resolver - -DNS resolver in Golang, based on [miekg/dns](https://github.com/miekg/dns). - -### Goal - -1. Simple interface -2. Rich and neat output -3. Easy to figure -4. High performance - -### Install -```shell -go get github.com/Focinfi/go-dns-resolver -``` - -### Example - -```go -package main - -import ( - dns "github.com/Focinfi/go-dns-resolver" - "log" -) - -func main() { - domains := []string{"google.com", "twitter.com"} - types := []dns.QueryType{dns.TypeA, dns.TypeNS, dns.TypeMX, dns.TypeTXT} - - // Set timeout and retry times - dns.Config.SetTimeout(uint(2)) - dns.Config.RetryTimes = uint(4) - - // Simple usage - if results, err := dns.Exchange("google.com", "119.29.29.29", dns.TypeA); err == nil { - for _, r := range results { - log.Println(r.Record, r.Type, r.Ttl, r.Priority, r.Content) - } - } else { - log.Fatal(err) - } - - // Create and setup resolver with domains and types - resolver := dns.NewResolver("119.29.29.29") - resolver.Targets(domains...).Types(types...) - // Lookup - res := resolver.Lookup() - - //res.ResMap is a map[string]*ResultItem, key is the domain - for target := range res.ResMap { - log.Printf("%v: \n", target) - for _, r := range res.ResMap[target] { - log.Println(r.Record, r.Type, r.Ttl, r.Priority, r.Content) - } - } -} - -``` - -Output: -``` shell -google.com A 2m31s 0 216.58.197.110 - -twitter.com: -twitter.com A 10m3s 0 78.16.49.15 -twitter.com NS 11h49m58s 0 ns1.p34.dynect.net. -twitter.com NS 11h49m58s 0 ns4.p34.dynect.net. -twitter.com NS 11h49m58s 0 ns3.p34.dynect.net. -twitter.com NS 11h49m58s 0 ns2.p34.dynect.net. -google.com: -google.com TXT 19m26s 0 v=spf1 include:_spf.google.com ~all -google.com A 2m31s 0 216.58.197.110 -google.com NS 7h40m6s 0 ns1.google.com. -google.com NS 7h40m6s 0 ns3.google.com. -google.com NS 7h40m6s 0 ns2.google.com. -google.com NS 7h40m6s 0 ns4.google.com. -google.com MX 10m0s 20 alt1.aspmx.l.google.com. -google.com MX 10m0s 10 aspmx.l.google.com. -google.com MX 10m0s 50 alt4.aspmx.l.google.com. -google.com MX 10m0s 40 alt3.aspmx.l.google.com. -google.com MX 10m0s 30 alt2.aspmx.l.google.com. -[Finished in 2.3s] -``` - -### Todo - -1. Support more DNS record types - diff --git a/pkg/pillar/vendor/github.com/Focinfi/go-dns-resolver/config.go b/pkg/pillar/vendor/github.com/Focinfi/go-dns-resolver/config.go deleted file mode 100644 index bc747d7c98..0000000000 --- a/pkg/pillar/vendor/github.com/Focinfi/go-dns-resolver/config.go +++ /dev/null @@ -1,16 +0,0 @@ -package resolver - -import ( - "time" -) - -type Configuration struct { - Timeout time.Duration - RetryTimes uint -} - -func (c *Configuration) SetTimeout(seconds uint) { - c.Timeout = time.Second * time.Duration(seconds) -} - -var Config = Configuration{Timeout: time.Second * time.Duration(2), RetryTimes: uint(0)} diff --git a/pkg/pillar/vendor/github.com/Focinfi/go-dns-resolver/dns-resolver.go b/pkg/pillar/vendor/github.com/Focinfi/go-dns-resolver/dns-resolver.go deleted file mode 100644 index c9746117a6..0000000000 --- a/pkg/pillar/vendor/github.com/Focinfi/go-dns-resolver/dns-resolver.go +++ /dev/null @@ -1,76 +0,0 @@ -package resolver - -import ( - "sync" - - "github.com/miekg/dns" -) - -type Resolver struct { - Server string - Query *Query -} - -func NewResolver(server string) *Resolver { - resolver := Resolver{Server: server + ":53"} - return &resolver -} - -func (r *Resolver) Targets(targets ...string) *Query { - query := NewQueryWithTargets(targets...) - r.Query = query - return query -} - -func (r *Resolver) Lookup() *Result { - result := Result{Server: r.Server, ResMap: map[string][]*ResultItem{}} - - resultsChan := make(chan []*ResultItem, r.Query.Count()) - var wg sync.WaitGroup - for _, queryItem := range r.Query.Items { - target := queryItem.Target - for _, t := range queryItem.Types { - wg.Add(1) - go func(queryType QueryType) { - defer wg.Done() - goExchange(target, r.Server, queryType, resultsChan) - }(t) - } - } - - wg.Wait() - close(resultsChan) - - for res := range resultsChan { - if len(res) > 0 { - target := res[0].Record - result.ResMap[target] = append(result.ResMap[target], res...) - } - } - return &result -} - -func goExchange(target string, server string, queryType QueryType, resultsChan chan []*ResultItem) { - for i := -1; i < int(Config.RetryTimes); i++ { - if results, err := Exchange(target, server, queryType); err == nil { - resultsChan <- results - return - } - } -} - -func Exchange(target string, server string, queryType QueryType) ([]*ResultItem, error) { - var results []*ResultItem - msg := &dns.Msg{} - msg.SetQuestion(target+".", uint16(queryType)) - client := &dns.Client{DialTimeout: Config.Timeout} - res, _, err := client.Exchange(msg, server) - if err == nil && len(res.Answer) > 0 { - for _, answer := range res.Answer { - result := NewResultItemWithDnsRR(queryType, answer) - result.Record = target - results = append(results, result) - } - } - return results, err -} diff --git a/pkg/pillar/vendor/github.com/Focinfi/go-dns-resolver/query-type.go b/pkg/pillar/vendor/github.com/Focinfi/go-dns-resolver/query-type.go deleted file mode 100644 index 43b5b856e8..0000000000 --- a/pkg/pillar/vendor/github.com/Focinfi/go-dns-resolver/query-type.go +++ /dev/null @@ -1,38 +0,0 @@ -package resolver - -import ( - "github.com/miekg/dns" -) - -type QueryType uint16 - -const ( - TypeA = QueryType(dns.TypeA) - TypeAAAA = QueryType(dns.TypeAAAA) - TypeNS = QueryType(dns.TypeNS) - TypeMX = QueryType(dns.TypeMX) - TypeSOA = QueryType(dns.TypeSOA) - TypeCNAME = QueryType(dns.TypeCNAME) - TypeTXT = QueryType(dns.TypeTXT) -) - -func (q QueryType) String() string { - switch q { - case TypeA: - return "A" - case TypeAAAA: - return "AAAA" - case TypeNS: - return "NS" - case TypeMX: - return "MX" - case TypeSOA: - return "SOA" - case TypeCNAME: - return "CNAME" - case TypeTXT: - return "TXT" - default: - return "Unknown Type" - } -} diff --git a/pkg/pillar/vendor/github.com/Focinfi/go-dns-resolver/query.go b/pkg/pillar/vendor/github.com/Focinfi/go-dns-resolver/query.go deleted file mode 100644 index 24a479a0e5..0000000000 --- a/pkg/pillar/vendor/github.com/Focinfi/go-dns-resolver/query.go +++ /dev/null @@ -1,32 +0,0 @@ -package resolver - -type QueryItem struct { - Target string - Types []QueryType -} - -type Query struct { - Items []*QueryItem -} - -func NewQueryWithTargets(targets ...string) *Query { - query := Query{Items: make([]*QueryItem, len(targets), len(targets))} - for i, target := range targets { - query.Items[i] = &QueryItem{Target: target} - } - return &query -} - -func (query *Query) Types(types ...QueryType) *Query { - for _, queryItem := range query.Items { - queryItem.Types = types - } - return query -} - -func (query *Query) Count() int { - if len(query.Items) == 0 { - return 0 - } - return len(query.Items) * len(query.Items[0].Types) -} diff --git a/pkg/pillar/vendor/github.com/Focinfi/go-dns-resolver/result.go b/pkg/pillar/vendor/github.com/Focinfi/go-dns-resolver/result.go deleted file mode 100644 index 00f018bd6e..0000000000 --- a/pkg/pillar/vendor/github.com/Focinfi/go-dns-resolver/result.go +++ /dev/null @@ -1,62 +0,0 @@ -package resolver - -import ( - "github.com/miekg/dns" - "strings" - "time" -) - -type Result struct { - Server string - ResMap map[string][]*ResultItem -} - -type ResultItem struct { - Record string - Type string - Ttl time.Duration - Priority uint16 - Content string -} - -func (resultItem *ResultItem) setTtl(rr dns.RR_Header) { - resultItem.Ttl = time.Second * time.Duration(rr.Ttl) -} - -func NewResultItemWithDnsRR(queryType QueryType, answer dns.RR) (resultItem *ResultItem) { - resultItem = &ResultItem{Type: queryType.String()} - switch queryType { - case TypeA: - if a, ok := answer.(*dns.A); ok { - resultItem.setTtl(a.Hdr) - resultItem.Content = a.A.String() - } - case TypeAAAA: - if a, ok := answer.(*dns.AAAA); ok { - resultItem.setTtl(a.Hdr) - resultItem.Content = a.AAAA.String() - } - case TypeCNAME: - if cname, ok := answer.(*dns.CNAME); ok { - resultItem.setTtl(cname.Hdr) - resultItem.Content = cname.Target - } - case TypeMX: - if mx, ok := answer.(*dns.MX); ok { - resultItem.setTtl(mx.Hdr) - resultItem.Content = mx.Mx - resultItem.Priority = mx.Preference - } - case TypeNS: - if ns, ok := answer.(*dns.NS); ok { - resultItem.setTtl(ns.Hdr) - resultItem.Content = ns.Ns - } - case TypeTXT: - if txt, ok := answer.(*dns.TXT); ok { - resultItem.setTtl(txt.Hdr) - resultItem.Content = strings.Join(txt.Txt, " ") - } - } - return -} diff --git a/pkg/pillar/vendor/modules.txt b/pkg/pillar/vendor/modules.txt index 5711769558..dd905963ca 100644 --- a/pkg/pillar/vendor/modules.txt +++ b/pkg/pillar/vendor/modules.txt @@ -26,9 +26,6 @@ github.com/Azure/azure-storage-blob-go/azblob ## explicit; go 1.16 github.com/Azure/go-ansiterm github.com/Azure/go-ansiterm/winterm -# github.com/Focinfi/go-dns-resolver v1.0.1 -## explicit; go 1.14 -github.com/Focinfi/go-dns-resolver # github.com/Microsoft/go-winio v0.5.2 ## explicit; go 1.13 github.com/Microsoft/go-winio