mirror of
https://github.com/AdguardTeam/AdGuardHome.git
synced 2025-10-26 11:27:18 +00:00
Pull request 2484: AGDNS-3118-upd-urlfilter
Squashed commit of the following: commit fd449c5931b8d0bff325f1f6edabe16b965e77d8 Merge:c4a416ee5d0b89e4d3Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Fri Sep 26 15:06:54 2025 +0300 Merge branch 'master' into AGDNS-3118-upd-urlfilter commitc4a416ee59Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Wed Sep 24 17:26:29 2025 +0300 filtering: imp code, docs commita7d2af91f4Author: Ainar Garipov <A.Garipov@AdGuard.COM> Date: Wed Sep 24 13:52:56 2025 +0300 all: upd urlfilter, other deps, tools, etc.
This commit is contained in:
parent
d0b89e4d36
commit
fbc4a27007
62
go.mod
62
go.mod
@ -4,9 +4,8 @@ go 1.25.1
|
||||
|
||||
require (
|
||||
github.com/AdguardTeam/dnsproxy v0.76.1
|
||||
// TODO(s.chzhen): Use osutil/executil and fakeos/fakeexec.
|
||||
github.com/AdguardTeam/golibs v0.34.0
|
||||
github.com/AdguardTeam/urlfilter v0.21.0
|
||||
github.com/AdguardTeam/golibs v0.34.1
|
||||
github.com/AdguardTeam/urlfilter v0.22.0
|
||||
github.com/NYTimes/gziphandler v1.1.1
|
||||
github.com/ameshkov/dnscrypt/v2 v2.4.0
|
||||
github.com/bluele/gcache v0.0.2
|
||||
@ -20,34 +19,34 @@ require (
|
||||
github.com/google/gopacket v1.1.19
|
||||
github.com/google/renameio/v2 v2.0.0
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/insomniacslk/dhcp v0.0.0-20250417080101-5f8cf70e8c5f
|
||||
github.com/kardianos/service v1.2.2
|
||||
github.com/insomniacslk/dhcp v0.0.0-20250828142853-d3abe7ccb0ad
|
||||
github.com/kardianos/service v1.2.4
|
||||
github.com/mdlayher/ethernet v0.0.0-20220221185849-529eae5b6118
|
||||
github.com/mdlayher/netlink v1.7.2
|
||||
github.com/mdlayher/netlink v1.8.0
|
||||
github.com/mdlayher/packet v1.1.2
|
||||
// TODO(a.garipov): This package is deprecated; find a new one or use our
|
||||
// own code for that. Perhaps, use gopacket.
|
||||
github.com/mdlayher/raw v0.1.0
|
||||
github.com/miekg/dns v1.1.68
|
||||
github.com/quic-go/quic-go v0.53.0
|
||||
github.com/quic-go/quic-go v0.54.0
|
||||
github.com/stretchr/testify v1.11.1
|
||||
github.com/ti-mo/netfilter v0.5.3
|
||||
go.etcd.io/bbolt v1.4.1
|
||||
go.etcd.io/bbolt v1.4.3
|
||||
go.yaml.in/yaml/v4 v4.0.0-rc.2
|
||||
golang.org/x/crypto v0.41.0
|
||||
golang.org/x/exp v0.0.0-20250813145105-42675adae3e6
|
||||
golang.org/x/net v0.43.0
|
||||
golang.org/x/sys v0.35.0
|
||||
golang.org/x/crypto v0.42.0
|
||||
golang.org/x/exp v0.0.0-20250911091902-df9299821621
|
||||
golang.org/x/net v0.44.0
|
||||
golang.org/x/sys v0.36.0
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1
|
||||
howett.net/plist v1.0.1
|
||||
)
|
||||
|
||||
require (
|
||||
cloud.google.com/go v0.121.6 // indirect
|
||||
cloud.google.com/go v0.122.0 // indirect
|
||||
cloud.google.com/go/ai v0.12.1 // indirect
|
||||
cloud.google.com/go/auth v0.16.5 // indirect
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.8.0 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.8.3 // indirect
|
||||
cloud.google.com/go/longrunning v0.6.7 // indirect
|
||||
github.com/BurntSushi/toml v1.5.0 // indirect
|
||||
github.com/ameshkov/dnsstamps v1.0.3 // indirect
|
||||
@ -80,33 +79,34 @@ require (
|
||||
github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701 // indirect
|
||||
github.com/uudashr/gocognit v1.2.0 // indirect
|
||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 // indirect
|
||||
go.opentelemetry.io/otel v1.38.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.38.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.38.0 // indirect
|
||||
go.uber.org/mock v0.5.2 // indirect
|
||||
golang.org/x/exp/typeparams v0.0.0-20250819193227-8b4c13bb791b // indirect
|
||||
golang.org/x/mod v0.27.0 // indirect
|
||||
golang.org/x/oauth2 v0.30.0 // indirect
|
||||
golang.org/x/sync v0.16.0 // indirect
|
||||
golang.org/x/telemetry v0.0.0-20250829165349-50b750f55de1 // indirect
|
||||
golang.org/x/term v0.34.0 // indirect
|
||||
golang.org/x/text v0.28.0 // indirect
|
||||
golang.org/x/time v0.12.0 // indirect
|
||||
golang.org/x/tools v0.36.0 // indirect
|
||||
go.uber.org/mock v0.6.0 // indirect
|
||||
golang.org/x/exp/typeparams v0.0.0-20250911091902-df9299821621 // indirect
|
||||
golang.org/x/mod v0.28.0 // indirect
|
||||
golang.org/x/oauth2 v0.31.0 // indirect
|
||||
golang.org/x/sync v0.17.0 // indirect
|
||||
golang.org/x/telemetry v0.0.0-20250908211612-aef8a434d053 // indirect
|
||||
golang.org/x/term v0.35.0 // indirect
|
||||
golang.org/x/text v0.29.0 // indirect
|
||||
golang.org/x/time v0.13.0 // indirect
|
||||
golang.org/x/tools v0.37.0 // indirect
|
||||
golang.org/x/vuln v1.1.4 // indirect
|
||||
gonum.org/v1/gonum v0.16.0 // indirect
|
||||
google.golang.org/api v0.248.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250826171959-ef028d996bc1 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250826171959-ef028d996bc1 // indirect
|
||||
google.golang.org/grpc v1.75.0 // indirect
|
||||
google.golang.org/protobuf v1.36.8 // indirect
|
||||
google.golang.org/api v0.249.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20250908214217-97024824d090 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250908214217-97024824d090 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250908214217-97024824d090 // indirect
|
||||
google.golang.org/grpc v1.75.1 // indirect
|
||||
google.golang.org/protobuf v1.36.9 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
honnef.co/go/tools v0.6.1 // indirect
|
||||
mvdan.cc/editorconfig v0.3.0 // indirect
|
||||
mvdan.cc/gofumpt v0.9.0 // indirect
|
||||
mvdan.cc/gofumpt v0.9.1 // indirect
|
||||
mvdan.cc/sh/v3 v3.12.0 // indirect
|
||||
mvdan.cc/unparam v0.0.0-20250301125049-0df0534333a4 // indirect
|
||||
)
|
||||
|
||||
141
go.sum
141
go.sum
@ -1,21 +1,21 @@
|
||||
cloud.google.com/go v0.121.6 h1:waZiuajrI28iAf40cWgycWNgaXPO06dupuS+sgibK6c=
|
||||
cloud.google.com/go v0.121.6/go.mod h1:coChdst4Ea5vUpiALcYKXEpR1S9ZgXbhEzzMcMR66vI=
|
||||
cloud.google.com/go v0.122.0 h1:0JTLGrcSIs3HIGsgVPvTx3cfyFSP/k9CI8vLPHTd6Wc=
|
||||
cloud.google.com/go v0.122.0/go.mod h1:xBoMV08QcqUGuPW65Qfm1o9Y4zKZBpGS+7bImXLTAZU=
|
||||
cloud.google.com/go/ai v0.12.1 h1:m1n/VjUuHS+pEO/2R4/VbuuEIkgk0w67fDQvFaMngM0=
|
||||
cloud.google.com/go/ai v0.12.1/go.mod h1:5vIPNe1ZQsVZqCliXIPL4QnhObQQY4d9hAGHdVc4iw4=
|
||||
cloud.google.com/go/auth v0.16.5 h1:mFWNQ2FEVWAliEQWpAdH80omXFokmrnbDhUS9cBywsI=
|
||||
cloud.google.com/go/auth v0.16.5/go.mod h1:utzRfHMP+Vv0mpOkTRQoWD2q3BatTOoWbA7gCc2dUhQ=
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc=
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c=
|
||||
cloud.google.com/go/compute/metadata v0.8.0 h1:HxMRIbao8w17ZX6wBnjhcDkW6lTFpgcaobyVfZWqRLA=
|
||||
cloud.google.com/go/compute/metadata v0.8.0/go.mod h1:sYOGTp851OV9bOFJ9CH7elVvyzopvWQFNNghtDQ/Biw=
|
||||
cloud.google.com/go/compute/metadata v0.8.3 h1:1AzcHmzbrX8t3m0CVosfxCAwGvaAShtrnlNxDriLgIk=
|
||||
cloud.google.com/go/compute/metadata v0.8.3/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10=
|
||||
cloud.google.com/go/longrunning v0.6.7 h1:IGtfDWHhQCgCjwQjV9iiLnUta9LBCo8R9QmAFsS/PrE=
|
||||
cloud.google.com/go/longrunning v0.6.7/go.mod h1:EAFV3IZAKmM56TyiE6VAP3VoTzhZzySwI/YI1s/nRsY=
|
||||
github.com/AdguardTeam/dnsproxy v0.76.1 h1:ms5vgdbYYXrKGPEpMFqUeql2j3aSfK1tGbCKju9rUgM=
|
||||
github.com/AdguardTeam/dnsproxy v0.76.1/go.mod h1:9Mw3wQMTYwM/HR9FdtatQAd+m0S8mbwq2J+UZiy/gXc=
|
||||
github.com/AdguardTeam/golibs v0.34.0 h1:JQK024DkTYxE7vsPVsYsoyDHW/53Nun7OYb9qscniK8=
|
||||
github.com/AdguardTeam/golibs v0.34.0/go.mod h1:K4C2EbfSEM1zY5YXoti9SfbTAHN/kIX97LpDtCwORrM=
|
||||
github.com/AdguardTeam/urlfilter v0.21.0 h1:ThIxiP7yoaXt8JTEroGQeU5ftQSoFpUq+t1L+TIx2pA=
|
||||
github.com/AdguardTeam/urlfilter v0.21.0/go.mod h1:xoZ3AF5qpE9ngbbeSShY9hgVeyHtm9MdH5xH1u714Wg=
|
||||
github.com/AdguardTeam/golibs v0.34.1 h1:RyBpZiXnJqlO3T+xjWldlxsEZDelmaFfKvXiJHDZZFQ=
|
||||
github.com/AdguardTeam/golibs v0.34.1/go.mod h1:K4C2EbfSEM1zY5YXoti9SfbTAHN/kIX97LpDtCwORrM=
|
||||
github.com/AdguardTeam/urlfilter v0.22.0 h1:ybOz3FywbpGDGC+8gFFkM1LMUOSosY7CWSBXIYXnG1U=
|
||||
github.com/AdguardTeam/urlfilter v0.22.0/go.mod h1:q0lWKapXlYTA4TUWUM1YDwU6Q0PKvQEokztcvRV2OW0=
|
||||
github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=
|
||||
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
||||
github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I=
|
||||
@ -48,8 +48,6 @@ github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
||||
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||
github.com/go-ping/ping v1.2.0 h1:vsJ8slZBZAXNCK4dPcI2PEE9eM9n9RbXbGouVQ/Y4yQ=
|
||||
github.com/go-ping/ping v1.2.0/go.mod h1:xIFjORFzTxqIV/tDVGO4eDy/bLuSyawEeojSm3GfRGk=
|
||||
github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI=
|
||||
@ -95,29 +93,27 @@ github.com/gordonklaus/ineffassign v0.2.0 h1:Uths4KnmwxNJNzq87fwQQDDnbNb7De00VOk
|
||||
github.com/gordonklaus/ineffassign v0.2.0/go.mod h1:TIpymnagPSexySzs7F9FnO1XFTy8IT3a59vmZp5Y9Lw=
|
||||
github.com/hugelgupf/socketpair v0.0.0-20190730060125-05d35a94e714 h1:/jC7qQFrv8CrSJVmaolDVOxTfS9kc36uB6H40kdbQq8=
|
||||
github.com/hugelgupf/socketpair v0.0.0-20190730060125-05d35a94e714/go.mod h1:2Goc3h8EklBH5mspfHFxBnEoURQCGzQQH1ga9Myjvis=
|
||||
github.com/insomniacslk/dhcp v0.0.0-20250417080101-5f8cf70e8c5f h1:dd33oobuIv9PcBVqvbEiCXEbNTomOHyj3WFuC5YiPRU=
|
||||
github.com/insomniacslk/dhcp v0.0.0-20250417080101-5f8cf70e8c5f/go.mod h1:zhFlBeJssZ1YBCMZ5Lzu1pX4vhftDvU10WUVb1uXKtM=
|
||||
github.com/insomniacslk/dhcp v0.0.0-20250828142853-d3abe7ccb0ad h1:F2k0SD55QlicoEZ1IK+a6QEt/eUqT+okQAoQG7AwSk0=
|
||||
github.com/insomniacslk/dhcp v0.0.0-20250828142853-d3abe7ccb0ad/go.mod h1:qfvBmyDNp+/liLEYWRvqny/PEz9hGe2Dz833eXILSmo=
|
||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
github.com/josharian/native v1.0.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
|
||||
github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA=
|
||||
github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
|
||||
github.com/jstemmer/go-junit-report/v2 v2.1.0 h1:X3+hPYlSczH9IMIpSC9CQSZA0L+BipYafciZUWHEmsc=
|
||||
github.com/jstemmer/go-junit-report/v2 v2.1.0/go.mod h1:mgHVr7VUo5Tn8OLVr1cKnLuEy0M92wdRntM99h7RkgQ=
|
||||
github.com/kardianos/service v1.2.2 h1:ZvePhAHfvo0A7Mftk/tEzqEZ7Q4lgnR8sGz4xu1YX60=
|
||||
github.com/kardianos/service v1.2.2/go.mod h1:CIMRFEJVL+0DS1a3Nx06NaMn4Dz63Ng6O7dl0qH0zVM=
|
||||
github.com/kardianos/service v1.2.4 h1:XNlGtZOYNx2u91urOdg/Kfmc+gfmuIo1Dd3rEi2OgBk=
|
||||
github.com/kardianos/service v1.2.4/go.mod h1:E4V9ufUuY82F7Ztlu1eN9VXWIQxg8NoLQlmFe0MtrXc=
|
||||
github.com/kisielk/errcheck v1.9.0 h1:9xt1zI9EBfcYBvdU1nVrzMzzUPUtPKs9bVSIM3TAb3M=
|
||||
github.com/kisielk/errcheck v1.9.0/go.mod h1:kQxWMMVZgIkDq7U8xtG/n2juOjbLgZtedi0D+/VL/i8=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
|
||||
github.com/mdlayher/ethernet v0.0.0-20220221185849-529eae5b6118 h1:2oDp6OOhLxQ9JBoUuysVz9UZ9uI6oLUbvAZu0x8o+vE=
|
||||
github.com/mdlayher/ethernet v0.0.0-20220221185849-529eae5b6118/go.mod h1:ZFUnHIVchZ9lJoWoEGUg8Q3M4U8aNNWA3CVSUTkW4og=
|
||||
github.com/mdlayher/netlink v0.0.0-20190313131330-258ea9dff42c/go.mod h1:eQB3mZE4aiYnlUsyGGCOpPETfdQq4Jhsgf1fk3cwQaA=
|
||||
github.com/mdlayher/netlink v1.7.2 h1:/UtM3ofJap7Vl4QWCPDGXY8d3GIY2UGSDbK+QWmY8/g=
|
||||
github.com/mdlayher/netlink v1.7.2/go.mod h1:xraEF7uJbxLhc5fpHL4cPe221LI2bdttWlU+ZGLfQSw=
|
||||
github.com/mdlayher/netlink v1.8.0 h1:e7XNIYJKD7hUct3Px04RuIGJbBxy1/c4nX7D5YyvvlM=
|
||||
github.com/mdlayher/netlink v1.8.0/go.mod h1:UhgKXUlDQhzb09DrCl2GuRNEglHmhYoWAHid9HK3594=
|
||||
github.com/mdlayher/packet v1.0.0/go.mod h1:eE7/ctqDhoiRhQ44ko5JZU2zxB88g+JH/6jmnjzPjOU=
|
||||
github.com/mdlayher/packet v1.1.2 h1:3Up1NG6LZrsgDVn6X4L9Ge/iyRyxFEFD9o6Pr3Q1nQY=
|
||||
github.com/mdlayher/packet v1.1.2/go.mod h1:GEu1+n9sG5VtiRE4SydOmX5GTwyyYlteZiFU+x0kew4=
|
||||
@ -141,22 +137,16 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||
github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI=
|
||||
github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg=
|
||||
github.com/quic-go/quic-go v0.53.0 h1:QHX46sISpG2S03dPeZBgVIZp8dGagIaiu2FiVYvpCZI=
|
||||
github.com/quic-go/quic-go v0.53.0/go.mod h1:e68ZEaCdyviluZmy44P6Iey98v/Wfz6HCjQEm+l8zTY=
|
||||
github.com/quic-go/quic-go v0.54.0 h1:6s1YB9QotYI6Ospeiguknbp2Znb/jZYjZLRXn9kMQBg=
|
||||
github.com/quic-go/quic-go v0.54.0/go.mod h1:e68ZEaCdyviluZmy44P6Iey98v/Wfz6HCjQEm+l8zTY=
|
||||
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
|
||||
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
|
||||
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
|
||||
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
|
||||
github.com/securego/gosec/v2 v2.22.8 h1:3NMpmfXO8wAVFZPNsd3EscOTa32Jyo6FLLlW53bexMI=
|
||||
github.com/securego/gosec/v2 v2.22.8/go.mod h1:ZAw8K2ikuH9qDlfdV87JmNghnVfKB1XC7+TVzk6Utto=
|
||||
github.com/shirou/gopsutil/v3 v3.24.5 h1:i0t8kL+kQTvpAYToeuiVk3TgDeKOFioZO3Ztz/iZ9pI=
|
||||
github.com/shirou/gopsutil/v3 v3.24.5/go.mod h1:bsoOS1aStSs9ErQ1WWfxllSeS1K5D+U30r2NfcubMVk=
|
||||
github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM=
|
||||
github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
@ -166,22 +156,16 @@ github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD
|
||||
github.com/ti-mo/netfilter v0.2.0/go.mod h1:8GbBGsY/8fxtyIdfwy29JiluNcPK4K7wIT+x42ipqUU=
|
||||
github.com/ti-mo/netfilter v0.5.3 h1:ikzduvnaUMwre5bhbNwWOd6bjqLMVb33vv0XXbK0xGQ=
|
||||
github.com/ti-mo/netfilter v0.5.3/go.mod h1:08SyBCg6hu1qyQk4s3DjjJKNrm3RTb32nm6AzyT972E=
|
||||
github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU=
|
||||
github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
|
||||
github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk=
|
||||
github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY=
|
||||
github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701 h1:pyC9PaHYZFgEKFdlp3G8RaCKgVpHZnecvArXvPXcFkM=
|
||||
github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701/go.mod h1:P3a5rG4X7tI17Nn3aOIAYr5HbIMukwXG0urG0WuL8OA=
|
||||
github.com/uudashr/gocognit v1.2.0 h1:3BU9aMr1xbhPlvJLSydKwdLN3tEUUrzPSSM8S4hDYRA=
|
||||
github.com/uudashr/gocognit v1.2.0/go.mod h1:k/DdKPI6XBZO1q7HgoV2juESI2/Ofj9AcHPZhBBdrTU=
|
||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
|
||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
|
||||
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
|
||||
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||
go.etcd.io/bbolt v1.4.1 h1:5mOV+HWjIPLEAlUGMsveaUvK2+byZMFOzojoi7bh7uI=
|
||||
go.etcd.io/bbolt v1.4.1/go.mod h1:c8zu2BnXWTu2XM4XcICtbGSl9cFwsXtcf9zLt2OncM8=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
||||
go.etcd.io/bbolt v1.4.3 h1:dEadXpI6G79deX5prL3QRNP6JB8UxVkqo4UPnHaNXJo=
|
||||
go.etcd.io/bbolt v1.4.3/go.mod h1:tKQlpPaYCVFctUIgFKFnAlvbmB3tpy1vkTnDWohtc0E=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0 h1:YH4g8lQroajqUwWbq/tr2QX1JFmEXaDLgG+ew9bLMWo=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0/go.mod h1:fvPi2qXDqFs8M4B4fmJhE92TyQs9Ydjlg3RvfUp+NbQ=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 h1:RbKq8BG0FI8OiXhBfcRtqqHcZcka+gU3cskNuf05R18=
|
||||
@ -198,62 +182,61 @@ go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJr
|
||||
go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs=
|
||||
go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs=
|
||||
go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8=
|
||||
go.uber.org/mock v0.5.2 h1:LbtPTcP8A5k9WPXj54PPPbjcI4Y6lhyOZXn+VS7wNko=
|
||||
go.uber.org/mock v0.5.2/go.mod h1:wLlUxC2vVTPTaE3UD51E0BGOAElKrILxhVSDYQLld5o=
|
||||
go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y=
|
||||
go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU=
|
||||
go.yaml.in/yaml/v4 v4.0.0-rc.2 h1:/FrI8D64VSr4HtGIlUtlFMGsm7H7pWTbj6vOLVZcA6s=
|
||||
go.yaml.in/yaml/v4 v4.0.0-rc.2/go.mod h1:aZqd9kCMsGL7AuUv/m/PvWLdg5sjJsZ4oHDEnfPPfY0=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4=
|
||||
golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
|
||||
golang.org/x/exp v0.0.0-20250813145105-42675adae3e6 h1:SbTAbRFnd5kjQXbczszQ0hdk3ctwYf3qBNH9jIsGclE=
|
||||
golang.org/x/exp v0.0.0-20250813145105-42675adae3e6/go.mod h1:4QTo5u+SEIbbKW1RacMZq1YEfOBqeXa19JeshGi+zc4=
|
||||
golang.org/x/exp/typeparams v0.0.0-20250819193227-8b4c13bb791b h1:GU1ttDuJS89SePnuEsEuLj7dMMFP2JkGsDV1Z51iDXo=
|
||||
golang.org/x/exp/typeparams v0.0.0-20250819193227-8b4c13bb791b/go.mod h1:4Mzdyp/6jzw9auFDJ3OMF5qksa7UvPnzKqTVGcb04ms=
|
||||
golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI=
|
||||
golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8=
|
||||
golang.org/x/exp v0.0.0-20250911091902-df9299821621 h1:2id6c1/gto0kaHYyrixvknJ8tUK/Qs5IsmBtrc+FtgU=
|
||||
golang.org/x/exp v0.0.0-20250911091902-df9299821621/go.mod h1:TwQYMMnGpvZyc+JpB/UAuTNIsVJifOlSkrZkhcvpVUk=
|
||||
golang.org/x/exp/typeparams v0.0.0-20250911091902-df9299821621 h1:Yl4H5w2RV7L/dvSHp2GerziT5K2CORgFINPaMFxWGWw=
|
||||
golang.org/x/exp/typeparams v0.0.0-20250911091902-df9299821621/go.mod h1:4Mzdyp/6jzw9auFDJ3OMF5qksa7UvPnzKqTVGcb04ms=
|
||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ=
|
||||
golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc=
|
||||
golang.org/x/mod v0.28.0 h1:gQBtGhjxykdjY9YhZpSlZIsbnaE2+PgjfLWUQTnoZ1U=
|
||||
golang.org/x/mod v0.28.0/go.mod h1:yfB/L0NOf/kmEbXjzCPOx1iK1fRutOydrCMsqRhEBxI=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
|
||||
golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
|
||||
golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
|
||||
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
|
||||
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
|
||||
golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I=
|
||||
golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY=
|
||||
golang.org/x/oauth2 v0.31.0 h1:8Fq0yVZLh4j4YA47vHKFTa9Ew5XIrCP8LC6UeNZnLxo=
|
||||
golang.org/x/oauth2 v0.31.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
|
||||
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
|
||||
golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190322080309-f49334f85ddc/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
|
||||
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/telemetry v0.0.0-20250829165349-50b750f55de1 h1:zRLyLxwtVA3d2qsYvSJVSNco/qz2wzR8oJNhpLTN6x8=
|
||||
golang.org/x/telemetry v0.0.0-20250829165349-50b750f55de1/go.mod h1:JIJwPkb04vX0KeIBbQ7epGtgIjA8ihHbsAtW4A/lIQ4=
|
||||
golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k=
|
||||
golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/telemetry v0.0.0-20250908211612-aef8a434d053 h1:dHQOQddU4YHS5gY33/6klKjq7Gp3WwMyOXGNp5nzRj8=
|
||||
golang.org/x/telemetry v0.0.0-20250908211612-aef8a434d053/go.mod h1:+nZKN+XVh4LCiA9DV3ywrzN4gumyCnKjau3NGb9SGoE=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4=
|
||||
golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw=
|
||||
golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ=
|
||||
golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
|
||||
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
|
||||
golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE=
|
||||
golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
|
||||
golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
|
||||
golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
|
||||
golang.org/x/time v0.13.0 h1:eUlYslOIt32DgYD6utsuUeHs4d7AsEYLuIAdg7FlYgI=
|
||||
golang.org/x/time v0.13.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg=
|
||||
golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s=
|
||||
golang.org/x/tools v0.37.0 h1:DVSRzp7FwePZW356yEAChSdNcQo6Nsp+fex1SUW09lE=
|
||||
golang.org/x/tools v0.37.0/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w=
|
||||
golang.org/x/tools/go/expect v0.1.1-deprecated h1:jpBZDwmgPhXsKZC6WhL20P4b/wmnpsEAGHaNy0n/rJM=
|
||||
golang.org/x/tools/go/expect v0.1.1-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY=
|
||||
golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated h1:1h2MnaIAIXISqTFKdENegdpAgUXz6NrPEsbIeWaBRvM=
|
||||
@ -264,18 +247,18 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
|
||||
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
|
||||
google.golang.org/api v0.248.0 h1:hUotakSkcwGdYUqzCRc5yGYsg4wXxpkKlW5ryVqvC1Y=
|
||||
google.golang.org/api v0.248.0/go.mod h1:yAFUAF56Li7IuIQbTFoLwXTCI6XCFKueOlS7S9e4F9k=
|
||||
google.golang.org/genproto v0.0.0-20250603155806-513f23925822 h1:rHWScKit0gvAPuOnu87KpaYtjK5zBMLcULh7gxkCXu4=
|
||||
google.golang.org/genproto v0.0.0-20250603155806-513f23925822/go.mod h1:HubltRL7rMh0LfnQPkMH4NPDFEWp0jw3vixw7jEM53s=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250826171959-ef028d996bc1 h1:APHvLLYBhtZvsbnpkfknDZ7NyH4z5+ub/I0u8L3Oz6g=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250826171959-ef028d996bc1/go.mod h1:xUjFWUnWDpZ/C0Gu0qloASKFb6f8/QXiiXhSPFsD668=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250826171959-ef028d996bc1 h1:pmJpJEvT846VzausCQ5d7KreSROcDqmO388w5YbnltA=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250826171959-ef028d996bc1/go.mod h1:GmFNa4BdJZ2a8G+wCe9Bg3wwThLrJun751XstdJt5Og=
|
||||
google.golang.org/grpc v1.75.0 h1:+TW+dqTd2Biwe6KKfhE5JpiYIBWq865PhKGSXiivqt4=
|
||||
google.golang.org/grpc v1.75.0/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ=
|
||||
google.golang.org/protobuf v1.36.8 h1:xHScyCOEuuwZEc6UtSOvPbAT4zRh0xcNRYekJwfqyMc=
|
||||
google.golang.org/protobuf v1.36.8/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
|
||||
google.golang.org/api v0.249.0 h1:0VrsWAKzIZi058aeq+I86uIXbNhm9GxSHpbmZ92a38w=
|
||||
google.golang.org/api v0.249.0/go.mod h1:dGk9qyI0UYPwO/cjt2q06LG/EhUpwZGdAbYF14wHHrQ=
|
||||
google.golang.org/genproto v0.0.0-20250908214217-97024824d090 h1:ywCL7vA2n3vVHyf+bx1ZV/knaTPRI8GIeKY0MEhEeOc=
|
||||
google.golang.org/genproto v0.0.0-20250908214217-97024824d090/go.mod h1:zwJI9HzbJJlw2KXy0wX+lmT2JuZoaKK9JC4ppqmxxjk=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250908214217-97024824d090 h1:d8Nakh1G+ur7+P3GcMjpRDEkoLUcLW2iU92XVqR+XMQ=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250908214217-97024824d090/go.mod h1:U8EXRNSd8sUYyDfs/It7KVWodQr+Hf9xtxyxWudSwEw=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250908214217-97024824d090 h1:/OQuEa4YWtDt7uQWHd3q3sUMb+QOLQUg1xa8CEsRv5w=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250908214217-97024824d090/go.mod h1:GmFNa4BdJZ2a8G+wCe9Bg3wwThLrJun751XstdJt5Og=
|
||||
google.golang.org/grpc v1.75.1 h1:/ODCNEuf9VghjgO3rqLcfg8fiOP0nSluljWFlDxELLI=
|
||||
google.golang.org/grpc v1.75.1/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ=
|
||||
google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw=
|
||||
google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
@ -290,8 +273,8 @@ howett.net/plist v1.0.1 h1:37GdZ8tP09Q35o9ych3ehygcsL+HqKSwzctveSlarvM=
|
||||
howett.net/plist v1.0.1/go.mod h1:lqaXoTrLY4hg8tnEzNru53gicrbv7rrk+2xJA/7hw9g=
|
||||
mvdan.cc/editorconfig v0.3.0 h1:D1D2wLYEYGpawWT5SpM5pRivgEgXjtEXwC9MWhEY0gQ=
|
||||
mvdan.cc/editorconfig v0.3.0/go.mod h1:NcJHuDtNOTEJ6251indKiWuzK6+VcrMuLzGMLKBFupQ=
|
||||
mvdan.cc/gofumpt v0.9.0 h1:W0wNHMSvDBDIyZsm3nnGbVfgp5AknzBrGJnfLCy501w=
|
||||
mvdan.cc/gofumpt v0.9.0/go.mod h1:3xYtNemnKiXaTh6R4VtlqDATFwBbdXI8lJvH/4qk7mw=
|
||||
mvdan.cc/gofumpt v0.9.1 h1:p5YT2NfFWsYyTieYgwcQ8aKV3xRvFH4uuN/zB2gBbMQ=
|
||||
mvdan.cc/gofumpt v0.9.1/go.mod h1:3xYtNemnKiXaTh6R4VtlqDATFwBbdXI8lJvH/4qk7mw=
|
||||
mvdan.cc/sh/v3 v3.12.0 h1:ejKUR7ONP5bb+UGHGEG/k9V5+pRVIyD+LsZz7o8KHrI=
|
||||
mvdan.cc/sh/v3 v3.12.0/go.mod h1:Se6Cj17eYSn+sNooLZiEUnNNmNxg0imoYlTu4CyaGyg=
|
||||
mvdan.cc/unparam v0.0.0-20250301125049-0df0534333a4 h1:WjUu4yQoT5BHT1w8Zu56SP8367OuBV5jvo+4Ulppyf8=
|
||||
|
||||
@ -1,25 +1,29 @@
|
||||
package aghalg
|
||||
|
||||
import (
|
||||
"cmp"
|
||||
"slices"
|
||||
)
|
||||
|
||||
// SortedMap is a map that keeps elements in order with internal sorting
|
||||
// function. Must be initialized by the [NewSortedMap].
|
||||
// function. It must be initialized with [NewSortedMap] or [NewSortedMapFunc].
|
||||
type SortedMap[K comparable, V any] struct {
|
||||
vals map[K]V
|
||||
cmp func(a, b K) (res int)
|
||||
keys []K
|
||||
}
|
||||
|
||||
// NewSortedMap initializes the new instance of sorted map. cmp is a sort
|
||||
// function to keep elements in order.
|
||||
//
|
||||
// TODO(s.chzhen): Use cmp.Compare in Go 1.21.
|
||||
func NewSortedMap[K comparable, V any](cmp func(a, b K) (res int)) SortedMap[K, V] {
|
||||
return SortedMap[K, V]{
|
||||
// NewSortedMap initializes a new instance of sorted map.
|
||||
func NewSortedMap[K cmp.Ordered, V any]() (m *SortedMap[K, V]) {
|
||||
return NewSortedMapFunc[K, V](cmp.Compare[K])
|
||||
}
|
||||
|
||||
// NewSortedMapFunc initializes a new instance of sorted map. cmpFunc is a
|
||||
// comparison function to keep elements in order. cmpFunc must not be nil.
|
||||
func NewSortedMapFunc[K comparable, V any](cmpFunc func(a, b K) (res int)) (m *SortedMap[K, V]) {
|
||||
return &SortedMap[K, V]{
|
||||
vals: map[K]V{},
|
||||
cmp: cmp,
|
||||
cmp: cmpFunc,
|
||||
}
|
||||
}
|
||||
|
||||
@ -69,7 +73,7 @@ func (m *SortedMap[K, V]) Clear() {
|
||||
return
|
||||
}
|
||||
|
||||
m.keys = nil
|
||||
m.keys = m.keys[:0]
|
||||
clear(m.vals)
|
||||
}
|
||||
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
package aghalg_test
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/aghalg"
|
||||
@ -9,7 +8,7 @@ import (
|
||||
)
|
||||
|
||||
func TestNewSortedMap(t *testing.T) {
|
||||
var m aghalg.SortedMap[string, int]
|
||||
var m *aghalg.SortedMap[string, int]
|
||||
|
||||
letters := []string{}
|
||||
for i := range 10 {
|
||||
@ -18,7 +17,7 @@ func TestNewSortedMap(t *testing.T) {
|
||||
}
|
||||
|
||||
t.Run("create_and_fill", func(t *testing.T) {
|
||||
m = aghalg.NewSortedMap[string, int](strings.Compare)
|
||||
m = aghalg.NewSortedMap[string, int]()
|
||||
|
||||
nums := []int{}
|
||||
for i, r := range letters {
|
||||
|
||||
@ -31,6 +31,9 @@ func macToKey(mac net.HardwareAddr) (key macKey) {
|
||||
|
||||
// index stores all information about persistent clients.
|
||||
type index struct {
|
||||
// subnetToUID maps subnet to UID.
|
||||
subnetToUID *aghalg.SortedMap[netip.Prefix, UID]
|
||||
|
||||
// nameToUID maps client name to UID.
|
||||
nameToUID map[string]UID
|
||||
|
||||
@ -45,18 +48,15 @@ type index struct {
|
||||
|
||||
// uidToClient maps UID to the persistent client.
|
||||
uidToClient map[UID]*Persistent
|
||||
|
||||
// subnetToUID maps subnet to UID.
|
||||
subnetToUID aghalg.SortedMap[netip.Prefix, UID]
|
||||
}
|
||||
|
||||
// newIndex initializes the new instance of client index.
|
||||
func newIndex() (ci *index) {
|
||||
return &index{
|
||||
subnetToUID: aghalg.NewSortedMapFunc[netip.Prefix, UID](subnetCompare),
|
||||
nameToUID: map[string]UID{},
|
||||
clientIDToUID: map[ClientID]UID{},
|
||||
ipToUID: map[netip.Addr]UID{},
|
||||
subnetToUID: aghalg.NewSortedMap[netip.Prefix, UID](subnetCompare),
|
||||
macToUID: map[macKey]UID{},
|
||||
uidToClient: map[UID]*Persistent{},
|
||||
}
|
||||
|
||||
@ -191,6 +191,8 @@ func (c *Persistent) SetIDs(ids []string) (err error) {
|
||||
// subnetCompare is a comparison function for the two subnets. It returns -1 if
|
||||
// x sorts before y, 1 if x sorts after y, and 0 if their relative sorting
|
||||
// position is the same.
|
||||
//
|
||||
// TODO(s.chzhen): Use netip.Prefix.Compare in Go 1.26.
|
||||
func subnetCompare(x, y netip.Prefix) (cmp int) {
|
||||
if x == y {
|
||||
return 0
|
||||
|
||||
@ -32,7 +32,7 @@ func initBlockedServices(ctx context.Context, l *slog.Logger) {
|
||||
for i, s := range blockedServices {
|
||||
netRules := make([]*rules.NetworkRule, 0, len(s.Rules))
|
||||
for _, text := range s.Rules {
|
||||
rule, err := rules.NewNetworkRule(text, rulelist.URLFilterIDBlockedService)
|
||||
rule, err := rules.NewNetworkRule(text, rulelist.IDBlockedService)
|
||||
if err == nil {
|
||||
netRules = append(netRules, rule)
|
||||
|
||||
|
||||
@ -29,10 +29,9 @@ func (d *DNSFilter) processDNSRewrites(dnsr []*rules.NetworkRule) (res Result) {
|
||||
dr := nr.DNSRewrite
|
||||
if dr.NewCNAME != "" {
|
||||
// NewCNAME rules have a higher priority than other rules.
|
||||
rules = []*ResultRule{{
|
||||
FilterListID: nr.GetFilterListID(),
|
||||
Text: nr.RuleText,
|
||||
}}
|
||||
rules = []*ResultRule{
|
||||
NewResultRule(nr),
|
||||
}
|
||||
|
||||
return Result{
|
||||
Rules: rules,
|
||||
@ -45,17 +44,13 @@ func (d *DNSFilter) processDNSRewrites(dnsr []*rules.NetworkRule) (res Result) {
|
||||
case dns.RcodeSuccess:
|
||||
dnsrr.RCode = dr.RCode
|
||||
dnsrr.Response[dr.RRType] = append(dnsrr.Response[dr.RRType], dr.Value)
|
||||
rules = append(rules, &ResultRule{
|
||||
FilterListID: nr.GetFilterListID(),
|
||||
Text: nr.RuleText,
|
||||
})
|
||||
rules = append(rules, NewResultRule(nr))
|
||||
default:
|
||||
// RcodeRefused and other such codes have higher priority. Return
|
||||
// immediately.
|
||||
rules = []*ResultRule{{
|
||||
FilterListID: nr.GetFilterListID(),
|
||||
Text: nr.RuleText,
|
||||
}}
|
||||
rules = []*ResultRule{
|
||||
NewResultRule(nr),
|
||||
}
|
||||
dnsrr = &DNSRewriteResult{
|
||||
RCode: dr.RCode,
|
||||
}
|
||||
|
||||
@ -52,7 +52,8 @@ func (filter *FilterYAML) Path(dataDir string) string {
|
||||
return filepath.Join(
|
||||
dataDir,
|
||||
filterDir,
|
||||
strconv.FormatInt(int64(filter.ID), 10)+".txt")
|
||||
strconv.FormatUint(uint64(filter.ID), 10)+".txt",
|
||||
)
|
||||
}
|
||||
|
||||
// ensureName sets provided title or default name for the filter if it doesn't
|
||||
@ -612,6 +613,7 @@ func (d *DNSFilter) load(ctx context.Context, flt *FilterYAML) (err error) {
|
||||
|
||||
d.logger.DebugContext(ctx, "loading filter", "id", flt.ID, "path", fileName)
|
||||
|
||||
// #nosec G304 -- Assume that fileName is always within DataDir.
|
||||
file, err := os.Open(fileName)
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
// Do nothing, file doesn't exist.
|
||||
@ -655,7 +657,7 @@ func (d *DNSFilter) EnableFilters(async bool) {
|
||||
func (d *DNSFilter) enableFiltersLocked(ctx context.Context, async bool) {
|
||||
filters := make([]Filter, 1, len(d.conf.Filters)+len(d.conf.WhitelistFilters)+1)
|
||||
filters[0] = Filter{
|
||||
ID: rulelist.URLFilterIDCustom,
|
||||
ID: rulelist.IDCustom,
|
||||
Data: []byte(strings.Join(d.conf.UserRules, "\n")),
|
||||
}
|
||||
|
||||
|
||||
@ -302,86 +302,10 @@ type Filter struct {
|
||||
// Data is the content of the file.
|
||||
Data []byte `yaml:"-"`
|
||||
|
||||
// ID is automatically assigned when filter is added using nextFilterID.
|
||||
ID rulelist.URLFilterID `yaml:"id"`
|
||||
// ID is automatically assigned when filter is added.
|
||||
ID rules.ListID `yaml:"id"`
|
||||
}
|
||||
|
||||
// Reason holds an enum detailing why it was filtered or not filtered
|
||||
type Reason int
|
||||
|
||||
const (
|
||||
// reasons for not filtering
|
||||
|
||||
// NotFilteredNotFound - host was not find in any checks, default value for result
|
||||
NotFilteredNotFound Reason = iota
|
||||
// NotFilteredAllowList - the host is explicitly allowed
|
||||
NotFilteredAllowList
|
||||
// NotFilteredError is returned when there was an error during
|
||||
// checking. Reserved, currently unused.
|
||||
NotFilteredError
|
||||
|
||||
// reasons for filtering
|
||||
|
||||
// FilteredBlockList - the host was matched to be advertising host
|
||||
FilteredBlockList
|
||||
// FilteredSafeBrowsing - the host was matched to be malicious/phishing
|
||||
FilteredSafeBrowsing
|
||||
// FilteredParental - the host was matched to be outside of parental control settings
|
||||
FilteredParental
|
||||
// FilteredInvalid - the request was invalid and was not processed
|
||||
FilteredInvalid
|
||||
// FilteredSafeSearch - the host was replaced with safesearch variant
|
||||
FilteredSafeSearch
|
||||
// FilteredBlockedService - the host is blocked by "blocked services" settings
|
||||
FilteredBlockedService
|
||||
|
||||
// Rewritten is returned when there was a rewrite by a legacy DNS rewrite
|
||||
// rule.
|
||||
Rewritten
|
||||
|
||||
// RewrittenAutoHosts is returned when there was a rewrite by autohosts
|
||||
// rules (/etc/hosts and so on).
|
||||
RewrittenAutoHosts
|
||||
|
||||
// RewrittenRule is returned when a $dnsrewrite filter rule was applied.
|
||||
//
|
||||
// TODO(a.garipov): Remove Rewritten and RewrittenAutoHosts by merging their
|
||||
// functionality into RewrittenRule.
|
||||
//
|
||||
// See https://github.com/AdguardTeam/AdGuardHome/issues/2499.
|
||||
RewrittenRule
|
||||
)
|
||||
|
||||
// TODO(a.garipov): Resync with actual code names or replace completely
|
||||
// in HTTP API v1.
|
||||
var reasonNames = []string{
|
||||
NotFilteredNotFound: "NotFilteredNotFound",
|
||||
NotFilteredAllowList: "NotFilteredWhiteList",
|
||||
NotFilteredError: "NotFilteredError",
|
||||
|
||||
FilteredBlockList: "FilteredBlackList",
|
||||
FilteredSafeBrowsing: "FilteredSafeBrowsing",
|
||||
FilteredParental: "FilteredParental",
|
||||
FilteredInvalid: "FilteredInvalid",
|
||||
FilteredSafeSearch: "FilteredSafeSearch",
|
||||
FilteredBlockedService: "FilteredBlockedService",
|
||||
|
||||
Rewritten: "Rewrite",
|
||||
RewrittenAutoHosts: "RewriteEtcHosts",
|
||||
RewrittenRule: "RewriteRule",
|
||||
}
|
||||
|
||||
func (r Reason) String() string {
|
||||
if r < 0 || int(r) >= len(reasonNames) {
|
||||
return ""
|
||||
}
|
||||
|
||||
return reasonNames[r]
|
||||
}
|
||||
|
||||
// In returns true if reasons include r.
|
||||
func (r Reason) In(reasons ...Reason) (ok bool) { return slices.Contains(reasons, r) }
|
||||
|
||||
// SetEnabled sets the status of the *DNSFilter.
|
||||
func (d *DNSFilter) SetEnabled(enabled bool) {
|
||||
atomic.StoreUint32(&d.conf.enabled, mathutil.BoolToNumber[uint32](enabled))
|
||||
@ -556,54 +480,6 @@ func (d *DNSFilter) ParentalBlockHost() (host string) {
|
||||
return d.conf.ParentalBlockHost
|
||||
}
|
||||
|
||||
// ResultRule contains information about applied rules.
|
||||
type ResultRule struct {
|
||||
// Text is the text of the rule.
|
||||
Text string `json:",omitempty"`
|
||||
|
||||
// IP is the host IP. It is nil unless the rule uses the
|
||||
// /etc/hosts syntax or the reason is FilteredSafeSearch.
|
||||
IP netip.Addr `json:",omitempty"`
|
||||
|
||||
// FilterListID is the ID of the rule's filter list.
|
||||
FilterListID rulelist.URLFilterID `json:",omitempty"`
|
||||
}
|
||||
|
||||
// Result contains the result of a request check.
|
||||
//
|
||||
// All fields transitively have omitempty tags so that the query log doesn't
|
||||
// become too large.
|
||||
//
|
||||
// TODO(a.garipov): Clarify relationships between fields. Perhaps replace with
|
||||
// a sum type or an interface?
|
||||
type Result struct {
|
||||
// DNSRewriteResult is the $dnsrewrite filter rule result.
|
||||
DNSRewriteResult *DNSRewriteResult `json:",omitempty"`
|
||||
|
||||
// CanonName is the CNAME value from the lookup rewrite result. It is empty
|
||||
// unless Reason is set to Rewritten or RewrittenRule.
|
||||
CanonName string `json:",omitempty"`
|
||||
|
||||
// ServiceName is the name of the blocked service. It is empty unless
|
||||
// Reason is set to FilteredBlockedService.
|
||||
ServiceName string `json:",omitempty"`
|
||||
|
||||
// IPList is the lookup rewrite result. It is empty unless Reason is set to
|
||||
// Rewritten.
|
||||
IPList []netip.Addr `json:",omitempty"`
|
||||
|
||||
// Rules are applied rules. If Rules are not empty, each rule is not nil.
|
||||
Rules []*ResultRule `json:",omitempty"`
|
||||
|
||||
// Reason is the reason for blocking or unblocking the request.
|
||||
Reason Reason `json:",omitempty"`
|
||||
|
||||
// IsFiltered is true if the request is filtered.
|
||||
//
|
||||
// TODO(d.kolyshev): Get rid of this flag.
|
||||
IsFiltered bool `json:",omitempty"`
|
||||
}
|
||||
|
||||
// Matched returns true if any match at all was found regardless of
|
||||
// whether it was filtered or not.
|
||||
func (r Reason) Matched() bool {
|
||||
@ -741,7 +617,9 @@ func (d *DNSFilter) matchBlockedServicesRules(
|
||||
|
||||
ruleText := rule.Text()
|
||||
res.Rules = []*ResultRule{{
|
||||
FilterListID: rule.GetFilterListID(),
|
||||
// #nosec G115 -- The overflow is required for backwards
|
||||
// compatibility.
|
||||
FilterListID: rulelist.APIID(rule.GetFilterListID()),
|
||||
Text: ruleText,
|
||||
}}
|
||||
|
||||
@ -793,11 +671,9 @@ func newRuleStorage(filters []Filter) (rs *filterlist.RuleStorage, err error) {
|
||||
|
||||
// ruleListFromFilter returns a rule list from a Filter.
|
||||
func ruleListFromFilter(f Filter) (rl filterlist.Interface, skip bool, err error) {
|
||||
id := int(f.ID)
|
||||
|
||||
if len(f.Data) != 0 {
|
||||
return filterlist.NewBytes(&filterlist.BytesConfig{
|
||||
ID: id,
|
||||
ID: f.ID,
|
||||
RulesText: f.Data,
|
||||
IgnoreCosmetic: true,
|
||||
}), false, nil
|
||||
@ -819,14 +695,14 @@ func ruleListFromFilter(f Filter) (rl filterlist.Interface, skip bool, err error
|
||||
}
|
||||
|
||||
return filterlist.NewBytes(&filterlist.BytesConfig{
|
||||
ID: id,
|
||||
ID: f.ID,
|
||||
RulesText: data,
|
||||
IgnoreCosmetic: true,
|
||||
}), false, nil
|
||||
}
|
||||
|
||||
rl, err = filterlist.NewFile(&filterlist.FileConfig{
|
||||
ID: id,
|
||||
ID: f.ID,
|
||||
Path: f.FilePath,
|
||||
IgnoreCosmetic: true,
|
||||
})
|
||||
@ -1048,10 +924,7 @@ func (d *DNSFilter) matchHost(
|
||||
func makeResult(matchedRules []rules.Rule, reason Reason) (res Result) {
|
||||
resRules := make([]*ResultRule, len(matchedRules))
|
||||
for i, mr := range matchedRules {
|
||||
resRules[i] = &ResultRule{
|
||||
FilterListID: mr.GetFilterListID(),
|
||||
Text: mr.Text(),
|
||||
}
|
||||
resRules[i] = NewResultRule(mr)
|
||||
}
|
||||
|
||||
return Result{
|
||||
@ -1072,8 +945,9 @@ func New(c *Config, blockFilters []Filter) (d *DNSFilter, err error) {
|
||||
ctx := context.TODO()
|
||||
|
||||
d = &DNSFilter{
|
||||
logger: c.Logger,
|
||||
idGen: newIDGenerator(int32(time.Now().Unix()), c.Logger),
|
||||
logger: c.Logger,
|
||||
// #nosec G115 -- The Unix epoch time is highly unlikely to be negative.
|
||||
idGen: newIDGenerator(uint64(time.Now().Unix()), c.Logger),
|
||||
bufPool: syncutil.NewSlicePool[byte](rulelist.DefaultRuleBufSize),
|
||||
safeSearch: c.SafeSearch,
|
||||
refreshLock: &sync.Mutex{},
|
||||
@ -1253,7 +1127,7 @@ func (d *DNSFilter) checkSafeBrowsing(
|
||||
res = Result{
|
||||
Rules: []*ResultRule{{
|
||||
Text: "adguard-malware-shavar",
|
||||
FilterListID: rulelist.URLFilterIDSafeBrowsing,
|
||||
FilterListID: rulelist.APIIDSafeBrowsing,
|
||||
}},
|
||||
Reason: FilteredSafeBrowsing,
|
||||
IsFiltered: true,
|
||||
@ -1289,7 +1163,7 @@ func (d *DNSFilter) checkParental(
|
||||
res = Result{
|
||||
Rules: []*ResultRule{{
|
||||
Text: "parental CATEGORY_BLACKLISTED",
|
||||
FilterListID: rulelist.URLFilterIDParentalControl,
|
||||
FilterListID: rulelist.APIIDParentalControl,
|
||||
}},
|
||||
Reason: FilteredParental,
|
||||
IsFiltered: true,
|
||||
|
||||
@ -21,6 +21,8 @@ type cacheItem struct {
|
||||
// toCacheItem decodes cacheItem from data. data must be at least equal to
|
||||
// expiry size.
|
||||
func toCacheItem(data []byte) *cacheItem {
|
||||
// #nosec G115 -- Assume that the values are as the ones that have been
|
||||
// encoded.
|
||||
t := time.Unix(int64(binary.BigEndian.Uint64(data)), 0)
|
||||
|
||||
data = data[expirySize:]
|
||||
@ -43,6 +45,7 @@ func fromCacheItem(item *cacheItem) (data []byte) {
|
||||
data = make([]byte, 0, len(item.hashes)*hashSize+expirySize)
|
||||
|
||||
expiry := item.expiry.Unix()
|
||||
// #nosec G115 -- The Unix epoch time is highly unlikely to be negative.
|
||||
data = binary.BigEndian.AppendUint64(data, uint64(expiry))
|
||||
|
||||
for _, v := range item.hashes {
|
||||
|
||||
@ -75,7 +75,7 @@ func (d *DNSFilter) hostsRewrites(
|
||||
vals = append(vals, name)
|
||||
rls = append(rls, &ResultRule{
|
||||
Text: fmt.Sprintf("%s %s", addr, name),
|
||||
FilterListID: rulelist.URLFilterIDEtcHosts,
|
||||
FilterListID: rulelist.APIIDEtcHosts,
|
||||
})
|
||||
}
|
||||
|
||||
@ -97,7 +97,7 @@ func (d *DNSFilter) hostsRewrites(
|
||||
}
|
||||
rls = append(rls, &ResultRule{
|
||||
Text: fmt.Sprintf("%s %s", addr, host),
|
||||
FilterListID: rulelist.URLFilterIDEtcHosts,
|
||||
FilterListID: rulelist.APIIDEtcHosts,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@ -76,7 +76,7 @@ func TestDNSFilter_CheckHost_hostsContainer(t *testing.T) {
|
||||
dtyp: dns.TypeA,
|
||||
wantRules: []*filtering.ResultRule{{
|
||||
Text: "1.2.3.4 v4.host.example",
|
||||
FilterListID: rulelist.URLFilterIDEtcHosts,
|
||||
FilterListID: rulelist.APIIDEtcHosts,
|
||||
}},
|
||||
wantResps: []rules.RRValue{addrv4},
|
||||
}, {
|
||||
@ -85,7 +85,7 @@ func TestDNSFilter_CheckHost_hostsContainer(t *testing.T) {
|
||||
dtyp: dns.TypeAAAA,
|
||||
wantRules: []*filtering.ResultRule{{
|
||||
Text: "::1 v6.host.example",
|
||||
FilterListID: rulelist.URLFilterIDEtcHosts,
|
||||
FilterListID: rulelist.APIIDEtcHosts,
|
||||
}},
|
||||
wantResps: []rules.RRValue{addrv6},
|
||||
}, {
|
||||
@ -94,7 +94,7 @@ func TestDNSFilter_CheckHost_hostsContainer(t *testing.T) {
|
||||
dtyp: dns.TypeAAAA,
|
||||
wantRules: []*filtering.ResultRule{{
|
||||
Text: "::ffff:1.2.3.4 mapped.host.example",
|
||||
FilterListID: rulelist.URLFilterIDEtcHosts,
|
||||
FilterListID: rulelist.APIIDEtcHosts,
|
||||
}},
|
||||
wantResps: []rules.RRValue{addrMapped},
|
||||
}, {
|
||||
@ -103,7 +103,7 @@ func TestDNSFilter_CheckHost_hostsContainer(t *testing.T) {
|
||||
dtyp: dns.TypePTR,
|
||||
wantRules: []*filtering.ResultRule{{
|
||||
Text: "1.2.3.4 v4.host.example",
|
||||
FilterListID: rulelist.URLFilterIDEtcHosts,
|
||||
FilterListID: rulelist.APIIDEtcHosts,
|
||||
}},
|
||||
wantResps: []rules.RRValue{"v4.host.example"},
|
||||
}, {
|
||||
@ -112,7 +112,7 @@ func TestDNSFilter_CheckHost_hostsContainer(t *testing.T) {
|
||||
dtyp: dns.TypePTR,
|
||||
wantRules: []*filtering.ResultRule{{
|
||||
Text: "::ffff:1.2.3.4 mapped.host.example",
|
||||
FilterListID: rulelist.URLFilterIDEtcHosts,
|
||||
FilterListID: rulelist.APIIDEtcHosts,
|
||||
}},
|
||||
wantResps: []rules.RRValue{"mapped.host.example"},
|
||||
}, {
|
||||
@ -139,7 +139,7 @@ func TestDNSFilter_CheckHost_hostsContainer(t *testing.T) {
|
||||
dtyp: dns.TypeAAAA,
|
||||
wantRules: []*filtering.ResultRule{{
|
||||
Text: fmt.Sprintf("%s v4.host.example", addrv4),
|
||||
FilterListID: rulelist.URLFilterIDEtcHosts,
|
||||
FilterListID: rulelist.APIIDEtcHosts,
|
||||
}},
|
||||
wantResps: nil,
|
||||
}, {
|
||||
@ -148,7 +148,7 @@ func TestDNSFilter_CheckHost_hostsContainer(t *testing.T) {
|
||||
dtyp: dns.TypeA,
|
||||
wantRules: []*filtering.ResultRule{{
|
||||
Text: fmt.Sprintf("%s v6.host.example", addrv6),
|
||||
FilterListID: rulelist.URLFilterIDEtcHosts,
|
||||
FilterListID: rulelist.APIIDEtcHosts,
|
||||
}},
|
||||
wantResps: nil,
|
||||
}, {
|
||||
@ -169,7 +169,7 @@ func TestDNSFilter_CheckHost_hostsContainer(t *testing.T) {
|
||||
dtyp: dns.TypeA,
|
||||
wantRules: []*filtering.ResultRule{{
|
||||
Text: "4.3.2.1 v4.host.with-dup",
|
||||
FilterListID: rulelist.URLFilterIDEtcHosts,
|
||||
FilterListID: rulelist.APIIDEtcHosts,
|
||||
}},
|
||||
wantResps: []rules.RRValue{addrv4Dup},
|
||||
}}
|
||||
|
||||
@ -327,12 +327,14 @@ func (d *DNSFilter) handleFilteringRefresh(w http.ResponseWriter, r *http.Reques
|
||||
}
|
||||
|
||||
type filterJSON struct {
|
||||
URL string `json:"url"`
|
||||
Name string `json:"name"`
|
||||
LastUpdated string `json:"last_updated,omitempty"`
|
||||
ID rulelist.URLFilterID `json:"id"`
|
||||
RulesCount uint32 `json:"rules_count"`
|
||||
Enabled bool `json:"enabled"`
|
||||
URL string `json:"url"`
|
||||
Name string `json:"name"`
|
||||
LastUpdated string `json:"last_updated,omitempty"`
|
||||
|
||||
ID rulelist.APIID `json:"id"`
|
||||
|
||||
RulesCount uint64 `json:"rules_count"`
|
||||
Enabled bool `json:"enabled"`
|
||||
}
|
||||
|
||||
type filteringConfig struct {
|
||||
@ -345,11 +347,13 @@ type filteringConfig struct {
|
||||
|
||||
func filterToJSON(f FilterYAML) filterJSON {
|
||||
fj := filterJSON{
|
||||
ID: f.ID,
|
||||
Enabled: f.Enabled,
|
||||
URL: f.URL,
|
||||
Name: f.Name,
|
||||
RulesCount: uint32(f.RulesCount),
|
||||
// #nosec G115 -- The overflow is required for backwards compatibility.
|
||||
ID: rulelist.APIID(f.ID),
|
||||
Enabled: f.Enabled,
|
||||
URL: f.URL,
|
||||
Name: f.Name,
|
||||
// #nosec G115 -- The number of rules must not be negative.
|
||||
RulesCount: uint64(f.RulesCount),
|
||||
}
|
||||
|
||||
if !f.LastUpdated.IsZero() {
|
||||
@ -408,8 +412,9 @@ func (d *DNSFilter) handleFilteringConfig(w http.ResponseWriter, r *http.Request
|
||||
}
|
||||
|
||||
type checkHostRespRule struct {
|
||||
Text string `json:"text"`
|
||||
FilterListID rulelist.URLFilterID `json:"filter_list_id"`
|
||||
Text string `json:"text"`
|
||||
|
||||
FilterListID rulelist.APIID `json:"filter_list_id"`
|
||||
}
|
||||
|
||||
type checkHostResp struct {
|
||||
@ -432,7 +437,7 @@ type checkHostResp struct {
|
||||
// FilterID is the ID of the rule's filter list.
|
||||
//
|
||||
// Deprecated: Use Rules[*].FilterListID.
|
||||
FilterID rulelist.URLFilterID `json:"filter_id"`
|
||||
FilterID rulelist.APIID `json:"filter_id"`
|
||||
}
|
||||
|
||||
// handleCheckHost is the handler for the GET /control/filtering/check_host HTTP
|
||||
|
||||
@ -6,8 +6,8 @@ import (
|
||||
"log/slog"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/filtering/rulelist"
|
||||
"github.com/AdguardTeam/golibs/container"
|
||||
"github.com/AdguardTeam/urlfilter/rules"
|
||||
)
|
||||
|
||||
// idGenerator generates filtering-list IDs in a way broadly compatible with the
|
||||
@ -16,15 +16,15 @@ import (
|
||||
// TODO(a.garipov): Get rid of this once we switch completely to the new
|
||||
// rule-list architecture.
|
||||
type idGenerator struct {
|
||||
current *atomic.Int32
|
||||
current *atomic.Uint64
|
||||
logger *slog.Logger
|
||||
}
|
||||
|
||||
// newIDGenerator returns a new ID generator initialized with the given seed
|
||||
// value.
|
||||
func newIDGenerator(seed int32, l *slog.Logger) (g *idGenerator) {
|
||||
// value. l must not be nil.
|
||||
func newIDGenerator(seed uint64, l *slog.Logger) (g *idGenerator) {
|
||||
g = &idGenerator{
|
||||
current: &atomic.Int32{},
|
||||
current: &atomic.Uint64{},
|
||||
logger: l,
|
||||
}
|
||||
|
||||
@ -34,18 +34,18 @@ func newIDGenerator(seed int32, l *slog.Logger) (g *idGenerator) {
|
||||
}
|
||||
|
||||
// next returns the next ID from the generator. It is safe for concurrent use.
|
||||
func (g *idGenerator) next() (id rulelist.URLFilterID) {
|
||||
id32 := g.current.Add(1)
|
||||
if id32 < 0 {
|
||||
panic(fmt.Errorf("invalid current id value %d", id32))
|
||||
func (g *idGenerator) next() (id rules.ListID) {
|
||||
id64 := g.current.Add(1)
|
||||
if id64 == 0 {
|
||||
panic(fmt.Errorf("invalid current id value %d", id64))
|
||||
}
|
||||
|
||||
return rulelist.URLFilterID(id32)
|
||||
return rules.ListID(id64)
|
||||
}
|
||||
|
||||
// fix ensures that flts all have unique IDs.
|
||||
func (g *idGenerator) fix(flts []FilterYAML) {
|
||||
set := container.NewMapSet[rulelist.URLFilterID]()
|
||||
set := container.NewMapSet[rules.ListID]()
|
||||
for i, f := range flts {
|
||||
id := f.ID
|
||||
if id == 0 {
|
||||
|
||||
@ -4,8 +4,8 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/aghalg"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/filtering/rulelist"
|
||||
"github.com/AdguardTeam/golibs/logutil/slogutil"
|
||||
"github.com/AdguardTeam/urlfilter/rules"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
@ -78,7 +78,7 @@ func TestIDGenerator_Fix(t *testing.T) {
|
||||
func assertUniqueIDs(tb testing.TB, flts []FilterYAML) {
|
||||
tb.Helper()
|
||||
|
||||
uc := aghalg.UniqChecker[rulelist.URLFilterID]{}
|
||||
uc := aghalg.UniqChecker[rules.ListID]{}
|
||||
for _, f := range flts {
|
||||
uc.Add(f.ID)
|
||||
}
|
||||
|
||||
152
internal/filtering/result.go
Normal file
152
internal/filtering/result.go
Normal file
@ -0,0 +1,152 @@
|
||||
package filtering
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/netip"
|
||||
"slices"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/filtering/rulelist"
|
||||
"github.com/AdguardTeam/urlfilter/rules"
|
||||
)
|
||||
|
||||
// Result contains the result of a request check. All fields transitively have
|
||||
// omitempty tags so that the query log doesn't become too large.
|
||||
//
|
||||
// TODO(a.garipov): Clarify relationships between fields. Perhaps replace with
|
||||
// a sum type or an interface?
|
||||
type Result struct {
|
||||
// DNSRewriteResult is the $dnsrewrite filter rule result.
|
||||
DNSRewriteResult *DNSRewriteResult `json:",omitempty"`
|
||||
|
||||
// CanonName is the CNAME value from the lookup rewrite result. It is empty
|
||||
// unless Reason is set to Rewritten or RewrittenRule.
|
||||
CanonName string `json:",omitempty"`
|
||||
|
||||
// ServiceName is the name of the blocked service. It is empty unless
|
||||
// Reason is set to FilteredBlockedService.
|
||||
ServiceName string `json:",omitempty"`
|
||||
|
||||
// IPList is the lookup rewrite result. It is empty unless Reason is set to
|
||||
// Rewritten.
|
||||
IPList []netip.Addr `json:",omitempty"`
|
||||
|
||||
// Rules are applied rules. If Rules are not empty, each rule is not nil.
|
||||
Rules []*ResultRule `json:",omitempty"`
|
||||
|
||||
// Reason is the reason for blocking or unblocking the request.
|
||||
Reason Reason `json:",omitempty"`
|
||||
|
||||
// IsFiltered is true if the request is filtered.
|
||||
//
|
||||
// TODO(d.kolyshev): Get rid of this flag.
|
||||
IsFiltered bool `json:",omitempty"`
|
||||
}
|
||||
|
||||
// ResultRule contains information about applied rules.
|
||||
type ResultRule struct {
|
||||
// Text is the text of the rule.
|
||||
Text string `json:",omitempty"`
|
||||
|
||||
// IP is the host IP. It is nil unless the rule uses the /etc/hosts syntax
|
||||
// or the reason is [FilteredSafeSearch].
|
||||
IP netip.Addr `json:",omitzero"`
|
||||
|
||||
// FilterListID is the ID of the rule's filter list.
|
||||
FilterListID rulelist.APIID `json:",omitempty"`
|
||||
}
|
||||
|
||||
// NewResultRule converts an URLFilter rule into a *ResultRule. nr must not be
|
||||
// nil.
|
||||
func NewResultRule(r rules.Rule) (rr *ResultRule) {
|
||||
return &ResultRule{
|
||||
// #nosec G115 -- The overflow is required for backwards
|
||||
// compatibility.
|
||||
FilterListID: rulelist.APIID(r.GetFilterListID()),
|
||||
Text: r.Text(),
|
||||
}
|
||||
}
|
||||
|
||||
// Reason holds an enum detailing why it was filtered or not filtered
|
||||
type Reason int
|
||||
|
||||
const (
|
||||
// NotFilteredNotFound: the host was not find in any checks, default value
|
||||
// for results.
|
||||
NotFilteredNotFound Reason = iota
|
||||
|
||||
// NotFilteredAllowList: the host is explicitly allowed.
|
||||
NotFilteredAllowList
|
||||
|
||||
// NotFilteredError is returned when there was an error during checking.
|
||||
// Reserved, currently unused.
|
||||
NotFilteredError
|
||||
|
||||
// FilteredBlockList: the host was matched to be advertising host.
|
||||
FilteredBlockList
|
||||
|
||||
// FilteredSafeBrowsing: the host was matched to be malicious/phishing.
|
||||
FilteredSafeBrowsing
|
||||
|
||||
// FilteredParental: the host was matched to be outside of parental control
|
||||
// settings.
|
||||
FilteredParental
|
||||
|
||||
// FilteredInvalid: the request was invalid and was not processed.
|
||||
FilteredInvalid
|
||||
|
||||
// FilteredSafeSearch: the host was replaced with safesearch variant.
|
||||
FilteredSafeSearch
|
||||
|
||||
// FilteredBlockedService: the host is blocked by the blocked services
|
||||
// feature.
|
||||
FilteredBlockedService
|
||||
|
||||
// Rewritten is returned when there was a rewrite by a legacy DNS rewrite
|
||||
// rule.
|
||||
Rewritten
|
||||
|
||||
// RewrittenAutoHosts is returned when there was a rewrite by /etc/hosts.
|
||||
RewrittenAutoHosts
|
||||
|
||||
// RewrittenRule is returned when a $dnsrewrite filter rule was applied.
|
||||
//
|
||||
// TODO(a.garipov): Remove [Rewritten] and [RewrittenAutoHosts] by merging
|
||||
// their functionality into RewrittenRule.
|
||||
//
|
||||
// See https://github.com/AdguardTeam/AdGuardHome/issues/2499.
|
||||
RewrittenRule
|
||||
)
|
||||
|
||||
// TODO(a.garipov): Resync with actual code names or replace completely in HTTP
|
||||
// API v1.
|
||||
var reasonNames = []string{
|
||||
NotFilteredNotFound: "NotFilteredNotFound",
|
||||
NotFilteredAllowList: "NotFilteredWhiteList",
|
||||
NotFilteredError: "NotFilteredError",
|
||||
|
||||
FilteredBlockList: "FilteredBlackList",
|
||||
FilteredSafeBrowsing: "FilteredSafeBrowsing",
|
||||
FilteredParental: "FilteredParental",
|
||||
FilteredInvalid: "FilteredInvalid",
|
||||
FilteredSafeSearch: "FilteredSafeSearch",
|
||||
FilteredBlockedService: "FilteredBlockedService",
|
||||
|
||||
Rewritten: "Rewrite",
|
||||
RewrittenAutoHosts: "RewriteEtcHosts",
|
||||
RewrittenRule: "RewriteRule",
|
||||
}
|
||||
|
||||
// type check
|
||||
var _ fmt.Stringer = NotFilteredNotFound
|
||||
|
||||
// String implements the [fmt.Stringer] interface for Reason.
|
||||
func (r Reason) String() (s string) {
|
||||
if r < 0 || int(r) >= len(reasonNames) {
|
||||
return ""
|
||||
}
|
||||
|
||||
return reasonNames[r]
|
||||
}
|
||||
|
||||
// In returns true if reasons include r.
|
||||
func (r Reason) In(reasons ...Reason) (ok bool) { return slices.Contains(reasons, r) }
|
||||
@ -40,7 +40,7 @@ type Config struct {
|
||||
Rewrites []*Item
|
||||
|
||||
// ListID is used as an identifier of the underlying rules list.
|
||||
ListID int
|
||||
ListID rules.ListID
|
||||
}
|
||||
|
||||
// DefaultStorage is the default storage for rewrite rules.
|
||||
@ -61,10 +61,7 @@ type DefaultStorage struct {
|
||||
rewrites []*Item
|
||||
|
||||
// urlFilterID is the synthetic integer identifier for the urlfilter engine.
|
||||
//
|
||||
// TODO(a.garipov): Change the type to a string in module urlfilter and
|
||||
// remove this crutch.
|
||||
urlFilterID int
|
||||
urlFilterID rules.ListID
|
||||
}
|
||||
|
||||
// NewDefaultStorage returns new rewrites storage. conf must not be nil.
|
||||
@ -140,7 +137,7 @@ func (s *DefaultStorage) resolveCNAMEChain(
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
if isSelfMatchingWildcard(host, rwAns, rule.RuleText) {
|
||||
if isSelfMatchingWildcard(host, rwAns, rule.Text()) {
|
||||
return nil, rule.DNSRewrite
|
||||
}
|
||||
|
||||
|
||||
@ -13,6 +13,9 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// testListID is the common rule-list ID for tests.
|
||||
const testListID rules.ListID = 1
|
||||
|
||||
func TestNewDefaultStorage(t *testing.T) {
|
||||
items := []*Item{{
|
||||
Domain: "example.com",
|
||||
@ -22,7 +25,7 @@ func TestNewDefaultStorage(t *testing.T) {
|
||||
s, err := NewDefaultStorage(&Config{
|
||||
Logger: slogutil.NewDiscardLogger(),
|
||||
Rewrites: items,
|
||||
ListID: -1,
|
||||
ListID: testListID,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
@ -35,7 +38,7 @@ func TestDefaultStorage_CRUD(t *testing.T) {
|
||||
s, err := NewDefaultStorage(&Config{
|
||||
Logger: slogutil.NewDiscardLogger(),
|
||||
Rewrites: items,
|
||||
ListID: -1,
|
||||
ListID: testListID,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Len(t, s.List(), 0)
|
||||
@ -124,7 +127,7 @@ func TestDefaultStorage_MatchRequest(t *testing.T) {
|
||||
s, err := NewDefaultStorage(&Config{
|
||||
Logger: slogutil.NewDiscardLogger(),
|
||||
Rewrites: items,
|
||||
ListID: -1,
|
||||
ListID: testListID,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
@ -300,7 +303,7 @@ func TestDefaultStorage_MatchRequest_Levels(t *testing.T) {
|
||||
s, err := NewDefaultStorage(&Config{
|
||||
Logger: slogutil.NewDiscardLogger(),
|
||||
Rewrites: items,
|
||||
ListID: -1,
|
||||
ListID: testListID,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
@ -372,7 +375,7 @@ func TestDefaultStorage_MatchRequest_ExceptionCNAME(t *testing.T) {
|
||||
s, err := NewDefaultStorage(&Config{
|
||||
Logger: slogutil.NewDiscardLogger(),
|
||||
Rewrites: items,
|
||||
ListID: -1,
|
||||
ListID: testListID,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
@ -440,7 +443,7 @@ func TestDefaultStorage_MatchRequest_ExceptionIP(t *testing.T) {
|
||||
s, err := NewDefaultStorage(&Config{
|
||||
Logger: slogutil.NewDiscardLogger(),
|
||||
Rewrites: items,
|
||||
ListID: -1,
|
||||
ListID: testListID,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
|
||||
@ -16,6 +16,7 @@ import (
|
||||
"github.com/AdguardTeam/golibs/errors"
|
||||
"github.com/AdguardTeam/golibs/ioutil"
|
||||
"github.com/AdguardTeam/urlfilter/filterlist"
|
||||
"github.com/AdguardTeam/urlfilter/rules"
|
||||
"github.com/c2h5oh/datasize"
|
||||
)
|
||||
|
||||
@ -42,7 +43,7 @@ type Filter struct {
|
||||
uid UID
|
||||
|
||||
// urlFilterID is used for working with package urlfilter.
|
||||
urlFilterID URLFilterID
|
||||
urlFilterID rules.ListID
|
||||
|
||||
// rulesCount contains the number of rules in this rule-list filter.
|
||||
rulesCount int
|
||||
@ -72,7 +73,7 @@ type FilterConfig struct {
|
||||
UID UID
|
||||
|
||||
// URLFilterID is used for working with package urlfilter.
|
||||
URLFilterID URLFilterID
|
||||
URLFilterID rules.ListID
|
||||
|
||||
// Enabled, if true, means that this rule-list filter is used for filtering.
|
||||
Enabled bool
|
||||
@ -154,16 +155,15 @@ func (f *Filter) setFromHTTP(
|
||||
) (parseRes *ParseResult, err error) {
|
||||
defer func() { err = errors.Annotate(err, "setting from http: %w") }()
|
||||
|
||||
text, parseRes, err := f.readFromHTTP(ctx, parseBuf, cli, cachePath, maxSize)
|
||||
data, parseRes, err := f.readFromHTTP(ctx, parseBuf, cli, cachePath, maxSize)
|
||||
if err != nil {
|
||||
// Don't wrap the error, because it's informative enough as is.
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// TODO(a.garipov): Add filterlist.BytesRuleList.
|
||||
f.ruleList = filterlist.NewString(&filterlist.StringConfig{
|
||||
f.ruleList = filterlist.NewBytes(&filterlist.BytesConfig{
|
||||
ID: f.urlFilterID,
|
||||
RulesText: text,
|
||||
RulesText: data,
|
||||
IgnoreCosmetic: true,
|
||||
})
|
||||
|
||||
@ -179,27 +179,27 @@ func (f *Filter) readFromHTTP(
|
||||
cli *http.Client,
|
||||
cachePath string,
|
||||
maxSize uint64,
|
||||
) (text string, parseRes *ParseResult, err error) {
|
||||
) (data []byte, parseRes *ParseResult, err error) {
|
||||
urlStr := f.url.String()
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, urlStr, nil)
|
||||
if err != nil {
|
||||
return "", nil, fmt.Errorf("making request for http url %q: %w", urlStr, err)
|
||||
return nil, nil, fmt.Errorf("making request for http url %q: %w", urlStr, err)
|
||||
}
|
||||
|
||||
resp, err := cli.Do(req)
|
||||
if err != nil {
|
||||
return "", nil, fmt.Errorf("requesting from http url: %w", err)
|
||||
return nil, nil, fmt.Errorf("requesting from http url: %w", err)
|
||||
}
|
||||
defer func() { err = errors.WithDeferred(err, resp.Body.Close()) }()
|
||||
|
||||
// TODO(a.garipov): Use [agdhttp.CheckStatus] when it's moved to golibs.
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return "", nil, fmt.Errorf("got status code %d, want %d", resp.StatusCode, http.StatusOK)
|
||||
return nil, nil, fmt.Errorf("got status code %d, want %d", resp.StatusCode, http.StatusOK)
|
||||
}
|
||||
|
||||
fltFile, err := aghrenameio.NewPendingFile(cachePath, aghos.DefaultPermFile)
|
||||
if err != nil {
|
||||
return "", nil, fmt.Errorf("creating temp file: %w", err)
|
||||
return nil, nil, fmt.Errorf("creating temp file: %w", err)
|
||||
}
|
||||
defer func() { err = aghrenameio.WithDeferredCleanup(err, fltFile) }()
|
||||
|
||||
@ -210,10 +210,10 @@ func (f *Filter) readFromHTTP(
|
||||
httpBody := ioutil.LimitReader(resp.Body, maxSize)
|
||||
parseRes, err = parser.Parse(mw, httpBody, parseBuf)
|
||||
if err != nil {
|
||||
return "", nil, fmt.Errorf("parsing response from http url %q: %w", urlStr, err)
|
||||
return nil, nil, fmt.Errorf("parsing response from http url %q: %w", urlStr, err)
|
||||
}
|
||||
|
||||
return buf.String(), parseRes, nil
|
||||
return buf.Bytes(), parseRes, nil
|
||||
}
|
||||
|
||||
// setName sets the title using either the already-present name, the given title
|
||||
|
||||
@ -6,7 +6,9 @@ package rulelist
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
|
||||
"github.com/AdguardTeam/urlfilter/rules"
|
||||
"github.com/c2h5oh/datasize"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
@ -21,26 +23,33 @@ const DefaultRuleBufSize = 1024
|
||||
// DefaultMaxRuleListSize is the default maximum filtering-rule list size.
|
||||
const DefaultMaxRuleListSize = 64 * datasize.MB
|
||||
|
||||
// URLFilterID is a semantic type-alias for IDs used for working with package
|
||||
// urlfilter.
|
||||
type URLFilterID = int
|
||||
// APIID is the type for the rule-list IDs used in the HTTP API.
|
||||
type APIID int64
|
||||
|
||||
// The IDs of built-in filter lists.
|
||||
// The IDs of built-in filter lists for the HTTP API.
|
||||
//
|
||||
// NOTE: Do not change without the need for it and keep in sync with
|
||||
// NOTE: Do not change without the need for it and keep in sync with
|
||||
// client/src/helpers/constants.ts.
|
||||
const (
|
||||
APIIDCustom APIID = 0
|
||||
APIIDEtcHosts APIID = -1
|
||||
APIIDBlockedService APIID = -2
|
||||
APIIDParentalControl APIID = -3
|
||||
APIIDSafeBrowsing APIID = -4
|
||||
APIIDSafeSearch APIID = -5
|
||||
)
|
||||
|
||||
// The IDs of built-in filter lists. The IDs for the blocked-service and the
|
||||
// safe-search filters are chosen so that they equal to their [APIID]
|
||||
// counterparts when converted to it.
|
||||
//
|
||||
// TODO(a.garipov): Add type [URLFilterID] once it is used consistently in
|
||||
// package filtering.
|
||||
// NOTE: Keep in sync with [APIIDCustom] etc.
|
||||
//
|
||||
// TODO(d.kolyshev): Add URLFilterIDLegacyRewrite here and to the UI.
|
||||
const (
|
||||
URLFilterIDCustom URLFilterID = 0
|
||||
URLFilterIDEtcHosts URLFilterID = -1
|
||||
URLFilterIDBlockedService URLFilterID = -2
|
||||
URLFilterIDParentalControl URLFilterID = -3
|
||||
URLFilterIDSafeBrowsing URLFilterID = -4
|
||||
URLFilterIDSafeSearch URLFilterID = -5
|
||||
IDCustom rules.ListID = rules.ListID(APIIDCustom)
|
||||
IDBlockedService rules.ListID = math.MaxUint64 - rules.ListID(-APIIDBlockedService) + 1
|
||||
IDSafeSearch rules.ListID = math.MaxUint64 - rules.ListID(-APIIDSafeSearch) + 1
|
||||
)
|
||||
|
||||
// UID is the type for the unique IDs of filtering-rule lists.
|
||||
|
||||
@ -13,14 +13,16 @@ import (
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/filtering/rulelist"
|
||||
"github.com/AdguardTeam/golibs/netutil/urlutil"
|
||||
"github.com/AdguardTeam/golibs/testutil"
|
||||
"github.com/AdguardTeam/urlfilter/rules"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// testTimeout is the common timeout for tests.
|
||||
const testTimeout = 1 * time.Second
|
||||
|
||||
// testURLFilterID is the common [rulelist.URLFilterID] for tests.
|
||||
const testURLFilterID rulelist.URLFilterID = 1
|
||||
// testURLFilterID is the common rules.ListID for tests.
|
||||
const testURLFilterID rules.ListID = 1
|
||||
|
||||
// testTitle is the common title for tests.
|
||||
const testTitle = "Test Title"
|
||||
@ -42,11 +44,11 @@ const (
|
||||
)
|
||||
|
||||
// urlFilterIDCounter is the atomic integer used to create unique filter IDs.
|
||||
var urlFilterIDCounter = &atomic.Int32{}
|
||||
var urlFilterIDCounter = &atomic.Uint64{}
|
||||
|
||||
// newURLFilterID returns a new unique URLFilterID.
|
||||
func newURLFilterID() (id rulelist.URLFilterID) {
|
||||
return rulelist.URLFilterID(urlFilterIDCounter.Add(1))
|
||||
func newURLFilterID() (id rules.ListID) {
|
||||
return rules.ListID(urlFilterIDCounter.Add(1))
|
||||
}
|
||||
|
||||
// newFilter is a helper for creating new filters in tests. It does not
|
||||
@ -115,3 +117,15 @@ func newStringHTTPServer(s string) (srv *httptest.Server) {
|
||||
require.NoError(pt, err)
|
||||
}))
|
||||
}
|
||||
|
||||
func TestIDs(t *testing.T) {
|
||||
// Use a variable to prevent compilation errors.
|
||||
id := rulelist.IDCustom
|
||||
assert.Equal(t, rulelist.APIIDCustom, rulelist.APIID(id))
|
||||
|
||||
id = rulelist.IDBlockedService
|
||||
assert.Equal(t, rulelist.APIIDBlockedService, rulelist.APIID(id))
|
||||
|
||||
id = rulelist.IDSafeSearch
|
||||
assert.Equal(t, rulelist.APIIDSafeSearch, rulelist.APIID(id))
|
||||
}
|
||||
|
||||
@ -40,11 +40,13 @@ type StorageConfig struct {
|
||||
CacheDir string
|
||||
|
||||
// AllowFilters are the filtering-rule lists used to exclude domain names
|
||||
// from the filtering. Each item must not be nil.
|
||||
// from the filtering. Each item must not be nil and must have unique IDs
|
||||
// between AllowFilters and BlockFilters.
|
||||
AllowFilters []*Filter
|
||||
|
||||
// BlockFilters are the filtering-rule lists used to block domain names.
|
||||
// Each item must not be nil.
|
||||
// Each item must not be nil and must have unique IDs between AllowFilters
|
||||
// and BlockFilters.
|
||||
BlockFilters []*Filter
|
||||
|
||||
// CustomRules contains custom rules of the user. They have priority over
|
||||
@ -62,7 +64,7 @@ func NewStorage(c *StorageConfig) (s *Storage, err error) {
|
||||
custom, err := NewTextEngine(&TextEngineConfig{
|
||||
Name: EngineNameCustom,
|
||||
Rules: c.CustomRules,
|
||||
ID: URLFilterIDCustom,
|
||||
ID: IDCustom,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("creating custom engine: %w", err)
|
||||
|
||||
@ -7,6 +7,7 @@ import (
|
||||
|
||||
"github.com/AdguardTeam/urlfilter"
|
||||
"github.com/AdguardTeam/urlfilter/filterlist"
|
||||
"github.com/AdguardTeam/urlfilter/rules"
|
||||
)
|
||||
|
||||
// TextEngine is a single DNS filter based on a list of rules in text form.
|
||||
@ -35,7 +36,7 @@ type TextEngineConfig struct {
|
||||
Rules []string
|
||||
|
||||
// ID is the ID to use inside a URL-filter engine.
|
||||
ID URLFilterID
|
||||
ID rules.ListID
|
||||
}
|
||||
|
||||
// NewTextEngine returns a new rule-list filtering engine that uses rules
|
||||
|
||||
@ -38,5 +38,5 @@ func TestNewTextEngine(t *testing.T) {
|
||||
require.NotNil(t, fltRes)
|
||||
require.NotNil(t, fltRes.NetworkRule)
|
||||
|
||||
assert.Equal(t, fltRes.NetworkRule.FilterListID, testURLFilterID)
|
||||
assert.Equal(t, fltRes.NetworkRule.GetFilterListID(), testURLFilterID)
|
||||
}
|
||||
|
||||
@ -120,7 +120,7 @@ func NewDefault(ctx context.Context, conf *DefaultConfig) (ss *Default, err erro
|
||||
}
|
||||
|
||||
// TODO(s.chzhen): Move to [Default.InitialRefresh].
|
||||
err = ss.resetEngine(ctx, rulelist.URLFilterIDSafeSearch, conf.ServicesConfig)
|
||||
err = ss.resetEngine(ctx, rulelist.IDSafeSearch, conf.ServicesConfig)
|
||||
if err != nil {
|
||||
// Don't wrap the error, because it's informative enough as is.
|
||||
return nil, err
|
||||
@ -133,7 +133,7 @@ func NewDefault(ctx context.Context, conf *DefaultConfig) (ss *Default, err erro
|
||||
// sets it in ss.
|
||||
func (ss *Default) resetEngine(
|
||||
ctx context.Context,
|
||||
listID int,
|
||||
id rules.ListID,
|
||||
conf filtering.SafeSearchConfig,
|
||||
) (err error) {
|
||||
if !conf.Enabled {
|
||||
@ -151,7 +151,7 @@ func (ss *Default) resetEngine(
|
||||
|
||||
strList := []filterlist.Interface{
|
||||
filterlist.NewString(&filterlist.StringConfig{
|
||||
ID: listID,
|
||||
ID: id,
|
||||
RulesText: sb.String(),
|
||||
IgnoreCosmetic: true,
|
||||
}),
|
||||
@ -260,7 +260,7 @@ func (ss *Default) newResult(
|
||||
}
|
||||
|
||||
res.Rules = []*filtering.ResultRule{{
|
||||
FilterListID: rulelist.URLFilterIDSafeSearch,
|
||||
FilterListID: rulelist.APIIDSafeSearch,
|
||||
IP: ip,
|
||||
}}
|
||||
|
||||
@ -274,12 +274,16 @@ func (ss *Default) newResult(
|
||||
|
||||
// setCacheResult stores data in cache for host. qtype is expected to be either
|
||||
// [dns.TypeA] or [dns.TypeAAAA].
|
||||
//
|
||||
// TODO(a.garipov): Remove gob and use uint64.
|
||||
func (ss *Default) setCacheResult(
|
||||
ctx context.Context,
|
||||
host string,
|
||||
qtype rules.RRType,
|
||||
res filtering.Result,
|
||||
) {
|
||||
// #nosec G115 -- The Unix epoch time is highly unlikely to be negative, and
|
||||
// also see the TODO.
|
||||
expire := uint32(time.Now().Add(ss.cacheTTL).Unix())
|
||||
exp := make([]byte, 4)
|
||||
binary.BigEndian.PutUint32(exp, expire)
|
||||
@ -305,6 +309,8 @@ func (ss *Default) setCacheResult(
|
||||
|
||||
// getCachedResult returns stored data from cache for host. qtype is expected
|
||||
// to be either [dns.TypeA] or [dns.TypeAAAA].
|
||||
//
|
||||
// TODO(a.garipov): Remove gob and use uint64.
|
||||
func (ss *Default) getCachedResult(
|
||||
ctx context.Context,
|
||||
host string,
|
||||
@ -318,6 +324,8 @@ func (ss *Default) getCachedResult(
|
||||
}
|
||||
|
||||
exp := binary.BigEndian.Uint32(data[:4])
|
||||
// #nosec G115 -- The Unix epoch time is highly unlikely to be negative, and
|
||||
// also see the TODO.
|
||||
if exp <= uint32(time.Now().Unix()) {
|
||||
ss.cache.Del([]byte(host))
|
||||
|
||||
@ -342,7 +350,7 @@ func (ss *Default) Update(ctx context.Context, conf filtering.SafeSearchConfig)
|
||||
ss.mu.Lock()
|
||||
defer ss.mu.Unlock()
|
||||
|
||||
err = ss.resetEngine(ctx, rulelist.URLFilterIDSafeSearch, conf)
|
||||
err = ss.resetEngine(ctx, rulelist.IDSafeSearch, conf)
|
||||
if err != nil {
|
||||
// Don't wrap the error, because it's informative enough as is.
|
||||
return err
|
||||
|
||||
@ -101,7 +101,7 @@ func TestDefault_CheckHost_yandex(t *testing.T) {
|
||||
|
||||
rule := res.Rules[0]
|
||||
assert.Equal(t, tc.want, rule.IP)
|
||||
assert.Equal(t, rulelist.URLFilterIDSafeSearch, rule.FilterListID)
|
||||
assert.Equal(t, rulelist.APIIDSafeSearch, rule.FilterListID)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@ -188,7 +188,7 @@ func (l *queryLog) decodeResultRuleKey(
|
||||
ent.Result.Rules, vToken = l.decodeVTokenAndAddRule(ctx, key, i, dec, ent.Result.Rules)
|
||||
if n, ok := vToken.(json.Number); ok {
|
||||
id, _ := n.Int64()
|
||||
ent.Result.Rules[i].FilterListID = rulelist.URLFilterID(id)
|
||||
ent.Result.Rules[i].FilterListID = rulelist.APIID(id)
|
||||
}
|
||||
case "IP":
|
||||
ent.Result.Rules, vToken = l.decodeVTokenAndAddRule(ctx, key, i, dec, ent.Result.Rules)
|
||||
@ -643,7 +643,7 @@ var resultHandlers = map[string]logEntryHandler{
|
||||
l++
|
||||
}
|
||||
|
||||
ent.Result.Rules[l-1].FilterListID = rulelist.URLFilterID(id)
|
||||
ent.Result.Rules[l-1].FilterListID = rulelist.APIID(id)
|
||||
|
||||
return nil
|
||||
},
|
||||
|
||||
@ -17,6 +17,7 @@ import (
|
||||
"github.com/AdguardTeam/golibs/errors"
|
||||
"github.com/AdguardTeam/golibs/ioutil"
|
||||
"github.com/AdguardTeam/golibs/logutil/slogutil"
|
||||
"github.com/AdguardTeam/golibs/syncutil"
|
||||
)
|
||||
|
||||
// download and save all translations.
|
||||
@ -47,7 +48,7 @@ func (c *twoskyClient) download(ctx context.Context, l *slog.Logger) (err error)
|
||||
dw := &downloadWorker{
|
||||
ctx: ctx,
|
||||
l: l,
|
||||
failed: &sync.Map{},
|
||||
failed: syncutil.NewMap[string, struct{}](),
|
||||
client: &http.Client{
|
||||
Timeout: 10 * time.Second,
|
||||
},
|
||||
@ -72,25 +73,24 @@ func (c *twoskyClient) download(ctx context.Context, l *slog.Logger) (err error)
|
||||
return nil
|
||||
}
|
||||
|
||||
// printFailedLocales prints sorted list of failed downloads, if any.
|
||||
func printFailedLocales(ctx context.Context, l *slog.Logger, failed *sync.Map) {
|
||||
keys := []string{}
|
||||
failed.Range(func(k, _ any) bool {
|
||||
s, ok := k.(string)
|
||||
if !ok {
|
||||
panic("unexpected type")
|
||||
}
|
||||
|
||||
keys = append(keys, s)
|
||||
|
||||
return true
|
||||
})
|
||||
// printFailedLocales prints sorted list of failed downloads, if any. l and
|
||||
// failed must not be nil.
|
||||
func printFailedLocales(
|
||||
ctx context.Context,
|
||||
l *slog.Logger,
|
||||
failed *syncutil.Map[string, struct{}],
|
||||
) {
|
||||
var keys []string
|
||||
for k := range failed.Range {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
|
||||
if len(keys) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
slices.Sort(keys)
|
||||
|
||||
l.InfoContext(ctx, "failed", "locales", keys)
|
||||
}
|
||||
|
||||
@ -100,7 +100,7 @@ func printFailedLocales(ctx context.Context, l *slog.Logger, failed *sync.Map) {
|
||||
type downloadWorker struct {
|
||||
ctx context.Context
|
||||
l *slog.Logger
|
||||
failed *sync.Map
|
||||
failed *syncutil.Map[string, struct{}]
|
||||
client *http.Client
|
||||
uriCh <-chan *url.URL
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user