forked from coredns/coredns
/
msg_to_dns.go
148 lines (122 loc) · 3.29 KB
/
msg_to_dns.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
146
147
148
package external
import (
"math"
"github.com/coredns/coredns/plugin/etcd/msg"
"github.com/coredns/coredns/request"
"github.com/miekg/dns"
)
func (e *External) a(services []msg.Service, state request.Request) (records []dns.RR) {
dup := make(map[string]struct{})
for _, s := range services {
what, ip := s.HostType()
switch what {
case dns.TypeCNAME:
// can't happen
case dns.TypeA:
if _, ok := dup[s.Host]; !ok {
dup[s.Host] = struct{}{}
rr := s.NewA(state.QName(), ip)
rr.Hdr.Ttl = e.ttl
records = append(records, rr)
}
case dns.TypeAAAA:
// nada
}
}
return records
}
func (e *External) aaaa(services []msg.Service, state request.Request) (records []dns.RR) {
dup := make(map[string]struct{})
for _, s := range services {
what, ip := s.HostType()
switch what {
case dns.TypeCNAME:
// can't happen
case dns.TypeA:
// nada
case dns.TypeAAAA:
if _, ok := dup[s.Host]; !ok {
dup[s.Host] = struct{}{}
rr := s.NewAAAA(state.QName(), ip)
rr.Hdr.Ttl = e.ttl
records = append(records, rr)
}
}
}
return records
}
func (e *External) srv(services []msg.Service, state request.Request) (records, extra []dns.RR) {
dup := make(map[item]struct{})
// Looping twice to get the right weight vs priority. This might break because we may drop duplicate SRV records latter on.
w := make(map[int]int)
for _, s := range services {
weight := 100
if s.Weight != 0 {
weight = s.Weight
}
if _, ok := w[s.Priority]; !ok {
w[s.Priority] = weight
continue
}
w[s.Priority] += weight
}
for _, s := range services {
// Don't add the entry if the port is -1 (invalid). The kubernetes plugin uses port -1 when a service/endpoint
// does not have any declared ports.
if s.Port == -1 {
continue
}
w1 := 100.0 / float64(w[s.Priority])
if s.Weight == 0 {
w1 *= 100
} else {
w1 *= float64(s.Weight)
}
weight := uint16(math.Floor(w1))
what, ip := s.HostType()
switch what {
case dns.TypeCNAME:
// can't happen
case dns.TypeA, dns.TypeAAAA:
addr := s.Host
s.Host = msg.Domain(s.Key)
srv := s.NewSRV(state.QName(), weight)
if ok := isDuplicate(dup, srv.Target, "", srv.Port); !ok {
records = append(records, srv)
}
if ok := isDuplicate(dup, srv.Target, addr, 0); !ok {
hdr := dns.RR_Header{Name: srv.Target, Rrtype: what, Class: dns.ClassINET, Ttl: e.ttl}
switch what {
case dns.TypeA:
extra = append(extra, &dns.A{Hdr: hdr, A: ip})
case dns.TypeAAAA:
extra = append(extra, &dns.AAAA{Hdr: hdr, AAAA: ip})
}
}
}
}
return records, extra
}
// not sure if this is even needed.
// item holds records.
type item struct {
name string // name of the record (either owner or something else unique).
port uint16 // port of the record (used for address records, A and AAAA).
addr string // address of the record (A and AAAA).
}
// isDuplicate uses m to see if the combo (name, addr, port) already exists. If it does
// not exist already IsDuplicate will also add the record to the map.
func isDuplicate(m map[item]struct{}, name, addr string, port uint16) bool {
if addr != "" {
_, ok := m[item{name, 0, addr}]
if !ok {
m[item{name, 0, addr}] = struct{}{}
}
return ok
}
_, ok := m[item{name, port, ""}]
if !ok {
m[item{name, port, ""}] = struct{}{}
}
return ok
}