mirror of
https://github.com/folbricht/routedns.git
synced 2026-02-12 03:58:55 -06:00
100 lines
2.6 KiB
Go
100 lines
2.6 KiB
Go
package rdns
|
|
|
|
import (
|
|
"github.com/miekg/dns"
|
|
)
|
|
|
|
// StaticTemplateResolver is a resolver that always returns a predefined set of records
|
|
// which can be customized with information from the question. It is similar to
|
|
// StaticResolver but allows the use of templates with placeholders as input.
|
|
type StaticTemplateResolver struct {
|
|
id string
|
|
answer []*Template
|
|
ns []*Template
|
|
extra []*Template
|
|
rcode int
|
|
truncate bool
|
|
opt StaticResolverOptions
|
|
}
|
|
|
|
var _ Resolver = &StaticTemplateResolver{}
|
|
|
|
// NewStaticTemplateResolver returns a new instance of a StaticTemplateResolver resolver.
|
|
func NewStaticTemplateResolver(id string, opt StaticResolverOptions) (*StaticTemplateResolver, error) {
|
|
r := &StaticTemplateResolver{id: id, opt: opt}
|
|
|
|
for _, record := range opt.Answer {
|
|
tpl, err := NewTemplate(record)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
r.answer = append(r.answer, tpl)
|
|
}
|
|
for _, record := range opt.NS {
|
|
tpl, err := NewTemplate(record)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
r.ns = append(r.ns, tpl)
|
|
}
|
|
for _, record := range opt.Extra {
|
|
tpl, err := NewTemplate(record)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
r.extra = append(r.extra, tpl)
|
|
}
|
|
r.rcode = opt.RCode
|
|
r.truncate = opt.Truncate
|
|
|
|
return r, nil
|
|
}
|
|
|
|
// Resolve a DNS query by incorporating data from the query into a fixed response.
|
|
func (r *StaticTemplateResolver) Resolve(q *dns.Msg, ci ClientInfo) (*dns.Msg, error) {
|
|
answer := new(dns.Msg)
|
|
answer.SetReply(q)
|
|
log := logger(r.id, q, ci)
|
|
|
|
answer.Answer = r.processRRTemplates(q, ci, r.answer...)
|
|
answer.Ns = r.processRRTemplates(q, ci, r.ns...)
|
|
answer.Extra = r.processRRTemplates(q, ci, r.extra...)
|
|
answer.Rcode = r.rcode
|
|
answer.Truncated = r.truncate
|
|
|
|
if err := r.opt.EDNS0EDETemplate.Apply(answer, q); err != nil {
|
|
log.WithError(err).Error("failed to apply edns0ede template")
|
|
}
|
|
|
|
logger(r.id, q, ci).WithField("truncated", r.truncate).Debug("responding")
|
|
|
|
return answer, nil
|
|
}
|
|
|
|
func (r *StaticTemplateResolver) String() string {
|
|
return r.id
|
|
}
|
|
|
|
func (r *StaticTemplateResolver) processRRTemplates(q *dns.Msg, ci ClientInfo, templates ...*Template) []dns.RR {
|
|
log := logger(r.id, q, ci)
|
|
|
|
resp := make([]dns.RR, 0, len(templates))
|
|
for _, tpl := range templates {
|
|
text, err := tpl.Apply(q)
|
|
if err != nil {
|
|
log.WithError(err).Error("failed to apply template")
|
|
continue
|
|
}
|
|
|
|
rr, err := dns.NewRR(text)
|
|
if err != nil {
|
|
log.WithError(err).Error("failed to parse template output")
|
|
continue
|
|
}
|
|
// Update the name of every answer record to match that of the query
|
|
// rr.Header().Name = qName(q)
|
|
resp = append(resp, rr)
|
|
}
|
|
return resp
|
|
}
|