• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

joohoi / acme-dns / 21650705446

03 Feb 2026 10:42PM UTC coverage: 77.593% (+4.3%) from 73.276%
21650705446

Pull #325

github

web-flow
Merge b7d9f4476 into b7a0a8a7b
Pull Request #325: Refactoring

578 of 754 new or added lines in 20 files covered. (76.66%)

3 existing lines in 1 file now uncovered.

793 of 1022 relevant lines covered (77.59%)

14.46 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

99.2
/pkg/nameserver/handler.go
1
package nameserver
2

3
import (
4
        "fmt"
5
        "strings"
6

7
        "github.com/miekg/dns"
8
)
9

10
func (n *Nameserver) handleRequest(w dns.ResponseWriter, r *dns.Msg) {
20✔
11
        m := new(dns.Msg)
20✔
12
        m.SetReply(r)
20✔
13
        // handle edns0
20✔
14
        opt := r.IsEdns0()
20✔
15
        if opt != nil {
24✔
16
                if opt.Version() != 0 {
6✔
17
                        // Only EDNS0 is standardized
2✔
18
                        m.Rcode = dns.RcodeBadVers
2✔
19
                        m.SetEdns0(512, false)
2✔
20
                } else {
4✔
21
                        // We can safely do this as we know that we're not setting other OPT RRs within acme-dns.
2✔
22
                        m.SetEdns0(512, false)
2✔
23
                        if r.Opcode == dns.OpcodeQuery {
4✔
24
                                n.readQuery(m)
2✔
25
                        }
2✔
26
                }
27
        } else {
16✔
28
                if r.Opcode == dns.OpcodeQuery {
32✔
29
                        n.readQuery(m)
16✔
30
                }
16✔
31
        }
32
        _ = w.WriteMsg(m)
20✔
33
}
34

35
func (n *Nameserver) readQuery(m *dns.Msg) {
18✔
36
        var authoritative = false
18✔
37
        for _, que := range m.Question {
36✔
38
                if rr, rc, auth, err := n.answer(que); err == nil {
36✔
39
                        if auth {
32✔
40
                                authoritative = auth
14✔
41
                        }
14✔
42
                        m.Rcode = rc
18✔
43
                        m.Answer = append(m.Answer, rr...)
18✔
44
                }
45
        }
46
        m.Authoritative = authoritative
18✔
47
        if authoritative {
32✔
48
                if m.Rcode == dns.RcodeNameError {
18✔
49
                        m.Ns = append(m.Ns, n.SOA)
4✔
50
                }
4✔
51
        }
52
}
53

54
func (n *Nameserver) answer(q dns.Question) ([]dns.RR, int, bool, error) {
26✔
55
        var rcode int
26✔
56
        var err error
26✔
57
        var txtRRs []dns.RR
26✔
58
        loweredName := strings.ToLower(q.Name)
26✔
59
        var authoritative = n.isAuthoritative(loweredName)
26✔
60
        if !n.isOwnChallenge(loweredName) && !n.answeringForDomain(loweredName) {
42✔
61
                rcode = dns.RcodeNameError
16✔
62
        }
16✔
63
        r, _ := n.getRecord(loweredName, q.Qtype)
26✔
64
        if q.Qtype == dns.TypeTXT {
32✔
65
                if n.isOwnChallenge(loweredName) {
6✔
NEW
66
                        txtRRs, err = n.answerOwnChallenge(q)
×
67
                } else {
6✔
68
                        txtRRs, err = n.answerTXT(q)
6✔
69
                }
6✔
70
                if err == nil {
12✔
71
                        r = append(r, txtRRs...)
6✔
72
                }
6✔
73
        }
74
        if len(r) > 0 {
38✔
75
                // Make sure that we return NOERROR if there were dynamic records for the domain
12✔
76
                rcode = dns.RcodeSuccess
12✔
77
        }
12✔
78
        n.Logger.Debugw("Answering question for domain",
26✔
79
                "qtype", dns.TypeToString[q.Qtype],
26✔
80
                "domain", q.Name,
26✔
81
                "rcode", dns.RcodeToString[rcode])
26✔
82
        return r, rcode, authoritative, nil
26✔
83
}
84

85
func (n *Nameserver) answerTXT(q dns.Question) ([]dns.RR, error) {
10✔
86
        var ra []dns.RR
10✔
87
        subdomain := sanitizeDomainQuestion(q.Name)
10✔
88
        atxt, err := n.DB.GetTXTForDomain(subdomain)
10✔
89
        if err != nil {
14✔
90
                n.Logger.Errorw("Error while trying to get record",
4✔
91
                        "error", err.Error())
4✔
92
                return ra, err
4✔
93
        }
4✔
94
        for _, v := range atxt {
14✔
95
                if len(v) > 0 {
12✔
96
                        r := new(dns.TXT)
4✔
97
                        r.Hdr = dns.RR_Header{Name: q.Name, Rrtype: dns.TypeTXT, Class: dns.ClassINET, Ttl: 1}
4✔
98
                        r.Txt = append(r.Txt, v)
4✔
99
                        ra = append(ra, r)
4✔
100
                }
4✔
101
        }
102
        return ra, nil
6✔
103
}
104

105
func (n *Nameserver) isAuthoritative(name string) bool {
34✔
106
        if n.answeringForDomain(name) {
48✔
107
                return true
14✔
108
        }
14✔
109
        off := 0
20✔
110
        for {
52✔
111
                i, next := dns.NextLabel(name, off)
32✔
112
                if next {
40✔
113
                        return false
8✔
114
                }
8✔
115
                off = i
24✔
116
                if n.answeringForDomain(name[off:]) {
36✔
117
                        return true
12✔
118
                }
12✔
119
        }
120
}
121

122
func (n *Nameserver) isOwnChallenge(name string) bool {
40✔
123
        if strings.HasPrefix(name, "_acme-challenge.") {
44✔
124
                domain := name[16:]
4✔
125
                if domain == n.OwnDomain {
6✔
126
                        return true
2✔
127
                }
2✔
128
        }
129
        return false
38✔
130
}
131

132
// answeringForDomain checks if we have any records for a domain
133
func (n *Nameserver) answeringForDomain(name string) bool {
84✔
134
        if n.OwnDomain == name {
114✔
135
                return true
30✔
136
        }
30✔
137
        _, ok := n.Domains[name]
54✔
138
        return ok
54✔
139
}
140

141
func (n *Nameserver) getRecord(name string, qtype uint16) ([]dns.RR, error) {
26✔
142
        var rr []dns.RR
26✔
143
        var cnames []dns.RR
26✔
144
        domain, ok := n.Domains[name]
26✔
145
        if !ok {
42✔
146
                return rr, fmt.Errorf("no records for domain %s", name)
16✔
147
        }
16✔
148
        for _, ri := range domain.Records {
28✔
149
                if ri.Header().Rrtype == qtype {
26✔
150
                        rr = append(rr, ri)
8✔
151
                }
8✔
152
                if ri.Header().Rrtype == dns.TypeCNAME {
20✔
153
                        cnames = append(cnames, ri)
2✔
154
                }
2✔
155
        }
156
        if len(rr) == 0 {
12✔
157
                return cnames, nil
2✔
158
        }
2✔
159
        return rr, nil
8✔
160
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc