[agent/codex:gpt-5.3-codex-spark] Read docs/RFC.md fully. Find ONE feature described in the sp... #6

Merged
Virgil merged 1 commit from main into dev 2026-04-03 19:53:47 +00:00
4 changed files with 424 additions and 1 deletions

10
go.mod
View file

@ -1,3 +1,13 @@
module dappco.re/go/dns
go 1.22
require github.com/miekg/dns v1.1.62
require (
golang.org/x/mod v0.18.0 // indirect
golang.org/x/net v0.27.0 // indirect
golang.org/x/sync v0.7.0 // indirect
golang.org/x/sys v0.22.0 // indirect
golang.org/x/tools v0.22.0 // indirect
)

12
go.sum Normal file
View file

@ -0,0 +1,12 @@
github.com/miekg/dns v1.1.62 h1:cN8OuEF1/x5Rq6Np+h1epln8OiyPWV+lROx9LxcGgIQ=
github.com/miekg/dns v1.1.62/go.mod h1:mvDlcItzm+br7MToIKqkglaGhlFMHJ9DTNNWONWXbNQ=
golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0=
golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys=
golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE=
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA=
golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c=

274
serve.go Normal file
View file

@ -0,0 +1,274 @@
package dns
import (
"net"
"strconv"
"strings"
"time"
dnsprotocol "github.com/miekg/dns"
)
const dnsTTL = 300
// DNSServer handles a live UDP+TCP DNS endpoint and owns listener resources.
type DNSServer struct {
udpListener net.PacketConn
tcpListener net.Listener
udpServer *dnsprotocol.Server
tcpServer *dnsprotocol.Server
}
func (server *DNSServer) Address() string {
if server.udpListener == nil {
return ""
}
return server.udpListener.LocalAddr().String()
}
func (server *DNSServer) Close() error {
if server.udpListener != nil {
_ = server.udpListener.Close()
}
if server.tcpListener != nil {
_ = server.tcpListener.Close()
}
var err error
if server.udpServer != nil {
err = server.udpServer.Shutdown()
}
if server.tcpServer != nil {
err = server.tcpServer.Shutdown()
}
return err
}
// Serve starts DNS over UDP and TCP at bind:port and returns a running server handle.
// Example:
//
// srv, err := service.Serve("127.0.0.1", 0)
func (service *Service) Serve(bind string, port int) (*DNSServer, error) {
if bind == "" {
bind = "127.0.0.1"
}
addr := net.JoinHostPort(bind, strconv.Itoa(port))
udpListener, err := net.ListenPacket("udp", addr)
if err != nil {
return nil, err
}
tcpListener, err := net.Listen("tcp", addr)
if err != nil {
_ = udpListener.Close()
return nil, err
}
handler := &dnsRequestHandler{service: service}
mux := dnsprotocol.NewServeMux()
mux.HandleFunc(".", handler.ServeDNS)
udpServer := &dnsprotocol.Server{Net: "udp", PacketConn: udpListener, Handler: mux}
tcpServer := &dnsprotocol.Server{Net: "tcp", Listener: tcpListener, Handler: mux}
run := &DNSServer{
udpListener: udpListener,
tcpListener: tcpListener,
udpServer: udpServer,
tcpServer: tcpServer,
}
go func() {
_ = udpServer.ActivateAndServe()
}()
go func() {
_ = tcpServer.ActivateAndServe()
}()
return run, nil
}
type dnsRequestHandler struct {
service *Service
}
func (handler *dnsRequestHandler) ServeDNS(responseWriter dnsprotocol.ResponseWriter, request *dnsprotocol.Msg) {
reply := new(dnsprotocol.Msg)
reply.Compress = true
if request == nil {
reply.SetRcode(reply, dnsprotocol.RcodeNotImplemented)
_ = responseWriter.WriteMsg(reply)
return
}
reply.SetReply(request)
if request.Opcode != dnsprotocol.OpcodeQuery {
reply.SetRcode(request, dnsprotocol.RcodeNotImplemented)
_ = responseWriter.WriteMsg(reply)
return
}
if len(request.Question) == 0 {
reply.SetRcode(request, dnsprotocol.RcodeFormatError)
_ = responseWriter.WriteMsg(reply)
return
}
question := request.Question[0]
name := strings.TrimSuffix(strings.ToLower(question.Name), ".")
record, found := handler.service.findRecord(name)
switch question.Qtype {
case dnsprotocol.TypeA:
if !found {
goto noRecord
}
for _, value := range record.A {
parsedIP := net.ParseIP(value)
if parsedIP == nil || parsedIP.To4() == nil {
continue
}
reply.Answer = append(reply.Answer, &dnsprotocol.A{
Hdr: dnsprotocol.RR_Header{Name: question.Name, Rrtype: dnsprotocol.TypeA, Class: dnsprotocol.ClassINET, Ttl: dnsTTL},
A: parsedIP.To4(),
})
}
case dnsprotocol.TypeAAAA:
if !found {
goto noRecord
}
for _, value := range record.AAAA {
parsedIP := net.ParseIP(value)
if parsedIP == nil || parsedIP.To4() != nil {
continue
}
reply.Answer = append(reply.Answer, &dnsprotocol.AAAA{
Hdr: dnsprotocol.RR_Header{Name: question.Name, Rrtype: dnsprotocol.TypeAAAA, Class: dnsprotocol.ClassINET, Ttl: dnsTTL},
AAAA: parsedIP.To16(),
})
}
case dnsprotocol.TypeTXT:
if !found {
goto noRecord
}
for _, value := range record.TXT {
reply.Answer = append(reply.Answer, &dnsprotocol.TXT{
Hdr: dnsprotocol.RR_Header{Name: question.Name, Rrtype: dnsprotocol.TypeTXT, Class: dnsprotocol.ClassINET, Ttl: dnsTTL},
Txt: []string{value},
})
}
case dnsprotocol.TypeNS:
if !found {
goto noRecord
}
for _, value := range record.NS {
reply.Answer = append(reply.Answer, &dnsprotocol.NS{
Hdr: dnsprotocol.RR_Header{Name: question.Name, Rrtype: dnsprotocol.TypeNS, Class: dnsprotocol.ClassINET, Ttl: dnsTTL},
Ns: normalizeName(value) + ".",
})
}
case dnsprotocol.TypePTR:
ip, ok := parsePTRIP(name)
if !ok {
reply.SetRcode(request, dnsprotocol.RcodeFormatError)
_ = responseWriter.WriteMsg(reply)
return
}
values, ok := handler.service.ResolveReverse(ip)
if !ok {
goto noRecord
}
for _, value := range values {
reply.Answer = append(reply.Answer, &dnsprotocol.PTR{
Hdr: dnsprotocol.RR_Header{Name: question.Name, Rrtype: dnsprotocol.TypePTR, Class: dnsprotocol.ClassINET, Ttl: dnsTTL},
Ptr: normalizeName(value) + ".",
})
}
case dnsprotocol.TypeSOA:
if !found {
goto noRecord
}
reply.Answer = append(reply.Answer, &dnsprotocol.SOA{
Hdr: dnsprotocol.RR_Header{Name: question.Name, Rrtype: dnsprotocol.TypeSOA, Class: dnsprotocol.ClassINET, Ttl: dnsTTL},
Ns: normalizeName("ns."+name) + ".",
Mbox: "hostmaster." + name + ".",
Serial: uint32(time.Now().Unix()),
Refresh: 86400,
Retry: 3600,
Expire: 3600,
Minttl: 300,
})
default:
reply.SetRcode(request, dnsprotocol.RcodeNotImplemented)
_ = responseWriter.WriteMsg(reply)
return
}
if len(reply.Answer) == 0 {
goto noRecord
}
_ = responseWriter.WriteMsg(reply)
return
noRecord:
reply.SetRcode(request, dnsprotocol.RcodeNameError)
_ = responseWriter.WriteMsg(reply)
}
func parsePTRIP(name string) (string, bool) {
lookup := strings.TrimSuffix(strings.ToLower(name), ".")
if strings.HasSuffix(lookup, ".in-addr.arpa") {
base := strings.TrimSuffix(strings.TrimSuffix(lookup, ".in-addr.arpa"), ".")
labels := strings.Split(base, ".")
if len(labels) != 4 {
return "", false
}
for _, label := range labels {
if label == "" {
return "", false
}
}
reversed := make([]string, 4)
for i := 0; i < 4; i++ {
reversed[i] = labels[3-i]
}
candidate := strings.Join(reversed, ".")
parsed := net.ParseIP(candidate)
if parsed == nil || parsed.To4() == nil {
return "", false
}
return parsed.String(), true
}
if strings.HasSuffix(lookup, ".ip6.arpa") {
base := strings.TrimSuffix(strings.TrimSuffix(lookup, ".ip6.arpa"), ".")
labels := strings.Split(base, ".")
if len(labels) != 32 {
return "", false
}
for _, label := range labels {
if len(label) != 1 {
return "", false
}
}
reversed := make([]string, 32)
for i := 0; i < 32; i++ {
reversed[i] = labels[31-i]
}
blocks := make([]string, 8)
for i := 0; i < 8; i++ {
block := strings.Join(reversed[i*4:(i+1)*4], "")
if len(block) != 4 {
return "", false
}
blocks[i] = block
}
candidate := strings.Join(blocks, ":")
parsed := net.ParseIP(candidate)
if parsed == nil {
return "", false
}
return parsed.String(), true
}
return "", false
}

View file

@ -1,6 +1,30 @@
package dns
import "testing"
import (
"strings"
"testing"
"time"
dnsprotocol "github.com/miekg/dns"
)
func exchangeWithRetry(t *testing.T, client dnsprotocol.Client, request *dnsprotocol.Msg, address string) *dnsprotocol.Msg {
t.Helper()
for attempt := 0; attempt < 80; attempt++ {
response, _, err := client.Exchange(request, address)
if err == nil {
return response
}
if !strings.Contains(err.Error(), "connection refused") {
t.Fatalf("dns query failed: %v", err)
}
time.Sleep(25 * time.Millisecond)
}
t.Fatalf("dns query failed after retrying due to startup timing")
return nil
}
func TestServiceResolveUsesExactNameBeforeWildcard(t *testing.T) {
service := NewService(ServiceOptions{
@ -243,3 +267,106 @@ func TestServiceDiscoverReturnsNilWithoutDiscoverer(t *testing.T) {
t.Fatalf("expected no error when discoverer is missing: %v", err)
}
}
func TestServiceServeResolvesAAndAAAARecords(t *testing.T) {
service := NewService(ServiceOptions{
Records: map[string]NameRecords{
"gateway.charon.lthn": {
A: []string{"10.10.10.10"},
AAAA: []string{"2600:1f1c:7f0:4f01::1"},
},
},
})
srv, err := service.Serve("127.0.0.1", 0)
if err != nil {
t.Fatalf("expected server to start: %v", err)
}
defer func() { _ = srv.Close() }()
client := dnsprotocol.Client{}
query := func(qtype uint16) *dnsprotocol.Msg {
request := new(dnsprotocol.Msg)
request.SetQuestion("gateway.charon.lthn.", qtype)
response := exchangeWithRetry(t, client, request, srv.Address())
if response.Rcode != dnsprotocol.RcodeSuccess {
t.Fatalf("unexpected rcode for qtype %d: %d", qtype, response.Rcode)
}
return response
}
aResponse := query(dnsprotocol.TypeA)
if len(aResponse.Answer) != 1 {
t.Fatalf("expected one A answer, got %d", len(aResponse.Answer))
}
if got, ok := aResponse.Answer[0].(*dnsprotocol.A); !ok || got.A.String() != "10.10.10.10" {
t.Fatalf("unexpected A answer: %#v", aResponse.Answer[0])
}
aaaaResponse := query(dnsprotocol.TypeAAAA)
if len(aaaaResponse.Answer) != 1 {
t.Fatalf("expected one AAAA answer, got %d", len(aaaaResponse.Answer))
}
if got, ok := aaaaResponse.Answer[0].(*dnsprotocol.AAAA); !ok || got.AAAA.String() != "2600:1f1c:7f0:4f01::1" {
t.Fatalf("unexpected AAAA answer: %#v", aaaaResponse.Answer[0])
}
}
func TestServiceServeResolvesWildcardAndPTRRecords(t *testing.T) {
service := NewService(ServiceOptions{
Records: map[string]NameRecords{
"*.charon.lthn": {
A: []string{"10.0.0.1"},
},
"gateway.charon.lthn": {
A: []string{"10.10.10.10"},
},
},
})
srv, err := service.Serve("127.0.0.1", 0)
if err != nil {
t.Fatalf("expected server to start: %v", err)
}
defer func() { _ = srv.Close() }()
client := dnsprotocol.Client{}
request := new(dnsprotocol.Msg)
request.SetQuestion("node1.charon.lthn.", dnsprotocol.TypeA)
response := exchangeWithRetry(t, client, request, srv.Address())
if response.Rcode != dnsprotocol.RcodeSuccess {
t.Fatalf("unexpected rcode: %d", response.Rcode)
}
if got, ok := response.Answer[0].(*dnsprotocol.A); !ok || got.A.String() != "10.0.0.1" {
t.Fatalf("unexpected wildcard A answer: %#v", response.Answer)
}
ptrName := "10.10.10.10.in-addr.arpa."
ptrRequest := new(dnsprotocol.Msg)
ptrRequest.SetQuestion(ptrName, dnsprotocol.TypePTR)
ptrResponse := exchangeWithRetry(t, client, ptrRequest, srv.Address())
if len(ptrResponse.Answer) == 0 {
t.Fatal("expected PTR answer")
}
if got, ok := ptrResponse.Answer[0].(*dnsprotocol.PTR); !ok || got.Ptr != "gateway.charon.lthn." {
t.Fatalf("unexpected PTR answer: %#v", ptrResponse.Answer)
}
}
func TestServiceServeReturnsNXDOMAINWhenMissing(t *testing.T) {
service := NewService(ServiceOptions{})
srv, err := service.Serve("127.0.0.1", 0)
if err != nil {
t.Fatalf("expected server to start: %v", err)
}
defer func() { _ = srv.Close() }()
client := dnsprotocol.Client{}
request := new(dnsprotocol.Msg)
request.SetQuestion("missing.charon.lthn.", dnsprotocol.TypeA)
response := exchangeWithRetry(t, client, request, srv.Address())
if response.Rcode != dnsprotocol.RcodeNameError {
t.Fatalf("expected NXDOMAIN, got %d", response.Rcode)
}
}