docs: comprehensive documentation for ExploreDNS
CI / test (pull_request) Failing after 2m13s

- Rewrite README.md with overview, features, installation (go install +
  build from source), quick start, full CLI flag reference table,
  output section descriptions, project structure, and development guide

- Add package-level doc comments to all five internal packages:
  config, dns, fingerprint, output, traverse (via doc.go or existing
  package-declaration files)

- Add GoDoc comments on every exported type, constant, function, and
  method across all packages:
  - internal/config: Config struct fields, all Parse*/Default/Validate
  - internal/dns: QueryConfig, Resolver, BasicResolver, CachingResolver,
    ExchangeFunc, RootServer, RootDiscoveryConfig, DecodedResponse,
    ResponseClassification, all exported helpers
  - internal/fingerprint: Fingerprinter, New, NewWithTimeout, Query,
    FingerprintAll
  - internal/traverse: Traverser, TraverserConfig, TraversalResult,
    Referral, ResolutionState, Response, ResponseType, InfoCache,
    Stack, TraverserHooks, EventStage, TraversalEvent, EventHandler,
    CircularReferralError, UnresolvableNameserverError
  - internal/output: Format, Config, Formatter, SummaryStats,
    NewFormatter, AttachHooks, RunTraversal, DefaultConfig,
    ComputeSummary

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 04:01:51 +10:00
co-authored by Copilot multica-agent
parent fe1afe2a97
commit 9aa85d8e5d
21 changed files with 675 additions and 91 deletions
+23 -4
View File
@@ -9,14 +9,22 @@ import (
"github.com/miekg/dns"
)
// QueryConfig controls the transport-level behaviour of DNS queries.
type QueryConfig struct {
UDPSize int
Timeout time.Duration
Retries int
UseTCP bool
// UDPSize is the EDNS0 advertised UDP payload size in bytes.
UDPSize int
// Timeout is the per-attempt network timeout.
Timeout time.Duration
// Retries is the total number of query attempts (first try + retries - 1 extra attempts).
Retries int
// UseTCP forces all queries over TCP when true.
UseTCP bool
// AllowTCP enables automatic TCP retry when a UDP response is truncated.
AllowTCP bool
}
// DefaultQueryConfig returns a QueryConfig with sensible defaults:
// 2048-byte UDP buffer, 5-second timeout, 3 retries, UDP with TCP fallback.
func DefaultQueryConfig() *QueryConfig {
return &QueryConfig{
UDPSize: DefaultEDNS0UDPSize(),
@@ -27,8 +35,13 @@ func DefaultQueryConfig() *QueryConfig {
}
}
// ExchangeFunc is a function that sends a DNS message to server and returns
// the response. Injecting an ExchangeFunc in tests avoids real network calls.
type ExchangeFunc func(ctx context.Context, server string, msg *dns.Msg, useTCP bool) (*dns.Msg, error)
// Query sends a standard (recursion-desired) DNS query to server for name/qtype
// using the provided cfg. cfg may be nil; DefaultQueryConfig is used in that case.
// Retries with exponential back-off are performed on transient errors.
func Query(ctx context.Context, server net.IP, name string, qtype uint16, cfg *QueryConfig) (*dns.Msg, error) {
if cfg == nil {
cfg = DefaultQueryConfig()
@@ -75,6 +88,8 @@ func realExchange(ctx context.Context, server string, msg *dns.Msg, useTCP bool)
return r, nil
}
// QueryWithExchange is the testable core of Query. It uses exchangeFn instead
// of the real network, enabling deterministic unit tests.
func QueryWithExchange(ctx context.Context, server net.IP, name string, qtype uint16, cfg *QueryConfig, exchangeFn ExchangeFunc) (*dns.Msg, error) {
if cfg == nil {
cfg = DefaultQueryConfig()
@@ -127,6 +142,9 @@ func QueryWithExchange(ctx context.Context, server net.IP, name string, qtype ui
return nil, fmt.Errorf("query %s %s failed after %d retries: %w", name, QNameType(qtype), cfg.Retries, lastErr)
}
// IterativeQuery sends a non-recursive (RD=false) DNS query intended for
// authoritative nameservers. Use this during iterative traversal to prevent
// resolvers from answering on behalf of the authoritative server.
func IterativeQuery(ctx context.Context, server net.IP, name string, qtype uint16, cfg *QueryConfig) (*dns.Msg, error) {
if cfg == nil {
cfg = DefaultQueryConfig()
@@ -137,6 +155,7 @@ func IterativeQuery(ctx context.Context, server net.IP, name string, qtype uint1
return IterativeQueryWithExchange(ctx, server, name, qtype, cfg, realExchange)
}
// IterativeQueryWithExchange is the testable core of IterativeQuery.
func IterativeQueryWithExchange(ctx context.Context, server net.IP, name string, qtype uint16, cfg *QueryConfig, exchangeFn ExchangeFunc) (*dns.Msg, error) {
if cfg == nil {
cfg = DefaultQueryConfig()