Documentation
¶
Overview ¶
Package dnsclient owns SDNS's upstream DNS transport: wire framing, buffer pooling, dialing, deadlines and exchange policy (ID match, question-section guard, UDP->TCP truncation fallback). It is written clean-room and depends on github.com/miekg/dns only as the message codec (dns.Msg / Pack / Unpack), not as a transport.
Index ¶
- Variables
- func AcquireBuf(size uint16) []byte
- func QuestionMatches(req dns.Question, resp []dns.Question) bool
- func ReleaseBuf(buf []byte)
- type CancelInterrupt
- type Client
- type Conn
- func (co *Conn) BeginCancelInterrupt(ctx context.Context) CancelInterrupt
- func (co *Conn) Exchange(m *dns.Msg) (r *dns.Msg, rtt time.Duration, err error)
- func (co *Conn) ExchangeContext(ctx context.Context, m *dns.Msg) (r *dns.Msg, rtt time.Duration, err error)
- func (co *Conn) Read(p []byte) (n int, err error)
- func (co *Conn) ReadMsg() (*dns.Msg, error)
- func (co *Conn) Write(p []byte) (int, error)
- func (co *Conn) WriteMsg(m *dns.Msg) (err error)
Constants ¶
This section is empty.
Variables ¶
var ErrQuestion = errors.New("dns: response question did not match request")
ErrQuestion is returned by (*Conn).Exchange when the response's question section does not match the outstanding request. Accepting a mismatched question lets a malicious upstream plant a cache entry under an unrelated name (issue #469).
Functions ¶
func AcquireBuf ¶
AcquireBuf returns a buffer from the appropriate pool.
func QuestionMatches ¶
QuestionMatches reports whether the response's question section answers the outstanding request question. DNS names are compared case-insensitively because they are not case-sensitive on the wire.
Types ¶
type CancelInterrupt ¶ added in v1.7.4
type CancelInterrupt struct {
// contains filtered or unexported fields
}
CancelInterrupt identifies one connection-cancellation registration. Stop must complete before the Conn or its underlying connection is reused.
func (CancelInterrupt) Stop ¶ added in v1.7.4
func (h CancelInterrupt) Stop()
Stop detaches the cancellation callback and waits if it has already started. Stop has one owner and must not be called concurrently for the same handle. Sequential repeated calls and stale-generation handles are no-ops.
type Client ¶
type Client struct {
Proto string // "udp" | "tcp" | "tcp-tls" | "doh"; empty means "udp"
Timeout time.Duration // per-exchange dial+read+write budget; 0 means none
TLSConfig *tls.Config // DoT (tcp-tls) server config
DoHURL string // DoH endpoint URL
DoHClient *http.Client // DoH HTTP client (reused transport / HTTP2 pool)
// BeforeAttempt runs immediately before each wire transport attempt.
// It is inherited by the transparent UDP-to-TCP fallback, allowing
// request-wide work accounting to reject that second attempt before it
// dials. Nil preserves the historical behaviour.
BeforeAttempt func(proto string) error
// SkipQuestionCheck disables the response question-section guard.
// The guard is on by default; leave this false unless a caller has
// a specific reason to accept mismatched questions.
SkipQuestionCheck bool
}
Client is a high-level, dial-per-Exchange DNS client for callers that don't maintain their own connection pool — the forwarder, failover, and the config IPv6 probe. The resolver hot path uses Conn directly so it keeps its own pooling, circuit breaker and retry policy.
The zero value with Proto unset behaves as plain UDP. The question- section guard is on by default; the response transaction ID is always validated.
type Conn ¶
type Conn struct {
net.Conn // underlying connection
UDPSize uint16 // minimum receive buffer for UDP messages
// contains filtered or unexported fields
}
Conn represents a connection to a DNS server. It wraps a net.Conn (either a connected UDP socket or a TCP/TLS stream) and tracks the negotiated UDP receive size.
func (*Conn) BeginCancelInterrupt ¶ added in v1.7.4
func (co *Conn) BeginCancelInterrupt(ctx context.Context) CancelInterrupt
BeginCancelInterrupt makes a synchronous connection operation observe context cancellation after dialing has completed. It captures the current underlying connection rather than the reusable wrapper, and Stop joins an already-started callback before reuse is allowed.
A Conn supports one active interrupt registration at a time; overlapping registration is a connection-reuse invariant violation and panics. The zero handle returned for a context without a Done channel has no allocation or cleanup cost.
func (*Conn) Exchange ¶
Exchange performs a synchronous query over co: it writes m, reads the response, and validates the transaction ID and question section. The caller is responsible for dialing co and setting any deadline before calling Exchange.
func (*Conn) ExchangeContext ¶ added in v1.7.4
func (co *Conn) ExchangeContext(ctx context.Context, m *dns.Msg) (r *dns.Msg, rtt time.Duration, err error)
ExchangeContext performs Exchange with a cancellation interrupt bound to ctx. The caller still owns dialing and the ordinary network deadline. The deferred Stop makes the interrupt lifecycle panic-safe and guarantees that the connection is reusable only after a started cancellation callback ends.
func (*Conn) Read ¶
Read implements net.Conn. For a UDP connection it reads a single datagram. For a stream connection it reads the 2-byte length prefix (RFC 1035 §4.2.2) and then exactly that many bytes into p.
func (*Conn) ReadMsg ¶
ReadMsg reads a single DNS message from co. The buffer is always returned to the pool, even on a timed-out UDP read or a truncated TCP read, so failed upstream reads never leak the buffer. On success only the bytes actually read are unpacked — feeding Unpack the trailing capacity of a pooled UDP buffer would let stale bytes from a previous use bleed into the parsed message.