summaryrefslogtreecommitdiff
path: root/internal/server
diff options
context:
space:
mode:
Diffstat (limited to 'internal/server')
-rw-r--r--internal/server/handler.go32
-rw-r--r--internal/server/server_test.go23
2 files changed, 46 insertions, 9 deletions
diff --git a/internal/server/handler.go b/internal/server/handler.go
index 4516468..46699d6 100644
--- a/internal/server/handler.go
+++ b/internal/server/handler.go
@@ -1,20 +1,36 @@
package server
import (
+ "codeberg.org/miekg/dns"
+ "codeberg.org/miekg/dns/rdata"
"context"
+ "errors"
"io"
+ "linum/internal/blocklist"
+ "linum/internal/cache"
+ "linum/internal/resolver"
"log/slog"
"net"
"net/netip"
+ "runtime/debug"
"time"
-
- "codeberg.org/miekg/dns"
- "codeberg.org/miekg/dns/rdata"
- "linum/internal/blocklist"
- "linum/internal/cache"
)
func (s *Server) handleQuery(ctx context.Context, w dns.ResponseWriter, req *dns.Msg) {
+ defer func() {
+ if r := recover(); r != nil {
+ slog.Error("panic in query handler", "recover", r, "stack", string(debug.Stack()))
+ m := new(dns.Msg)
+ m.Response = true
+ m.Rcode = dns.RcodeServerFailure
+ if req != nil {
+ m.ID = req.ID
+ m.Question = req.Question
+ }
+ io.Copy(w, m)
+ }
+ }()
+
clientIP := parseClientIP(w.RemoteAddr())
if !s.isAllowed(clientIP) {
slog.Warn("query denied by ACL", "client", clientIP)
@@ -92,13 +108,17 @@ func (s *Server) buildResponse(req *dns.Msg) (*dns.Msg, bool) {
reply, err := s.resolver.Lookup(ctx, qname, qtype)
if err != nil {
+ rcode := dns.RcodeServerFailure
+ if errors.Is(err, resolver.ErrUnsupportedType) {
+ rcode = dns.RcodeNotImplemented
+ }
slog.Error("resolution failed",
"err", err,
"qname", qname,
"qtype", dns.TypeToString[qtype],
)
m := new(dns.Msg)
- m.Rcode = dns.RcodeServerFailure
+ m.Rcode = uint16(rcode)
m.Response = true
m.ID = req.ID
m.Question = req.Question
diff --git a/internal/server/server_test.go b/internal/server/server_test.go
index 2340acd..93e2a69 100644
--- a/internal/server/server_test.go
+++ b/internal/server/server_test.go
@@ -1,15 +1,32 @@
package server
import (
+ "codeberg.org/miekg/dns"
+ "codeberg.org/miekg/dns/rdata"
"context"
+ "linum/internal/resolver"
"log/slog"
"testing"
"time"
-
- "codeberg.org/miekg/dns"
- "linum/internal/resolver"
)
+func TestBuildResponseUnknownType(t *testing.T) {
+ s := testServer(t)
+ m := new(dns.Msg)
+ m.Question = []dns.RR{&dns.RFC3597{
+ Hdr: dns.Header{Name: "example.com.", Class: dns.ClassINET},
+ RFC3597: rdata.RFC3597{RRType: 0xaa58},
+ }}
+
+ resp, _ := s.buildResponse(m)
+ if resp == nil {
+ t.Fatal("buildResponse returned nil")
+ }
+ if resp.Rcode != dns.RcodeNotImplemented {
+ t.Errorf("expected NOTIMPL, got %d", resp.Rcode)
+ }
+}
+
func testServer(t *testing.T) *Server {
t.Helper()
r := resolver.New(