dns-remap: rewrite dns answer handling

This commit is contained in:
Konstantin Demin 2024-06-04 10:58:37 +03:00
parent 856dca3154
commit 7a8867433f
Signed by: krd
GPG Key ID: 4D56F87A8BA65FD0

View File

@ -18,117 +18,114 @@ type DnsAnswer struct {
} }
func dnsRemap(qname string, qtype uint16, orig *dns.Msg) ([]PowerDnsAnswer, error) { func dnsRemap(qname string, qtype uint16, orig *dns.Msg) ([]PowerDnsAnswer, error) {
result := make([]PowerDnsAnswer, 0)
interim := make([]DnsAnswer, 0, len(orig.Answer)) interim := make([]DnsAnswer, 0, len(orig.Answer))
real_qnames := make([]string, 0)
for _, rr := range orig.Answer { needle := qname
if rr.Header().Name != qname { name_seen := map[string]bool{
needle: true,
}
cname_dive := true
for {
if !cname_dive {
break
}
cname_dive = false
for _, rr := range orig.Answer {
if rr.Header().Name != needle {
continue
}
if rr.Header().Rrtype != dns.TypeCNAME {
continue
}
cname_dive = true
cname := rr.(*dns.CNAME)
_, seen := name_seen[cname.Target]
if seen {
// CNAME loop?
return []PowerDnsAnswer{}, nil
}
needle = cname.Target
name_seen[needle] = true
break
}
if cname_dive {
continue continue
} }
r := DnsAnswer{ for _, rr := range orig.Answer {
Qname: qname, if rr.Header().Name != needle {
Qtype: rr.Header().Rrtype, continue
Ttl: rr.Header().Ttl, }
}
switch r.Qtype { t := rr.Header().Rrtype
case dns.TypeA: switch t {
r.Addr = rr.(*dns.A).A case dns.TypeA, dns.TypeAAAA:
r.AddrLen = net.IPv4len // continue below
default:
continue
}
r := DnsAnswer{
Qname: qname,
Qtype: t,
Ttl: rr.Header().Ttl,
}
switch r.Qtype {
case dns.TypeA:
r.Addr = rr.(*dns.A).A
r.AddrLen = net.IPv4len
case dns.TypeAAAA:
r.Addr = rr.(*dns.AAAA).AAAA
r.AddrLen = net.IPv6len
}
interim = append(interim, r) interim = append(interim, r)
case dns.TypeAAAA:
r.Addr = rr.(*dns.AAAA).AAAA
r.AddrLen = net.IPv6len
interim = append(interim, r)
case dns.TypeCNAME:
cname := rr.(*dns.CNAME)
real_qnames = append(real_qnames, cname.Target)
} }
} }
var wg sync.WaitGroup // fix missing A/AAAA records
var mtx_interim sync.Mutex if (len(interim) == 0) && ((needle != qname) || (qtype == dns.TypeANY)) {
// reprocess answers due to CNAME var wg sync.WaitGroup
for _, real_qname := range real_qnames { var a, aaaa []PowerDnsAnswer
wg.Add(1)
go func(real_name string) {
defer wg.Done()
found_qname := false if qtype != dns.TypeAAAA {
for _, rr := range orig.Answer { wg.Add(1)
if rr.Header().Name != real_name { go func() {
continue defer wg.Done()
x, _ := dnsApi_lookup_int(needle, dns.TypeA)
if x != nil {
a = x.([]PowerDnsAnswer)
} }
found_qname = true }()
}
r := DnsAnswer{ if qtype != dns.TypeA {
Qname: qname, wg.Add(1)
Qtype: rr.Header().Rrtype, go func() {
Ttl: rr.Header().Ttl, defer wg.Done()
x, _ := dnsApi_lookup_int(needle, dns.TypeAAAA)
if x != nil {
aaaa = x.([]PowerDnsAnswer)
} }
switch r.Qtype { }()
case dns.TypeA: }
r.Addr = rr.(*dns.A).A
r.AddrLen = net.IPv4len
mtx_interim.Lock() wg.Wait()
interim = append(interim, r)
mtx_interim.Unlock()
case dns.TypeAAAA:
r.Addr = rr.(*dns.AAAA).AAAA
r.AddrLen = net.IPv6len
mtx_interim.Lock() if a != nil {
interim = append(interim, r) result = append(result, a...)
mtx_interim.Unlock() }
} if aaaa != nil {
} result = append(result, aaaa...)
if found_qname { }
return
}
resp, err := dnsCustomResolve(real_name, dns.TypeANY) // HACK: replace qname
if err != nil { for i := range result {
return result[i].Qname = qname
} }
if resp == nil {
return
}
for _, rr := range resp.Answer {
if rr.Header().Name != real_name {
continue
}
r := DnsAnswer{
Qname: qname,
Qtype: rr.Header().Rrtype,
Ttl: rr.Header().Ttl,
}
switch r.Qtype {
case dns.TypeA:
r.Addr = rr.(*dns.A).A
r.AddrLen = net.IPv4len
mtx_interim.Lock()
interim = append(interim, r)
mtx_interim.Unlock()
case dns.TypeAAAA:
r.Addr = rr.(*dns.AAAA).AAAA
r.AddrLen = net.IPv6len
mtx_interim.Lock()
interim = append(interim, r)
mtx_interim.Unlock()
}
}
}(real_qname)
}
wg.Wait()
result := make([]PowerDnsAnswer, 0, len(interim))
// nothing to do
if len(interim) == 0 {
return result, nil return result, nil
} }
@ -139,7 +136,6 @@ func dnsRemap(qname string, qtype uint16, orig *dns.Msg) ([]PowerDnsAnswer, erro
for _, r := range interim { for _, r := range interim {
switch r.AddrLen { switch r.AddrLen {
case net.IPv4len, net.IPv6len: case net.IPv4len, net.IPv6len:
break
default: default:
continue continue
} }