-
-
Notifications
You must be signed in to change notification settings - Fork 199
/
resolver.go
151 lines (123 loc) · 3.68 KB
/
resolver.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
149
150
151
package resolver
import (
"fmt"
"net"
"strings"
"time"
"github.com/0xERR0R/blocky/log"
"github.com/0xERR0R/blocky/model"
"github.com/0xERR0R/blocky/util"
"github.com/miekg/dns"
"github.com/sirupsen/logrus"
)
// Resolver is not configured.
const (
configStatusEnabled string = "enabled"
configStatusDisabled string = "disabled"
)
var (
// note: this is not used by all resolvers: only those that don't print any other configuration
configEnabled = []string{configStatusEnabled} //nolint:gochecknoglobals
configDisabled = []string{configStatusDisabled} //nolint:gochecknoglobals
)
func newRequest(question string, rType dns.Type, logger ...*logrus.Entry) *model.Request {
var loggerEntry *logrus.Entry
if len(logger) == 1 {
loggerEntry = logger[0]
} else {
loggerEntry = logrus.NewEntry(log.Log())
}
return &model.Request{
Req: util.NewMsgWithQuestion(question, rType),
Log: loggerEntry,
Protocol: model.RequestProtocolUDP,
}
}
func newRequestWithClient(question string, rType dns.Type, ip string, clientNames ...string) *model.Request {
return &model.Request{
ClientIP: net.ParseIP(ip),
ClientNames: clientNames,
Req: util.NewMsgWithQuestion(question, rType),
Log: logrus.NewEntry(log.Log()),
RequestTS: time.Time{},
Protocol: model.RequestProtocolUDP,
}
}
// newResponseMsg creates a new dns.Msg as response for a request
func newResponseMsg(request *model.Request) *dns.Msg {
response := new(dns.Msg)
response.SetReply(request.Req)
return response
}
// returnResponseModel wrapps a dns.Msg into a model.Response
func returnResponseModel(response *dns.Msg, rtype model.ResponseType, reason string) (*model.Response, error) {
return &model.Response{
Res: response,
RType: rtype,
Reason: reason,
}, nil
}
func newRequestWithClientID(question string, rType dns.Type, ip, requestClientID string) *model.Request {
return &model.Request{
ClientIP: net.ParseIP(ip),
RequestClientID: requestClientID,
Req: util.NewMsgWithQuestion(question, rType),
Log: logrus.NewEntry(log.Log()),
RequestTS: time.Time{},
Protocol: model.RequestProtocolUDP,
}
}
// Resolver generic interface for all resolvers
type Resolver interface {
// Resolve performs resolution of a DNS request
Resolve(req *model.Request) (*model.Response, error)
// Configuration returns current resolver configuration
Configuration() []string
}
// ChainedResolver represents a resolver, which can delegate result to the next one
type ChainedResolver interface {
Resolver
// Next sets the next resolver
Next(n Resolver)
// GetNext returns the next resolver
GetNext() Resolver
}
// NextResolver is the base implementation of ChainedResolver
type NextResolver struct {
next Resolver
}
// Next sets the next resolver
func (r *NextResolver) Next(n Resolver) {
r.next = n
}
// GetNext returns the next resolver
func (r *NextResolver) GetNext() Resolver {
return r.next
}
// NamedResolver is a resolver with a special name
type NamedResolver interface {
// Name returns the full name of the resolver
Name() string
}
// Chain creates a chain of resolvers
func Chain(resolvers ...Resolver) Resolver {
for i, res := range resolvers {
if i+1 < len(resolvers) {
if cr, ok := res.(ChainedResolver); ok {
cr.Next(resolvers[i+1])
}
}
}
return resolvers[0]
}
// Name returns a user-friendly name of a resolver
func Name(resolver Resolver) string {
if named, ok := resolver.(NamedResolver); ok {
return named.Name()
}
return defaultName(resolver)
}
// defaultName returns a short user-friendly name of a resolver
func defaultName(resolver Resolver) string {
return strings.Split(fmt.Sprintf("%T", resolver), ".")[1]
}