net/dnscache: add a bunch of synthetic failure knobs

This commit is contained in:
Andrew Dunham 2022-09-02 12:06:25 -04:00 committed by Andrew Dunham
parent 6f700925ce
commit a37032932f
2 changed files with 51 additions and 9 deletions

View File

@ -15,6 +15,7 @@
"fmt"
"log"
"net"
"os"
"runtime"
"sync"
"time"
@ -108,6 +109,11 @@ func (r *Resolver) ttl() time.Duration {
// If err is nil, ip will be non-nil. The v6 address may be nil even
// with a nil error.
func (r *Resolver) LookupIP(ctx context.Context, host string) (ip, v6 net.IP, allIPs []net.IPAddr, err error) {
if fileExists("/tmp/dnscache-synthetic-resolve-failure.txt") {
log.Printf("dnscache: synthetic resolve failure for %s", host)
return nil, nil, nil, fmt.Errorf("synthetic resolve failure for %s", host)
}
if ip := net.ParseIP(host); ip != nil {
if ip4 := ip.To4(); ip4 != nil {
return ip4, nil, []net.IPAddr{{IP: ip4}}, nil
@ -266,6 +272,7 @@ func (r *Resolver) addIPCache(host string, ip, ip6 net.IP, allIPs []net.IPAddr,
if r.ipCache == nil {
r.ipCache = make(map[string]ipCacheEntry)
}
if false { // DEBUG DEBUG
r.ipCache[host] = ipCacheEntry{
ip: ip,
ip6: ip6,
@ -273,6 +280,7 @@ func (r *Resolver) addIPCache(host string, ip, ip6 net.IP, allIPs []net.IPAddr,
expires: time.Now().Add(d),
}
}
}
type DialContextFunc func(ctx context.Context, network, address string) (net.Conn, error)
@ -369,12 +377,30 @@ type dialCall struct {
// dnsWasTrustworthy reports whether we think the IP address(es) we
// tried (and failed) to dial were probably the correct IPs. Currently
// the heuristic is whether they ever worked previously.
func (dc *dialCall) dnsWasTrustworthy() bool {
func (dc *dialCall) dnsWasTrustworthy() (ret bool) {
dc.d.mu.Lock()
defer dc.d.mu.Unlock()
dc.mu.Lock()
defer dc.mu.Unlock()
defer func() {
log.Printf("dnscache: dnsWasTrustworthy = %v", ret)
}()
// DEBUG DEBUG DEBUG
if fileExists("/tmp/dnscache-drop-fails.txt") {
log.Printf("dnscache: clearing failed list")
dc.fails = map[netaddr.IP]error{}
}
if fileExists("/tmp/dnscache-drop-pastconnect.txt") {
log.Printf("dnscache: clearing past connections list")
dc.d.pastConnect = map[netaddr.IP]time.Time{}
}
if debug {
log.Printf("dnscache: we have %d failures and %d past connections", len(dc.fails), len(dc.d.pastConnect))
}
if len(dc.fails) == 0 {
// No information.
return false
@ -384,14 +410,30 @@ func (dc *dialCall) dnsWasTrustworthy() bool {
// this dialer, assume the DNS is fine.
for ip := range dc.fails {
if _, ok := dc.d.pastConnect[ip]; ok {
if debug {
log.Printf("dnscache: DNS trustworthy due to past connection to %v", ip)
}
return true
}
}
return false
}
func (dc *dialCall) dialOne(ctx context.Context, ip netaddr.IP) (net.Conn, error) {
c, err := dc.d.fwd(ctx, dc.network, net.JoinHostPort(ip.String(), dc.port))
func fileExists(path string) bool {
st, err := os.Stat(path)
if err != nil {
return false
}
return st.Mode().IsRegular()
}
func (dc *dialCall) dialOne(ctx context.Context, ip netaddr.IP) (c net.Conn, err error) {
if fileExists("/tmp/dnscache-synthetic-dial-failure.txt") {
log.Printf("dnscache: synthetic dial failure for %s", ip)
err = fmt.Errorf("synthetic dial failure for %s", ip)
} else {
c, err = dc.d.fwd(ctx, dc.network, net.JoinHostPort(ip.String(), dc.port))
}
dc.noteDialResult(ip, err)
return c, err
}

View File

@ -19,6 +19,6 @@ pkgs.mkShell {
# - gopls, the language server for Go to increase editor integration
# - git, the version control program (used in some scripts)
buildInputs = with pkgs; [
go goimports gopls git
go gopls git
];
}