mirror of
https://github.com/folbricht/routedns.git
synced 2025-12-17 23:54:37 -06:00
83 lines
1.9 KiB
Go
83 lines
1.9 KiB
Go
package rdns
|
|
|
|
import (
|
|
"errors"
|
|
|
|
"github.com/miekg/dns"
|
|
)
|
|
|
|
// EDNS0Modifier manipulates EDNS0 options, typically for codes in the 65001-65534 range.
|
|
type EDNS0Modifier struct {
|
|
id string
|
|
resolver Resolver
|
|
modifier EDNS0ModifierFunc
|
|
}
|
|
|
|
var _ Resolver = &EDNS0Modifier{}
|
|
|
|
// EDNS0ModifierFunc takes a DNS query and modifies its EDN0 records
|
|
type EDNS0ModifierFunc func(q *dns.Msg, ci ClientInfo)
|
|
|
|
// NewEDNS0Modifier initializes an EDNS0 modifier.
|
|
func NewEDNS0Modifier(id string, resolver Resolver, f EDNS0ModifierFunc) (*EDNS0Modifier, error) {
|
|
c := &EDNS0Modifier{id: id, resolver: resolver, modifier: f}
|
|
return c, nil
|
|
}
|
|
|
|
// Resolve modifies the OPT EDNS0 record and passes it to the next resolver.
|
|
func (r *EDNS0Modifier) Resolve(q *dns.Msg, ci ClientInfo) (*dns.Msg, error) {
|
|
if len(q.Question) < 1 {
|
|
return nil, errors.New("no question in query")
|
|
}
|
|
|
|
// Modify the query
|
|
if r.modifier != nil {
|
|
r.modifier(q, ci)
|
|
}
|
|
|
|
// Pass it on upstream
|
|
return r.resolver.Resolve(q, ci)
|
|
}
|
|
|
|
func (r *EDNS0Modifier) String() string {
|
|
return r.id
|
|
}
|
|
|
|
func EDNS0ModifierDelete(code uint16) EDNS0ModifierFunc {
|
|
return func(q *dns.Msg, ci ClientInfo) {
|
|
edns0 := q.IsEdns0()
|
|
if edns0 == nil {
|
|
return
|
|
}
|
|
// Filter out any EDNS0 option with the same code
|
|
newOpt := make([]dns.EDNS0, 0, len(edns0.Option))
|
|
for _, opt := range edns0.Option {
|
|
if opt.Option() == code {
|
|
continue
|
|
}
|
|
newOpt = append(newOpt, opt)
|
|
}
|
|
edns0.Option = newOpt
|
|
}
|
|
}
|
|
|
|
func EDNS0ModifierAdd(code uint16, data []byte) EDNS0ModifierFunc {
|
|
return func(q *dns.Msg, ci ClientInfo) {
|
|
// Drop any existing EDNS0 options with the same code
|
|
EDNS0ModifierDelete(code)(q, ci)
|
|
|
|
// Add a new record if there's no EDNS0 at all
|
|
edns0 := q.IsEdns0()
|
|
if edns0 == nil {
|
|
q.SetEdns0(4096, false)
|
|
edns0 = q.IsEdns0()
|
|
}
|
|
|
|
// Append the EDNS0 option
|
|
opt := new(dns.EDNS0_LOCAL)
|
|
opt.Code = code
|
|
opt.Data = data
|
|
edns0.Option = append(edns0.Option, opt)
|
|
}
|
|
}
|