@@ -447,11 +447,11 @@ func (p *xips) rmv(tid string) (done bool) {
447447 }
448448 if strings .HasPrefix (k , tid ) {
449449 j ++
450- done = done || true
451450 v .ttl = time .Now () // mark as expired
452451 p .aux [k ] = v
453452 }
454453 }
454+ done = (i + j ) > 0
455455 if done {
456456 p .vaccumLocked ()
457457 }
@@ -465,7 +465,8 @@ func (p *xips) rmv(tid string) (done bool) {
465465func (p * xips ) relegateLocked (k string , v expaddr ) {
466466 if cur , ok := p .past [k ]; ok && cur .withinStaleThres () {
467467 cur .ips = copyUniq (cur .ips , v .ips )
468- if v .dob .Before (cur .dob ) {
468+ // extend lifetime: keep it younger
469+ if cur .dob .Before (v .dob ) {
469470 cur .dob = v .dob
470471 }
471472 p .past [k ] = cur
@@ -908,7 +909,7 @@ func (p *xdomains) merge(q *xdomains) (szprialiv, szpri int) {
908909 }
909910
910911 if ! pv .fresherThan (qv ) {
911- pv . ttl = qv .ttl
912+ ttl = qv .ttl
912913 }
913914 v := expdomains {domains : doms , ttl : ttl , dob : dob }
914915 p .pri [qk ] = v
@@ -961,7 +962,11 @@ func (a *algans) String() string {
961962}
962963
963964func (a * algans ) extend (by time.Duration ) {
964- a .ttl = time .Now ().Add (by )
965+ if a == nil || a .ttl .IsZero () || time .Since (a .ttl ) > 0 {
966+ a .ttl = time .Now ().Add (by )
967+ } else {
968+ a .ttl = a .ttl .Add (by )
969+ }
965970}
966971
967972func (a * algans ) after (b * algans ) bool {
@@ -1044,10 +1049,12 @@ func NewDNSGateway(pctx context.Context, fakeaddrs []netip.AddrPort, outer RdnsR
10441049 fake : fakeaddrs ,
10451050 rdns : outer ,
10461051 dns64 : dns64 ,
1047- octets : rfc6598 ,
1048- hexes : rfc8215a ,
1052+ octets : make ([] uint8 , len ( rfc6598 )) ,
1053+ hexes : make ([] uint16 , len ( rfc8215a )) ,
10491054 chash : true ,
10501055 }
1056+ copy (t .octets , rfc6598 )
1057+ copy (t .hexes , rfc8215a )
10511058
10521059 context .AfterFunc (pctx , t .stop )
10531060 log .I ("alg: setup done" )
@@ -1117,8 +1124,9 @@ func (t *dnsgateway) stop() {
11171124 clear (t .alg )
11181125 clear (t .nat )
11191126 clear (t .ptr )
1120- t .octets = rfc6598
1121- t .hexes = rfc8215a
1127+ // Copy values to avoid mutating global state
1128+ copy (t .octets , rfc6598 )
1129+ copy (t .hexes , rfc8215a )
11221130}
11231131
11241132func (t * dnsgateway ) fromInternalCache (tid , uid , fid string , q * dns.Msg , typ iptype ) (ans * dns.Msg , err error ) {
@@ -1302,7 +1310,7 @@ func (t *dnsgateway) q(t1, t2 Transport, preset []netip.Addr, origin, network, u
13021310 usepreset := len (preset ) > 0 // preset may be nil
13031311 mod := ! uidself && fromtun && t .mod .Load () // allow alg?
13041312 discarduid := ! t .split .Load () // do not split tunnel?
1305- hasblock := isAnyBlockAll (idstr (t2 ), idstr (t2 ))
1313+ hasblock := isAnyBlockAll (idstr (t1 ), idstr (t2 ))
13061314 hasfixed := isAnyFixed (idstr (t1 )) // fixed transport?
13071315 usefixed := ! usepreset && mod && hasfixed // use preset fixed realips?
13081316 skipcache := skipInternalCache (idstr (t1 ), idstr (t2 ))
@@ -1651,10 +1659,10 @@ func withDNS64Summary(ans64 *dns.Msg, s *x.DNSSummary) {
16511659}
16521660
16531661func withAlgSummary (s * x.DNSSummary , algips ... netip.Addr ) {
1654- if settings .Debug {
1655- // convert algips to ipcsv; any algips may be invalid
1656- ipcsv := Netip2Csv (algips )
1662+ // convert algips to ipcsv; any algips may be invalid
1663+ ipcsv := Netip2Csv (algips )
16571664
1665+ if settings .Debug {
16581666 if len (s .RData ) > 0 {
16591667 s .RData = s .RData + "," + ipcsv
16601668 } else {
@@ -1668,7 +1676,8 @@ func withAlgSummary(s *x.DNSSummary, algips ...netip.Addr) {
16681676 }
16691677 }
16701678 // if modified alg ips are being returned, then these are not authentic
1671- s .AD = len (algips ) > 0
1679+ // only set AD=true if we actually have valid algips
1680+ s .AD = len (ipcsv ) > 0
16721681}
16731682
16741683func (t * dnsgateway ) registerLocked (q , tid , uid , fid string , algip4 , algip6 netip.Addr , realips []netip.Addr , ttl time.Duration , targets []string , secres secans ) bool {
@@ -1690,11 +1699,12 @@ func (t *dnsgateway) registerLocked(q, tid, uid, fid string, algip4, algip6 neti
16901699 // for just-in-time re-resolution of the same domain by common.go via
16911700 // dialers.ResolverFor(uid) which may be called on new tcp / udp conn.
16921701 ttl = min (ttl8s , ttl )
1702+ algttl := min (ttl2m , ttl )
16931703
16941704 now := time .Now ()
16951705 // ttl is used for algans and xips, but the alg'fied dns answer
16961706 // has a lower ttl as defined by const algttl (currently, 8s).
1697- ansttl := now .Add (max ( ttl2m , ttl ) )
1707+ ansttl := now .Add (algttl )
16981708 xipsttl := now .Add (ttl )
16991709 // secres.ips may be empty on timeout errors, or
17001710 // or same as realips if t2 is nil; realips can be nil
@@ -1759,7 +1769,7 @@ func (t *dnsgateway) registerLocked(q, tid, uid, fid string, algip4, algip6 neti
17591769 didRegister = true
17601770 }
17611771 logeif (! didRegister )("alg: reg: algips (reg? %t / new? %t) (alg: %s+%s => real: %s) for %s@%s[%s] %s; real? %d, sec? %d; until (ans: %s / xips: %s)" ,
1762- didRegister , newEntry , algip4 , algip6 , realips , q , tid , uid , fid , len (realips ), len (secres .ips ), time .Until (ansttl ), time .Until (xipsttl ))
1772+ didRegister , newEntry , algip4 , algip6 , realips , q , tid , uid , fid , len (realips ), len (secres .ips ), time .Until (algttl ), time .Until (xipsttl ))
17631773
17641774 return didRegister
17651775}
@@ -1772,14 +1782,15 @@ func (t *dnsgateway) take4Locked(q string, idx int) (netip.Addr, bool) {
17721782 ans .extend (ttl2m )
17731783 return ip , true
17741784 } else {
1775- // shouldn't happen; if it does, rm erroneous entry
1785+ // shouldn't happen; if it does, rm erroneous entry and fall through to generate new
17761786 delete (t .alg , k )
17771787 delete (t .nat , ip )
17781788 ans .ips .each (func (ip netip.Addr ) {
17791789 if pans := t .ptr [ip ]; pans == ans .baseans {
17801790 delete (t .ptr , ip )
17811791 }
17821792 })
1793+ log .E ("alg: gen: take4: found %s but not ip4 %s; removed: %s" , k , ip , ans )
17831794 }
17841795 }
17851796
@@ -1793,7 +1804,7 @@ func (t *dnsgateway) take4Locked(q string, idx int) (netip.Addr, bool) {
17931804 return genip , genip .IsValid ()
17941805 }
17951806 }
1796- log .W ("alg: gen: no more IP4s (%v)" , q )
1807+ log .E ("alg: gen: no more IP4s (%v)" , q )
17971808 return zeroaddr , false
17981809 }
17991810
@@ -1814,8 +1825,8 @@ func (t *dnsgateway) take4Locked(q string, idx int) (netip.Addr, bool) {
18141825 if i > maxiter {
18151826 break
18161827 }
1817- if d := time .Since (ent .ttl ); d > 0 {
1818- log .I ("alg: reuse stale alg %s for %s" , kx , k )
1828+ if d := time .Since (ent .ttl ); d > 0 && ent . algip . Is4 () {
1829+ log .I ("alg: gen: take4: reuse stale alg %s for %s" , kx , k )
18191830 delete (t .alg , kx )
18201831 delete (t .nat , ent .algip )
18211832 ent .ips .each (func (ip netip.Addr ) {
@@ -1835,13 +1846,13 @@ func (t *dnsgateway) take4Locked(q string, idx int) (netip.Addr, bool) {
18351846 genip := netip .AddrFrom4 (b4 ).Unmap ()
18361847 return genip , genip .IsValid ()
18371848 } else {
1838- log .W ("alg: no more IP4s (%v)" , t .octets )
1849+ log .E ("alg: gen: take4 : no more IP4s (%v)" , t .octets )
18391850 }
18401851 return zeroaddr , false
18411852}
18421853
1843- func gen4Locked (k string , hop int ) netip.Addr {
1844- s := strconv .Itoa (hop ) + k
1854+ func gen4Locked (k string , salt int ) netip.Addr {
1855+ s := strconv .Itoa (salt ) + k
18451856 v22 := hash22 (s )
18461857 // 100.64.y.z/15 2m+ ip4s
18471858 b4 := [4 ]byte {
@@ -1871,6 +1882,7 @@ func (t *dnsgateway) take6Locked(q string, idx int) (netip.Addr, bool) {
18711882 delete (t .ptr , ip )
18721883 }
18731884 })
1885+ log .E ("alg: gen: take6: found %s but not ip6 %s; removed: %s" , k , ip , ans )
18741886 }
18751887 }
18761888
@@ -1881,7 +1893,7 @@ func (t *dnsgateway) take6Locked(q string, idx int) (netip.Addr, bool) {
18811893 return genip , genip .IsValid ()
18821894 }
18831895 }
1884- log .W ("alg: gen: no more IP6s (%v)" , q )
1896+ log .E ("alg: gen: take6 : no more IP6s (%v)" , q )
18851897 return zeroaddr , false
18861898 }
18871899
@@ -1898,6 +1910,25 @@ func (t *dnsgateway) take6Locked(q string, idx int) (netip.Addr, bool) {
18981910 t .hexes [7 ] = 1 // z
18991911 } else {
19001912 // possible that we run out of 200 trillion ips...?
1913+ // try recycling stale entries before giving up
1914+ i := 0
1915+ for kx , ent := range t .alg {
1916+ if i > maxiter {
1917+ break
1918+ }
1919+ if d := time .Since (ent .ttl ); d > 0 && ent .algip .Is6 () {
1920+ log .I ("alg: gen: take6: reuse stale alg %s for %s" , kx , k )
1921+ delete (t .alg , kx )
1922+ delete (t .nat , ent .algip )
1923+ ent .ips .each (func (ip netip.Addr ) {
1924+ if pans := t .ptr [ip ]; pans == ent .baseans {
1925+ delete (t .ptr , ip )
1926+ }
1927+ })
1928+ return ent .algip , true
1929+ }
1930+ i += 1
1931+ }
19011932 gen = false
19021933 }
19031934 if gen {
@@ -1910,7 +1941,7 @@ func (t *dnsgateway) take6Locked(q string, idx int) (netip.Addr, bool) {
19101941 genip := netip .AddrFrom16 (b16 )
19111942 return genip , genip .IsValid ()
19121943 } else {
1913- log .W ("alg: no more IP6s (%x)" , t .hexes )
1944+ log .E ("alg: gen: take6 : no more IP6s (%x)" , t .hexes )
19141945 }
19151946 return zeroaddr , false
19161947}
@@ -2346,7 +2377,7 @@ func (t *dnsgateway) rdnsblLocked(algip netip.Addr, useptr bool) (bcsv string) {
23462377 return
23472378}
23482379
2349- // xor fold fnv to 18 bits: www.isthe.com/chongo/tech/comp/fnv
2380+ // xor fold fnv to 22 bits: www.isthe.com/chongo/tech/comp/fnv
23502381func hash22 (s string ) uint32 {
23512382 h := fnv .New64a ()
23522383 _ , _ = h .Write ([]byte (s ))
0 commit comments