mirror of
https://github.com/coredns/coredns.git
synced 2025-11-01 02:33:14 -04:00
middleware/file: proper support for wildcard (#323)
Add support for wildcard records, while taking care of wildcard-cnames and DNSSEC. Add enough tests to check all the corner cases.
This commit is contained in:
@@ -4,7 +4,8 @@ import "github.com/miekg/dns"
|
||||
|
||||
// Elem is an element in the tree.
|
||||
type Elem struct {
|
||||
m map[uint16][]dns.RR
|
||||
m map[uint16][]dns.RR
|
||||
name string // owner name
|
||||
}
|
||||
|
||||
// newElem returns a new elem.
|
||||
@@ -14,13 +15,20 @@ func newElem(rr dns.RR) *Elem {
|
||||
return &e
|
||||
}
|
||||
|
||||
// Types returns the RRs with type qtype from e.
|
||||
func (e *Elem) Types(qtype uint16) []dns.RR {
|
||||
if rrs, ok := e.m[qtype]; ok {
|
||||
return rrs
|
||||
// Types returns the RRs with type qtype from e. If qname is given (only the
|
||||
// first one is used), the RR are copied and the owner is replaced with qname[0].
|
||||
func (e *Elem) Types(qtype uint16, qname ...string) []dns.RR {
|
||||
rrs := e.m[qtype]
|
||||
|
||||
if rrs != nil && len(qname) > 0 {
|
||||
copied := make([]dns.RR, len(rrs))
|
||||
for i := range rrs {
|
||||
copied[i] = dns.Copy(rrs[i])
|
||||
copied[i].Header().Name = qname[0]
|
||||
}
|
||||
return copied
|
||||
}
|
||||
// nodata
|
||||
return nil
|
||||
return rrs
|
||||
}
|
||||
|
||||
// All returns all RRs from e, regardless of type.
|
||||
@@ -34,12 +42,25 @@ func (e *Elem) All() []dns.RR {
|
||||
|
||||
// Name returns the name for this node.
|
||||
func (e *Elem) Name() string {
|
||||
if e.name != "" {
|
||||
return e.name
|
||||
}
|
||||
for _, rrs := range e.m {
|
||||
return rrs[0].Header().Name
|
||||
e.name = rrs[0].Header().Name
|
||||
return e.name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// Wildcard returns true if this name starts with a wildcard label (*.)
|
||||
func (e *Elem) IsWildcard() bool {
|
||||
n := e.Name()
|
||||
if len(n) < 2 {
|
||||
return false
|
||||
}
|
||||
return n[0] == '*' && n[1] == '.'
|
||||
}
|
||||
|
||||
// Insert inserts rr into e. If rr is equal to existing rrs this is a noop.
|
||||
func (e *Elem) Insert(rr dns.RR) {
|
||||
t := rr.Header().Rrtype
|
||||
|
||||
@@ -179,12 +179,22 @@ func (t *Tree) SearchGlue(qname string) (*Elem, Result) {
|
||||
}
|
||||
|
||||
// search searches the tree for qname and type. If glue is true the search *does* not
|
||||
// spot when hitting NS records, but descends in search of glue. The qtype for this
|
||||
// stop when hitting NS records, but descends in search of glue. The qtype for this
|
||||
// kind of search can only be AAAA or A.
|
||||
func (n *Node) search(qname string, qtype uint16, glue bool) (*Node, Result) {
|
||||
old := n
|
||||
|
||||
var wild *Node
|
||||
|
||||
for n != nil {
|
||||
|
||||
// Is this a wildcard that applies to us
|
||||
if n.Elem.IsWildcard() {
|
||||
if dns.IsSubDomain(n.Elem.Name()[2:], qname) {
|
||||
wild = n
|
||||
}
|
||||
}
|
||||
|
||||
switch c := Less(n.Elem, qname); {
|
||||
case c == 0:
|
||||
return n, Found
|
||||
@@ -200,6 +210,13 @@ func (n *Node) search(qname string, qtype uint16, glue bool) (*Node, Result) {
|
||||
n = n.Right
|
||||
}
|
||||
}
|
||||
|
||||
// If we have seen a wildcard "on-the-way-to-here", we should return this wildcard
|
||||
// instead. This is to be able to have a more specific RR defined *under* the wildcard.
|
||||
if wild != nil {
|
||||
return wild, Found
|
||||
}
|
||||
|
||||
if dns.CountLabel(qname) < dns.CountLabel(old.Elem.Name()) {
|
||||
return n, EmptyNonTerminal
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user