aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--middleware/rewrite/README.md16
-rw-r--r--middleware/rewrite/class.go31
-rw-r--r--middleware/rewrite/field.go13
-rw-r--r--middleware/rewrite/name.go29
-rw-r--r--middleware/rewrite/rewrite.go65
-rw-r--r--middleware/rewrite/rewrite_test.go6
-rw-r--r--middleware/rewrite/setup.go10
-rw-r--r--middleware/rewrite/type.go30
8 files changed, 124 insertions, 76 deletions
diff --git a/middleware/rewrite/README.md b/middleware/rewrite/README.md
index 92118b955..ed5aa58e1 100644
--- a/middleware/rewrite/README.md
+++ b/middleware/rewrite/README.md
@@ -7,24 +7,26 @@ accommodate most dynamic back-end applications.
## Syntax
~~~
-rewrite FROM TO
+rewrite FIELD FROM TO
~~~
+* **FIELD** is (`type`, `class`, `name`, ...)
* **FROM** is the exact name of type to match
* **TO** is the destination name or type to rewrite to
-If from *and* to look like a DNS type (`A`, `MX`, etc.), the type of the message will be rewriten;
-e.g., to rewrite ANY queries to HINFO, use `rewrite ANY HINFO`.
+When the FIELD is `type` and FROM is (`A`, `MX`, etc.), the type of the message will be rewritten;
+e.g., to rewrite ANY queries to HINFO, use `rewrite type ANY HINFO`.
-If from *and* to look like a DNS class (`IN`, `CH`, or `HS`) the class of the message will be
-rewritten; e.g., to rewrite CH queries to IN use `rewrite CH IN`.
+When the FIELD is `class` and FROM is (`IN`, `CH`, or `HS`) the class of the message will be
+rewritten; e.g., to rewrite CH queries to IN use `rewrite class CH IN`.
-If it does not look like a type a name is assumed and the qname in the message is rewritten; this
-needs to be a full match of the name, e.g., `rewrite miek.nl example.org`.
+When the FIELD is `name` the query name in the message is rewritten; this
+needs to be a full match of the name, e.g., `rewrite name miek.nl example.org`.
If you specify multiple rules and an incoming query matches on multiple (simple) rules, only
the first rewrite is applied.
+
> Everything below this line has not been implemented, yet.
~~~
diff --git a/middleware/rewrite/class.go b/middleware/rewrite/class.go
new file mode 100644
index 000000000..78cca1a13
--- /dev/null
+++ b/middleware/rewrite/class.go
@@ -0,0 +1,31 @@
+// Package rewrite is middleware for rewriting requests internally to something different.
+package rewrite
+
+import (
+ "strings"
+
+ "github.com/miekg/dns"
+)
+
+// ClassRule is a class rewrite rule.
+type ClassRule struct {
+ fromClass, toClass uint16
+}
+
+// Initializer
+func (rule ClassRule) New(args ...string) Rule {
+ from, to := args[0], strings.Join(args[1:], " ")
+ return &ClassRule{dns.StringToClass[from], dns.StringToClass[to]}
+
+}
+
+// Rewrite rewrites the the current request.
+func (rule ClassRule) Rewrite(r *dns.Msg) Result {
+ if rule.fromClass > 0 && rule.toClass > 0 {
+ if r.Question[0].Qclass == rule.fromClass {
+ r.Question[0].Qclass = rule.toClass
+ return RewriteDone
+ }
+ }
+ return RewriteIgnored
+}
diff --git a/middleware/rewrite/field.go b/middleware/rewrite/field.go
new file mode 100644
index 000000000..5ccad0d60
--- /dev/null
+++ b/middleware/rewrite/field.go
@@ -0,0 +1,13 @@
+// Package rewrite is middleware for rewriting requests internally to something different.
+package rewrite
+
+/*
+Additional FIELD keywords may be implemented to support more rewrite use-cases.
+New Rule types must be added to the Fields map.
+The type must implement `New` and `Rewrite` functions.
+*/
+var Fields = map[string]Rule{
+ "name": NameRule{},
+ "type": TypeRule{},
+ "class": ClassRule{},
+}
diff --git a/middleware/rewrite/name.go b/middleware/rewrite/name.go
new file mode 100644
index 000000000..645e1dc04
--- /dev/null
+++ b/middleware/rewrite/name.go
@@ -0,0 +1,29 @@
+// Package rewrite is middleware for rewriting requests internally to something different.
+package rewrite
+
+import (
+ "strings"
+
+ "github.com/miekg/coredns/middleware"
+ "github.com/miekg/dns"
+)
+
+// NameRule is a name rewrite rule.
+type NameRule struct {
+ From, To string
+}
+
+// Initializer
+func (rule NameRule) New(args ...string) Rule {
+ from, to := args[0], strings.Join(args[1:], " ")
+ return &NameRule{middleware.Name(from).Normalize(), middleware.Name(to).Normalize()}
+}
+
+// Rewrite rewrites the the current request.
+func (rule NameRule) Rewrite(r *dns.Msg) Result {
+ if rule.From == r.Question[0].Name {
+ r.Question[0].Name = rule.To
+ return RewriteDone
+ }
+ return RewriteIgnored
+}
diff --git a/middleware/rewrite/rewrite.go b/middleware/rewrite/rewrite.go
index adbdbca15..cb5bbc288 100644
--- a/middleware/rewrite/rewrite.go
+++ b/middleware/rewrite/rewrite.go
@@ -2,10 +2,7 @@
package rewrite
import (
- "strings"
-
"github.com/miekg/coredns/middleware"
-
"github.com/miekg/dns"
"golang.org/x/net/context"
)
@@ -59,64 +56,6 @@ func (rw Rewrite) Name() string { return "rewrite" }
type Rule interface {
// Rewrite rewrites the internal location of the current request.
Rewrite(*dns.Msg) Result
-}
-
-// SimpleRule is a simple rewrite rule. If the From and To look like a type
-// the type of the request is rewritten, otherwise the name is.
-// Note: TSIG signed requests will be invalid.
-type SimpleRule struct {
- From, To string
- fromType, toType uint16
- fromClass, toClass uint16
-}
-
-// NewSimpleRule creates a new Simple Rule
-func NewSimpleRule(from, to string) SimpleRule {
- tpf := dns.StringToType[from]
- tpt := dns.StringToType[to]
-
- // ANY is both a type and class, ANY class rewritting is way more less frequent
- // so we default to ANY as a type.
- clf := dns.StringToClass[from]
- clt := dns.StringToClass[to]
- if from == "ANY" {
- clf = 0
- clt = 0
- }
-
- // It's only a type/class if uppercase is used.
- if from != strings.ToUpper(from) {
- tpf = 0
- clf = 0
- from = middleware.Name(from).Normalize()
- }
- if to != strings.ToUpper(to) {
- tpt = 0
- clt = 0
- to = middleware.Name(to).Normalize()
- }
- return SimpleRule{From: from, To: to, fromType: tpf, toType: tpt, fromClass: clf, toClass: clt}
-}
-
-// Rewrite rewrites the the current request.
-func (s SimpleRule) Rewrite(r *dns.Msg) Result {
- if s.fromType > 0 && s.toType > 0 {
- if r.Question[0].Qtype == s.fromType {
- r.Question[0].Qtype = s.toType
- return RewriteDone
- }
- }
-
- if s.fromClass > 0 && s.toClass > 0 {
- if r.Question[0].Qclass == s.fromClass {
- r.Question[0].Qclass = s.toClass
- return RewriteDone
- }
- }
-
- if s.From == r.Question[0].Name {
- r.Question[0].Name = s.To
- return RewriteDone
- }
- return RewriteIgnored
+ // New returns a new rule.
+ New(...string) Rule
}
diff --git a/middleware/rewrite/rewrite_test.go b/middleware/rewrite/rewrite_test.go
index 2dc658738..c9753635c 100644
--- a/middleware/rewrite/rewrite_test.go
+++ b/middleware/rewrite/rewrite_test.go
@@ -20,9 +20,9 @@ func TestRewrite(t *testing.T) {
rw := Rewrite{
Next: middleware.HandlerFunc(msgPrinter),
Rules: []Rule{
- NewSimpleRule("from.nl.", "to.nl."),
- NewSimpleRule("CH", "IN"),
- NewSimpleRule("ANY", "HINFO"),
+ Fields["name"].New("from.nl.", "to.nl."),
+ Fields["class"].New("CH", "IN"),
+ Fields["type"].New("ANY", "HINFO"),
},
noRevert: true,
}
diff --git a/middleware/rewrite/setup.go b/middleware/rewrite/setup.go
index 9405fcd6a..81fbacfb9 100644
--- a/middleware/rewrite/setup.go
+++ b/middleware/rewrite/setup.go
@@ -1,7 +1,7 @@
package rewrite
import (
- "strings"
+ "log"
"github.com/miekg/coredns/core/dnsserver"
"github.com/miekg/coredns/middleware"
@@ -108,8 +108,12 @@ func rewriteParse(c *caddy.Controller) ([]Rule, error) {
// the only unhandled case is 2 and above
default:
- rule = NewSimpleRule(args[0], strings.Join(args[1:], " "))
- simpleRules = append(simpleRules, rule)
+ if _, ok := Fields[args[0]]; ok {
+ rule = Fields[args[0]].New(args[1:]...)
+ simpleRules = append(simpleRules, rule)
+ } else {
+ log.Printf("[WARN] %s is not a valid field, ignore %s", args[0], args)
+ }
}
}
diff --git a/middleware/rewrite/type.go b/middleware/rewrite/type.go
new file mode 100644
index 000000000..1cbc882ec
--- /dev/null
+++ b/middleware/rewrite/type.go
@@ -0,0 +1,30 @@
+// Package rewrite is middleware for rewriting requests internally to something different.
+package rewrite
+
+import (
+ "strings"
+
+ "github.com/miekg/dns"
+)
+
+// TypeRule is a type rewrite rule.
+type TypeRule struct {
+ fromType, toType uint16
+}
+
+// Initializer
+func (rule TypeRule) New(args ...string) Rule {
+ from, to := args[0], strings.Join(args[1:], " ")
+ return &TypeRule{dns.StringToType[from], dns.StringToType[to]}
+}
+
+// Rewrite rewrites the the current request.
+func (rule TypeRule) Rewrite(r *dns.Msg) Result {
+ if rule.fromType > 0 && rule.toType > 0 {
+ if r.Question[0].Qtype == rule.fromType {
+ r.Question[0].Qtype = rule.toType
+ return RewriteDone
+ }
+ }
+ return RewriteIgnored
+}