fix: address code review issues on PR #9
CI / test (pull_request) Waiting to run

- gofmt main.go to fix tab indentation in main() body
- stats.go ComputeSummary: return nil when Answers and ByType are empty
- dns/types.go: remove duplicate ParseQueryType (dead code)
- formatter.go: log hook errors to stderr when Debug > 0; add Debug to Config
- text.go referralID: remove redundant depth==0 branch
- text.go writeServers: remove version lookup placeholder string

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
Gary Hansen
2026-06-08 02:32:58 +10:00
co-authored by Copilot multica-agent
parent 5a54834c5f
commit 8e7beacc22
14 changed files with 268 additions and 294 deletions
+187 -186
View File
@@ -1,219 +1,220 @@
package main
import (
"context"
"flag"
"fmt"
"os"
"time"
"context"
"flag"
"fmt"
"os"
"time"
"github.com/hits/ExploreDNS/internal/config"
"github.com/hits/ExploreDNS/internal/dns"
"github.com/hits/ExploreDNS/internal/output"
"github.com/hits/ExploreDNS/internal/traverse"
"github.com/hits/ExploreDNS/internal/config"
"github.com/hits/ExploreDNS/internal/dns"
"github.com/hits/ExploreDNS/internal/output"
"github.com/hits/ExploreDNS/internal/traverse"
)
func main() {
cfg := config.DefaultConfig()
cfg := config.DefaultConfig()
queryType := flag.String("type", cfg.QueryType, "Record type (A, AAAA, NS, CNAME, MX, TXT, SOA, PTR, ANY)")
rootServer := flag.String("root-server", cfg.RootServer, "Override root server")
allRootServers := flag.Bool("all-root-servers", cfg.AllRootServers, "Use all 13 root servers")
rootAAAA := flag.Bool("root-aaaa", cfg.RootAAAA, "Include IPv6 root addresses")
followAAAA := flag.Bool("follow-aaaa", cfg.FollowAAAA, "Only follow AAAA for referrals")
udpSize := flag.Int("udp-size", cfg.UDPSize, "EDNS0 buffer size (512-4096)")
allowTCP := flag.Bool("allow-tcp", cfg.AllowTCP, "TCP fallback on truncation")
alwaysTCP := flag.Bool("always-tcp", cfg.AlwaysTCP, "Always use TCP")
maxDepth := flag.Int("max-depth", cfg.MaxDepth, "Max traversal depth (1-100)")
retries := flag.Int("retries", cfg.Retries, "Retry count (0-10)")
fast := flag.Bool("fast", cfg.Fast, "Fast mode: reuse earlier branch cache")
jsonOutput := flag.Bool("json", false, "Output results as JSON")
queryType := flag.String("type", cfg.QueryType, "Record type (A, AAAA, NS, CNAME, MX, TXT, SOA, PTR, ANY)")
rootServer := flag.String("root-server", cfg.RootServer, "Override root server")
allRootServers := flag.Bool("all-root-servers", cfg.AllRootServers, "Use all 13 root servers")
rootAAAA := flag.Bool("root-aaaa", cfg.RootAAAA, "Include IPv6 root addresses")
followAAAA := flag.Bool("follow-aaaa", cfg.FollowAAAA, "Only follow AAAA for referrals")
udpSize := flag.Int("udp-size", cfg.UDPSize, "EDNS0 buffer size (512-4096)")
allowTCP := flag.Bool("allow-tcp", cfg.AllowTCP, "TCP fallback on truncation")
alwaysTCP := flag.Bool("always-tcp", cfg.AlwaysTCP, "Always use TCP")
maxDepth := flag.Int("max-depth", cfg.MaxDepth, "Max traversal depth (1-100)")
retries := flag.Int("retries", cfg.Retries, "Retry count (0-10)")
fast := flag.Bool("fast", cfg.Fast, "Fast mode: reuse earlier branch cache")
jsonOutput := flag.Bool("json", false, "Output results as JSON")
// Verbose: long and short form share the same variable.
var verboseVal bool
flag.BoolVar(&verboseVal, "verbose", cfg.Verbose, "Verbose output")
flag.BoolVar(&verboseVal, "v", cfg.Verbose, "Verbose output (shorthand)")
// Verbose: long and short form share the same variable.
var verboseVal bool
flag.BoolVar(&verboseVal, "verbose", cfg.Verbose, "Verbose output")
flag.BoolVar(&verboseVal, "v", cfg.Verbose, "Verbose output (shorthand)")
// Debug: -d sets level 1, -dd sets level 2 (library debug).
var dFlag, ddFlag bool
flag.BoolVar(&dFlag, "d", false, "Debug mode (stackable: -dd for library debug)")
flag.BoolVar(&dFlag, "debug", false, "Debug mode")
flag.BoolVar(&ddFlag, "dd", false, "Library debug mode (equivalent to -d -d)")
// Debug: -d sets level 1, -dd sets level 2 (library debug).
var dFlag, ddFlag bool
flag.BoolVar(&dFlag, "d", false, "Debug mode (stackable: -dd for library debug)")
flag.BoolVar(&dFlag, "debug", false, "Debug mode")
flag.BoolVar(&ddFlag, "dd", false, "Library debug mode (equivalent to -d -d)")
// Quiet: long and short form share the same variable.
var quietVal bool
flag.BoolVar(&quietVal, "quiet", cfg.Quiet, "Suppress supplementary info")
flag.BoolVar(&quietVal, "q", cfg.Quiet, "Suppress supplementary info (shorthand)")
// Quiet: long and short form share the same variable.
var quietVal bool
flag.BoolVar(&quietVal, "quiet", cfg.Quiet, "Suppress supplementary info")
flag.BoolVar(&quietVal, "q", cfg.Quiet, "Suppress supplementary info (shorthand)")
showProgress := flag.Bool("show-progress", cfg.ShowProgress, "Show traversal progress")
noShowProgress := flag.Bool("no-show-progress", false, "Hide traversal progress")
showResolves := flag.Bool("show-resolves", cfg.ShowResolves, "Show glue resolution details")
noShowResolves := flag.Bool("no-show-resolves", false, "Hide glue resolution details")
showServers := flag.Bool("show-servers", cfg.ShowServers, "Show servers queried")
noShowServers := flag.Bool("no-show-servers", false, "Hide servers queried")
showVersions := flag.Bool("show-versions", cfg.ShowVersions, "Show server versions")
noShowVersions := flag.Bool("no-show-versions", false, "Hide server versions")
showAllStats := flag.Bool("show-all-stats", cfg.ShowAllStats, "Show all statistics")
noShowAllStats := flag.Bool("no-show-all-stats", false, "Hide all statistics")
showResults := flag.Bool("show-results", cfg.ShowResults, "Show query results")
noShowResults := flag.Bool("no-show-results", false, "Hide query results")
showSummaryResults := flag.Bool("show-summary-results", cfg.ShowSummaryResults, "Show summary of results")
noShowSummaryResults := flag.Bool("no-show-summary-results", false, "Hide summary of results")
showProgress := flag.Bool("show-progress", cfg.ShowProgress, "Show traversal progress")
noShowProgress := flag.Bool("no-show-progress", false, "Hide traversal progress")
showResolves := flag.Bool("show-resolves", cfg.ShowResolves, "Show glue resolution details")
noShowResolves := flag.Bool("no-show-resolves", false, "Hide glue resolution details")
showServers := flag.Bool("show-servers", cfg.ShowServers, "Show servers queried")
noShowServers := flag.Bool("no-show-servers", false, "Hide servers queried")
showVersions := flag.Bool("show-versions", cfg.ShowVersions, "Show server versions")
noShowVersions := flag.Bool("no-show-versions", false, "Hide server versions")
showAllStats := flag.Bool("show-all-stats", cfg.ShowAllStats, "Show all statistics")
noShowAllStats := flag.Bool("no-show-all-stats", false, "Hide all statistics")
showResults := flag.Bool("show-results", cfg.ShowResults, "Show query results")
noShowResults := flag.Bool("no-show-results", false, "Hide query results")
showSummaryResults := flag.Bool("show-summary-results", cfg.ShowSummaryResults, "Show summary of results")
noShowSummaryResults := flag.Bool("no-show-summary-results", false, "Hide summary of results")
flag.Usage = config.PrintUsage
flag.Usage = config.PrintUsage
flag.Parse()
flag.Parse()
args := flag.Args()
args := flag.Args()
cfg.QueryType = *queryType
cfg.RootServer = *rootServer
cfg.AllRootServers = *allRootServers
cfg.RootAAAA = *rootAAAA
cfg.FollowAAAA = *followAAAA
cfg.UDPSize = *udpSize
cfg.AllowTCP = *allowTCP
cfg.AlwaysTCP = *alwaysTCP
cfg.MaxDepth = *maxDepth
cfg.Retries = *retries
cfg.Fast = *fast
cfg.Verbose = verboseVal
cfg.Debug = config.ParseDebugLevel(dFlag, ddFlag)
cfg.Quiet = quietVal
cfg.QueryType = *queryType
cfg.RootServer = *rootServer
cfg.AllRootServers = *allRootServers
cfg.RootAAAA = *rootAAAA
cfg.FollowAAAA = *followAAAA
cfg.UDPSize = *udpSize
cfg.AllowTCP = *allowTCP
cfg.AlwaysTCP = *alwaysTCP
cfg.MaxDepth = *maxDepth
cfg.Retries = *retries
cfg.Fast = *fast
cfg.Verbose = verboseVal
cfg.Debug = config.ParseDebugLevel(dFlag, ddFlag)
cfg.Quiet = quietVal
if *noShowProgress {
cfg.ShowProgress = false
} else if *showProgress {
cfg.ShowProgress = true
}
if *noShowResolves {
cfg.ShowResolves = false
} else if *showResolves {
cfg.ShowResolves = true
}
if *noShowServers {
cfg.ShowServers = false
} else if *showServers {
cfg.ShowServers = true
}
if *noShowVersions {
cfg.ShowVersions = false
} else if *showVersions {
cfg.ShowVersions = true
}
if *noShowAllStats {
cfg.ShowAllStats = false
} else if *showAllStats {
cfg.ShowAllStats = true
}
if *noShowResults {
cfg.ShowResults = false
} else if *showResults {
cfg.ShowResults = true
}
if *noShowSummaryResults {
cfg.ShowSummaryResults = false
} else if *showSummaryResults {
cfg.ShowSummaryResults = true
}
if *noShowProgress {
cfg.ShowProgress = false
} else if *showProgress {
cfg.ShowProgress = true
}
if *noShowResolves {
cfg.ShowResolves = false
} else if *showResolves {
cfg.ShowResolves = true
}
if *noShowServers {
cfg.ShowServers = false
} else if *showServers {
cfg.ShowServers = true
}
if *noShowVersions {
cfg.ShowVersions = false
} else if *showVersions {
cfg.ShowVersions = true
}
if *noShowAllStats {
cfg.ShowAllStats = false
} else if *showAllStats {
cfg.ShowAllStats = true
}
if *noShowResults {
cfg.ShowResults = false
} else if *showResults {
cfg.ShowResults = true
}
if *noShowSummaryResults {
cfg.ShowSummaryResults = false
} else if *showSummaryResults {
cfg.ShowSummaryResults = true
}
if err := cfg.Validate(); err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
os.Exit(1)
}
if err := cfg.Validate(); err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
os.Exit(1)
}
domain, err := cfg.GetDomain(args)
if err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
os.Exit(1)
}
domain, err := cfg.GetDomain(args)
if err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
os.Exit(1)
}
rootIP, err := cfg.ParseRootServer()
if err != nil {
fmt.Fprintf(os.Stderr, "Error: invalid root server: %v\n", err)
os.Exit(1)
}
rootIP, err := cfg.ParseRootServer()
if err != nil {
fmt.Fprintf(os.Stderr, "Error: invalid root server: %v\n", err)
os.Exit(1)
}
queryTypeValue, err := config.ParseQueryType(cfg.QueryType)
if err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
os.Exit(1)
}
queryTypeValue, err := config.ParseQueryType(cfg.QueryType)
if err != nil {
fmt.Fprintf(os.Stderr, "Error: %v\n", err)
os.Exit(1)
}
var rootServerAddr string
if rootIP != nil {
rootServerAddr = rootIP.String()
}
var rootServerAddr string
if rootIP != nil {
rootServerAddr = rootIP.String()
}
queryConfig := &dns.QueryConfig{
UDPSize: cfg.UDPSize,
Timeout: 5 * time.Second,
Retries: cfg.Retries,
UseTCP: cfg.AlwaysTCP,
AllowTCP: cfg.AllowTCP,
}
queryConfig := &dns.QueryConfig{
UDPSize: cfg.UDPSize,
Timeout: 5 * time.Second,
Retries: cfg.Retries,
UseTCP: cfg.AlwaysTCP,
AllowTCP: cfg.AllowTCP,
}
rootConfig := &dns.RootDiscoveryConfig{
IncludeAAAA: cfg.RootAAAA,
Server: rootServerAddr,
AllRoots: cfg.AllRootServers,
}
rootConfig := &dns.RootDiscoveryConfig{
IncludeAAAA: cfg.RootAAAA,
Server: rootServerAddr,
AllRoots: cfg.AllRootServers,
}
traverserConfig := &traverse.TraverserConfig{
MaxDepth: cfg.MaxDepth,
QueryType: queryTypeValue,
RootConfig: rootConfig,
QueryConfig: queryConfig,
}
traverserConfig := &traverse.TraverserConfig{
MaxDepth: cfg.MaxDepth,
QueryType: queryTypeValue,
RootConfig: rootConfig,
QueryConfig: queryConfig,
}
traverser := traverse.NewTraverser(traverserConfig)
traverser := traverse.NewTraverser(traverserConfig)
if cfg.Debug > 0 {
fmt.Fprintf(os.Stderr, "Debug: Config loaded\n")
fmt.Fprintf(os.Stderr, " Domain: %s\n", domain)
fmt.Fprintf(os.Stderr, " Query Type: %s\n", cfg.QueryType)
fmt.Fprintf(os.Stderr, " Max Depth: %d\n", cfg.MaxDepth)
fmt.Fprintf(os.Stderr, " UDP Size: %d\n", cfg.UDPSize)
fmt.Fprintf(os.Stderr, " Retries: %d\n", cfg.Retries)
fmt.Fprintf(os.Stderr, " Allow TCP: %v\n", cfg.AllowTCP)
fmt.Fprintf(os.Stderr, " Always TCP: %v\n", cfg.AlwaysTCP)
fmt.Fprintf(os.Stderr, " Fast Mode: %v\n", cfg.Fast)
}
if cfg.Debug > 0 {
fmt.Fprintf(os.Stderr, "Debug: Config loaded\n")
fmt.Fprintf(os.Stderr, " Domain: %s\n", domain)
fmt.Fprintf(os.Stderr, " Query Type: %s\n", cfg.QueryType)
fmt.Fprintf(os.Stderr, " Max Depth: %d\n", cfg.MaxDepth)
fmt.Fprintf(os.Stderr, " UDP Size: %d\n", cfg.UDPSize)
fmt.Fprintf(os.Stderr, " Retries: %d\n", cfg.Retries)
fmt.Fprintf(os.Stderr, " Allow TCP: %v\n", cfg.AllowTCP)
fmt.Fprintf(os.Stderr, " Always TCP: %v\n", cfg.AlwaysTCP)
fmt.Fprintf(os.Stderr, " Fast Mode: %v\n", cfg.Fast)
}
if !cfg.Quiet && !*jsonOutput {
fmt.Printf("ExploreDNS - exploring: %s (type: %s)\n", domain, cfg.QueryType)
}
if !cfg.Quiet && !*jsonOutput {
fmt.Printf("ExploreDNS - exploring: %s (type: %s)\n", domain, cfg.QueryType)
}
outFmt := output.FormatText
if *jsonOutput {
outFmt = output.FormatJSON
}
outFmt := output.FormatText
if *jsonOutput {
outFmt = output.FormatJSON
}
outCfg := &output.Config{
Format: outFmt,
Domain: domain,
QueryType: cfg.QueryType,
ShowProgress: cfg.ShowProgress,
ShowResolves: cfg.ShowResolves,
ShowServers: cfg.ShowServers,
ShowVersions: cfg.ShowVersions,
ShowAllStats: cfg.ShowAllStats,
ShowResults: cfg.ShowResults,
ShowSummaryResults: cfg.ShowSummaryResults,
Verbose: cfg.Verbose,
Quiet: cfg.Quiet,
Color: os.Getenv("NO_COLOR") == "",
}
outCfg := &output.Config{
Format: outFmt,
Domain: domain,
QueryType: cfg.QueryType,
ShowProgress: cfg.ShowProgress,
ShowResolves: cfg.ShowResolves,
ShowServers: cfg.ShowServers,
ShowVersions: cfg.ShowVersions,
ShowAllStats: cfg.ShowAllStats,
ShowResults: cfg.ShowResults,
ShowSummaryResults: cfg.ShowSummaryResults,
Verbose: cfg.Verbose,
Quiet: cfg.Quiet,
Color: os.Getenv("NO_COLOR") == "",
Debug: cfg.Debug,
}
ctx := context.Background()
formatter := output.NewFormatter(outCfg, os.Stdout)
_, err = output.RunTraversal(ctx, traverser, outCfg, formatter, domain)
if err != nil {
fmt.Fprintf(os.Stderr, "Error: traversal failed: %v\n", err)
os.Exit(1)
}
ctx := context.Background()
formatter := output.NewFormatter(outCfg, os.Stdout)
_, err = output.RunTraversal(ctx, traverser, outCfg, formatter, domain)
if err != nil {
fmt.Fprintf(os.Stderr, "Error: traversal failed: %v\n", err)
os.Exit(1)
}
if cfg.Debug > 0 {
fmt.Fprintf(os.Stderr, "Debug: Traversal completed\n")
}
if cfg.Debug > 0 {
fmt.Fprintf(os.Stderr, "Debug: Traversal completed\n")
}
}
+7 -7
View File
@@ -36,13 +36,13 @@ type Config struct {
Debug int
Quiet bool
ShowProgress bool
ShowResolves bool
ShowServers bool
ShowVersions bool
ShowAllStats bool
ShowResults bool
ShowSummaryResults bool
ShowProgress bool
ShowResolves bool
ShowServers bool
ShowVersions bool
ShowAllStats bool
ShowResults bool
ShowSummaryResults bool
}
func ParseQueryType(s string) (uint16, error) {
+5 -5
View File
@@ -314,8 +314,8 @@ func TestCNAMEChain(t *testing.T) {
func TestResponseClassificationString(t *testing.T) {
tests := []struct {
rc ResponseClassification
want string
rc ResponseClassification
want string
}{
{ResponseAnswer, "answer"},
{ResponseReferral, "referral"},
@@ -344,10 +344,10 @@ func TestFormatRecord(t *testing.T) {
t.Run("A record", func(t *testing.T) {
rr := &dns.A{
Hdr: dns.RR_Header{
Name: "example.com.",
Name: "example.com.",
Rrtype: dns.TypeA,
Class: dns.ClassINET,
Ttl: 300,
Class: dns.ClassINET,
Ttl: 300,
},
A: MustParseIP("93.184.216.34"),
}
-1
View File
@@ -328,4 +328,3 @@ func TestQueryNoTCPFallbackWhenDisabled(t *testing.T) {
t.Error("expected truncated response to be returned as-is")
}
}
-29
View File
@@ -1,9 +1,6 @@
package dns
import (
"fmt"
"strings"
"github.com/miekg/dns"
)
@@ -40,32 +37,6 @@ func QNameType(qtype uint16) string {
return dns.TypeToString[qtype]
}
func ParseQueryType(s string) (uint16, error) {
s = strings.ToUpper(strings.TrimSpace(s))
switch s {
case "A":
return TypeA, nil
case "AAAA":
return TypeAAAA, nil
case "NS":
return TypeNS, nil
case "CNAME":
return TypeCNAME, nil
case "MX":
return TypeMX, nil
case "TXT":
return TypeTXT, nil
case "SOA":
return TypeSOA, nil
case "PTR":
return TypePTR, nil
case "ANY":
return TypeANY, nil
default:
return 0, fmt.Errorf("invalid query type: %s", s)
}
}
func DefaultEDNS0UDPSize() int {
return 2048
}
+10 -3
View File
@@ -1,6 +1,7 @@
package output
import (
"fmt"
"io"
"os"
@@ -28,6 +29,7 @@ type Config struct {
Verbose bool
Quiet bool
Color bool
Debug int
}
func DefaultConfig() *Config {
@@ -69,16 +71,21 @@ func AttachHooks(cfg *Config, formatter Formatter) *traverse.TraverserHooks {
if cfg == nil || formatter == nil {
return nil
}
logErr := func(context string, err error) {
if err != nil && cfg.Debug > 0 {
fmt.Fprintf(os.Stderr, "Debug: formatter %s: %v\n", context, err)
}
}
return &traverse.TraverserHooks{
OnEvent: func(event traverse.TraversalEvent) {
switch {
case event.IsResolve && cfg.ShowResolves:
_ = formatter.WriteResolve(event)
logErr("WriteResolve", formatter.WriteResolve(event))
case !event.IsResolve && cfg.ShowProgress:
_ = formatter.WriteProgress(event)
logErr("WriteProgress", formatter.WriteProgress(event))
}
if event.Stage == traverse.EventComplete && cfg.ShowAllStats {
_ = formatter.WriteResult(event.Result)
logErr("WriteResult", formatter.WriteResult(event.Result))
}
},
}
+2 -2
View File
@@ -54,8 +54,8 @@ type jsonSummary struct {
}
type jsonAnswerStat struct {
RData string `json:"rdata"`
Probability float64 `json:"probability"`
RData string `json:"rdata"`
Probability float64 `json:"probability"`
Records []string `json:"records,omitempty"`
}
+3
View File
@@ -73,6 +73,9 @@ func ComputeSummary(results []traverse.TraversalResult) *SummaryStats {
return stats.Answers[i].RData < stats.Answers[j].RData
})
if len(stats.Answers) == 0 && len(stats.ByType) == 0 {
return nil
}
return stats
}
+1 -8
View File
@@ -99,11 +99,7 @@ func (f *textFormatter) writeServers(results []traverse.TraversalResult) error {
for _, name := range names {
for _, ip := range servers[name] {
version := ""
if f.cfg.ShowVersions {
version = " (version lookup pending)"
}
if _, err := fmt.Fprintf(f.w, "%*s: %-15s%s\n", width, name, ip, version); err != nil {
if _, err := fmt.Fprintf(f.w, "%*s: %-15s\n", width, name, ip); err != nil {
return err
}
}
@@ -234,9 +230,6 @@ func referralID(ref *traverse.Referral) string {
if ref == nil {
return ""
}
if ref.Depth == 0 {
return "1"
}
return fmt.Sprintf("%d", ref.Depth+1)
}
+4 -4
View File
@@ -9,10 +9,10 @@ import (
)
type InfoCache struct {
parent *InfoCache
mu sync.RWMutex
ns map[string][]string
glue map[string][]net.IP
parent *InfoCache
mu sync.RWMutex
ns map[string][]string
glue map[string][]net.IP
}
func NewInfoCache(parent *InfoCache) *InfoCache {
+9 -9
View File
@@ -32,18 +32,18 @@ func (s ResolutionState) String() string {
}
type Referral struct {
Name string
Qtype uint16
Qclass uint16
Name string
Qtype uint16
Qclass uint16
Bailiwick string
Addresses []net.IP
State ResolutionState
NSName string
Parent *Referral
Depth int
Prob float64
NSName string
Parent *Referral
Depth int
Prob float64
}
func NewReferral(name string, qtype uint16, bailiwick string, depth int, prob float64, parent *Referral) *Referral {
@@ -81,7 +81,7 @@ func (r *Referral) SetAddresses(addrs []net.IP) {
}
type CircularReferralError struct {
Name string
Name string
Chain []string
}
@@ -90,7 +90,7 @@ func (e *CircularReferralError) Error() string {
}
type UnresolvableNameserverError struct {
Name string
Name string
Reason string
}
+1 -1
View File
@@ -10,7 +10,7 @@ import (
type ResponseType int
const (
RespReferral ResponseType = iota
RespReferral ResponseType = iota
RespAnswer
RespCNAMEFollow
RespNODATA
+2 -2
View File
@@ -3,7 +3,7 @@ package traverse
const DefaultMaxDepth = 20
type Stack struct {
items []*Referral
items []*Referral
maxDepth int
}
@@ -12,7 +12,7 @@ func NewStack(maxDepth int) *Stack {
maxDepth = DefaultMaxDepth
}
return &Stack{
items: make([]*Referral, 0),
items: make([]*Referral, 0),
maxDepth: maxDepth,
}
}
+36 -36
View File
@@ -44,9 +44,9 @@ func TestTraverserSimpleTraversal(t *testing.T) {
}()
tr := NewTraverser(&TraverserConfig{
MaxDepth: 5,
QueryType: dnsTypeA,
RootAddrs: []net.IP{net.ParseIP("198.41.0.4")},
MaxDepth: 5,
QueryType: dnsTypeA,
RootAddrs: []net.IP{net.ParseIP("198.41.0.4")},
})
tr.SetExchange(func(ctx context.Context, server string, msg *dns.Msg, useTCP bool) (*dns.Msg, error) {
return answerResp.Copy(), nil
@@ -94,9 +94,9 @@ func TestTraverserReferralTraversal(t *testing.T) {
})
tr := NewTraverser(&TraverserConfig{
MaxDepth: 5,
QueryType: dnsTypeA,
RootAddrs: []net.IP{net.ParseIP("198.41.0.4")},
MaxDepth: 5,
QueryType: dnsTypeA,
RootAddrs: []net.IP{net.ParseIP("198.41.0.4")},
})
tr.SetExchange(func(ctx context.Context, server string, msg *dns.Msg, useTCP bool) (*dns.Msg, error) {
q := msg.Question[0]
@@ -124,9 +124,9 @@ func TestTraverserReferralTraversal(t *testing.T) {
func TestTraverserMaxDepth(t *testing.T) {
callCount := 0
tr := NewTraverser(&TraverserConfig{
MaxDepth: 2,
QueryType: dnsTypeA,
RootAddrs: []net.IP{net.ParseIP("198.41.0.4")},
MaxDepth: 2,
QueryType: dnsTypeA,
RootAddrs: []net.IP{net.ParseIP("198.41.0.4")},
})
tr.SetExchange(func(ctx context.Context, server string, msg *dns.Msg, useTCP bool) (*dns.Msg, error) {
callCount++
@@ -170,9 +170,9 @@ func TestTraverserMaxDepth(t *testing.T) {
func TestTraverserContextCancellation(t *testing.T) {
tr := NewTraverser(&TraverserConfig{
MaxDepth: 5,
QueryType: dnsTypeA,
RootAddrs: []net.IP{net.ParseIP("198.41.0.4")},
MaxDepth: 5,
QueryType: dnsTypeA,
RootAddrs: []net.IP{net.ParseIP("198.41.0.4")},
})
tr.SetExchange(func(ctx context.Context, server string, msg *dns.Msg, useTCP bool) (*dns.Msg, error) {
m := new(dns.Msg)
@@ -203,9 +203,9 @@ func TestTraverserNXDOMAIN(t *testing.T) {
nxdResp.Rcode = dns.RcodeNameError
tr := NewTraverser(&TraverserConfig{
MaxDepth: 5,
QueryType: dnsTypeA,
RootAddrs: []net.IP{net.ParseIP("198.41.0.4")},
MaxDepth: 5,
QueryType: dnsTypeA,
RootAddrs: []net.IP{net.ParseIP("198.41.0.4")},
})
tr.SetExchange(func(ctx context.Context, server string, msg *dns.Msg, useTCP bool) (*dns.Msg, error) {
return nxdResp.Copy(), nil
@@ -229,9 +229,9 @@ func TestTraverserSERVFAIL(t *testing.T) {
sfResp.Rcode = dns.RcodeServerFailure
tr := NewTraverser(&TraverserConfig{
MaxDepth: 5,
QueryType: dnsTypeA,
RootAddrs: []net.IP{net.ParseIP("198.41.0.4")},
MaxDepth: 5,
QueryType: dnsTypeA,
RootAddrs: []net.IP{net.ParseIP("198.41.0.4")},
})
tr.SetExchange(func(ctx context.Context, server string, msg *dns.Msg, useTCP bool) (*dns.Msg, error) {
return sfResp.Copy(), nil
@@ -268,9 +268,9 @@ func TestTraverserCNAMEFollow(t *testing.T) {
})
tr := NewTraverser(&TraverserConfig{
MaxDepth: 5,
QueryType: dnsTypeA,
RootAddrs: []net.IP{net.ParseIP("198.41.0.4")},
MaxDepth: 5,
QueryType: dnsTypeA,
RootAddrs: []net.IP{net.ParseIP("198.41.0.4")},
})
tr.SetExchange(func(ctx context.Context, server string, msg *dns.Msg, useTCP bool) (*dns.Msg, error) {
q := msg.Question[0]
@@ -328,9 +328,9 @@ func TestTraverserProbabilityCalculation(t *testing.T) {
})
tr := NewTraverser(&TraverserConfig{
MaxDepth: 5,
QueryType: dnsTypeA,
RootAddrs: []net.IP{net.ParseIP("1.2.3.4")},
MaxDepth: 5,
QueryType: dnsTypeA,
RootAddrs: []net.IP{net.ParseIP("1.2.3.4")},
})
tr.SetExchange(func(ctx context.Context, server string, msg *dns.Msg, useTCP bool) (*dns.Msg, error) {
q := msg.Question[0]
@@ -364,9 +364,9 @@ func TestTraverserNODATA(t *testing.T) {
})
tr := NewTraverser(&TraverserConfig{
MaxDepth: 5,
QueryType: dnsTypeA,
RootAddrs: []net.IP{net.ParseIP("198.41.0.4")},
MaxDepth: 5,
QueryType: dnsTypeA,
RootAddrs: []net.IP{net.ParseIP("198.41.0.4")},
})
tr.SetExchange(func(ctx context.Context, server string, msg *dns.Msg, useTCP bool) (*dns.Msg, error) {
return nodataResp.Copy(), nil
@@ -394,9 +394,9 @@ func TestTraverserMultipleRoots(t *testing.T) {
})
tr := NewTraverser(&TraverserConfig{
MaxDepth: 5,
QueryType: dnsTypeA,
RootAddrs: []net.IP{net.ParseIP("198.41.0.4"), net.ParseIP("199.9.14.201")},
MaxDepth: 5,
QueryType: dnsTypeA,
RootAddrs: []net.IP{net.ParseIP("198.41.0.4"), net.ParseIP("199.9.14.201")},
})
tr.SetExchange(func(ctx context.Context, server string, msg *dns.Msg, useTCP bool) (*dns.Msg, error) {
return answerResp.Copy(), nil
@@ -414,9 +414,9 @@ func TestTraverserMultipleRoots(t *testing.T) {
func TestTraverserNilExchangeResponse(t *testing.T) {
tr := NewTraverser(&TraverserConfig{
MaxDepth: 5,
QueryType: dnsTypeA,
RootAddrs: []net.IP{net.ParseIP("198.41.0.4")},
MaxDepth: 5,
QueryType: dnsTypeA,
RootAddrs: []net.IP{net.ParseIP("198.41.0.4")},
})
tr.SetExchange(func(ctx context.Context, server string, msg *dns.Msg, useTCP bool) (*dns.Msg, error) {
return nil, nil
@@ -451,9 +451,9 @@ func TestTraverserCacheChaining(t *testing.T) {
})
tr := NewTraverser(&TraverserConfig{
MaxDepth: 5,
QueryType: dnsTypeA,
RootAddrs: []net.IP{net.ParseIP("198.41.0.4")},
MaxDepth: 5,
QueryType: dnsTypeA,
RootAddrs: []net.IP{net.ParseIP("198.41.0.4")},
})
tr.SetExchange(func(ctx context.Context, server string, msg *dns.Msg, useTCP bool) (*dns.Msg, error) {
q := msg.Question[0]