Commit Diff


commit - 7e5b66014d8e51608b3c909ab643e1f91f12b8db
commit + 2c109646ee0be071d39acc68f8cda66157d37582
blob - ca9087535c873b2e3b6c49b86ed6a39ac8dd432b
blob + 90337d381fc684d9d17c40a0cea994840f60d762
--- cmd/recursor/recursor.go
+++ cmd/recursor/recursor.go
@@ -9,32 +9,32 @@ import (
 	"olowe.co/dns"
 )
 
+func shouldReject(m *dnsmessage.Message) (bool, dnsmessage.RCode) {
+	if !m.Header.RecursionDesired {
+		return true, dnsmessage.RCodeRefused
+	} else if m.Header.OpCode != dns.OpCodeQUERY {
+		return true, dnsmessage.RCodeRefused
+	} else if len(m.Questions) != 1 {
+		return true, dnsmessage.RCodeFormatError
+	} else if m.Questions[0].Type == dnsmessage.TypeALL {
+		return true, dnsmessage.RCodeNotImplemented
+	}
+	return false, dnsmessage.RCodeSuccess
+}
+
 func handler(w dns.ResponseWriter, qmsg *dnsmessage.Message) {
 	var rmsg dnsmessage.Message
 	rmsg.Header.ID = qmsg.Header.ID
 	rmsg.Header.Response = true
 	rmsg.Questions = qmsg.Questions
 
-	if !qmsg.Header.RecursionDesired {
-		rmsg.Header.RCode = dnsmessage.RCodeRefused
+	if reject, rc := shouldReject(qmsg); reject {
+		rmsg.Header.RCode = rc
 		w.WriteMsg(rmsg)
 		return
 	}
-	// Reject multiple questions; not even BIND supports it.
-	if len(qmsg.Questions) > 1 {
-		rmsg.Header.RCode = dnsmessage.RCodeFormatError
-		w.WriteMsg(rmsg)
-		return
-	}
 
 	q := qmsg.Questions[0]
-	// CloudFlare rejects these queries too. See RFC 8482
-	if q.Type == dnsmessage.TypeALL {
-		rmsg.Header.RCode = dnsmessage.RCodeNotImplemented
-		w.WriteMsg(rmsg)
-		return
-	}
-
 	cache.RLock()
 	if answers, ok := cache.m[q]; ok {
 		rmsg.Answers = answers
blob - dd7b5f2f459e6e76827e5b097efb0938d67b0156
blob + dc38d3fcf077993bf8f3c91ae6db467d16f841ac
--- dns.go
+++ dns.go
@@ -82,6 +82,8 @@ import (
 const MediaType string = "application/dns-message"
 const MaxMsgSize int = 65535 // max size of a message in bytes
 
+const OpCodeQUERY dnsmessage.OpCode = 0
+
 var errMismatchedID = errors.New("mismatched message id")
 
 var randomsrc *rand.Rand = rand.New(rand.NewSource(time.Now().UnixNano()))