Skip to content
This repository was archived by the owner on Sep 2, 2025. It is now read-only.

Commit 4d85128

Browse files
authored
Merge pull request #11 from redsift/feature/expose-ttl
exposed ttl for spf cache work
2 parents 122be78 + 33daba5 commit 4d85128

14 files changed

+291
-230
lines changed

cachedump_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ func TestCacheDump(t *testing.T) {
1717
}))
1818
defer dns.HandleRemove("multiline.test.")
1919

20-
if _, err := testResolver.LookupTXT("multiline.test."); err != nil {
20+
if _, _, err := testResolver.LookupTXT("multiline.test."); err != nil {
2121
t.Error(err)
2222
}
2323

listener.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,15 @@ package spf
22

33
import (
44
"net"
5+
"time"
56
)
67

78
type Listener interface {
89
CheckHost(ip net.IP, domain, sender string)
9-
CheckHostResult(r Result, explanation string, err error)
10+
CheckHostResult(r Result, explanation string, ttl time.Duration, err error)
1011
SPFRecord(s string)
1112
Directive(unused bool, qualifier, mechanism, value, effectiveValue string)
1213
NonMatch(qualifier, mechanism, value string, result Result, err error)
13-
Match(qualifier, mechanism, value string, result Result, explanation string, err error)
14+
Match(qualifier, mechanism, value string, result Result, explanation string, ttl time.Duration, err error)
1415
MatchingIP(qualifier, mechanism, value string, fqdn string, ipn net.IPNet, host string, ip net.IP)
1516
}

parser.go

Lines changed: 30 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -138,9 +138,10 @@ func newParserWithVisited(visited *stringsStack, opts ...Option) *parser {
138138
// and error as the reason for the encountered problem.
139139
func (p *parser) checkHost(ip net.IP, domain, sender string) (r Result, expl string, spf string, err error) {
140140
var u unused
141+
var ttl time.Duration
141142
p.fireCheckHost(ip, domain, sender)
142143
defer func() {
143-
p.fireCheckHostResult(r, expl, err)
144+
p.fireCheckHostResult(r, expl, ttl, err)
144145
for _, t := range u.mechanisms {
145146
p.fireUnusedDirective(t)
146147
}
@@ -161,7 +162,8 @@ func (p *parser) checkHost(ip net.IP, domain, sender string) (r Result, expl str
161162
return Permerror, "", "", ErrLoopDetected
162163
}
163164

164-
txts, err := p.resolver.LookupTXTStrict(NormalizeFQDN(domain))
165+
var txts []string
166+
txts, ttl, err = p.resolver.LookupTXTStrict(NormalizeFQDN(domain))
165167
switch err {
166168
case nil:
167169
// continue
@@ -218,6 +220,7 @@ func (p *parser) check() (Result, string, error, unused) {
218220
matches bool
219221
token *token
220222
i int
223+
ttl time.Duration
221224
)
222225

223226
mechanisms, redirect, explanation, err := sortTokens(tokens)
@@ -234,17 +237,17 @@ func (p *parser) check() (Result, string, error, unused) {
234237
all = true
235238
matches, result, err = p.parseAll(token)
236239
case tA:
237-
matches, result, err = p.parseA(token)
240+
matches, result, ttl, err = p.parseA(token)
238241
case tIP4:
239242
matches, result, err = p.parseIP4(token)
240243
case tIP6:
241244
matches, result, err = p.parseIP6(token)
242245
case tMX:
243-
matches, result, err = p.parseMX(token)
246+
matches, result, ttl, err = p.parseMX(token)
244247
case tInclude:
245248
matches, result, err = p.parseInclude(token)
246249
case tExists:
247-
matches, result, err = p.parseExists(token)
250+
matches, result, ttl, err = p.parseExists(token)
248251
case tPTR:
249252
_, _, _ = p.parsePtr(token)
250253
default:
@@ -256,7 +259,7 @@ func (p *parser) check() (Result, string, error, unused) {
256259
if result == Fail && explanation != nil {
257260
s, err = p.handleExplanation(explanation)
258261
}
259-
p.fireMatch(token, result, s, err)
262+
p.fireMatch(token, result, s, ttl, err)
260263
return result, s, err, unused{mechanisms[i+1:], redirect}
261264
}
262265
p.fireNonMatch(token, result, err)
@@ -287,11 +290,11 @@ func (p *parser) fireCheckHost(ip net.IP, domain, sender string) {
287290
p.listener.CheckHost(ip, domain, sender)
288291
}
289292

290-
func (p *parser) fireCheckHostResult(r Result, explanation string, e error) {
293+
func (p *parser) fireCheckHostResult(r Result, explanation string, ttl time.Duration, e error) {
291294
if p.listener == nil {
292295
return
293296
}
294-
p.listener.CheckHostResult(r, explanation, e)
297+
p.listener.CheckHostResult(r, explanation, ttl, e)
295298
}
296299

297300
func (p *parser) fireSPFRecord(s string) {
@@ -329,11 +332,11 @@ func (p *parser) fireNonMatch(t *token, r Result, e error) {
329332
p.listener.NonMatch(t.qualifier.String(), t.mechanism.String(), t.value, r, e)
330333
}
331334

332-
func (p *parser) fireMatch(t *token, r Result, explanation string, e error) {
335+
func (p *parser) fireMatch(t *token, r Result, explanation string, ttl time.Duration, e error) {
333336
if p.listener == nil {
334337
return
335338
}
336-
p.listener.Match(t.qualifier.String(), t.mechanism.String(), t.value, r, explanation, e)
339+
p.listener.Match(t.qualifier.String(), t.mechanism.String(), t.value, r, explanation, ttl, e)
337340
}
338341

339342
func sortTokens(tokens []*token) (mechanisms []*token, redirect, explanation *token, err error) {
@@ -437,7 +440,7 @@ func (p *parser) parseIP6(t *token) (bool, Result, error) {
437440
return ip.Equal(p.ip), result, nil
438441
}
439442

440-
func (p *parser) parseA(t *token) (bool, Result, error) {
443+
func (p *parser) parseA(t *token) (bool, Result, time.Duration, error) {
441444
fqdn, ip4Mask, ip6Mask, err := splitDomainDualCIDR(domainSpec(t.value, p.domain))
442445
if err == nil {
443446
fqdn, err = parseMacro(p, fqdn, false)
@@ -451,12 +454,12 @@ func (p *parser) parseA(t *token) (bool, Result, error) {
451454
fqdn = NormalizeFQDN(fqdn)
452455
p.fireDirective(t, fqdn)
453456
if err != nil {
454-
return true, Permerror, SyntaxError{t, err}
457+
return true, Permerror, 0, SyntaxError{t, err}
455458
}
456459

457460
result, _ := matchingResult(t.qualifier)
458461

459-
found, err := p.resolver.MatchIP(fqdn, func(ip net.IP, host string) (bool, error) {
462+
found, ttl, err := p.resolver.MatchIP(fqdn, func(ip net.IP, host string) (bool, error) {
460463
n := net.IPNet{
461464
IP: ip,
462465
}
@@ -469,10 +472,10 @@ func (p *parser) parseA(t *token) (bool, Result, error) {
469472
p.fireMatchingIP(t, fqdn, n, host, p.ip)
470473
return n.Contains(p.ip), nil
471474
})
472-
return found, result, err
475+
return found, result, ttl, err
473476
}
474477

475-
func (p *parser) parseMX(t *token) (bool, Result, error) {
478+
func (p *parser) parseMX(t *token) (bool, Result, time.Duration, error) {
476479
fqdn, ip4Mask, ip6Mask, err := splitDomainDualCIDR(domainSpec(t.value, p.domain))
477480
if err == nil {
478481
fqdn, err = parseMacro(p, fqdn, false)
@@ -486,11 +489,11 @@ func (p *parser) parseMX(t *token) (bool, Result, error) {
486489
fqdn = NormalizeFQDN(fqdn)
487490
p.fireDirective(t, fqdn)
488491
if err != nil {
489-
return true, Permerror, SyntaxError{t, err}
492+
return true, Permerror, 0, SyntaxError{t, err}
490493
}
491494

492495
result, _ := matchingResult(t.qualifier)
493-
found, err := p.resolver.MatchMX(fqdn, func(ip net.IP, host string) (bool, error) {
496+
found, ttl, err := p.resolver.MatchMX(fqdn, func(ip net.IP, host string) (bool, error) {
494497
n := net.IPNet{
495498
IP: ip,
496499
}
@@ -504,9 +507,9 @@ func (p *parser) parseMX(t *token) (bool, Result, error) {
504507
return n.Contains(p.ip), nil
505508
})
506509
if err != nil {
507-
return true, Permerror, SyntaxError{t, err}
510+
return true, Permerror, 0, SyntaxError{t, err}
508511
}
509-
return found, result, err
512+
return found, result, ttl, err
510513
}
511514

512515
func (p *parser) parseInclude(t *token) (bool, Result, error) {
@@ -570,7 +573,7 @@ func (p *parser) parseInclude(t *token) (bool, Result, error) {
570573

571574
}
572575

573-
func (p *parser) parseExists(t *token) (bool, Result, error) {
576+
func (p *parser) parseExists(t *token) (bool, Result, time.Duration, error) {
574577
resolvedDomain, err := parseMacroToken(p, t)
575578
if err == nil {
576579
resolvedDomain, err = truncateFQDN(resolvedDomain)
@@ -581,22 +584,22 @@ func (p *parser) parseExists(t *token) (bool, Result, error) {
581584
resolvedDomain = NormalizeFQDN(resolvedDomain)
582585
p.fireDirective(t, resolvedDomain)
583586
if err != nil {
584-
return true, Permerror, SyntaxError{t, err}
587+
return true, Permerror, 0, SyntaxError{t, err}
585588
}
586589
if resolvedDomain == "" {
587-
return true, Permerror, SyntaxError{t, ErrEmptyDomain}
590+
return true, Permerror, 0, SyntaxError{t, ErrEmptyDomain}
588591
}
589592

590593
result, _ := matchingResult(t.qualifier)
591594

592-
found, err := p.resolver.Exists(resolvedDomain)
595+
found, ttl, err := p.resolver.Exists(resolvedDomain)
593596
switch err {
594597
case nil:
595-
return found, result, nil
598+
return found, result, ttl, nil
596599
case ErrDNSPermerror:
597-
return false, result, nil
600+
return false, result, 0, nil
598601
default:
599-
return false, Temperror, err // was true 8-|
602+
return false, Temperror, 0, err // was true 8-|
600603
}
601604
}
602605

@@ -659,7 +662,7 @@ func (p *parser) handleExplanation(t *token) (string, error) {
659662
return "", SyntaxError{t, newInvalidDomainError(domain)}
660663
}
661664

662-
txts, err := p.resolver.LookupTXT(NormalizeFQDN(domain))
665+
txts, _, err := p.resolver.LookupTXT(NormalizeFQDN(domain))
663666
if err != nil {
664667
return "", err
665668
}

0 commit comments

Comments
 (0)