- 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:
co-authored by
Copilot
multica-agent
parent
5a54834c5f
commit
8e7beacc22
@@ -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) {
|
||||
@@ -235,4 +235,4 @@ func DefaultConfig() *Config {
|
||||
ShowResults: true,
|
||||
ShowSummaryResults: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"),
|
||||
}
|
||||
|
||||
@@ -328,4 +328,3 @@ func TestQueryNoTCPFallbackWhenDisabled(t *testing.T) {
|
||||
t.Error("expected truncated response to be returned as-is")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
@@ -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"`
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
type ResponseType int
|
||||
|
||||
const (
|
||||
RespReferral ResponseType = iota
|
||||
RespReferral ResponseType = iota
|
||||
RespAnswer
|
||||
RespCNAMEFollow
|
||||
RespNODATA
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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]
|
||||
|
||||
Reference in New Issue
Block a user