Skip to content

Commit c22183c

Browse files
committed
Pull request 2638: AGDNS-3945-imp-querylog
Squashed commit of the following: commit 9ca94b0 Merge: 5516a95 44dfffc Author: Ainar Garipov <a.garipov@adguard.com> Date: Fri Apr 24 15:44:56 2026 +0300 Merge branch 'master' into AGDNS-3945-imp-querylog commit 5516a95 Author: Ainar Garipov <a.garipov@adguard.com> Date: Thu Apr 23 17:10:12 2026 +0300 all: imp doc, names commit 6e8ab13 Author: Ainar Garipov <a.garipov@adguard.com> Date: Wed Apr 22 21:51:04 2026 +0300 all: imp go.mod, names, errors commit 20f5e33 Author: Ainar Garipov <a.garipov@adguard.com> Date: Wed Apr 22 21:02:13 2026 +0300 all: modernize code; imp querylog
1 parent 44dfffc commit c22183c

15 files changed

Lines changed: 412 additions & 294 deletions

File tree

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ require (
3636
// TODO(e.burkov): Update to a stable tag.
3737
go.yaml.in/yaml/v4 v4.0.0-rc.4.0.20260405193028-802e24f4fbcc
3838
golang.org/x/crypto v0.50.0
39-
golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f
4039
golang.org/x/net v0.53.0
4140
golang.org/x/sys v0.43.0
4241
gopkg.in/natefinch/lumberjack.v2 v2.2.1
@@ -91,6 +90,7 @@ require (
9190
go.opentelemetry.io/otel/metric v1.43.0 // indirect
9291
go.opentelemetry.io/otel/trace v1.43.0 // indirect
9392
go.yaml.in/yaml/v3 v3.0.4 // indirect
93+
golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f // indirect
9494
golang.org/x/exp/typeparams v0.0.0-20260410095643-746e56fc9e2f // indirect
9595
golang.org/x/mod v0.35.0 // indirect
9696
golang.org/x/sync v0.20.0 // indirect

internal/aghalg/aghalg.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,9 @@
44
package aghalg
55

66
import (
7+
"cmp"
78
"fmt"
89
"slices"
9-
10-
"golang.org/x/exp/constraints"
1110
)
1211

1312
// CoalesceSlice returns the first non-zero value. It is named after function
@@ -26,7 +25,7 @@ func CoalesceSlice[E any, S []E](values ...S) (res S) {
2625
//
2726
// TODO(a.garipov): The Ordered constraint is only really necessary in Validate.
2827
// Consider ways of making this constraint comparable instead.
29-
type UniqChecker[T constraints.Ordered] map[T]int64
28+
type UniqChecker[T cmp.Ordered] map[T]int64
3029

3130
// Add adds a value to the validator. v must not be nil.
3231
func (uc UniqChecker[T]) Add(elems ...T) {

internal/aghnet/net.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"net"
1212
"net/netip"
1313
"net/url"
14+
"slices"
1415
"strings"
1516
"syscall"
1617

@@ -255,10 +256,8 @@ func InterfaceByIP(ip netip.Addr) (ifaceName string) {
255256
}
256257

257258
for _, iface := range ifaces {
258-
for _, addr := range iface.Addresses {
259-
if ip == addr {
260-
return iface.Name
261-
}
259+
if slices.Contains(iface.Addresses, ip) {
260+
return iface.Name
262261
}
263262
}
264263

internal/configmigrate/v10.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,8 @@ func addQUICPort(ups string, port int) (withPort string) {
8989

9090
var doms string
9191
withPort = ups
92-
if strings.HasPrefix(ups, "[/") {
93-
domsAndUps := strings.Split(strings.TrimPrefix(ups, "[/"), "/]")
92+
if after, ok := strings.CutPrefix(ups, "[/"); ok {
93+
domsAndUps := strings.Split(after, "/]")
9494
if len(domsAndUps) != 2 {
9595
return ups
9696
}

internal/dnsforward/filter.go

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -42,18 +42,32 @@ func (s *Server) filterDNSRequest(
4242

4343
// TODO(a.garipov): Make CheckHost return a pointer.
4444
res = &resVal
45-
switch {
46-
case isRewrittenCNAME(res):
45+
46+
checkReason := true
47+
if isRewrittenCNAME(res) {
4748
// Resolve the new canonical name, not the original host name. The
4849
// original question is readded in processFilteringAfterResponse.
4950
dctx.origQuestion = q
5051
req.Question[0].Name = dns.Fqdn(res.CanonName)
51-
case res.IsFiltered:
52+
checkReason = false
53+
} else if res.IsFiltered {
5254
l.DebugContext(ctx, "host is filtered", "reason", res.Reason)
5355
pctx.Res = s.genDNSFilterMessage(ctx, l, pctx, res)
54-
case res.Reason.In(filtering.Rewritten, filtering.FilteredSafeSearch):
56+
checkReason = false
57+
}
58+
59+
if !checkReason {
60+
return res, err
61+
}
62+
63+
switch res.Reason {
64+
case
65+
filtering.FilteredSafeSearch,
66+
filtering.Rewritten:
5567
pctx.Res = s.getCNAMEWithIPs(ctx, req, res.IPList, res.CanonName)
56-
case res.Reason.In(filtering.RewrittenRule, filtering.RewrittenAutoHosts):
68+
case
69+
filtering.RewrittenAutoHosts,
70+
filtering.RewrittenRule:
5771
if err = s.filterDNSRewrite(ctx, req, res, pctx); err != nil {
5872
return nil, err
5973
}
@@ -65,12 +79,15 @@ func (s *Server) filterDNSRequest(
6579
// isRewrittenCNAME returns true if the request considered to be rewritten with
6680
// CNAME and has no resolved IPs.
6781
func isRewrittenCNAME(res *filtering.Result) (ok bool) {
68-
return res.Reason.In(
82+
switch res.Reason {
83+
case
84+
filtering.FilteredSafeSearch,
6985
filtering.Rewritten,
70-
filtering.RewrittenRule,
71-
filtering.FilteredSafeSearch) &&
72-
res.CanonName != "" &&
73-
len(res.IPList) == 0
86+
filtering.RewrittenRule:
87+
return res.CanonName != "" && len(res.IPList) == 0
88+
default:
89+
return false
90+
}
7491
}
7592

7693
// checkHostRules checks the host against filters. It is safe for concurrent
@@ -161,9 +178,12 @@ func removeIPv6Hints(rr *dns.HTTPS) {
161178
}
162179

163180
// filterHTTPSRecords filters HTTPS answers information through all rule list
164-
// filters of the server filters. Removes IPv6 hints if IPv6 resolving is
165-
// disabled.
166-
func (s *Server) filterHTTPSRecords(rr *dns.HTTPS, setts *filtering.Settings) (r *filtering.Result, err error) {
181+
// filters of the server filters. It removes IPv6 hints if IPv6 resolving is
182+
// disabled. All arguments must not be nil.
183+
func (s *Server) filterHTTPSRecords(
184+
rr *dns.HTTPS,
185+
setts *filtering.Settings,
186+
) (r *filtering.Result, err error) {
167187
if s.conf.AAAADisabled {
168188
removeIPv6Hints(rr)
169189
}

internal/filtering/reason.go

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
package filtering
2+
3+
import "fmt"
4+
5+
// Reason holds an enum detailing why it was filtered, allowed, or rewritten.
6+
type Reason uint8
7+
8+
const (
9+
// NotFilteredNotFound: the host was not find in any checks, default value
10+
// for results.
11+
NotFilteredNotFound Reason = iota
12+
13+
// NotFilteredAllowList: the host is explicitly allowed.
14+
NotFilteredAllowList
15+
16+
// NotFilteredError is returned when there was an error during checking.
17+
// Reserved, currently unused.
18+
NotFilteredError
19+
20+
// FilteredBlockList: the host was matched to be advertising host.
21+
FilteredBlockList
22+
23+
// FilteredSafeBrowsing: the host was matched to be malicious/phishing.
24+
FilteredSafeBrowsing
25+
26+
// FilteredParental: the host was matched to be outside of parental control
27+
// settings.
28+
FilteredParental
29+
30+
// FilteredInvalid: the request was invalid and was not processed.
31+
FilteredInvalid
32+
33+
// FilteredSafeSearch: the host was replaced with safesearch variant.
34+
FilteredSafeSearch
35+
36+
// FilteredBlockedService: the host is blocked by the blocked services
37+
// feature.
38+
FilteredBlockedService
39+
40+
// Rewritten is returned when there was a rewrite by a legacy DNS rewrite
41+
// rule.
42+
Rewritten
43+
44+
// RewrittenAutoHosts is returned when there was a rewrite by /etc/hosts.
45+
RewrittenAutoHosts
46+
47+
// RewrittenRule is returned when a $dnsrewrite filter rule was applied.
48+
//
49+
// TODO(a.garipov): Remove [Rewritten] and [RewrittenAutoHosts] by merging
50+
// their functionality into RewrittenRule.
51+
//
52+
// See https://github.com/AdguardTeam/AdGuardHome/issues/2499.
53+
RewrittenRule
54+
)
55+
56+
// TODO(a.garipov): Resync with actual code names or replace completely in the
57+
// next version of HTTP API.
58+
var reasonNames = []string{
59+
NotFilteredNotFound: "NotFilteredNotFound",
60+
NotFilteredAllowList: "NotFilteredWhiteList",
61+
NotFilteredError: "NotFilteredError",
62+
63+
FilteredBlockList: "FilteredBlackList",
64+
FilteredSafeBrowsing: "FilteredSafeBrowsing",
65+
FilteredParental: "FilteredParental",
66+
FilteredInvalid: "FilteredInvalid",
67+
FilteredSafeSearch: "FilteredSafeSearch",
68+
FilteredBlockedService: "FilteredBlockedService",
69+
70+
Rewritten: "Rewrite",
71+
RewrittenAutoHosts: "RewriteEtcHosts",
72+
RewrittenRule: "RewriteRule",
73+
}
74+
75+
// type check
76+
var _ fmt.Stringer = NotFilteredNotFound
77+
78+
// String implements the [fmt.Stringer] interface for Reason.
79+
func (r Reason) String() (s string) {
80+
if int(r) >= len(reasonNames) {
81+
return ""
82+
}
83+
84+
return reasonNames[r]
85+
}

internal/filtering/result.go

Lines changed: 0 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
package filtering
22

33
import (
4-
"fmt"
54
"net/netip"
6-
"slices"
75

86
"github.com/AdguardTeam/AdGuardHome/internal/filtering/rulelist"
97
"github.com/AdguardTeam/urlfilter/rules"
@@ -65,88 +63,3 @@ func NewResultRule(r rules.Rule) (rr *ResultRule) {
6563
Text: r.Text(),
6664
}
6765
}
68-
69-
// Reason holds an enum detailing why it was filtered or not filtered
70-
type Reason int
71-
72-
const (
73-
// NotFilteredNotFound: the host was not find in any checks, default value
74-
// for results.
75-
NotFilteredNotFound Reason = iota
76-
77-
// NotFilteredAllowList: the host is explicitly allowed.
78-
NotFilteredAllowList
79-
80-
// NotFilteredError is returned when there was an error during checking.
81-
// Reserved, currently unused.
82-
NotFilteredError
83-
84-
// FilteredBlockList: the host was matched to be advertising host.
85-
FilteredBlockList
86-
87-
// FilteredSafeBrowsing: the host was matched to be malicious/phishing.
88-
FilteredSafeBrowsing
89-
90-
// FilteredParental: the host was matched to be outside of parental control
91-
// settings.
92-
FilteredParental
93-
94-
// FilteredInvalid: the request was invalid and was not processed.
95-
FilteredInvalid
96-
97-
// FilteredSafeSearch: the host was replaced with safesearch variant.
98-
FilteredSafeSearch
99-
100-
// FilteredBlockedService: the host is blocked by the blocked services
101-
// feature.
102-
FilteredBlockedService
103-
104-
// Rewritten is returned when there was a rewrite by a legacy DNS rewrite
105-
// rule.
106-
Rewritten
107-
108-
// RewrittenAutoHosts is returned when there was a rewrite by /etc/hosts.
109-
RewrittenAutoHosts
110-
111-
// RewrittenRule is returned when a $dnsrewrite filter rule was applied.
112-
//
113-
// TODO(a.garipov): Remove [Rewritten] and [RewrittenAutoHosts] by merging
114-
// their functionality into RewrittenRule.
115-
//
116-
// See https://github.com/AdguardTeam/AdGuardHome/issues/2499.
117-
RewrittenRule
118-
)
119-
120-
// TODO(a.garipov): Resync with actual code names or replace completely in HTTP
121-
// API v1.
122-
var reasonNames = []string{
123-
NotFilteredNotFound: "NotFilteredNotFound",
124-
NotFilteredAllowList: "NotFilteredWhiteList",
125-
NotFilteredError: "NotFilteredError",
126-
127-
FilteredBlockList: "FilteredBlackList",
128-
FilteredSafeBrowsing: "FilteredSafeBrowsing",
129-
FilteredParental: "FilteredParental",
130-
FilteredInvalid: "FilteredInvalid",
131-
FilteredSafeSearch: "FilteredSafeSearch",
132-
FilteredBlockedService: "FilteredBlockedService",
133-
134-
Rewritten: "Rewrite",
135-
RewrittenAutoHosts: "RewriteEtcHosts",
136-
RewrittenRule: "RewriteRule",
137-
}
138-
139-
// type check
140-
var _ fmt.Stringer = NotFilteredNotFound
141-
142-
// String implements the [fmt.Stringer] interface for Reason.
143-
func (r Reason) String() (s string) {
144-
if r < 0 || int(r) >= len(reasonNames) {
145-
return ""
146-
}
147-
148-
return reasonNames[r]
149-
}
150-
151-
// In returns true if reasons include r.
152-
func (r Reason) In(reasons ...Reason) (ok bool) { return slices.Contains(reasons, r) }

0 commit comments

Comments
 (0)