Observe resolv.conf changes

This commit is contained in:
Adam Harrison committed 2016-06-16 16:55:40 +01:00
1 parent 73a393823a
commit 27e7ec08d4
5 files changed
+86 -27

No files matched your search

+61 -21
View File
@@ -5,8 +5,10 @@ import (
"fmt"
"math/rand"
"net"
"os"
"sort"
"strings"
"sync"
"time"
"github.com/miekg/dns"
@@ -17,7 +19,6 @@ import (
const (
topDomain = "."
reverseDNSdomain = "in-addr.arpa."
etcResolvConf = "/etc/resolv.conf"
udpBuffSize = uint16(4096)
minUDPSize = 512
@@ -26,16 +27,48 @@ const (
DefaultClientTimeout = 5 * time.Second
)
type DNSServer struct {
ns *Nameserver
domain string
ttl uint32
address string
type Upstream interface {
Config() *dns.ClientConfig
}
servers []*dns.Server
upstream *dns.ClientConfig
tcpClient *dns.Client
udpClient *dns.Client
func NewUpstream(resolvConf, filterAddress string) Upstream {
return &upstream{
resolvConf: resolvConf,
filterAddress: filterAddress,
cachedConfig: &dns.ClientConfig{}}
}
type upstream struct {
sync.Mutex
resolvConf string
filterAddress string
cachedConfig *dns.ClientConfig
lastStat time.Time
lastModified time.Time
}
func (u *upstream) Config() *dns.ClientConfig {
u.Lock()
defer u.Unlock()
// If we checked less than five seconds ago return what we already have
now := time.Now()
if now.Sub(u.lastStat) < 5*time.Second {
return u.cachedConfig
}
u.lastStat = now
// Reread file if it has changed
if fi, err := os.Stat(u.resolvConf); err == nil && fi.ModTime() != u.lastModified {
if config, err := dns.ClientConfigFromFile(u.resolvConf); err == nil {
config.Servers = filter(config.Servers, u.filterAddress)
u.lastModified = fi.ModTime()
u.cachedConfig = config
}
}
return u.cachedConfig
}
func filter(ss []string, s string) []string {
@@ -49,24 +82,30 @@ func filter(ss []string, s string) []string {
return ss
}
func NewDNSServer(ns *Nameserver, domain, address, effectiveAddress string, ttl uint32, clientTimeout time.Duration) (*DNSServer, error) {
type DNSServer struct {
ns *Nameserver
domain string
ttl uint32
address string
servers []*dns.Server
upstream Upstream
tcpClient *dns.Client
udpClient *dns.Client
}
func NewDNSServer(ns *Nameserver, domain, address string, upstream Upstream, ttl uint32, clientTimeout time.Duration) (*DNSServer, error) {
s := &DNSServer{
ns: ns,
domain: dns.Fqdn(domain),
ttl: ttl,
address: address,
upstream: upstream,
tcpClient: &dns.Client{Net: "tcp", ReadTimeout: clientTimeout},
udpClient: &dns.Client{Net: "udp", ReadTimeout: clientTimeout, UDPSize: udpBuffSize},
}
var err error
if s.upstream, err = dns.ClientConfigFromFile(etcResolvConf); err != nil {
return nil, err
}
if s.upstream != nil {
s.upstream.Servers = filter(s.upstream.Servers, effectiveAddress)
}
err = s.listen(address)
err := s.listen(address)
return s, err
}
@@ -218,10 +257,11 @@ func (h *handler) handleRecursive(w dns.ResponseWriter, req *dns.Msg) {
}
}
for _, server := range h.upstream.Servers {
upstreamConfig := h.upstream.Config()
for _, server := range upstreamConfig.Servers {
reqCopy := req.Copy()
reqCopy.Id = dns.Id()
response, _, err := h.client.Exchange(reqCopy, fmt.Sprintf("%s:%s", server, h.upstream.Port))
response, _, err := h.client.Exchange(reqCopy, fmt.Sprintf("%s:%s", server, upstreamConfig.Port))
if (err != nil && err != dns.ErrTruncated) || response == nil {
h.ns.debugf("error trying %s: %v", server, err)
continue
+9 -4
View File
@@ -15,17 +15,22 @@ import (
"github.com/weaveworks/weave/net/address"
)
type mockUpstream struct {
config *dns.ClientConfig
}
func (mu *mockUpstream) Config() *dns.ClientConfig {
return mu.config
}
func startServer(t *testing.T, upstream *dns.ClientConfig) (*DNSServer, *Nameserver, int, int) {
peername, err := mesh.PeerNameFromString("00:00:00:02:00:00")
require.Nil(t, err)
nameserver := New(peername, "", func(mesh.PeerName) bool { return true })
dnsserver, err := NewDNSServer(nameserver, "weave.local.", "0.0.0.0:0", "", 30, 5*time.Second)
dnsserver, err := NewDNSServer(nameserver, "weave.local.", "0.0.0.0:0", &mockUpstream{upstream}, 30, 5*time.Second)
require.Nil(t, err)
udpPort := dnsserver.servers[0].PacketConn.LocalAddr().(*net.UDPAddr).Port
tcpPort := dnsserver.servers[1].Listener.Addr().(*net.TCPAddr).Port
if upstream != nil {
dnsserver.upstream = upstream
}
go dnsserver.ActivateAndServe()
return dnsserver, nameserver, udpPort, tcpPort
}
+1 -1
View File
@@ -38,7 +38,7 @@ func NewStatus(ns *Nameserver, dnsServer *DNSServer) *Status {
return &Status{
dnsServer.domain,
dnsServer.upstream.Servers,
dnsServer.upstream.Config().Servers,
dnsServer.address,
dnsServer.ttl,
entryStatusSlice}