dns: @hnw alternate proposal (#193)

* fix(dns): resolve CNAME chains and prevent invalid IP parsing

- Add automated in-band CNAME chain resolution to extract final A/AAAA IP addresses.
- Replace `MaxResponseAnswers` with `MaxIPs` and `MaxCNAMEs` to explicitly bound resource decoding and prevent memory exhaustion.
- Bound CNAME chain traversal to prevent infinite loops from cyclic records.

* refactor(dns): eagerly decode CNAME target into r.data, drop target field

Address review feedback on #189:

- Remove Resource.target: Resource.Decode expands CNAME RDATA in place
  into r.data (uncompressed wire format) while the full message is still
  available and updates header.Length, storing the name bytes exactly once.
- Add Resource.CNAMEView returning a length-bounded view of the expanded
  target; Message.WriteAnswers uses it.
- Rename matchesHost to ResourceHeader.pertainsTo.
- Make ResolveConfig.MaxCNAMEs explicit: drop the silent default in
  Client.StartResolve and let callers opt in (x/xnet).
- Reduce test suite to regression coverage only.

refs #189

* dns: simplify @hnw function and additional fixes

---------

Co-authored-by: Yoshio HANAWA <y@hnw.jp>
This commit is contained in:
Pat Whittingslow
2026-08-28 21:39:12 -03:00
committed by GitHub
parent ab9d3ee691
commit 75f1e02a20
9 changed files with 369 additions and 56 deletions
+4 -2
View File
@@ -25,7 +25,9 @@ type ResolveConfig struct {
Additional []Resource
EnableRecursion bool
// MaxResponseAnswers limits how many answer records are decoded from the
// DNS response. If zero it defaults to the number of Questions.
// DNS response. If zero it defaults to the number of Questions. Answers
// are decoded in wire order regardless of type, so a response resolved
// through CNAMEs needs room for the CNAME records as well as the addresses.
MaxResponseAnswers uint16
}
@@ -37,7 +39,7 @@ func (sudp *Client) ConnectionID() *uint64 { return &sudp.connID }
func (c *Client) StartResolve(localPort, txid uint16, cfg ResolveConfig) error {
nd := len(cfg.Questions)
if nd > math.MaxUint16 {
if nd > math.MaxUint16 || nd == 0 {
return lneto.ErrInvalidConfig
}
maxAns := cfg.MaxResponseAnswers