Fix tests and linters

This commit is contained in:
Daniel
2022-02-02 12:48:42 +01:00
parent f2fcad4d11
commit 60d8664e7b
171 changed files with 944 additions and 874 deletions

View File

@@ -6,7 +6,7 @@ import (
"github.com/miekg/dns"
)
// Supported upstream block detections
// Supported upstream block detections.
const (
BlockDetectionRefused = "refused"
BlockDetectionZeroIP = "zeroip"

View File

@@ -9,7 +9,7 @@ import (
"github.com/safing/portmaster/status"
)
// Configuration Keys
// Configuration Keys.
var (
defaultNameServers = []string{
// Collection of default DNS Servers

View File

@@ -14,21 +14,19 @@ const (
IPInfoProfileScopeGlobal = "global"
)
var (
ipInfoDatabase = database.NewInterface(&database.Options{
Local: true,
Internal: true,
var ipInfoDatabase = database.NewInterface(&database.Options{
Local: true,
Internal: true,
// Cache entries because new/updated entries will often be queries soon
// after inserted.
CacheSize: 256,
// Cache entries because new/updated entries will often be queries soon
// after inserted.
CacheSize: 256,
// We only use the cache database here, so we can delay and batch all our
// writes. Also, no one else accesses these records, so we are fine using
// this.
DelayCachedWrites: "cache",
})
)
// We only use the cache database here, so we can delay and batch all our
// writes. Also, no one else accesses these records, so we are fine using
// this.
DelayCachedWrites: "cache",
})
// ResolvedDomain holds a Domain name and a list of
// CNAMES that have been resolved.
@@ -54,7 +52,7 @@ type ResolvedDomain struct {
}
// String returns a string representation of ResolvedDomain including
// the CNAME chain. It implements fmt.Stringer
// the CNAME chain. It implements fmt.Stringer.
func (resolved *ResolvedDomain) String() string {
ret := resolved.Domain
cnames := ""
@@ -67,7 +65,7 @@ func (resolved *ResolvedDomain) String() string {
}
// ResolvedDomains is a helper type for operating on a slice
// of ResolvedDomain
// of ResolvedDomain.
type ResolvedDomains []ResolvedDomain
// String returns a string representation of all domains joined
@@ -141,21 +139,21 @@ func GetIPInfo(profileID, ip string) (*IPInfo, error) {
// unwrap
if r.IsWrapped() {
// only allocate a new struct, if we need it
new := &IPInfo{}
err = record.Unwrap(r, new)
newInfo := &IPInfo{}
err = record.Unwrap(r, newInfo)
if err != nil {
return nil, err
}
return new, nil
return newInfo, nil
}
// or adjust type
new, ok := r.(*IPInfo)
newInfo, ok := r.(*IPInfo)
if !ok {
return nil, fmt.Errorf("record not of type *IPInfo, but %T", r)
}
return new, nil
return newInfo, nil
}
// Save saves the IPInfo record to the database.
@@ -187,7 +185,7 @@ func (info *IPInfo) Save() error {
return ipInfoDatabase.Put(info)
}
// FmtDomains returns a string consisting of the domains that have seen to use this IP, joined by " or "
// String returns a string consisting of the domains that have seen to use this IP.
func (info *IPInfo) String() string {
info.Lock()
defer info.Unlock()

View File

@@ -7,6 +7,8 @@ import (
)
func TestIPInfo(t *testing.T) {
t.Parallel()
example := ResolvedDomain{
Domain: "example.com.",
}

View File

@@ -8,20 +8,19 @@ import (
"sync"
"time"
"github.com/tevino/abool"
"github.com/safing/portbase/log"
"github.com/safing/portbase/modules"
"github.com/safing/portbase/notifications"
"github.com/safing/portbase/utils/debug"
"github.com/safing/portmaster/intel"
"github.com/tevino/abool"
// module dependencies
// Dependency.
_ "github.com/safing/portmaster/core/base"
"github.com/safing/portmaster/intel"
)
var (
module *modules.Module
)
var module *modules.Module
func init() {
module = modules.Register("resolver", prep, start, nil, "base", "netenv")
@@ -93,9 +92,7 @@ func start() error {
return nil
}
var (
localAddrFactory func(network string) net.Addr
)
var localAddrFactory func(network string) net.Addr
// SetLocalAddrFactory supplies the intel package with a function to get permitted local addresses for connections.
func SetLocalAddrFactory(laf func(network string) net.Addr) {

View File

@@ -6,9 +6,7 @@ import (
"github.com/safing/portmaster/core/pmtesting"
)
var (
domainFeed = make(chan string)
)
var domainFeed = make(chan string)
func TestMain(m *testing.M) {
pmtesting.TestMain(m, module)
@@ -28,106 +26,104 @@ func feedDomains() {
// Data
var (
testDomains = []string{
"facebook.com.",
"google.com.",
"youtube.com.",
"twitter.com.",
"instagram.com.",
"linkedin.com.",
"microsoft.com.",
"apple.com.",
"wikipedia.org.",
"plus.google.com.",
"en.wikipedia.org.",
"googletagmanager.com.",
"youtu.be.",
"adobe.com.",
"vimeo.com.",
"pinterest.com.",
"itunes.apple.com.",
"play.google.com.",
"maps.google.com.",
"goo.gl.",
"wordpress.com.",
"blogspot.com.",
"bit.ly.",
"github.com.",
"player.vimeo.com.",
"amazon.com.",
"wordpress.org.",
"docs.google.com.",
"yahoo.com.",
"mozilla.org.",
"tumblr.com.",
"godaddy.com.",
"flickr.com.",
"parked-content.godaddy.com.",
"drive.google.com.",
"support.google.com.",
"apache.org.",
"gravatar.com.",
"europa.eu.",
"qq.com.",
"w3.org.",
"nytimes.com.",
"reddit.com.",
"macromedia.com.",
"get.adobe.com.",
"soundcloud.com.",
"sourceforge.net.",
"sites.google.com.",
"nih.gov.",
"amazonaws.com.",
"t.co.",
"support.microsoft.com.",
"forbes.com.",
"theguardian.com.",
"cnn.com.",
"github.io.",
"bbc.co.uk.",
"dropbox.com.",
"whatsapp.com.",
"medium.com.",
"creativecommons.org.",
"www.ncbi.nlm.nih.gov.",
"httpd.apache.org.",
"archive.org.",
"ec.europa.eu.",
"php.net.",
"apps.apple.com.",
"weebly.com.",
"support.apple.com.",
"weibo.com.",
"wixsite.com.",
"issuu.com.",
"who.int.",
"paypal.com.",
"m.facebook.com.",
"oracle.com.",
"msn.com.",
"gnu.org.",
"tinyurl.com.",
"reuters.com.",
"l.facebook.com.",
"cloudflare.com.",
"wsj.com.",
"washingtonpost.com.",
"domainmarket.com.",
"imdb.com.",
"bbc.com.",
"bing.com.",
"accounts.google.com.",
"vk.com.",
"api.whatsapp.com.",
"opera.com.",
"cdc.gov.",
"slideshare.net.",
"wpa.qq.com.",
"harvard.edu.",
"mit.edu.",
"code.google.com.",
"wikimedia.org.",
}
)
var testDomains = []string{
"facebook.com.",
"google.com.",
"youtube.com.",
"twitter.com.",
"instagram.com.",
"linkedin.com.",
"microsoft.com.",
"apple.com.",
"wikipedia.org.",
"plus.google.com.",
"en.wikipedia.org.",
"googletagmanager.com.",
"youtu.be.",
"adobe.com.",
"vimeo.com.",
"pinterest.com.",
"itunes.apple.com.",
"play.google.com.",
"maps.google.com.",
"goo.gl.",
"wordpress.com.",
"blogspot.com.",
"bit.ly.",
"github.com.",
"player.vimeo.com.",
"amazon.com.",
"wordpress.org.",
"docs.google.com.",
"yahoo.com.",
"mozilla.org.",
"tumblr.com.",
"godaddy.com.",
"flickr.com.",
"parked-content.godaddy.com.",
"drive.google.com.",
"support.google.com.",
"apache.org.",
"gravatar.com.",
"europa.eu.",
"qq.com.",
"w3.org.",
"nytimes.com.",
"reddit.com.",
"macromedia.com.",
"get.adobe.com.",
"soundcloud.com.",
"sourceforge.net.",
"sites.google.com.",
"nih.gov.",
"amazonaws.com.",
"t.co.",
"support.microsoft.com.",
"forbes.com.",
"theguardian.com.",
"cnn.com.",
"github.io.",
"bbc.co.uk.",
"dropbox.com.",
"whatsapp.com.",
"medium.com.",
"creativecommons.org.",
"www.ncbi.nlm.nih.gov.",
"httpd.apache.org.",
"archive.org.",
"ec.europa.eu.",
"php.net.",
"apps.apple.com.",
"weebly.com.",
"support.apple.com.",
"weibo.com.",
"wixsite.com.",
"issuu.com.",
"who.int.",
"paypal.com.",
"m.facebook.com.",
"oracle.com.",
"msn.com.",
"gnu.org.",
"tinyurl.com.",
"reuters.com.",
"l.facebook.com.",
"cloudflare.com.",
"wsj.com.",
"washingtonpost.com.",
"domainmarket.com.",
"imdb.com.",
"bbc.com.",
"bing.com.",
"accounts.google.com.",
"vk.com.",
"api.whatsapp.com.",
"opera.com.",
"cdc.gov.",
"slideshare.net.",
"wpa.qq.com.",
"harvard.edu.",
"mit.edu.",
"code.google.com.",
"wikimedia.org.",
}

View File

@@ -1,7 +1,6 @@
package resolver
import (
"context"
"errors"
"fmt"
"sync"
@@ -81,30 +80,30 @@ func GetNameRecord(domain, question string) (*NameRecord, error) {
// Unwrap record if it's wrapped.
if r.IsWrapped() {
// only allocate a new struct, if we need it
new := &NameRecord{}
err = record.Unwrap(r, new)
newNR := &NameRecord{}
err = record.Unwrap(r, newNR)
if err != nil {
return nil, err
}
// Check if the record is valid.
if !new.IsValid() {
if !newNR.IsValid() {
return nil, errors.New("record is invalid (outdated format)")
}
return new, nil
return newNR, nil
}
// Or just adjust the type.
new, ok := r.(*NameRecord)
newNR, ok := r.(*NameRecord)
if !ok {
return nil, fmt.Errorf("record not of type *NameRecord, but %T", r)
}
// Check if the record is valid.
if !new.IsValid() {
if !newNR.IsValid() {
return nil, errors.New("record is invalid (outdated format)")
}
return new, nil
return newNR, nil
}
// ResetCachedRecord deletes a NameRecord from the cache database.
@@ -118,16 +117,16 @@ func ResetCachedRecord(domain, question string) error {
}
// Save saves the NameRecord to the database.
func (rec *NameRecord) Save() error {
if rec.Domain == "" || rec.Question == "" {
func (nameRecord *NameRecord) Save() error {
if nameRecord.Domain == "" || nameRecord.Question == "" {
return errors.New("could not save NameRecord, missing Domain and/or Question")
}
rec.SetKey(makeNameRecordKey(rec.Domain, rec.Question))
rec.UpdateMeta()
rec.Meta().SetAbsoluteExpiry(rec.Expires + databaseOvertime)
nameRecord.SetKey(makeNameRecordKey(nameRecord.Domain, nameRecord.Question))
nameRecord.UpdateMeta()
nameRecord.Meta().SetAbsoluteExpiry(nameRecord.Expires + databaseOvertime)
return recordDatabase.PutNew(rec)
return recordDatabase.PutNew(nameRecord)
}
// clearNameCache clears all dns caches from the database.
@@ -144,18 +143,3 @@ func clearNameCache(ar *api.Request) (msg string, err error) {
log.Debugf("resolver: cleared %d entries from dns cache", n)
return fmt.Sprintf("cleared %d dns cache entries", n), nil
}
// DEPRECATED: remove in v0.7
func clearNameCacheEventHandler(ctx context.Context, _ interface{}) error {
log.Debugf("resolver: dns cache clearing started...")
recordDatabase.FlushCache()
recordDatabase.ClearCache()
n, err := recordDatabase.Purge(ctx, query.New(nameRecordsKeyPrefix))
if err != nil {
return err
}
log.Debugf("resolver: cleared %d entries from dns cache", n)
return nil
}

View File

@@ -3,6 +3,8 @@ package resolver
import "testing"
func TestNameRecordStorage(t *testing.T) {
t.Parallel()
testDomain := "Mk35mMqOWEHXSMk11MYcbjLOjTE8PQvDiAVUxf4BvwtgR.example.com."
testQuestion := "A"

View File

@@ -14,35 +14,36 @@ import (
"github.com/safing/portmaster/netenv"
)
// Errors.
var (
// basic errors
// Basic Errors.
// ErrNotFound is a basic error that will match all "not found" errors
// ErrNotFound is a basic error that will match all "not found" errors.
ErrNotFound = errors.New("record could not be found")
// ErrBlocked is basic error that will match all "blocked" errors
// ErrBlocked is basic error that will match all "blocked" errors.
ErrBlocked = errors.New("query was blocked")
// ErrLocalhost is returned to *.localhost queries
// ErrLocalhost is returned to *.localhost queries.
ErrLocalhost = errors.New("query for localhost")
// ErrTimeout is returned when a query times out
// ErrTimeout is returned when a query times out.
ErrTimeout = errors.New("query timed out")
// ErrOffline is returned when no network connection is detected
// ErrOffline is returned when no network connection is detected.
ErrOffline = errors.New("device is offine")
// ErrFailure is returned when the type of failure is unclear
// ErrFailure is returned when the type of failure is unclear.
ErrFailure = errors.New("query failed")
// ErrContinue is returned when the resolver has no answer, and the next resolver should be asked
// ErrContinue is returned when the resolver has no answer, and the next resolver should be asked.
ErrContinue = errors.New("resolver has no answer")
// ErrShuttingDown is returned when the resolver is shutting down.
ErrShuttingDown = errors.New("resolver is shutting down")
// detailed errors
// Detailed Errors.
// ErrTestDomainsDisabled wraps ErrBlocked
// ErrTestDomainsDisabled wraps ErrBlocked.
ErrTestDomainsDisabled = fmt.Errorf("%w: test domains disabled", ErrBlocked)
// ErrSpecialDomainsDisabled wraps ErrBlocked
// ErrSpecialDomainsDisabled wraps ErrBlocked.
ErrSpecialDomainsDisabled = fmt.Errorf("%w: special domains disabled", ErrBlocked)
// ErrInvalid wraps ErrNotFound
// ErrInvalid wraps ErrNotFound.
ErrInvalid = fmt.Errorf("%w: invalid request", ErrNotFound)
// ErrNoCompliance wraps ErrBlocked and is returned when no resolvers were able to comply with the current settings
// ErrNoCompliance wraps ErrBlocked and is returned when no resolvers were able to comply with the current settings.
ErrNoCompliance = fmt.Errorf("%w: no compliant resolvers for this query", ErrBlocked)
)
@@ -74,7 +75,7 @@ func (blocked *BlockedUpstreamError) Error() string {
return fmt.Sprintf("%s by upstream DNS resolver %s", ErrBlocked, blocked.ResolverName)
}
// Unwrap implements errors.Unwrapper
// Unwrap implements errors.Unwrapper.
func (blocked *BlockedUpstreamError) Unwrap() error {
return ErrBlocked
}
@@ -166,10 +167,9 @@ func checkCache(ctx context.Context, q *Query) *RRCache {
// Get data from cache.
rrCache, err := GetRRCache(q.FQDN, q.QType)
// Return if entry is not in cache.
if err != nil {
if err != database.ErrNotFound {
if !errors.Is(err, database.ErrNotFound) {
log.Tracer(ctx).Warningf("resolver: getting RRCache %s%s from database failed: %s", q.FQDN, q.QType.String(), err)
}
return nil
@@ -403,7 +403,7 @@ resolveLoop:
if err != nil {
// tried all resolvers, possibly twice
if i > 1 {
err = fmt.Errorf("all %d query-compliant resolvers failed, last error: %s", len(resolvers), err)
err = fmt.Errorf("all %d query-compliant resolvers failed, last error: %w", len(resolvers), err)
if primarySource == ServerSourceConfigured &&
netenv.Online() && CompatSelfCheckIsFailing() {

View File

@@ -7,12 +7,14 @@ import (
"strings"
"github.com/miekg/dns"
"github.com/safing/portbase/log"
"github.com/safing/portmaster/netenv"
"github.com/safing/portmaster/network/netutils"
)
const (
// InternalSpecialUseDomain is the domain scope used for internal services.
InternalSpecialUseDomain = "portmaster.home.arpa."
routerDomain = "router.local." + InternalSpecialUseDomain
@@ -91,8 +93,7 @@ func (er *envResolverConn) Query(ctx context.Context, q *Query) (*RRCache, error
}
// Check for suffix matches.
switch {
case strings.HasSuffix(q.FQDN, CompatDNSCheckInternalDomainScope):
if strings.HasSuffix(q.FQDN, CompatDNSCheckInternalDomainScope) {
subdomain := strings.TrimSuffix(q.FQDN, CompatDNSCheckInternalDomainScope)
respondWith := CompatSubmitDNSCheckDomain(subdomain)

View File

@@ -10,11 +10,12 @@ import (
"time"
"github.com/miekg/dns"
"github.com/safing/portbase/log"
"github.com/safing/portmaster/network/netutils"
)
// DNS Classes
// DNS Classes.
const (
DNSClassMulticast = dns.ClassINET | 1<<15
)
@@ -85,7 +86,9 @@ func listenToMDNS(ctx context.Context) error {
module.StartServiceWorker("mdns udp4 multicast listener", 0, func(ctx context.Context) error {
return listenForDNSPackets(ctx, multicast4Conn, messages)
})
defer multicast4Conn.Close()
defer func() {
_ = multicast4Conn.Close()
}()
}
multicast6Conn, err = net.ListenMulticastUDP("udp6", nil, &net.UDPAddr{IP: net.IP([]byte{0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb}), Port: 5353})
@@ -96,7 +99,9 @@ func listenToMDNS(ctx context.Context) error {
module.StartServiceWorker("mdns udp6 multicast listener", 0, func(ctx context.Context) error {
return listenForDNSPackets(ctx, multicast6Conn, messages)
})
defer multicast6Conn.Close()
defer func() {
_ = multicast6Conn.Close()
}()
}
unicast4Conn, err = net.ListenUDP("udp4", &net.UDPAddr{IP: net.IPv4zero, Port: 0})
@@ -107,7 +112,9 @@ func listenToMDNS(ctx context.Context) error {
module.StartServiceWorker("mdns udp4 unicast listener", 0, func(ctx context.Context) error {
return listenForDNSPackets(ctx, unicast4Conn, messages)
})
defer unicast4Conn.Close()
defer func() {
_ = unicast4Conn.Close()
}()
}
unicast6Conn, err = net.ListenUDP("udp6", &net.UDPAddr{IP: net.IPv6zero, Port: 0})
@@ -118,7 +125,9 @@ func listenToMDNS(ctx context.Context) error {
module.StartServiceWorker("mdns udp6 unicast listener", 0, func(ctx context.Context) error {
return listenForDNSPackets(ctx, unicast6Conn, messages)
})
defer unicast6Conn.Close()
defer func() {
_ = unicast6Conn.Close()
}()
}
// start message handler
@@ -131,8 +140,7 @@ func listenToMDNS(ctx context.Context) error {
return nil
}
//nolint:gocyclo,gocognit // TODO
func handleMDNSMessages(ctx context.Context, messages chan *dns.Msg) error {
func handleMDNSMessages(ctx context.Context, messages chan *dns.Msg) error { //nolint:maintidx // TODO: Improve.
for {
select {
case <-ctx.Done():
@@ -319,7 +327,6 @@ func handleMDNSMessages(ctx context.Context, messages chan *dns.Msg) error {
cleanSavedQuestions()
}
}
func listenForDNSPackets(ctx context.Context, conn *net.UDPConn, messages chan *dns.Msg) error {
@@ -377,30 +384,30 @@ func queryMulticastDNS(ctx context.Context, q *Query) (*RRCache, error) {
// pack qeury
buf, err := dnsQuery.Pack()
if err != nil {
return nil, fmt.Errorf("failed to pack query: %s", err)
return nil, fmt.Errorf("failed to pack query: %w", err)
}
// send queries
if unicast4Conn != nil && uint16(q.QType) != dns.TypeAAAA {
err = unicast4Conn.SetWriteDeadline(time.Now().Add(1 * time.Second))
if err != nil {
return nil, fmt.Errorf("failed to configure query (set timout): %s", err)
return nil, fmt.Errorf("failed to configure query (set timout): %w", err)
}
_, err = unicast4Conn.WriteToUDP(buf, &net.UDPAddr{IP: net.IPv4(224, 0, 0, 251), Port: 5353})
if err != nil {
return nil, fmt.Errorf("failed to send query: %s", err)
return nil, fmt.Errorf("failed to send query: %w", err)
}
}
if unicast6Conn != nil && uint16(q.QType) != dns.TypeA {
err = unicast6Conn.SetWriteDeadline(time.Now().Add(1 * time.Second))
if err != nil {
return nil, fmt.Errorf("failed to configure query (set timout): %s", err)
return nil, fmt.Errorf("failed to configure query (set timout): %w", err)
}
_, err = unicast6Conn.WriteToUDP(buf, &net.UDPAddr{IP: net.IP([]byte{0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfb}), Port: 5353})
if err != nil {
return nil, fmt.Errorf("failed to send query: %s", err)
return nil, fmt.Errorf("failed to send query: %w", err)
}
}
@@ -413,7 +420,7 @@ func queryMulticastDNS(ctx context.Context, q *Query) (*RRCache, error) {
case <-time.After(1 * time.Second):
// check cache again
rrCache, err := GetRRCache(q.FQDN, q.QType)
if err != nil {
if err == nil {
return rrCache, nil
}
case <-ctx.Done():

View File

@@ -2,10 +2,12 @@ package resolver
import (
"context"
"errors"
"net"
"time"
"github.com/miekg/dns"
"github.com/safing/portbase/log"
"github.com/safing/portmaster/netenv"
)
@@ -65,7 +67,8 @@ func (pr *PlainResolver) Query(ctx context.Context, q *Query) (*RRCache, error)
// error handling
if err != nil {
// Hint network environment at failed connection if err is not a timeout.
if nErr, ok := err.(net.Error); ok && !nErr.Timeout() {
var nErr net.Error
if errors.As(err, &nErr) && !nErr.Timeout() {
netenv.ReportFailedConnection()
}

View File

@@ -10,16 +10,16 @@ import (
"time"
"github.com/miekg/dns"
"github.com/tevino/abool"
"github.com/safing/portbase/log"
"github.com/safing/portmaster/netenv"
"github.com/tevino/abool"
)
const (
tcpConnectionEstablishmentTimeout = 3 * time.Second
tcpWriteTimeout = 2 * time.Second
heartbeatTimeout = 5 * time.Second
ignoreQueriesAfter = 5 * time.Minute
)
// TCPResolver is a resolver using just a single tcp connection with pipelining.

View File

@@ -15,7 +15,7 @@ import (
"github.com/safing/portmaster/network/netutils"
)
// DNS Resolver Attributes
// DNS Resolver Attributes.
const (
ServerTypeDNS = "dns"
ServerTypeTCP = "tcp"
@@ -30,10 +30,8 @@ const (
ServerSourceEnv = "env"
)
var (
// FailThreshold is amount of errors a resolvers must experience in order to be regarded as failed.
FailThreshold = 20
)
// FailThreshold is amount of errors a resolvers must experience in order to be regarded as failed.
var FailThreshold = 20
// Resolver holds information about an active resolver.
type Resolver struct {
@@ -73,7 +71,7 @@ type Resolver struct {
// ResolverInfo is a subset of resolver attributes that is attached to answers
// from that server in order to use it later for decision making. It must not
// be changed by anyone after creation and initialization is complete.
type ResolverInfo struct {
type ResolverInfo struct { //nolint:golint,maligned // TODO
// Name describes the name given to the resolver. The name is configured in the config URL using the name parameter.
Name string
@@ -178,7 +176,7 @@ func (resolver *Resolver) String() string {
}
// ResolverConn is an interface to implement different types of query backends.
type ResolverConn interface { //nolint:go-lint // TODO
type ResolverConn interface { //nolint:golint // TODO
Query(ctx context.Context, q *Query) (*RRCache, error)
ReportFailure()
IsFailing() bool

View File

@@ -7,9 +7,9 @@ import (
"testing"
"time"
"github.com/safing/portbase/log"
"github.com/miekg/dns"
"github.com/safing/portbase/log"
)
var (
@@ -27,10 +27,12 @@ func init() {
}
func startQuery(t *testing.T, wg *sync.WaitGroup, rc ResolverConn, q *Query) {
t.Helper()
start := time.Now()
_, err := rc.Query(silencingTraceCtx, q)
if err != nil {
t.Logf("client failed: %s", err) //nolint:staticcheck
t.Logf("client failed: %s", err)
wg.Done()
return
}
@@ -39,6 +41,8 @@ func startQuery(t *testing.T, wg *sync.WaitGroup, rc ResolverConn, q *Query) {
}
func TestSingleResolving(t *testing.T) {
t.Parallel()
// skip if short - this test depends on the Internet and might fail randomly
if testing.Short() {
t.Skip()
@@ -48,7 +52,6 @@ func TestSingleResolving(t *testing.T) {
// create separate resolver for this test
resolver, _, err := createResolver(testResolver, "config")
if err != nil {
t.Fatal(err)
}
@@ -59,7 +62,7 @@ func TestSingleResolving(t *testing.T) {
wg := &sync.WaitGroup{}
wg.Add(100)
for i := 0; i < 100; i++ {
startQuery(t, wg, resolver.Conn, &Query{ //nolint:staticcheck
startQuery(t, wg, resolver.Conn, &Query{
FQDN: <-domainFeed,
QType: dns.Type(dns.TypeA),
})
@@ -70,6 +73,8 @@ func TestSingleResolving(t *testing.T) {
}
func TestBulkResolving(t *testing.T) {
t.Parallel()
// skip if short - this test depends on the Internet and might fail randomly
if testing.Short() {
t.Skip()
@@ -79,7 +84,6 @@ func TestBulkResolving(t *testing.T) {
// create separate resolver for this test
resolver, _, err := createResolver(testResolver, "config")
if err != nil {
t.Fatal(err)
}
@@ -90,7 +94,7 @@ func TestBulkResolving(t *testing.T) {
wg := &sync.WaitGroup{}
wg.Add(100)
for i := 0; i < 100; i++ {
go startQuery(t, wg, resolver.Conn, &Query{ //nolint:staticcheck
go startQuery(t, wg, resolver.Conn, &Query{
FQDN: <-domainFeed,
QType: dns.Type(dns.TypeA),
})

View File

@@ -138,7 +138,7 @@ func createResolver(resolverURL, source string) (*Resolver, bool, error) {
return nil, false, fmt.Errorf("invalid value for upstream block detection (blockedif=)")
}
new := &Resolver{
newResolver := &Resolver{
ConfigURL: resolverURL,
Info: &ResolverInfo{
Name: query.Get("name"),
@@ -153,8 +153,8 @@ func createResolver(resolverURL, source string) (*Resolver, bool, error) {
UpstreamBlockDetection: blockType,
}
new.Conn = resolverConnFactory(new)
return new, false, nil
newResolver.Conn = resolverConnFactory(newResolver)
return newResolver, false, nil
}
func configureSearchDomains(resolver *Resolver, searches []string) {

View File

@@ -3,8 +3,11 @@ package resolver
import "testing"
func TestCheckResolverSearchScope(t *testing.T) {
t.Parallel()
test := func(t *testing.T, domain string, expectedResult bool) {
t.Helper()
if checkSearchScope(domain) != expectedResult {
if expectedResult {
t.Errorf("domain %s failed scope test", domain)

View File

@@ -6,6 +6,7 @@ import (
"strings"
"github.com/miekg/dns"
"github.com/safing/portbase/log"
)

View File

@@ -8,6 +8,8 @@ import (
)
func testReverse(t *testing.T, ip, result, expectedErr string) {
t.Helper()
ctx, tracer := log.AddTracer(context.Background())
defer tracer.Submit()
@@ -26,6 +28,8 @@ func testReverse(t *testing.T, ip, result, expectedErr string) {
}
func TestResolveIPAndValidate(t *testing.T) {
t.Parallel()
testReverse(t, "198.41.0.4", "a.root-servers.net.", "")
// testReverse(t, "9.9.9.9", "dns.quad9.net.", "") // started resolving to dns9.quad9.net.
// testReverse(t, "2620:fe::fe", "dns.quad9.net.", "") // fails sometimes for some (external) reason

View File

@@ -6,11 +6,11 @@ import (
"net"
"time"
"github.com/miekg/dns"
"github.com/safing/portbase/log"
"github.com/safing/portmaster/nameserver/nsutil"
"github.com/safing/portmaster/netenv"
"github.com/miekg/dns"
)
// RRCache is a single-use structure to hold a DNS response.
@@ -127,7 +127,7 @@ func (rrCache *RRCache) ExportAllARecords() (ips []net.IP) {
// ToNameRecord converts the RRCache to a NameRecord for cleaner persistence.
func (rrCache *RRCache) ToNameRecord() *NameRecord {
new := &NameRecord{
newRecord := &NameRecord{
Domain: rrCache.Domain,
Question: rrCache.Question.String(),
RCode: rrCache.RCode,
@@ -136,11 +136,11 @@ func (rrCache *RRCache) ToNameRecord() *NameRecord {
}
// Serialize RR entries to strings.
new.Answer = toNameRecordSection(rrCache.Answer)
new.Ns = toNameRecordSection(rrCache.Ns)
new.Extra = toNameRecordSection(rrCache.Extra)
newRecord.Answer = toNameRecordSection(rrCache.Answer)
newRecord.Ns = toNameRecordSection(rrCache.Ns)
newRecord.Extra = toNameRecordSection(rrCache.Extra)
return new
return newRecord
}
func toNameRecordSection(rrSection []dns.RR) []string {

View File

@@ -7,6 +7,8 @@ import (
)
func TestCaching(t *testing.T) {
t.Parallel()
testDomain := "Mk35mMqOWEHXSMk11MYcbjLOjTE8PQvDiAVUxf4BvwtgR.example.com."
testQuestion := "A"

View File

@@ -5,22 +5,22 @@ import (
"errors"
"strings"
"github.com/safing/portmaster/netenv"
"github.com/miekg/dns"
"github.com/safing/portbase/log"
"github.com/safing/portmaster/netenv"
)
// Domain Scopes
// Domain Scopes.
var (
// Localhost Domain
// Handling: Respond with 127.0.0.1 and ::1 to A and AAAA queries, respectively.
// RFC6761
// See RFC6761.
localhostDomain = ".localhost."
// Invalid Domain
// Handling: Always respond with NXDOMAIN.
// RFC6761
// See RFC6761.
invalidDomain = ".invalid."
// Internal Special-Use Domain
@@ -31,7 +31,7 @@ var (
// Multicast DNS
// Handling: Send to nameservers with matching search scope, then MDNS
// RFC6762
// See RFC6762.
multicastDomains = []string{
".local.",
".254.169.in-addr.arpa.",
@@ -89,7 +89,7 @@ var (
}
// Special-Service Domain Names
// Handling: Send to nameservers with matching search scope, then local and system assigned nameservers
// Handling: Send to nameservers with matching search scope, then local and system assigned nameservers.
specialServiceDomains = []string{
// RFC7686: Tor Hidden Services
".onion.",