/
mysql.go
145 lines (122 loc) · 2.96 KB
/
mysql.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
package coredns_mysql
import (
"fmt"
"strings"
"time"
"github.com/miekg/dns"
)
func (handler *CoreDNSMySql) findRecord(zone string, name string, types ...string) ([]*Record, error) {
db, err := handler.db()
if err != nil {
return nil, err
}
defer db.Close()
var query string
if name != zone {
query = strings.TrimSuffix(name, "."+zone)
}
sqlQuery := fmt.Sprintf("SELECT name, zone, ttl, record_type, content FROM %s WHERE zone = ? AND name = ? AND record_type IN ('%s')",
handler.tableName,
strings.Join(types, "','"))
result, err := db.Query(sqlQuery, zone, query)
if err != nil {
return nil, err
}
var recordName string
var recordZone string
var recordType string
var ttl uint32
var content string
records := make([]*Record, 0)
for result.Next() {
err = result.Scan(&recordName, &recordZone, &ttl, &recordType, &content)
if err != nil {
return nil, err
}
records = append(records, &Record{
Name: recordName,
Zone: recordZone,
RecordType: recordType,
Ttl: ttl,
Content: content,
handler: handler,
})
}
// If no records found, check for wildcard records.
if len(records) == 0 && name != zone {
return handler.findWildcardRecords(zone, name, types...)
}
return records, nil
}
// findWildcardRecords attempts to find wildcard records
// recursively until it finds matching records.
// e.g. x.y.z -> *.y.z -> *.z -> *
func (handler *CoreDNSMySql) findWildcardRecords(zone string, name string, types ...string) ([]*Record, error) {
const (
wildcard = "*"
wildcardPrefix = wildcard + "."
)
if name == wildcard {
return nil, nil
}
name = strings.TrimPrefix(name, wildcardPrefix)
target := wildcard
i, shot := dns.NextLabel(name, 0)
if !shot {
target = wildcardPrefix + name[i:]
}
return handler.findRecord(zone, target, types...)
}
func (handler *CoreDNSMySql) loadZones() error {
db, err := handler.db()
if err != nil {
return err
}
defer db.Close()
result, err := db.Query("SELECT DISTINCT zone FROM " + handler.tableName)
if err != nil {
return err
}
var zone string
zones := make([]string, 0)
for result.Next() {
err = result.Scan(&zone)
if err != nil {
return err
}
zones = append(zones, zone)
}
handler.lastZoneUpdate = time.Now()
handler.zones = zones
return nil
}
func (handler *CoreDNSMySql) hosts(zone string, name string) ([]dns.RR, error) {
recs, err := handler.findRecord(zone, name, "A", "AAAA", "CNAME")
if err != nil {
return nil, err
}
answers := make([]dns.RR, 0)
for _, rec := range recs {
switch rec.RecordType {
case "A":
aRec, _, err := rec.AsARecord()
if err != nil {
return nil, err
}
answers = append(answers, aRec)
case "AAAA":
aRec, _, err := rec.AsAAAARecord()
if err != nil {
return nil, err
}
answers = append(answers, aRec)
case "CNAME":
aRec, _, err := rec.AsCNAMERecord()
if err != nil {
return nil, err
}
answers = append(answers, aRec)
}
}
return answers, nil
}