Skip to content

Commit 47e8d30

Browse files
committed
dnsx/alg: preserve domains, ips mapping for 24h
1 parent fcab3ef commit 47e8d30

1 file changed

Lines changed: 110 additions & 16 deletions

File tree

intra/dnsx/alg.go

Lines changed: 110 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@ const (
4747
notransport = "NoTransport"
4848

4949
maxiter = 100 // max number alg/nat evict iterations
50+
51+
// stale threshold for retaining expired ips from merge
52+
staleXipsThres = 24 * time.Hour
53+
// stale threshold for retaining expired domains from merge
54+
staleDomainThres = 24 * time.Hour
5055
)
5156

5257
type iptype int
@@ -134,7 +139,7 @@ func (a expaddr) sizes() (alive, tot int) {
134139
if a.ips == nil {
135140
return
136141
}
137-
return len(a.get(xalive)), len(a.ips)
142+
return len(a.alive()), len(a.ips)
138143
}
139144

140145
func (a expaddr) all() []netip.Addr {
@@ -194,12 +199,14 @@ func expaddrDobSorter(a, b expaddr) int {
194199
}
195200

196201
type xips struct {
197-
// protects pri, aux
202+
// protects pri, aux, past
198203
pmu sync.RWMutex
199204
// resolved expaddr(v6 or v4) by tid; may be nil
200205
pri map[string]expaddr
201206
// resolved expaddr(v6 or v4) by secondary tid for a uid; may be nil
202207
aux map[string]expaddr
208+
// recently expired ips within staleXipsThres captured from merge; tid+uid -> expaddr
209+
past map[string]expaddr
203210
}
204211

205212
type xaddrstatus bool
@@ -247,8 +254,9 @@ func NewXips(tid, uid string, pri, sec []netip.Addr, ttl time.Time) *xips {
247254
}
248255

249256
x := &xips{
250-
pri: make(map[string]expaddr),
251-
aux: make(map[string]expaddr), // sec may be nil
257+
pri: make(map[string]expaddr),
258+
aux: make(map[string]expaddr), // sec may be nil
259+
past: make(map[string]expaddr),
252260
}
253261
now := time.Now()
254262
// id == "" for dnsx.NoDNS, in which case pri should be empty
@@ -281,7 +289,7 @@ func (p *xips) String() string {
281289
}
282290
p.pmu.RLock()
283291
defer p.pmu.RUnlock()
284-
return fmt.Sprintf("xips: pri(%v) sec(%v)", p.pri, p.aux)
292+
return fmt.Sprintf("xips: pri(%v) sec(%v) past(%v)", p.pri, p.aux, p.past)
285293
}
286294

287295
// secondary ips for all tids+uids
@@ -309,10 +317,17 @@ func (p *xips) allips(t xaddrtyp, s xaddrstatus) (out []netip.Addr) {
309317
}
310318
const all = 0
311319
addrs := append([]expaddr{}, vals(g, all)...)
312-
313320
for _, v := range core.Sort(addrs, expaddrDobSorter) {
314321
out = append(out, v.get(s)...)
315322
}
323+
// staleXipsThres only applies to pastips, not pri/aux entries
324+
if s == xall && t == xpri {
325+
for _, v := range core.Sort(vals(p.past, all), expaddrDobSorter) {
326+
if !v.dob.IsZero() && time.Since(v.dob) <= staleXipsThres {
327+
out = copyUniq(out, v.ips)
328+
}
329+
}
330+
}
316331
return
317332
}
318333

@@ -486,6 +501,19 @@ func (p *xips) merge(q *xips) (szprialiv, szpri, szsecaliv, szsec int) {
486501
for qk, qv := range q.pri {
487502
pv := p.pri[qk]
488503
if _, y := pv.fresh(); !y {
504+
// pv is not fresh; capture its stale ips before replacement
505+
if len(pv.ips) > 0 && !pv.dob.IsZero() && time.Since(pv.dob) <= staleXipsThres {
506+
if existing, ok := p.past[qk]; ok && time.Since(existing.dob) <= staleXipsThres {
507+
existing.ips = copyUniq(existing.ips, pv.ips)
508+
if pv.dob.Before(existing.dob) {
509+
existing.dob = pv.dob
510+
}
511+
p.past[qk] = existing
512+
} else {
513+
p.past[qk] = expaddr{ips: copyUniq(nil, pv.ips), ttl: pv.ttl, dob: pv.dob}
514+
}
515+
}
516+
489517
p.pri[qk] = qv // copy v from q into p
490518
szqaliv, szqpri := qv.sizes()
491519
szprialiv += szqaliv
@@ -502,6 +530,19 @@ func (p *xips) merge(q *xips) (szprialiv, szpri, szsecaliv, szsec int) {
502530
// pv is younger, so pv's ips should come first (youngest first ordering)
503531
ips = copyUniq(pv.alive(), qv.alive())
504532
}
533+
// capture stale (expired) ips from qv that would otherwise be lost
534+
if len(qv.ips) > 0 && !qv.dob.IsZero() && time.Since(qv.dob) <= staleXipsThres {
535+
if existing, ok := p.past[qk]; ok && time.Since(existing.dob) <= staleXipsThres {
536+
existing.ips = copyUniq(existing.ips, qv.ips)
537+
if qv.dob.Before(existing.dob) {
538+
existing.dob = qv.dob
539+
}
540+
p.past[qk] = existing
541+
} else {
542+
p.past[qk] = expaddr{ips: copyUniq(nil, qv.ips), ttl: qv.ttl, dob: qv.dob}
543+
}
544+
}
545+
505546
if !pv.fresherThan(qv) {
506547
// ips from aa & v both get assigned the latest ttl
507548
// which is strictly incorrect, but for accounting
@@ -540,7 +581,7 @@ func (p *xips) merge(q *xips) (szprialiv, szpri, szsecaliv, szsec int) {
540581
if !pv.fresherThan(qv) {
541582
ttl = qv.ttl
542583
}
543-
v := expaddr{ips, ttl, dob}
584+
v := expaddr{ips: ips, ttl: ttl, dob: dob}
544585
p.aux[qk] = v
545586
szqaliv, szqsec := v.sizes()
546587
szsecaliv += szqaliv
@@ -619,8 +660,9 @@ func expdomainsDobSorter(a, b expdomains) int {
619660

620661
// xdomains tracks domains per tid+uid; there is no secondary (aux) store.
621662
type xdomains struct {
622-
pmu *sync.RWMutex
623-
pri map[string]expdomains // tid+uid -> domains
663+
pmu *sync.RWMutex
664+
pri map[string]expdomains // tid+uid -> domains
665+
past map[string]expdomains // recently expired domains within staleDomainThres captured from merge; tid+uid -> expdomains
624666
}
625667

626668
// NewXdomains returns a new xdomains object keyed by tid+uid.
@@ -634,8 +676,9 @@ func NewXdomains(tid, uid string, pri []string, ttl time.Time) *xdomains {
634676
}
635677

636678
x := &xdomains{
637-
pmu: new(sync.RWMutex),
638-
pri: make(map[string]expdomains),
679+
pmu: new(sync.RWMutex),
680+
pri: make(map[string]expdomains),
681+
past: make(map[string]expdomains),
639682
}
640683

641684
if len(pri) > 0 { // pri may be nil
@@ -650,7 +693,7 @@ func (p *xdomains) String() string {
650693
}
651694
p.pmu.RLock()
652695
defer p.pmu.RUnlock()
653-
return fmt.Sprintf("xdomains: pri(%v)", p.pri)
696+
return fmt.Sprintf("xdomains: pri(%v) past(%v)", p.pri, p.past)
654697
}
655698

656699
func (p *xdomains) domainsFor(tid, uid string, forIP netip.Addr, s xaddrstatus) (out []string) {
@@ -682,11 +725,36 @@ func (p *xdomains) domainsFor(tid, uid string, forIP netip.Addr, s xaddrstatus)
682725
}
683726
out = append(out, v.get(s)...)
684727
}
685-
} else if v, ok := p.pri[key]; ok {
686-
if settings.Debug {
687-
ttls = append(ttls, v.ttl)
728+
// staleDomainThres only applies to pastdomains, not pri entries
729+
if s == xall {
730+
past := make([]expdomains, 0)
731+
for k, v := range p.past {
732+
if !strings.HasSuffix(k, uid) {
733+
continue
734+
}
735+
past = append(past, v)
736+
}
737+
for _, v := range core.Sort(past, expdomainsDobSorter) {
738+
if !v.dob.IsZero() && time.Since(v.dob) <= staleDomainThres {
739+
out = copyUniq(out, v.domains)
740+
}
741+
}
742+
}
743+
} else {
744+
if v, ok := p.pri[key]; ok {
745+
if settings.Debug {
746+
ttls = append(ttls, v.ttl)
747+
}
748+
out = v.get(s)
749+
}
750+
// staleDomainThres only applies to pastdomains, not pri entries
751+
if s == xall {
752+
if v, ok := p.past[key]; ok {
753+
if !v.dob.IsZero() && time.Since(v.dob) <= staleDomainThres {
754+
out = copyUniq(out, v.domains)
755+
}
756+
}
688757
}
689-
out = v.get(s)
690758
}
691759

692760
if settings.Debug {
@@ -740,6 +808,19 @@ func (p *xdomains) merge(q *xdomains) (szprialiv, szpri int) {
740808
for qk, qv := range q.pri {
741809
pv := p.pri[qk]
742810
if _, y := pv.fresh(); !y {
811+
// pv is not fresh; capture its stale domains before replacement
812+
if len(pv.domains) > 0 && !pv.dob.IsZero() && time.Since(pv.dob) <= staleDomainThres {
813+
if existing, ok := p.past[qk]; ok && time.Since(existing.dob) <= staleDomainThres {
814+
existing.domains = copyUniq(existing.domains, pv.domains)
815+
if pv.dob.Before(existing.dob) {
816+
existing.dob = pv.dob
817+
}
818+
p.past[qk] = existing
819+
} else {
820+
p.past[qk] = expdomains{domains: copyUniq(nil, pv.domains), ttl: pv.ttl, dob: pv.dob}
821+
}
822+
}
823+
743824
p.pri[qk] = qv // copy v from q into p
744825
szqaliv, szqpri := qv.sizes()
745826
szprialiv += szqaliv
@@ -756,6 +837,19 @@ func (p *xdomains) merge(q *xdomains) (szprialiv, szpri int) {
756837
// pv is younger, so pv's domains should come first (youngest first ordering)
757838
doms = copyUniq(pv.get(xalive), qv.get(xalive))
758839
}
840+
// capture stale (expired) domains from qv that would otherwise be lost
841+
if len(qv.domains) > 0 && !qv.dob.IsZero() && time.Since(qv.dob) <= staleDomainThres {
842+
if existing, ok := p.past[qk]; ok && time.Since(existing.dob) <= staleDomainThres {
843+
existing.domains = copyUniq(existing.domains, qv.domains)
844+
if qv.dob.Before(existing.dob) {
845+
existing.dob = qv.dob
846+
}
847+
p.past[qk] = existing
848+
} else {
849+
p.past[qk] = expdomains{domains: copyUniq(nil, qv.domains), ttl: qv.ttl, dob: qv.dob}
850+
}
851+
}
852+
759853
if !pv.fresherThan(qv) {
760854
pv.ttl = qv.ttl
761855
}

0 commit comments

Comments
 (0)