aboutsummaryrefslogtreecommitdiff
path: root/middleware/pkg/response/typify.go
diff options
context:
space:
mode:
Diffstat (limited to 'middleware/pkg/response/typify.go')
-rw-r--r--middleware/pkg/response/typify.go96
1 files changed, 96 insertions, 0 deletions
diff --git a/middleware/pkg/response/typify.go b/middleware/pkg/response/typify.go
new file mode 100644
index 000000000..6fdd0137a
--- /dev/null
+++ b/middleware/pkg/response/typify.go
@@ -0,0 +1,96 @@
+package response
+
+import (
+ "fmt"
+
+ "github.com/miekg/dns"
+)
+
+// Type is the type of the message
+type Type int
+
+const (
+ // Success indicates a positive reply
+ NoError Type = iota
+ // NameError is a NXDOMAIN in header, SOA in auth.
+ NameError
+ // NoData indicated name found, but not the type: NOERROR in header, SOA in auth.
+ NoData
+ // Delegation is a msg with a pointer to another nameserver: NOERROR in header, NS in auth, optionally fluff in additional (not checked).
+ Delegation
+ // OtherError indicated any other error: don't cache these.
+ OtherError
+)
+
+func (t Type) String() string {
+ switch t {
+ case NoError:
+ return "NOERROR"
+ case NameError:
+ return "NXDOMAIN"
+ case NoData:
+ return "NODATA"
+ case Delegation:
+ return "DELEGATION"
+ case OtherError:
+ return "OTHERERROR"
+ }
+ return ""
+}
+
+// TypeFromString returns the type from the string s. If not type matches
+// the OtherError type and an error are returned.
+func TypeFromString(s string) (Type, error) {
+ switch s {
+ case "NOERROR":
+ return NoError, nil
+ case "NXDOMAIN":
+ return NameError, nil
+ case "NODATA":
+ return NoData, nil
+ case "DELEGATION":
+ return Delegation, nil
+ case "OTHERERROR":
+ return OtherError, nil
+ }
+ return NoError, fmt.Errorf("invalid Type: %s", s)
+}
+
+// Typify classifies a message, it returns the Type.
+func Typify(m *dns.Msg) (Type, *dns.OPT) {
+ opt := m.IsEdns0()
+
+ if len(m.Answer) > 0 && m.Rcode == dns.RcodeSuccess {
+ return NoError, opt
+ }
+
+ soa := false
+ ns := 0
+ for _, r := range m.Ns {
+ if r.Header().Rrtype == dns.TypeSOA {
+ soa = true
+ continue
+ }
+ if r.Header().Rrtype == dns.TypeNS {
+ ns++
+ }
+ }
+
+ // Check length of different sections, and drop stuff that is just to large? TODO(miek).
+ if soa && m.Rcode == dns.RcodeSuccess {
+ return NoData, opt
+ }
+ if soa && m.Rcode == dns.RcodeNameError {
+ return NameError, opt
+ }
+
+ if ns > 0 && ns == len(m.Ns) && m.Rcode == dns.RcodeSuccess {
+ return Delegation, opt
+ }
+
+ if m.Rcode == dns.RcodeSuccess {
+ return NoError, opt
+ }
+
+ return OtherError, opt
+}