From b52d784f00d1dec70835817e065d52bd1287c5ca Mon Sep 17 00:00:00 2001 From: Simone Basso Date: Sun, 5 Sep 2021 20:12:05 +0200 Subject: [PATCH] fix(netxlite): resolver _always_ short circuits IP addrs (#458) We will use this in a moment when we will add support for the dnstransports that currently are in engine/netx. See https://github.com/ooni/probe/issues/1591 --- internal/netxlite/resolver.go | 20 ++++++++++++-- internal/netxlite/resolver_test.go | 42 +++++++++++++++++++++++++++++- 2 files changed, 59 insertions(+), 3 deletions(-) diff --git a/internal/netxlite/resolver.go b/internal/netxlite/resolver.go index f81dc5d..a3c8960 100644 --- a/internal/netxlite/resolver.go +++ b/internal/netxlite/resolver.go @@ -33,8 +33,10 @@ type ResolverConfig struct { func NewResolver(config *ResolverConfig) Resolver { return &resolverIDNA{ Resolver: &resolverLogger{ - Resolver: &resolverSystem{}, - Logger: config.Logger, + Resolver: &resolverShortCircuitIPAddr{ + Resolver: &resolverSystem{}, + }, + Logger: config.Logger, }, } } @@ -143,3 +145,17 @@ func (r *resolverIDNA) LookupHost(ctx context.Context, hostname string) ([]strin } return r.Resolver.LookupHost(ctx, host) } + +// resolverShortCircuitIPAddr recognizes when the input hostname is an +// IP address and returns it immediately to the caller. +type resolverShortCircuitIPAddr struct { + Resolver +} + +// LookupHost implements Resolver.LookupHost. +func (r *resolverShortCircuitIPAddr) LookupHost(ctx context.Context, hostname string) ([]string, error) { + if net.ParseIP(hostname) != nil { + return []string{hostname}, nil + } + return r.Resolver.LookupHost(ctx, hostname) +} diff --git a/internal/netxlite/resolver_test.go b/internal/netxlite/resolver_test.go index 274cdb1..ea9f098 100644 --- a/internal/netxlite/resolver_test.go +++ b/internal/netxlite/resolver_test.go @@ -194,7 +194,47 @@ func TestNewResolverTypeChain(t *testing.T) { if rl.Logger != log.Log { t.Fatal("invalid logger") } - if _, ok := rl.Resolver.(*resolverSystem); !ok { + scia, ok := rl.Resolver.(*resolverShortCircuitIPAddr) + if !ok { + t.Fatal("invalid resolver") + } + if _, ok := scia.Resolver.(*resolverSystem); !ok { t.Fatal("invalid resolver") } } + +func TestResolverShortCircuitIPAddrWithIPAddr(t *testing.T) { + r := &resolverShortCircuitIPAddr{ + Resolver: &mocks.Resolver{ + MockLookupHost: func(ctx context.Context, domain string) ([]string, error) { + return nil, errors.New("mocked error") + }, + }, + } + ctx := context.Background() + addrs, err := r.LookupHost(ctx, "8.8.8.8") + if err != nil { + t.Fatal(err) + } + if len(addrs) != 1 || addrs[0] != "8.8.8.8" { + t.Fatal("invalid result") + } +} + +func TestResolverShortCircuitIPAddrWithDomain(t *testing.T) { + r := &resolverShortCircuitIPAddr{ + Resolver: &mocks.Resolver{ + MockLookupHost: func(ctx context.Context, domain string) ([]string, error) { + return nil, errors.New("mocked error") + }, + }, + } + ctx := context.Background() + addrs, err := r.LookupHost(ctx, "dns.google") + if err == nil || err.Error() != "mocked error" { + t.Fatal("not the error we expected", err) + } + if addrs != nil { + t.Fatal("invalid result") + } +}