Compare commits

..

19 Commits

Author SHA1 Message Date
Eugene Burkov
ac8a0ec570 Pull request 2360: Update all
Merge in DNS/adguard-home from upd-all to master

Squashed commit of the following:

commit a9ec07f3810d94f1119d727a317db05a5f0d2d81
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Mon Mar 10 18:26:30 2025 +0300

    client: upd data

commit f1cba36a0048e47f28a9ed481d51529e82e24283
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Mon Mar 10 18:18:46 2025 +0300

    all: upd proxy
2025-03-10 18:38:11 +03:00
Stanislav Chzhen
3255efcaf3 Pull request 2354: AGDNS-2690-global-context-tls
Merge in DNS/adguard-home from AGDNS-2690-global-context-tls to master

Squashed commit of the following:

commit ae1d9e6f3f3b8abefbc5e776eb256577f7fbbb0f
Merge: 6f30f488a bf9be98c7
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Mon Mar 10 18:15:24 2025 +0300

    Merge branch 'master' into AGDNS-2690-global-context-tls

commit 6f30f488aa2305e518000dc6c1028ede83bf1cc6
Merge: baa187ab0 66fba942c
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Mon Mar 10 15:08:47 2025 +0300

    Merge branch 'master' into AGDNS-2690-global-context-tls

commit baa187ab0b6db7f41e49dece7b4d0430409e7cae
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Mon Mar 10 15:08:39 2025 +0300

    home: imp docs

commit 96a09389c5049a84bb30ed285cc5e1df9aaa438f
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Thu Mar 6 20:15:05 2025 +0300

    home: imp docs

commit 1cd007707af4a7a5160c8fe21b20b84543d59e5a
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Thu Mar 6 18:54:07 2025 +0300

    home: imp docs

commit ad3d2b6616c2c3aba566a2158ffc597e5802929f
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Tue Mar 4 19:38:45 2025 +0300

    home: global context tls
2025-03-10 18:24:41 +03:00
Eugene Burkov
bf9be98c71 Pull request 2357: 7555-fix-ra-packets
Merge in DNS/adguard-home from 7555-fix-ra-packets to master

* commit '0ed2cd04b22a7b447380ee863bc908603720877d':
  dhcpd: imp docs
  all: fix changelog
  dhcpd: imp docs
  all: imp code & test, log changes
  Change comment message to match implementation
  dhcpd: Fix slaac configuration which was not working due to invalid icmp packet
2025-03-10 16:30:15 +03:00
Eugene Burkov
0ed2cd04b2 Merge branch 'master' into 7555-fix-ra-packets 2025-03-10 16:17:54 +03:00
Ildar Kamalov
66fba942c8 Pull request: ADG-9775 fix disabled button for autofilled login form
Merge in DNS/adguard-home from ADG-9775 to master

Squashed commit of the following:

commit 3544ba8d463d80c69285fba4af1332e80cd2f0c8
Merge: 9631f6c4d 7f9cef948
Author: Ildar Kamalov <ik@adguard.com>
Date:   Mon Mar 10 13:55:27 2025 +0300

    Merge branch 'master' into ADG-9775

commit 9631f6c4d4e32a5f241ff30b0db9f51fcc7635dc
Author: Ildar Kamalov <ik@adguard.com>
Date:   Mon Mar 10 12:30:25 2025 +0300

    add changelog

commit 49fa7fe189f69758011cbdf8f78744bef5fcd0a0
Author: Ildar Kamalov <ik@adguard.com>
Date:   Fri Mar 7 17:02:45 2025 +0300

    ADG-9775 fix disabled button for autofilled login form
2025-03-10 14:25:56 +03:00
Eugene Burkov
7f9cef948c Pull request 2358: Update all
Merge in DNS/adguard-home from upd-all to master

Squashed commit of the following:

commit fb5e87e0cb5617d031a2dac932304917722b1a89
Merge: af4ef937e 64994c7fc
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Fri Mar 7 18:30:39 2025 +0300

    Merge branch 'master' into upd-all

commit af4ef937ee9ae1046cda083a4b0cb6b41ca3dc8c
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Fri Mar 7 12:50:48 2025 +0300

    all: log changes, revert trackers

commit ca1197dc69bb845daa5ec3f25d58d995f3d330ef
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Thu Mar 6 19:33:24 2025 +0300

    client: upd i18n

commit d6aa69668633afcabdf956a3e82b920077ddbc75
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Thu Mar 6 19:24:57 2025 +0300

    client: upd vetted filters, companiesdb, blocked services

commit ed6f706c8eafe248b1e851bb0b123f1c46795414
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Thu Mar 6 19:20:32 2025 +0300

    ipset: add bench results

commit 89c1fbe257163aebcddd1abf85b8e4d87536e0ef
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Thu Mar 6 19:14:34 2025 +0300

    all: upd go, tools
2025-03-07 18:51:31 +03:00
Eugene Burkov
3be90f7b75 Merge branch 'master' into 7555-fix-ra-packets 2025-03-07 18:32:14 +03:00
Ildar Kamalov
64994c7fcb Pull request: ADG-9715 formatting of elapsed times less than one millisecond
Merge in DNS/adguard-home from ADG-9715 to master

Squashed commit of the following:

commit d972608ad5429810e0f5ad430f11e037cd05ee40
Author: Ildar Kamalov <ik@adguard.com>
Date:   Thu Mar 6 12:46:29 2025 +0300

    ADG-9715 formatting of elapsed times less than one millisecond
2025-03-07 16:42:37 +03:00
Eugene Burkov
4b0db6d397 dhcpd: imp docs 2025-03-07 13:01:34 +03:00
Eugene Burkov
777b310a4b all: fix changelog 2025-03-06 16:12:10 +03:00
Eugene Burkov
148a407f6c Merge branch 'master' into 7555-fix-ra-packets 2025-03-06 16:03:25 +03:00
Eugene Burkov
ed947a048e dhcpd: imp docs 2025-03-06 15:54:02 +03:00
Eugene Burkov
74640fb06c all: imp code & test, log changes 2025-03-06 15:15:06 +03:00
Stanislav Chzhen
0d2163c1d6 Pull request 2355: AGDNS-2686-client-manager-clock
Merge in DNS/adguard-home from AGDNS-2686-client-manager-clock to master

Squashed commit of the following:

commit 1d3cafa7f1036a72b766feaee1db00398e51c364
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Tue Mar 4 20:52:39 2025 +0300

    all: client manager clock
2025-03-04 21:18:22 +03:00
Stanislav Chzhen
318bd2901a Pull request 2346: AGDNS-2686-client-upstream-manager
Merge in DNS/adguard-home from AGDNS-2686-client-upstream-manager to master

Squashed commit of the following:

commit 563cb583f01c26434fa04d0e37dcbe2ba15c0912
Merge: f4b0caf5c 61fe269cb
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Mon Mar 3 19:07:35 2025 +0300

    Merge branch 'master' into AGDNS-2686-client-upstream-manager

commit f4b0caf5c8bc48ee8be97f031cd1aa1399eb461c
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Thu Feb 27 21:52:51 2025 +0300

    client: imp docs

commit e7d74931b1cc9b62eeadbe1168ae5781d57d6c73
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Wed Feb 26 21:44:04 2025 +0300

    client: imp code

commit 1cba38c1bc3b6b5afb7829c230c4e831f789647e
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Wed Feb 26 18:06:17 2025 +0300

    client: fix typo

commit 65b6b1e8c0fde47f367c428a78fefc4c63bc45f9
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Wed Feb 26 17:52:02 2025 +0300

    all: imp code, docs

commit ed158ef09fc26bc9c57c91dbfa04d89fede583d0
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Wed Feb 26 14:34:50 2025 +0300

    client: imp code

commit ab897f64c8751ea158408521116d5b689e6d39a9
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Tue Feb 25 18:26:16 2025 +0300

    all: upd chlog

commit a2c30e3ede6fb61f6d23fd392cc3035dc96f77af
Merge: bdb08ee0e d8ce5b453
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Tue Feb 25 17:40:32 2025 +0300

    Merge branch 'master' into AGDNS-2686-client-upstream-manager

commit bdb08ee0e6122de727f2749a44f5df7e29d0eee2
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Tue Feb 25 17:16:31 2025 +0300

    all: imp tests

commit 00f0eb60474a2297567acf5a3a27e8b5c2d99229
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Thu Feb 20 21:37:58 2025 +0300

    all: imp code, docs

commit 13934176636dd70a17e53bc1956d6cf51602760a
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Wed Feb 19 15:58:11 2025 +0300

    all: client upstream manager
2025-03-03 19:19:46 +03:00
Stanislav Chzhen
61fe269cb8 Pull request 2352: AGDNS-2690-signal-handler
Merge in DNS/adguard-home from AGDNS-2690-signal-handler to master

Squashed commit of the following:

commit b6822142312ac814e7c206218bb079a4f364192a
Merge: f597ea1fd 8b2ab8ea8
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Mon Mar 3 18:10:27 2025 +0300

    Merge branch 'master' into AGDNS-2690-signal-handler

commit f597ea1fd27c1153f2b08a339fd17361807627e6
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Thu Feb 27 20:45:55 2025 +0300

    all: fix logger

commit 582e315ecac45e49e156bddb5755f5fb7114111c
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Thu Feb 27 18:40:57 2025 +0300

    home: imp code

commit 1e0f48d32a654b71a9c0a9e3cf3afceab00bc7e5
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Thu Feb 27 15:26:19 2025 +0300

    home: imp docs

commit aa43bbc1b20392429d606de5cfd1b1fed940755a
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Mon Feb 24 17:24:33 2025 +0300

    home: signal handler
2025-03-03 18:23:01 +03:00
Ildar Kamalov
8b2ab8ea87 Pull request 2322: ADG-9415
Merge in DNS/adguard-home from ADG-9415 to master

Squashed commit of the following:

commit 76bf99499a
Merge: 29529970a 0389515ee
Author: Ildar Kamalov <ik@adguard.com>
Date:   Wed Feb 26 18:31:41 2025 +0300

    Merge branch 'master' into ADG-9415

commit 29529970a3
Merge: b49790daf 782a1a982
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Mon Feb 24 15:44:38 2025 +0300

    Merge branch 'master' into ADG-9415

commit b49790daf8
Author: Ildar Kamalov <ik@adguard.com>
Date:   Mon Feb 24 15:30:18 2025 +0300

    fix default lease duration value

commit cb307472ec
Author: Ildar Kamalov <ik@adguard.com>
Date:   Mon Feb 24 10:35:26 2025 +0300

    fix default response status

commit 115e743e1a
Author: Ildar Kamalov <ik@adguard.com>
Date:   Mon Feb 24 10:32:46 2025 +0300

    fix upstream description

commit 26b0eddaca
Author: Ildar Kamalov <ik@adguard.com>
Date:   Tue Feb 18 17:40:41 2025 +0300

    use const for test config file

commit 58faa7c537
Author: Ildar Kamalov <ik@adguard.com>
Date:   Tue Feb 18 17:31:04 2025 +0300

    fix install config

commit 0a3346d911
Author: Ildar Kamalov <ik@adguard.com>
Date:   Mon Feb 17 15:25:23 2025 +0300

    fix install check config

commit 17c4c26ea8
Author: Ildar Kamalov <ik@adguard.com>
Date:   Fri Feb 14 17:18:20 2025 +0300

    fix query log

commit 14a2685ae3
Author: Ildar Kamalov <ik@adguard.com>
Date:   Fri Feb 14 15:52:36 2025 +0300

    fix dhcp initial values

commit e7a8db7afd
Author: Ildar Kamalov <ik@adguard.com>
Date:   Fri Feb 14 14:37:24 2025 +0300

    fix encryption form values

commit 1c8917f7ac
Author: Ildar Kamalov <ik@adguard.com>
Date:   Fri Feb 14 14:07:29 2025 +0300

    fix blocked services submit

commit 4dfa536cea
Author: Ildar Kamalov <ik@adguard.com>
Date:   Fri Feb 14 13:50:47 2025 +0300

    dns config ip validation

commit 4fee83fe13
Author: Ildar Kamalov <ik@adguard.com>
Date:   Wed Feb 12 17:49:54 2025 +0300

    add playwright warning

commit 8c2f36e7a6
Author: Ildar Kamalov <ik@adguard.com>
Date:   Tue Feb 11 18:36:18 2025 +0300

    fix config file name

commit 83db5f33dc
Author: Ildar Kamalov <ik@adguard.com>
Date:   Tue Feb 11 16:16:43 2025 +0300

    temp config file

commit 9080c1620f
Author: Ildar Kamalov <ik@adguard.com>
Date:   Tue Feb 11 15:01:46 2025 +0300

    update readme

commit ee1520307f
Merge: fd12e33c0 2fe2d254b
Author: Ildar Kamalov <ik@adguard.com>
Date:   Tue Feb 11 14:44:06 2025 +0300

    Merge branch 'master' into ADG-9415

commit fd12e33c06
Author: Igor Lobanov <bniwredyc@gmail.com>
Date:   Mon Feb 10 10:29:43 2025 +0100

    added typecheck on build, fixed eslint

commit b3849eebc4
Merge: 225167a8b 9bf3ee128
Author: Igor Lobanov <bniwredyc@gmail.com>
Date:   Mon Feb 10 09:43:32 2025 +0100

    Merge branch 'ADG-9415' of https://bit.int.agrd.dev/scm/dns/adguard-home into ADG-9415

... and 94 more commits
2025-02-26 19:37:52 +03:00
Gunjan Gupta
0c72cde4c3 Change comment message to match implementation
Signed-off-by: Gunjan Gupta <viraniac@gmail.com>
2025-01-04 01:50:00 +05:30
Gunjan Gupta
b1657c2b2a dhcpd: Fix slaac configuration which was not working due to invalid icmp packet
Signed-off-by: Gunjan Gupta <viraniac@gmail.com>
2025-01-04 01:12:28 +05:30
73 changed files with 1416 additions and 931 deletions

View File

@@ -1,7 +1,7 @@
'name': 'build'
'env':
'GO_VERSION': '1.23.6'
'GO_VERSION': '1.24.1'
'NODE_VERSION': '18'
'on':

View File

@@ -1,7 +1,7 @@
'name': 'lint'
'env':
'GO_VERSION': '1.23.6'
'GO_VERSION': '1.24.1'
'on':
'push':

View File

@@ -18,12 +18,27 @@ See also the [v0.107.58 GitHub milestone][ms-v0.107.58].
NOTE: Add new changes BELOW THIS COMMENT.
-->
### Security
- Go version has been updated to prevent the possibility of exploiting the Go vulnerabilities fixed in [1.24.1][go-1.24.1].
### Fixed
- Invalid ICMPv6 Router Advertisement messages ([#7547]).
- Disabled button for autofilled login form.
- Formatting of elapsed times less than one millisecond.
- Changes to global upstream DNS settings not applying to custom client upstream configurations.
- The formatting of large numbers in the clients tables on the *Client settings* page ([#7583]).
[#7547]: https://github.com/AdguardTeam/AdGuardHome/issues/7547
[#7583]: https://github.com/AdguardTeam/AdGuardHome/issues/7583
[go-1.24.1]: https://groups.google.com/g/golang-announce/c/4t3lzH3I0eI
<!--
NOTE: Add new changes ABOVE THIS COMMENT.
-->
@@ -47,6 +62,7 @@ See also the [v0.107.57 GitHub milestone][ms-v0.107.57].
### Fixed
- The hostnames of DHCP clients not being shown in the *Top clients* table on the dashboard ([#7627]).
- The formatting of large numbers in the upstream table and query log ([#7590]).
[#7590]: https://github.com/AdguardTeam/AdGuardHome/issues/7590

View File

@@ -27,7 +27,7 @@ DIST_DIR = dist
GOAMD64 = v1
GOPROXY = https://proxy.golang.org|direct
GOTELEMETRY = off
GOTOOLCHAIN = go1.23.6
GOTOOLCHAIN = go1.24.1
GPG_KEY = devteam@adguard.com
GPG_KEY_PASSPHRASE = not-a-real-password
NPM = npm

View File

@@ -8,7 +8,7 @@
'variables':
'channel': 'edge'
'dockerFrontend': 'adguard/home-js-builder:2.1-bullseye'
'dockerGo': 'adguard/go-builder:1.23.6--1'
'dockerGo': 'adguard/go-builder:1.24.1--1'
'stages':
- 'Build frontend':
@@ -278,7 +278,7 @@
'variables':
'channel': 'beta'
'dockerFrontend': 'adguard/home-js-builder:2.1-bullseye'
'dockerGo': 'adguard/go-builder:1.23.6--1'
'dockerGo': 'adguard/go-builder:1.24.1--1'
# release-vX.Y.Z branches are the branches from which the actual final
# release is built.
- '^release-v[0-9]+\.[0-9]+\.[0-9]+':
@@ -294,4 +294,4 @@
'variables':
'channel': 'release'
'dockerFrontend': 'adguard/home-js-builder:2.1-bullseye'
'dockerGo': 'adguard/go-builder:1.23.6--1'
'dockerGo': 'adguard/go-builder:1.24.1--1'

View File

@@ -6,7 +6,7 @@
'name': 'AdGuard Home - Build and run tests'
'variables':
'dockerFrontend': 'adguard/home-js-builder:2.1-bullseye'
'dockerGo': 'adguard/go-builder:1.23.6--1'
'dockerGo': 'adguard/go-builder:1.24.1--1'
'channel': 'development'
'stages':
@@ -234,5 +234,5 @@
# may need to build a few of these.
'variables':
'dockerFrontend': 'adguard/home-js-builder:2.1-bullseye'
'dockerGo': 'adguard/go-builder:1.23.6--1'
'dockerGo': 'adguard/go-builder:1.24.1--1'
'channel': 'candidate'

View File

@@ -327,10 +327,10 @@
"rate_limit_whitelist_placeholder": "Voer één IP-adres per regel in",
"blocking_ipv4_desc": "IP-adres dat moet worden teruggegeven voor een geblokkeerd A-verzoek",
"blocking_ipv6_desc": "IP-adres dat moet worden teruggegeven voor een geblokkeerd A-verzoek",
"blocking_mode_default": "Standaard: Reageer met een nul IP adres (0.0.0.0 for A; :: voor AAAA) wanneer geblokkeerd door een Adblock-type regel; reageer met het IP-adres dat is opgegeven in de regel wanneer geblokkeerd door een /etc/hosts type regel",
"blocking_mode_default": "Standaard: Reageer met een nul IP-adres (0.0.0.0 for A; :: voor AAAA) wanneer geblokkeerd door een Adblock-type regel; reageer met het IP-adres dat is opgegeven in de regel wanneer geblokkeerd door een /etc/hosts type regel",
"blocking_mode_refused": "REFUSED: Antwoorden met REFUSED code",
"blocking_mode_nxdomain": "NXDOMAIN: Reageer met NXDOMAIN code",
"blocking_mode_null_ip": "Nul IP: Reageer met een nul IP address (0.0.0.0 voor A; :: voor AAAA)",
"blocking_mode_null_ip": "Nul IP: Reageer met een nul IP-adres (0.0.0.0 voor A; :: voor AAAA)",
"blocking_mode_custom_ip": "Aangepast IP: Reageer met een handmatige ingesteld IP adres",
"theme_auto": "Automatisch",
"theme_light": "Licht",

View File

@@ -40,11 +40,11 @@
"dhcp_ipv4_settings": "DHCP IPv4 Ayarları",
"dhcp_ipv6_settings": "DHCP IPv6 Ayarları",
"form_error_required": "Gerekli alan",
"form_error_ip4_format": "Geçersiz IPv4 adresi",
"form_error_ip4_gateway_format": "Geçersiz ağ geçidi IPv4 adresi",
"form_error_ip6_format": "Geçersiz IPv6 adresi",
"form_error_ip_format": "Geçersiz IP adresi",
"form_error_mac_format": "Geçersiz MAC adresi",
"form_error_ip4_format": "IPv4 adresi geçersiz",
"form_error_ip4_gateway_format": "Ağ geçidi IPv4 adresi geçersiz",
"form_error_ip6_format": "IPv6 adresi geçersiz",
"form_error_ip_format": "IP adresi geçersiz",
"form_error_mac_format": "MAC adresi geçersiz",
"form_error_client_id_format": "İstemci Kimliği yalnızca sayılar, küçük harfler ve kısa çizgiler içermelidir",
"form_error_server_name": "Sunucu adı geçersiz",
"form_error_subnet": "\"{{cidr}}\" alt ağı, \"{{ip}}\" IP adresini içermiyor",
@@ -68,7 +68,7 @@
"ip": "IP",
"dhcp_table_hostname": "Ana makine Adı",
"dhcp_table_expires": "Bitiş tarihi",
"dhcp_warning": "DHCP sunucusunu yine de etkinleştirmek istiyorsanız, ağınızda başka aktif DHCP sunucusu olmadığından emin olun, aksi takdirde ağa bağlı cihazların internet bağlantısı kesilebilir!",
"dhcp_warning": "DHCP sunucusunu yine de etkinleştirmek istiyorsanız, ağınızda başka bir aktif DHCP sunucusu olmadığından emin olun, aksi takdirde ağa bağlı cihazların internet bağlantısı kesilebilir!",
"dhcp_error": "AdGuard Home, ağda başka bir etkin DHCP sunucusu olup olmadığını belirleyemedi",
"dhcp_static_ip_error": "DHCP sunucusunu kullanmak için sabit bir IP adresi ayarlanmalıdır. AdGuard Home, bu ağ arayüzünün sabit bir IP adresi kullanılarak yapılandırılıp yapılandırılmadığını belirleyemedi. Lütfen sabit IP adresini elle ayarlayın.",
"dhcp_dynamic_ip_found": "Sisteminiz, <0>{{interfaceName}}</0> arayüzü için dinamik IP adresi yapılandırması kullanıyor. DHCP sunucusunu kullanmak için sabit bir IP adresi ayarlanmalıdır. Geçerli olan IP adresiniz <0>{{ipAddress}}</0>. \"DHCP sunucusunu etkinleştir\" düğmesine basarsanız, AdGuard Home bu IP adresini otomatik bir şekilde sabit olarak ayarlayacaktır.",
@@ -147,13 +147,13 @@
"average_upstream_response_time": "Ortalama üst kaynak yanıt süresi",
"response_time": "Yanıt süresi",
"average_processing_time_hint": "Bir DNS isteğinin milisaniye cinsinden ortalama işlem süresi",
"block_domain_use_filters_and_hosts": "Filtre ve hosts dosyalarını kullanarak alan adlarını engelle",
"block_domain_use_filters_and_hosts": "Filtre ve ana bilgisayar dosyalarını kullanarak alan adlarını engelle",
"filters_block_toggle_hint": "<a>Filtreler</a> ayarlarında engelleme kuralları oluşturabilirsiniz.",
"use_adguard_browsing_sec": "AdGuard gezinti koruması web hizmetini kullan",
"use_adguard_browsing_sec_hint": "AdGuard Home, alan adının gezinti koruması web hizmeti tarafından engellenip engellenmediğini kontrol eder. Kontrolü gerçekleştirmek için gizlilik dostu arama API'sini kullanır: sunucuya yalnızca SHA256 karma alan adının kısa bir ön eki gönderilir.",
"use_adguard_parental": "AdGuard ebeveyn denetimi web hizmetini kullan",
"use_adguard_parental_hint": "AdGuard Home, alan adının yetişkin içerik bulundurup bulundurmadığını kontrol eder. Gezinti koruması web hizmeti ile kullandığımız aynı gizlilik dostu API'yi kullanır.",
"enforce_safe_search": "Güvenli Aramayı kullan",
"enforce_safe_search": "Güvenli aramayı kullan",
"enforce_save_search_hint": "AdGuard Home, şu arama motorlarında güvenli aramayı uygular: Google, YouTube, Bing, DuckDuckGo, Ecosia, Yandex, Pixabay.",
"no_servers_specified": "Sunucu belirtilmedi",
"general_settings": "Genel ayarlar",
@@ -294,6 +294,9 @@
"blocked_response_ttl": "Engellenen yanıt kullanım süresi",
"blocked_response_ttl_desc": "İstemcilerin filtrelenmiş bir yanıtı kaç saniye süreyle önbelleğe alması gerektiğini belirtir",
"form_enter_blocked_response_ttl": "Engellenen yanıt kullanım süresini girin (saniye)",
"upstream_timeout": "Üst kaynak zaman aşımı",
"upstream_timeout_desc": "Üst kaynak sunucusundan yanıt almak için kaç saniye bekleneceğini belirtir",
"form_enter_upstream_timeout": "Üst kaynak sunucusu zaman aşımı süresini saniye cinsinden girin",
"dnscrypt": "DNSCrypt",
"dns_over_https": "DNS-over-HTTPS",
"dns_over_tls": "DNS-over-TLS",
@@ -308,7 +311,7 @@
"form_enter_rate_limit": "Sıklık limitini girin",
"rate_limit": "Sıklık limiti",
"edns_enable": "EDNS istemci alt ağını etkinleştir",
"edns_cs_desc": "Kaynak yönü isteklerine EDNS İstemci Alt Ağı seçeneğini (ECS) ekleyin ve istemciler tarafından gönderilen değerleri sorgu günlüğüne kaydedin.",
"edns_cs_desc": "Üst sunucu isteklerine ECS (EDNS İstemci Alt Ağı) seçeneğini ekler ve istemciler tarafından gönderilen değerleri sorgu günlüğünde kaydeder.",
"edns_use_custom_ip": "EDNS için özel IP kullan",
"edns_use_custom_ip_desc": "EDNS için özel IP kullanımına izin ver",
"rate_limit_desc": "İstemci başına izin verilen saniyedeki istek sayısı. 0 olarak ayarlamak, sınır olmadığı anlamına gelir.",
@@ -342,17 +345,17 @@
"unknown_filter": "Bilinmeyen filtre {{filterId}}",
"known_tracker": "Bilinen izleyici",
"install_welcome_title": "AdGuard Home'a hoş geldiniz!",
"install_welcome_desc": "AdGuard Home, ağ genelinde reklamları ve izleyicileri engelleyen bir DNS sunucusudur. Tüm ağınızı ve tüm cihazlarınızı kontrol etmenizi sağlar, istemci tarafında herhangi bir program kullanmanıza gerek duymaz.",
"install_welcome_desc": "AdGuard Home, ağ genelinde reklam ve izleyici engelleyen bir DNS sunucusudur. Tüm ağınızı ve cihazlarınızı kontrol etmenizi sağlar ve istemci tarafında ek bir yazılım kullanmanıza gerek duymaz.",
"install_settings_title": "Yönetici Web Arayüzü",
"install_settings_listen": "Dinleme arayüzü",
"install_settings_port": "Bağlantı noktası",
"install_settings_interface_link": "AdGuard Home yönetici web arayüzünüz aşağıdaki adreslerde bulunacaktır:",
"install_settings_interface_link": "AdGuard Home yönetici web arayüzüne aşağıdaki adreslerden erişebilirsiniz:",
"form_error_port": "Geçerli bir bağlantı noktası değeri girin",
"install_settings_dns": "DNS sunucusu",
"install_settings_dns_desc": "Aşağıdaki adreslerde DNS sunucusunu kullanmak için cihazlarınızı veya yönlendiricinizi yapılandırmanız gerekir:",
"install_settings_dns_desc": "Cihazlarınızı veya yönlendiricinizi aşağıdaki adreslerdeki DNS sunucusunu kullanacak şekilde yapılandırmanız gerekir:",
"install_settings_all_interfaces": "Tüm arayüzler",
"install_auth_title": "Kimlik Doğrulama",
"install_auth_desc": "AdGuard Home yönetim web arayüzü için şifre doğrulaması yapılandırılmalıdır. AdGuard Home'a yalnızca yerel ağınızdan erişilebilir olsa bile, onu sınırsız erişimden korumak yine de önemlidir.",
"install_auth_desc": "AdGuard Home yönetici web arayüzüne parola ile kimlik doğrulama yapılandırılmalıdır. AdGuard Home yalnızca yerel ağınızdan erişilebilir olsa bile, yine de yetkisiz erişime karşı korunması önemlidir.",
"install_auth_username": "Kullanıcı adı",
"install_auth_password": "Parola",
"install_auth_confirm": "Parolayı onayla",
@@ -366,10 +369,10 @@
"install_devices_router": "Yönlendirici",
"install_devices_router_desc": "Bu kurulum, ev yönlendiricinize bağlı tüm cihazları otomatik olarak kapsar ve her birini elle yapılandırmanıza gerek yoktur.",
"install_devices_address": "AdGuard Home DNS sunucusu aşağıdaki adresleri dinliyor",
"install_devices_router_list_1": "Yönlendiricinizin ayarlarına gidin. Genellikle tarayıcınızdan http://192.168.0.1/ veya http://192.168.1.1/ gibi bir URL aracılığıyla erişebilirsiniz. Bir parola girmeniz istenebilir. Hatırlamıyorsanız, genellikle yönlendiricinin üzerindeki bir düğmeye basarak parolayı sıfırlayabilirsiniz, ancak bu işlemin seçilmesi durumunda yüksek ihtimalle tüm yönlendirici yapılandırmasını kaybedeceğinizi unutmayın. Yönlendiricinizin kurulumu için bir uygulama gerekiyorsa, lütfen uygulamayı telefonunuza veya PC'nize yükleyin ve yönlendiricinin ayarlarına erişmek için kullanın.",
"install_devices_router_list_1": "Yönlendiricinizin ayarlarına gidin. Genellikle, tarayıcınızdan http://192.168.0.1/ veya http://192.168.1.1/ gibi bir URL üzerinden erişebilirsiniz. Giriş yaparken bir parola girmeniz istenebilir. Parolanızı hatırlamıyorsanız, genellikle yönlendiricinin üzerindeki bir düğmeye basarak parolayı sıfırlayabilirsiniz, ancak bu işlemi seçerseniz yönlendiricinin tüm yapılandırmasını kaybedebileceğinizi unutmayın. Yönlendiricinizin kurulumu için bir uygulama gerekiyorsa, lütfen uygulamayı telefonunuza veya bilgisayarınıza yükleyin ve yönlendiricinin ayarlarına erişmek için bu uygulamayı kullanın.",
"install_devices_router_list_2": "DHCP/DNS ayarlarını bulun. DNS satırlarını arayın, genelde iki veya üç tanedir, üç rakam girilebilen dört ayrı grup içeren satırdır.",
"install_devices_router_list_3": "AdGuard Home sunucu adreslerinizi oraya girin.",
"install_devices_router_list_4": "Bazı yönlendirici türlerinde özel bir DNS sunucusu ayarlanamaz. Bu durumda, AdGuard Home'u <0>DHCP sunucusu</0> olarak ayarlamak yardımcı olabilir. Aksi takdirde, yönlendirici modeliniz için DNS sunucularını nasıl ayarlayacağınız konusunda yönlendirici kılavuzuna bakmalısınız.",
"install_devices_router_list_4": "Bazı yönlendirici türlerinde özel bir DNS sunucusu yapılandırılamaz. Bu durumda, AdGuard Home'u bir <0>DHCP sunucusu</0> olarak yapılandırmak yardımcı olabilir. Aksi takdirde, yönlendirici modelinizde DNS sunucularını nasıl özelleştireceğinizi öğrenmek için yönlendirici kılavuzunu kontrol etmelisiniz.",
"install_devices_windows_list_1": "Başlat menüsünden veya Windows araması aracılığıyla Denetim Masası'nıın.",
"install_devices_windows_list_2": "Ağ ve İnternet kategorisine girin ve ardından Ağ ve Paylaşım Merkezi'ne girin.",
"install_devices_windows_list_3": "Sol panelde \"Bağdaştırıcı ayarlarını değiştirin\" öğesine tıklayın.",
@@ -389,7 +392,7 @@
"install_devices_ios_list_2": "Sol menüde bulunan Wi-Fi bölümüne girin (telefon ağlar için özel DNS sunucusu ayarlanamaz).",
"install_devices_ios_list_3": "O anda aktif olan ağın adına dokunun.",
"install_devices_ios_list_4": "DNS alanına AdGuard Home sunucunuzun adreslerini girin.",
"get_started": "Başlayın",
"get_started": "Başla",
"next": "Sonraki",
"open_dashboard": "Panoyu Aç",
"install_saved": "Başarıyla kaydedildi",
@@ -452,14 +455,14 @@
"settings_global": "Genel",
"settings_custom": "Özel",
"table_client": "İstemci",
"table_name": "AdAdı",
"table_name": "Ad",
"save_btn": "Kaydet",
"client_add": "İstemci Ekle",
"client_new": "Yeni İstemci",
"client_edit": "İstemciyi Düzenle",
"client_identifier": "Tanımlayıcı",
"ip_address": "IP adresi",
"client_identifier_desc": "İstemciler IP adresleri, CIDR, MAC adresleri veya ClientID (DoT/DoH/DoQ için kullanılabilir) ile tanımlanabilir. İstemcileri nasıl tanımlayacağınız hakkında daha fazla bilgiyi <0>buradan</0> edinebilirsiniz.",
"client_identifier_desc": "İstemciler, IP adresi, CIDR, MAC adresi veya ClientID (DoT/DoH/DoQ için kullanılabilir) ile tanımlanabilir. İstemcileri nasıl tanımlayacağınız hakkında daha fazla bilgiye <0>buradan</0> ulaşabilirsiniz.",
"form_enter_ip": "IP girin",
"form_enter_subnet_ip": "\"{{cidr}}\" alt ağına bir IP adresi girin",
"form_enter_mac": "MAC adresi girin",
@@ -476,7 +479,7 @@
"client_confirm_delete": "\"{{key}}\" istemcisini silmek istediğinizden emin misiniz?",
"list_confirm_delete": "Bu listeyi silmek istediğinizden emin misiniz?",
"auto_clients_title": "Çalışma zamanı istemcileri",
"auto_clients_desc": "AdGuard Home'u kullanan veya kullanabilecek cihazların IP adresleri hakkında bilgiler. Bu bilgiler, hosts dosyaları, ters DNS, vb. dâhil olmak üzere çeşitli kaynaklardan toplanır.",
"auto_clients_desc": "AdGuard Home'u kullanan veya kullanabilecek cihazların IP adresleri hakkında bilgiler. Bu bilgiler, ana bilgisayar dosyaları, ters DNS sorguları ve çeşitli diğer kaynaklardan toplanmaktadır.",
"access_title": "Erişim ayarları",
"access_desc": "AdGuard Home DNS sunucusu için erişim kurallarını buradan yapılandırabilirsiniz",
"access_allowed_title": "İzin verilen istemciler",
@@ -598,12 +601,12 @@
"disable_ipv6": "IPv6 adreslerinin çözümlenmesini devre dışı bırak",
"disable_ipv6_desc": "IPv6 adresleri için tüm DNS sorgularını bırakın (AAAA yazın) ve HTTPS yanıtlarından IPv6 ipuçlarını kaldırın.",
"fastest_addr": "En hızlı IP adresi",
"fastest_addr_desc": "Tüm DNS sunucularını sorgulayın ve tüm yanıtlar arasından en hızlı olan IP adresini döndürün. AdGuard Home'un tüm DNS sunucularından yanıt beklemesi gerektiği için DNS sorgularını yavaşlatır, ancak genel bağlantıyı iyileştirir.",
"fastest_addr_desc": "<b>Tüm</b> DNS sunucularından yanıt bekler, her sunucu için TCP bağlantı hızını ölçer ve en hızlı bağlantı hızına sahip sunucunun IP adresini döndürür.<br/>Bu yapılandırma, bir veya daha fazla üst kaynak sunucusu yanıt vermediğinde, DNS sorgularını önemli ölçüde yavaşlatabilir. Üst kaynak sunucularınızın kararlı olduğundan ve üst kaynak zaman aşım sürenizin düşük olduğundan emin olun.",
"autofix_warning_text": "\"Düzelt\" seçeneğine tıklarsanız, AdGuard Home, sisteminizi AdGuard Home DNS sunucusunu kullanacak şekilde yapılandırır.",
"autofix_warning_list": "Bu görevleri gerçekleştirir: <0>Sistem DNSStubListener'ı devre dışı bırakın</0> <0>DNS sunucusu adresini 127.0.0.1 olarak ayarlayın</0> <0>/etc/resolv.conf'un sembolik bağlantı hedefini /run/systemd/resolve/resolv.conf ile değiştirin<0> <0>DNSStubListener'ı durdurun (systemd çözümlenmiş hizmeti yeniden yükleyin)</0>",
"autofix_warning_result": "Sonuç olarak, sisteminizden gelen tüm DNS istekleri varsayılan olarak AdGuard Home tarafından işlenecektir.",
"tags_title": "Etiketler",
"tags_desc": "İstemciye karşılık gelen etiketleri seçebilirsiniz. Etiketleri daha kesin olarak uygulamak için filtreleme kurallarına dâhil edin. <0>Daha fazla bilgi edinin</0>.",
"tags_desc": "İstemciyi tanımlayan etiketleri seçebilirsiniz. Filtreleme kurallarına etiketleri dahil ederek daha hassas bir şekilde uygulayabilirsiniz. <0>Daha fazla bilgi edinin</0>.",
"form_select_tags": "İstemci etiketlerini seçin",
"check_title": "Filtrelemeyi denetleyin",
"check_desc": "Ana makine adının filtreleme durumunu kontrol edin.",
@@ -624,11 +627,11 @@
"client_blocked": "\"{{ip}}\" istemcisi başarıyla engellendi",
"client_unblocked": "\"{{ip}}\" istemcinin engellemesi başarıyla kaldırıldı",
"static_ip": "Sabit IP adresi",
"static_ip_desc": "AdGuard Home bir sunucudur, bu nedenle düzgün çalışması için sabit bir IP adresine ihtiyacı vardır. Aksi takdirde, yönlendiriciniz bir zaman sonra bu cihaza farklı bir IP adresi atayabilir.",
"static_ip_desc": "AdGuard Home bir sunucudur, bu nedenle düzgün çalışabilmesi için sabit bir IP adresine ihtiyaç duyar. Aksi takdirde, yönlendiriciniz bu cihaza farklı bir IP adresi atayabilir.",
"set_static_ip": "Sabit IP adresi ayarla",
"install_static_ok": "Güzel haber! Sabit IP adresi zaten yapılandırılmış",
"install_static_error": "AdGuard Home, bu ağ arayüzü için otomatik olarak yapılandıramıyor. Lütfen bunu elle nasıl yapacağınızla ilgili talimatlara bakın.",
"install_static_configure": "AdGuard Home, <0>{{ip}}</0> dinamik IP adresinin kullanıldığını tespit etti. Sabit adresiniz olarak ayarlanmasını ister misiniz?",
"install_static_configure": "AdGuard Home, <0>{{ip}}</0> sabit IP adresinin kullanıldığını tespit etti. Sabit adresiniz olarak ayarlanmasını ister misiniz?",
"confirm_static_ip": "AdGuard Home, {{ip}} adresini sabit IP adresiniz olacak şekilde yapılandırır. Devam etmek istiyor musunuz?",
"list_updated": "{{count}} liste güncellendi",
"list_updated_plural": "{{count}} liste güncellendi",
@@ -707,8 +710,8 @@
"custom_rotation_input": "Rotasyonu saat cinsinden girin",
"protection_section_label": "Koruma",
"log_and_stats_section_label": "Sorgu günlüğü ve istatistikler",
"ignore_query_log": "Sorgu günlüğünde bu istemciyi yoksay",
"ignore_statistics": "İstatistiklerde bu istemciyi yoksay",
"ignore_query_log": "Sorgu günlüğünde bu istemciyi gösterme",
"ignore_statistics": "İstatistiklerde bu istemciyi gösterme",
"schedule_services": "Hizmet engellemeyi duraklat",
"schedule_services_desc": "Hizmet engelleme filtresinin duraklatma planını yapılandırın",
"schedule_services_desc_client": "Bu istemci için hizmet engelleme filtresinin duraklatma planını yapılandırın",
@@ -742,6 +745,6 @@
"friday_short": "Cum",
"saturday_short": "Cmt",
"upstream_dns_cache_configuration": "Üst kaynak DNS önbellek yapılandırması",
"enable_upstream_dns_cache": "Bu istemcinin özel üst kaynak yapılandırması için DNS önbelleğe almayı etkinleştir",
"enable_upstream_dns_cache": "Bu istemcinin özel üst kaynak yapılandırması için DNS önbelleğini etkinleştir",
"dns_cache_size": "DNS önbellek boyutu, bayt cinsinden"
}

View File

@@ -314,7 +314,7 @@ const ClientsTable = ({
}
if (!content) {
return content;
}
}
return <LogsSearchLink search={row.original.name}>{content}</LogsSearchLink>;
},
},

View File

@@ -28,12 +28,6 @@ export default {
"homepage": "https://badmojr.github.io/1Hosts/",
"source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_24.txt"
},
"1hosts_mini": {
"name": "1Hosts (mini)",
"categoryId": "general",
"homepage": "https://badmojr.github.io/1Hosts/",
"source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_38.txt"
},
"CHN_adrules": {
"name": "CHN: AdRules DNS List",
"categoryId": "regional",

View File

@@ -669,15 +669,17 @@ export const countClientsStatistics = (ids: any, autoClients: any) => {
* @returns {string}
*/
export const formatElapsedMs = (elapsedMs: string, t: (key: string) => string) => {
const parsedElapsedMs = parseInt(elapsedMs, 10);
const parsedElapsedMs = parseFloat(elapsedMs);
if (Number.isNaN(parsedElapsedMs)) {
return elapsedMs;
}
const formattedMs = formatNumber(parsedElapsedMs);
const formattedValue = parsedElapsedMs < 1
? parsedElapsedMs.toFixed(2)
: Math.floor(parsedElapsedMs).toString();
return `${formattedMs} ${t('milliseconds_abbreviation')}`;
return `${formattedValue} ${t('milliseconds_abbreviation')}`;
};
/**

View File

@@ -1,5 +1,5 @@
{
"timeUpdated": "2025-01-13T10:04:54.031Z",
"timeUpdated": "2025-03-10T15:13:28.992Z",
"categories": {
"0": "audio_video_player",
"1": "comments",
@@ -5940,7 +5940,8 @@
"name": "Digioh",
"categoryId": 4,
"url": "https://digioh.com/",
"companyId": null
"companyId": "digioh",
"source": "AdGuard"
},
"digital.gov": {
"name": "Digital.gov",
@@ -8261,8 +8262,8 @@
},
"google_marketing": {
"name": "Google Marketing",
"categoryId": 6,
"url": "https://marketingplatform.google.com/",
"categoryId": 4,
"url": "https://marketingplatform.google.com/about/enterprise",
"companyId": "google",
"source": "AdGuard"
},
@@ -9058,6 +9059,13 @@
"url": "https://www.ippen-digital.de/",
"companyId": null
},
"id5-sync": {
"name": "ID5 Sync",
"categoryId": 4,
"url": "https://id5.io/",
"companyId": "id5-sync",
"source": "AdGuard"
},
"id_services": {
"name": "ID Services",
"categoryId": 6,
@@ -20948,6 +20956,8 @@
"wunderloop.net": "audience_science",
"12mlbe.com": "audiencerate",
"audiencesquare.com": "audiencesquare.com",
"ad.gt": "audiencesquare.com",
"audigent.com": "audiencesquare.com",
"auditude.com": "auditude",
"audtd.com": "audtd.com",
"cdn.augur.io": "augur",
@@ -21682,9 +21692,6 @@
"dtmpub.com": "dotomi",
"double.net": "double.net",
"2mdn.net": "doubleclick",
"doubleclick.net": "doubleclick",
"invitemedia.com": "doubleclick",
"doubleclick.com": "doubleclick",
"doublepimp.com": "doublepimp",
"doublepimpssl.com": "doublepimp",
"redcourtside.com": "doublepimp",
@@ -21988,6 +21995,7 @@
"cdn.foxpush.net": "foxpush",
"foxpush.com": "foxpush",
"foxtel.com.au": "foxtel",
"foxtelgroupcdn.net.au": "foxtel",
"foxydeal.com": "foxydeal_com",
"yabidos.com": "fraudlogix",
"besucherstatistiken.com": "free_counter",
@@ -22389,6 +22397,8 @@
"maps.google.es": "google_maps",
"maps.google.se": "google_maps",
"maps.gstatic.com": "google_maps",
"doubleclick.net": "google_marketing",
"invitemedia.com": "google_marketing",
"adsense.google.com": "google_marketing",
"adservice.google.ca": "google_marketing",
"adservice.google.co.in": "google_marketing",
@@ -22419,6 +22429,7 @@
"adservice.google.vg": "google_marketing",
"adtrafficquality.google": "google_marketing",
"dai.google.com": "google_marketing",
"doubleclick.com": "google_marketing",
"doubleclickbygoogle.com": "google_marketing",
"googlesyndication-cn.com": "google_marketing",
"duo.google.com": "google_meet",
@@ -22604,6 +22615,9 @@
"icuazeczpeoohx.com": "icuazeczpeoohx.com",
"id-news.net": "id-news.net",
"idcdn.de": "id-news.net",
"eu-1-id5-sync.com": "id5-sync",
"id5-sync.com": "id5-sync",
"id5.io": "id5-sync",
"cdn.id.services": "id_services",
"e-generator.com": "ideal_media",
"idealo.com": "idealo_com",
@@ -23656,6 +23670,7 @@
"blockmetrics.com": "pagefair",
"pagefair.com": "pagefair",
"pagefair.net": "pagefair",
"btloader.com": "pagefair",
"ghmedia.com": "pagescience",
"777seo.com": "paid-to-promote",
"paid-to-promote.net": "paid-to-promote",

View File

@@ -21,7 +21,7 @@ const Form = ({ onSubmit, processing }: LoginFormProps) => {
control,
formState: { isValid },
} = useForm<LoginFormValues>({
mode: 'onBlur',
mode: 'onChange',
defaultValues: {
username: '',
password: '',

89
go.mod
View File

@@ -1,10 +1,10 @@
module github.com/AdguardTeam/AdGuardHome
go 1.23.6
go 1.24.1
require (
github.com/AdguardTeam/dnsproxy v0.75.0
github.com/AdguardTeam/golibs v0.32.1
github.com/AdguardTeam/dnsproxy v0.75.1
github.com/AdguardTeam/golibs v0.32.5
github.com/AdguardTeam/urlfilter v0.20.0
github.com/NYTimes/gziphandler v1.1.1
github.com/ameshkov/dnscrypt/v2 v2.3.0
@@ -15,7 +15,7 @@ require (
// TODO(e.burkov): This package is deprecated; find a new one or use our
// own code for that. Perhaps, use gopacket.
github.com/go-ping/ping v1.2.0
github.com/google/go-cmp v0.6.0
github.com/google/go-cmp v0.7.0
github.com/google/gopacket v1.1.19
github.com/google/renameio/v2 v2.0.0
github.com/google/uuid v1.6.0
@@ -33,23 +33,44 @@ require (
github.com/stretchr/testify v1.10.0
github.com/ti-mo/netfilter v0.5.2
go.etcd.io/bbolt v1.4.0
golang.org/x/crypto v0.32.0
golang.org/x/exp v0.0.0-20250207012021-f9890c6ad9f3
golang.org/x/net v0.34.0
golang.org/x/sys v0.30.0
golang.org/x/crypto v0.36.0
golang.org/x/exp v0.0.0-20250218142911-aa4b98e5adaa
golang.org/x/net v0.37.0
golang.org/x/sys v0.31.0
gopkg.in/natefinch/lumberjack.v2 v2.2.1
gopkg.in/yaml.v3 v3.0.1
howett.net/plist v1.0.1
)
require (
cloud.google.com/go v0.118.3 // indirect
cloud.google.com/go/ai v0.10.0 // indirect
cloud.google.com/go/auth v0.15.0 // indirect
cloud.google.com/go/auth/oauth2adapt v0.2.7 // indirect
cloud.google.com/go/compute/metadata v0.6.0 // indirect
cloud.google.com/go/longrunning v0.6.5 // indirect
github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c // indirect
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da // indirect
github.com/aead/poly1305 v0.0.0-20180717145839-3fee0db0b635 // indirect
github.com/ameshkov/dnsstamps v1.0.3 // indirect
github.com/beefsack/go-rate v0.0.0-20220214233405-116f4ca011a0 // indirect
github.com/ccojocar/zxcvbn-go v1.0.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fzipp/gocyclo v0.6.0 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
github.com/golangci/misspell v0.6.0 // indirect
github.com/google/generative-ai-go v0.19.0 // indirect
github.com/google/pprof v0.0.0-20250202011525-fc3143867406 // indirect
github.com/google/s2a-go v0.1.9 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.5 // indirect
github.com/googleapis/gax-go/v2 v2.14.1 // indirect
github.com/gookit/color v1.5.4 // indirect
github.com/gordonklaus/ineffassign v0.1.0 // indirect
github.com/jstemmer/go-junit-report/v2 v2.1.0 // indirect
github.com/kisielk/errcheck v1.9.0 // indirect
github.com/mdlayher/socket v0.5.1 // indirect
github.com/onsi/ginkgo/v2 v2.22.2 // indirect
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
@@ -58,11 +79,55 @@ require (
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/quic-go/qpack v0.5.1 // indirect
github.com/robfig/cron/v3 v3.0.1 // indirect
github.com/rogpeppe/go-internal v1.14.1 // indirect
github.com/securego/gosec/v2 v2.22.2 // indirect
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/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 // indirect
go.opentelemetry.io/otel v1.35.0 // indirect
go.opentelemetry.io/otel/metric v1.35.0 // indirect
go.opentelemetry.io/otel/trace v1.35.0 // indirect
go.uber.org/mock v0.5.0 // indirect
golang.org/x/mod v0.23.0 // indirect
golang.org/x/sync v0.11.0 // indirect
golang.org/x/text v0.22.0 // indirect
golang.org/x/tools v0.29.0 // indirect
golang.org/x/exp/typeparams v0.0.0-20250305212735-054e65f0b394 // indirect
golang.org/x/mod v0.24.0 // indirect
golang.org/x/oauth2 v0.28.0 // indirect
golang.org/x/sync v0.12.0 // indirect
golang.org/x/telemetry v0.0.0-20250305155315-2a181eac97a3 // indirect
golang.org/x/term v0.30.0 // indirect
golang.org/x/text v0.23.0 // indirect
golang.org/x/time v0.11.0 // indirect
golang.org/x/tools v0.31.0 // indirect
golang.org/x/vuln v1.1.4 // indirect
gonum.org/v1/gonum v0.15.1 // indirect
google.golang.org/api v0.224.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb // indirect
google.golang.org/grpc v1.71.0 // indirect
google.golang.org/protobuf v1.36.5 // indirect
honnef.co/go/tools v0.6.1 // indirect
mvdan.cc/editorconfig v0.3.0 // indirect
mvdan.cc/gofumpt v0.7.0 // indirect
mvdan.cc/sh/v3 v3.11.0 // indirect
mvdan.cc/unparam v0.0.0-20250301125049-0df0534333a4 // indirect
)
tool (
github.com/fzipp/gocyclo/cmd/gocyclo
github.com/golangci/misspell/cmd/misspell
github.com/gordonklaus/ineffassign
github.com/jstemmer/go-junit-report/v2
github.com/kisielk/errcheck
github.com/securego/gosec/v2/cmd/gosec
github.com/uudashr/gocognit/cmd/gocognit
golang.org/x/tools/go/analysis/passes/fieldalignment/cmd/fieldalignment
golang.org/x/tools/go/analysis/passes/nilness/cmd/nilness
golang.org/x/tools/go/analysis/passes/shadow/cmd/shadow
golang.org/x/vuln/cmd/govulncheck
honnef.co/go/tools/cmd/staticcheck
mvdan.cc/gofumpt
mvdan.cc/sh/v3/cmd/shfmt
mvdan.cc/unparam
)

171
go.sum
View File

@@ -1,9 +1,23 @@
github.com/AdguardTeam/dnsproxy v0.75.0 h1:v8/Oq/xPYzNoALR7SEUZEIbKmjnPcXLVhJLFVbrozEc=
github.com/AdguardTeam/dnsproxy v0.75.0/go.mod h1:O2qoXwF4BUBFui7OMUiWSYwapEDcYxKWeur4+jfy9nM=
github.com/AdguardTeam/golibs v0.32.1 h1:Ajf6Q0k+A9zjFbj8HOzNAbHImrV4JtbT0vwy02D6VeI=
github.com/AdguardTeam/golibs v0.32.1/go.mod h1:dXRLSsnJQDxOfQVl0ochy1bfk4NgnJQGQdR1YPJdwcw=
cloud.google.com/go v0.118.3 h1:jsypSnrE/w4mJysioGdMBg4MiW/hHx/sArFpaBWHdME=
cloud.google.com/go v0.118.3/go.mod h1:Lhs3YLnBlwJ4KA6nuObNMZ/fCbOQBPuWKPoE0Wa/9Vc=
cloud.google.com/go/ai v0.10.0 h1:hwj6CI6sMKubXodoJJGTy/c2T1RbbLGM6TL3QoAvzU8=
cloud.google.com/go/ai v0.10.0/go.mod h1:kvnt2KeHqX8+41PVeMRBETDyQAp/RFvBWGdx/aGjNMo=
cloud.google.com/go/auth v0.15.0 h1:Ly0u4aA5vG/fsSsxu98qCQBemXtAtJf+95z9HK+cxps=
cloud.google.com/go/auth v0.15.0/go.mod h1:WJDGqZ1o9E9wKIL+IwStfyn/+s59zl4Bi+1KQNVXLZ8=
cloud.google.com/go/auth/oauth2adapt v0.2.7 h1:/Lc7xODdqcEw8IrZ9SvwnlLX6j9FHQM74z6cBk9Rw6M=
cloud.google.com/go/auth/oauth2adapt v0.2.7/go.mod h1:NTbTTzfvPl1Y3V1nPpOgl2w6d/FjO7NNUQaWSox6ZMc=
cloud.google.com/go/compute/metadata v0.6.0 h1:A6hENjEsCDtC1k8byVsgwvVcioamEHvZ4j01OwKxG9I=
cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg=
cloud.google.com/go/longrunning v0.6.5 h1:sD+t8DO8j4HKW4QfouCklg7ZC1qC4uzVZt8iz3uTW+Q=
cloud.google.com/go/longrunning v0.6.5/go.mod h1:Et04XK+0TTLKa5IPYryKf5DkpwImy6TluQ1QTLwlKmY=
github.com/AdguardTeam/dnsproxy v0.75.1 h1:ux2sQfF/9+WRo6a32g9NtfaAPU19gJhqkEu2OZflxJg=
github.com/AdguardTeam/dnsproxy v0.75.1/go.mod h1:HKBI/IO2/ACOjfTV6qIzB5ZDDxfjgHHvQ3hIbGg9wvc=
github.com/AdguardTeam/golibs v0.32.5 h1:4Rkv2xBnyJe6l/EM2MFgoY1S4pweYwDgLTYg2MDArEA=
github.com/AdguardTeam/golibs v0.32.5/go.mod h1:agsvz8Iyv0uV9NU56hpCoFLAtSPkiBf9nPVhDvdUIb0=
github.com/AdguardTeam/urlfilter v0.20.0 h1:X32qiuVCVd8WDYCEsbdZKfXMzwdVqrdulamtUi4rmzs=
github.com/AdguardTeam/urlfilter v0.20.0/go.mod h1:gjrywLTxfJh6JOkwi9SU+frhP7kVVEZ5exFGkR99qpk=
github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c h1:pxW6RcqyfI9/kWtOwnv/G+AzdKuy2ZrqINhenH4HyNs=
github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I=
github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c=
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da h1:KjTM2ks9d14ZYCvmHS9iAKVt9AyzRSqNU1qabPih5BY=
@@ -20,35 +34,67 @@ github.com/bluele/gcache v0.0.2 h1:WcbfdXICg7G/DGBh1PFfcirkWOQV+v077yF1pSy3DGw=
github.com/bluele/gcache v0.0.2/go.mod h1:m15KV+ECjptwSPxKhOhQoAFQVtUFjTVkc3H8o0t/fp0=
github.com/c2h5oh/datasize v0.0.0-20231215233829-aa82cc1e6500 h1:6lhrsTEnloDPXyeZBvSYvQf8u86jbKehZPVDDlkgDl4=
github.com/c2h5oh/datasize v0.0.0-20231215233829-aa82cc1e6500/go.mod h1:S/7n9copUssQ56c7aAgHqftWO4LTf4xY6CGWt8Bc+3M=
github.com/ccojocar/zxcvbn-go v1.0.2 h1:na/czXU8RrhXO4EZme6eQJLR4PzcGsahsBOAwU6I3Vg=
github.com/ccojocar/zxcvbn-go v1.0.2/go.mod h1:g1qkXtUSvHP8lhHp5GrSmTz6uWALGRMQdw6Qnz/hi60=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/digineo/go-ipset/v2 v2.2.1 h1:k6skY+0fMqeUjjeWO/m5OuWPSZUAn7AucHMnQ1MX77g=
github.com/digineo/go-ipset/v2 v2.2.1/go.mod h1:wBsNzJlZlABHUITkesrggFnZQtgW5wkqw1uo8Qxe0VU=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M=
github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo=
github.com/fzipp/gocyclo v0.6.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/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=
github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow=
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/golangci/misspell v0.6.0 h1:JCle2HUTNWirNlDIAUO44hUsKhOFqGPoC4LZxlaSXDs=
github.com/golangci/misspell v0.6.0/go.mod h1:keMNyY6R9isGaSAu+4Q8NMBwMPkh15Gtc8UCVoDtAWo=
github.com/google/generative-ai-go v0.19.0 h1:R71szggh8wHMCUlEMsW2A/3T+5LdEIkiaHSYgSpUgdg=
github.com/google/generative-ai-go v0.19.0/go.mod h1:JYolL13VG7j79kM5BtHz4qwONHkeJQzOCkKXnpqtS/E=
github.com/google/go-cmdtest v0.4.1-0.20220921163831-55ab3332a786 h1:rcv+Ippz6RAtvaGgKxc+8FQIpxHgsF+HBzPyYL2cyVU=
github.com/google/go-cmdtest v0.4.1-0.20220921163831-55ab3332a786/go.mod h1:apVn/GCasLZUVpAJ6oWAuyP7Ne7CEsQbTnc0plM3m+o=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8=
github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo=
github.com/google/pprof v0.0.0-20250202011525-fc3143867406 h1:wlQI2cYY0BsWmmPPAnxfQ8SDW0S3Jasn+4B8kXFxprg=
github.com/google/pprof v0.0.0-20250202011525-fc3143867406/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
github.com/google/renameio v0.1.0 h1:GOZbcHa3HfsPKPlmyPyN2KEohoMXOhdMbHrvbpl2QaA=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/renameio/v2 v2.0.0 h1:UifI23ZTGY8Tt29JbYFiuyIU3eX+RNFtUwefq9qAhxg=
github.com/google/renameio/v2 v2.0.0/go.mod h1:BtmJXm5YlszgC+TD4HOEEUFgkJP3nLxehU6hfe7jRt4=
github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0=
github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM=
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/enterprise-certificate-proxy v0.3.5 h1:VgzTY2jogw3xt39CusEnFJWm7rlsq5yL5q9XdLOuP5g=
github.com/googleapis/enterprise-certificate-proxy v0.3.5/go.mod h1:MkHOF77EYAE7qfSuSS9PU6g4Nt4e11cnsDUowfwewLA=
github.com/googleapis/gax-go/v2 v2.14.1 h1:hb0FFeiPaQskmvakKu5EbCbpntQn48jyHuvrkurSS/Q=
github.com/googleapis/gax-go/v2 v2.14.1/go.mod h1:Hb/NubMaVM88SrNkvl8X/o8XWwDJEPqouaLeN2IUxoA=
github.com/gookit/color v1.5.4 h1:FZmqs7XOyGgCAxmWyPslpiok1k05wmY3SJTytgvYFs0=
github.com/gookit/color v1.5.4/go.mod h1:pZJOeOS8DM43rXbp4AZo1n9zCU2qjpcRko0b6/QJi9w=
github.com/gordonklaus/ineffassign v0.1.0 h1:y2Gd/9I7MdY1oEIt+n+rowjBNDcLQq3RsH5hwJd0f9s=
github.com/gordonklaus/ineffassign v0.1.0/go.mod h1:Qcp2HIAYhR7mNUVSIxZww3Guk4it82ghYcEXIAk+QT0=
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-20250109001534-8abf58130905 h1:q3OEI9RaN/wwcx+qgGo6ZaoJkCiDYe/gjDLfq7lQQF4=
@@ -57,8 +103,14 @@ github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJS
github.com/josharian/native v1.0.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
github.com/josharian/native v1.1.1-0.20230202152459-5c7d0dd6ab86 h1:elKwZS1OcdQ0WwEDBeqxKwb7WB62QX8bvZ/FJnVXIfk=
github.com/josharian/native v1.1.1-0.20230202152459-5c7d0dd6ab86/go.mod h1:aFAMtuldEgx/4q7iSGazk22+IcgvtiC+HIimFO9XlS8=
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/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=
@@ -78,8 +130,6 @@ github.com/mdlayher/socket v0.5.1 h1:VZaqt6RkGkt2OE9l3GcC6nZkqD3xKeQLyfleW/uBcos
github.com/mdlayher/socket v0.5.1/go.mod h1:TjPLHI1UgwEv5J1B5q0zTZq12A/6H7nKmtTanQE37IQ=
github.com/miekg/dns v1.1.63 h1:8M5aAw6OMZfFXTT7K5V0Eu5YiiL8l7nUAkyN6C9YwaY=
github.com/miekg/dns v1.1.63/go.mod h1:6NGHfjhpmr5lt3XPLuyfDJi5AXbNIPM9PY6H6sF1Nfs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/onsi/ginkgo/v2 v2.22.2 h1:/3X8Panh8/WwhU/3Ssa6rCKqPLuAkVY2I0RoyDLySlU=
github.com/onsi/ginkgo/v2 v2.22.2/go.mod h1:oeMosUL+8LtarXBHu/c0bx2D/K9zyQ6uX3cTyztHwsk=
github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8=
@@ -101,6 +151,10 @@ github.com/quic-go/quic-go v0.49.0 h1:w5iJHXwHxs1QxyBv1EHKuC50GX5to8mJAxvtnttJp9
github.com/quic-go/quic-go v0.49.0/go.mod h1:s2wDnmCdooUQBmQfpUSTCYBl1/D4FcqbULMMkASvR6s=
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.2 h1:IXbuI7cJninj0nRpZSLCUlotsj8jGusohfONMrHoF6g=
github.com/securego/gosec/v2 v2.22.2/go.mod h1:UEBGA+dSKb+VqM6TdehR7lnQtIIMorYJ4/9CW1KVQBE=
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=
@@ -120,34 +174,61 @@ github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+F
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/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
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.0 h1:TU77id3TnN/zKr7CO/uk+fBCwF2jGcMuw2B/FMAzYIk=
go.etcd.io/bbolt v1.4.0/go.mod h1:AsD+OCi/qPN1giOX1aiLAha3o1U8rAz65bvN4j0sRuk=
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 h1:x7wzEgXfnzJcHDwStJT+mxOz4etr2EcexjqhBvmoakw=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0/go.mod h1:rg+RlpR5dKwaS95IyyZqj5Wd4E13lk/msnTS0Xl9lJM=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 h1:sbiXRNDSWJOTobXh5HyQKjq6wUC5tNybqjIqDpAY4CU=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0/go.mod h1:69uWxva0WgAA/4bu2Yy70SLDBwZXuQ6PbBpbsa5iZrQ=
go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ=
go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y=
go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M=
go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE=
go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY=
go.opentelemetry.io/otel/sdk v1.35.0/go.mod h1:+ga1bZliga3DxJ3CQGg3updiaAJoNECOgJREo9KHGQg=
go.opentelemetry.io/otel/sdk/metric v1.35.0 h1:1RriWBmCKgkeHEhM7a2uMjMUfP7MsOF5JpUCaEqEI9o=
go.opentelemetry.io/otel/sdk/metric v1.35.0/go.mod h1:is6XYCUMpcKi+ZsOvfluY5YstFnhW0BidkR+gL+qN+w=
go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs=
go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc=
go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU=
go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM=
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.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc=
golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
golang.org/x/exp v0.0.0-20250207012021-f9890c6ad9f3 h1:qNgPs5exUA+G0C96DrPwNrvLSj7GT/9D+3WMWUcUg34=
golang.org/x/exp v0.0.0-20250207012021-f9890c6ad9f3/go.mod h1:tujkw807nyEEAamNbDrEGzRav+ilXA7PCRAd6xsmwiU=
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
golang.org/x/exp v0.0.0-20250218142911-aa4b98e5adaa h1:t2QcU6V556bFjYgu4L6C+6VrCPyJZ+eyRsABUPs1mz4=
golang.org/x/exp v0.0.0-20250218142911-aa4b98e5adaa/go.mod h1:BHOTPb3L19zxehTsLoJXVaTktb06DFgmdW6Wb9s8jqk=
golang.org/x/exp/typeparams v0.0.0-20250305212735-054e65f0b394 h1:VI4qDpTkfFaCXEPrbojidLgVQhj2x4nzTccG0hjaLlU=
golang.org/x/exp/typeparams v0.0.0-20250305212735-054e65f0b394/go.mod h1:LKZHyeOpPuZcMgxeHjJp4p5yvxrCX1xDvH10zYHhjjQ=
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.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM=
golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU=
golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
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.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c=
golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
golang.org/x/oauth2 v0.28.0 h1:CrgCKl8PPAVtLnU3c+EDw6x11699EWlsDeWNWKdIOkc=
golang.org/x/oauth2 v0.28.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
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.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
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=
@@ -155,35 +236,65 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
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-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
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.4.1-0.20230131160137-e7d7f63158de/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/telemetry v0.0.0-20250305155315-2a181eac97a3 h1:k+pofz4/0MRETtVtItAwfDgPUvNlWrUrFw+8dtUVUa8=
golang.org/x/telemetry v0.0.0-20250305155315-2a181eac97a3/go.mod h1:16eI1RtbPZAEm3u7hpIh7JM/w5AbmlDtnrdKYaREic8=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y=
golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g=
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.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=
golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.29.0 h1:Xx0h3TtM9rzQpQuR4dKLrdglAmCEN5Oi+P74JdhdzXE=
golang.org/x/tools v0.29.0/go.mod h1:KMQVMRsVxU6nHCFXrBPhDB8XncLNLM0lIy/F14RP588=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.31.0 h1:0EedkvKDbh+qistFTd0Bcwe/YLh4vHwWEkiI0toFIBU=
golang.org/x/tools v0.31.0/go.mod h1:naFTU+Cev749tSJRXJlna0T3WxKvb1kWEx15xA4SdmQ=
golang.org/x/vuln v1.1.4 h1:Ju8QsuyhX3Hk8ma3CesTbO8vfJD9EvUBgHvkxHBzj0I=
golang.org/x/vuln v1.1.4/go.mod h1:F+45wmU18ym/ca5PLTPLsSzr2KppzswxPP603ldA67s=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gonum.org/v1/gonum v0.15.1 h1:FNy7N6OUZVUaWG9pTiD+jlhdQ3lMP+/LcTpJ6+a8sQ0=
gonum.org/v1/gonum v0.15.1/go.mod h1:eZTZuRFrzu5pcyjN5wJhcIhnUdNijYxX1T2IcrOGY0o=
google.golang.org/protobuf v1.36.3 h1:82DV7MYdb8anAVi3qge1wSnMDrnKK7ebr+I0hHRN1BU=
google.golang.org/protobuf v1.36.3/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
google.golang.org/api v0.224.0 h1:Ir4UPtDsNiwIOHdExr3fAj4xZ42QjK7uQte3lORLJwU=
google.golang.org/api v0.224.0/go.mod h1:3V39my2xAGkodXy0vEqcEtkqgw2GtrFL5WuBZlCTCOQ=
google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb h1:p31xT4yrYrSM/G4Sn2+TNUkVhFCbG9y8itM2S6Th950=
google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:jbe3Bkdp+Dh2IrslsFCklNhweNTBgSYanP1UXhJDhKg=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb h1:TLPQVbx1GJ8VKZxz52VAxl1EBgKXXbTiU9Fc5fZeLn4=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I=
google.golang.org/grpc v1.71.0 h1:kF77BGdPTQ4/JZWMlb9VpJ5pa25aqvVqogsxNHHdeBg=
google.golang.org/grpc v1.71.0/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec=
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/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=
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0/go.mod h1:WDnlLJ4WF5VGsH/HVa3CI79GS0ol3YnhVnKP89i0kNg=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.6.1 h1:R094WgE8K4JirYjBaOpz/AvTyUu/3wbmAoskKN/pxTI=
honnef.co/go/tools v0.6.1/go.mod h1:3puzxxljPCe8RGJX7BIy1plGbxEOZni5mR2aXe3/uk4=
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.7.0 h1:bg91ttqXmi9y2xawvkuMXyvAA/1ZGJqYAEGjXuP0JXU=
mvdan.cc/gofumpt v0.7.0/go.mod h1:txVFJy/Sc/mvaycET54pV8SW8gWxTlUuGHVEcncmNUo=
mvdan.cc/sh/v3 v3.11.0 h1:q5h+XMDRfUGUedCqFFsjoFjrhwf2Mvtt1rkMvVz0blw=
mvdan.cc/sh/v3 v3.11.0/go.mod h1:LRM+1NjoYCzuq/WZ6y44x14YNAI0NK7FLPeQSaFagGg=
mvdan.cc/unparam v0.0.0-20250301125049-0df0534333a4 h1:WjUu4yQoT5BHT1w8Zu56SP8367OuBV5jvo+4Ulppyf8=
mvdan.cc/unparam v0.0.0-20250301125049-0df0534333a4/go.mod h1:rthT7OuvRbaGcd5ginj6dA2oLE7YNlta9qhBNNdCaLE=

View File

@@ -0,0 +1,24 @@
package aghnet
import "github.com/AdguardTeam/dnsproxy/upstream"
// UpstreamHTTPVersions returns the HTTP versions for upstream configuration
// depending on configuration.
func UpstreamHTTPVersions(http3 bool) (v []upstream.HTTPVersion) {
if !http3 {
return upstream.DefaultHTTPVersions
}
return []upstream.HTTPVersion{
upstream.HTTPVersion3,
upstream.HTTPVersion2,
upstream.HTTPVersion11,
}
}
// IsCommentOrEmpty returns true if s starts with a "#" character or is empty.
// This function is useful for filtering out non-upstream lines from upstream
// configs.
func IsCommentOrEmpty(s string) (ok bool) {
return len(s) == 0 || s[0] == '#'
}

View File

@@ -0,0 +1,26 @@
package aghnet_test
import (
"testing"
"github.com/AdguardTeam/AdGuardHome/internal/aghnet"
"github.com/stretchr/testify/assert"
)
func TestIsCommentOrEmpty(t *testing.T) {
for _, tc := range []struct {
want assert.BoolAssertionFunc
str string
}{{
want: assert.True,
str: "",
}, {
want: assert.True,
str: "# comment",
}, {
want: assert.False,
str: "1.2.3.4",
}} {
tc.want(t, aghnet.IsCommentOrEmpty(tc.str))
}
}

View File

@@ -10,7 +10,6 @@ import (
"github.com/AdguardTeam/AdGuardHome/internal/next/agh"
"github.com/AdguardTeam/AdGuardHome/internal/rdns"
"github.com/AdguardTeam/AdGuardHome/internal/whois"
"github.com/AdguardTeam/dnsproxy/proxy"
"github.com/AdguardTeam/dnsproxy/upstream"
"github.com/miekg/dns"
)
@@ -121,26 +120,6 @@ func (p *AddressUpdater) UpdateAddress(
p.OnUpdateAddress(ctx, ip, host, info)
}
// Package dnsforward
// ClientsContainer is a fake [dnsforward.ClientsContainer] implementation for
// tests.
type ClientsContainer struct {
OnUpstreamConfigByID func(
id string,
boot upstream.Resolver,
) (conf *proxy.CustomUpstreamConfig, err error)
}
// UpstreamConfigByID implements the [dnsforward.ClientsContainer] interface
// for *ClientsContainer.
func (c *ClientsContainer) UpstreamConfigByID(
id string,
boot upstream.Resolver,
) (conf *proxy.CustomUpstreamConfig, err error) {
return c.OnUpstreamConfigByID(id, boot)
}
// Package filtering
// Resolver is a fake [filtering.Resolver] implementation for tests.

View File

@@ -3,7 +3,6 @@ package aghtest_test
import (
"github.com/AdguardTeam/AdGuardHome/internal/aghtest"
"github.com/AdguardTeam/AdGuardHome/internal/client"
"github.com/AdguardTeam/AdGuardHome/internal/dnsforward"
"github.com/AdguardTeam/AdGuardHome/internal/filtering"
)
@@ -12,9 +11,6 @@ import (
// type check
var _ filtering.Resolver = (*aghtest.Resolver)(nil)
// type check
var _ dnsforward.ClientsContainer = (*aghtest.ClientsContainer)(nil)
// type check
//
// TODO(s.chzhen): It's here to avoid the import cycle. Remove it.

View File

@@ -9,7 +9,6 @@ import (
"strings"
"github.com/AdguardTeam/AdGuardHome/internal/aghalg"
"github.com/AdguardTeam/golibs/errors"
)
// macKey contains MAC as byte array of 6, 8, or 20 bytes.
@@ -35,7 +34,7 @@ type index struct {
// nameToUID maps client name to UID.
nameToUID map[string]UID
// clientIDToUID maps client ID to UID.
// clientIDToUID maps ClientID to UID.
clientIDToUID map[string]UID
// ipToUID maps IP address to UID.
@@ -205,19 +204,19 @@ func (ci *index) clashesMAC(c *Persistent) (p *Persistent, mac net.HardwareAddr)
return nil, nil
}
// find finds persistent client by string representation of the client ID, IP
// find finds persistent client by string representation of the ClientID, IP
// address, or MAC.
func (ci *index) find(id string) (c *Persistent, ok bool) {
uid, found := ci.clientIDToUID[id]
if found {
return ci.uidToClient[uid], true
c, ok = ci.findByClientID(id)
if ok {
return c, true
}
ip, err := netip.ParseAddr(id)
if err == nil {
// MAC addresses can be successfully parsed as IP addresses.
c, found = ci.findByIP(ip)
if found {
c, ok = ci.findByIP(ip)
if ok {
return c, true
}
}
@@ -230,6 +229,16 @@ func (ci *index) find(id string) (c *Persistent, ok bool) {
return nil, false
}
// findByClientID finds persistent client by ClientID.
func (ci *index) findByClientID(clientID string) (c *Persistent, ok bool) {
uid, ok := ci.clientIDToUID[clientID]
if ok {
return ci.uidToClient[uid], true
}
return nil, false
}
// findByName finds persistent client by name.
func (ci *index) findByName(name string) (c *Persistent, found bool) {
uid, found := ci.nameToUID[name]
@@ -343,18 +352,3 @@ func (ci *index) rangeByName(f func(c *Persistent) (cont bool)) {
}
}
}
// closeUpstreams closes upstream configurations of persistent clients.
func (ci *index) closeUpstreams() (err error) {
var errs []error
ci.rangeByName(func(c *Persistent) (cont bool) {
err = c.CloseUpstreams()
if err != nil {
errs = append(errs, err)
}
return true
})
return errors.Join(errs...)
}

View File

@@ -58,12 +58,6 @@ func (uid *UID) UnmarshalText(data []byte) error {
// Persistent contains information about persistent clients.
type Persistent struct {
// UpstreamConfig is the custom upstream configuration for this client. If
// it's nil, it has not been initialized yet. If it's non-nil and empty,
// there are no valid upstreams. If it's non-nil and non-empty, these
// upstream must be used.
UpstreamConfig *proxy.CustomUpstreamConfig
// SafeSearch handles search engine hosts rewrites.
SafeSearch filtering.SafeSearch
@@ -262,7 +256,7 @@ func ValidateClientID(id string) (err error) {
return nil
}
// IDs returns a list of client IDs containing at least one element.
// IDs returns a list of ClientIDs containing at least one element.
func (c *Persistent) IDs() (ids []string) {
ids = make([]string, 0, c.IDsLen())
@@ -281,7 +275,7 @@ func (c *Persistent) IDs() (ids []string) {
return append(ids, c.ClientIDs...)
}
// IDsLen returns a length of client ids.
// IDsLen returns a length of ClientIDs.
func (c *Persistent) IDsLen() (n int) {
return len(c.IPs) + len(c.Subnets) + len(c.MACs) + len(c.ClientIDs)
}
@@ -312,14 +306,3 @@ func (c *Persistent) ShallowClone() (clone *Persistent) {
return clone
}
// CloseUpstreams closes the client-specific upstream config of c if any.
func (c *Persistent) CloseUpstreams() (err error) {
if c.UpstreamConfig != nil {
if err = c.UpstreamConfig.Close(); err != nil {
return fmt.Errorf("closing upstreams of client %q: %w", c.Name, err)
}
}
return nil
}

View File

@@ -13,9 +13,11 @@ import (
"github.com/AdguardTeam/AdGuardHome/internal/arpdb"
"github.com/AdguardTeam/AdGuardHome/internal/dhcpsvc"
"github.com/AdguardTeam/AdGuardHome/internal/whois"
"github.com/AdguardTeam/dnsproxy/proxy"
"github.com/AdguardTeam/golibs/errors"
"github.com/AdguardTeam/golibs/hostsfile"
"github.com/AdguardTeam/golibs/logutil/slogutil"
"github.com/AdguardTeam/golibs/timeutil"
)
// allowedTags is the list of available client tags.
@@ -88,6 +90,10 @@ type StorageConfig struct {
// not be nil.
Logger *slog.Logger
// Clock is used by [upstreamManager] to retrieve the current time. It must
// not be nil.
Clock timeutil.Clock
// DHCP is used to match IPs against MACs of persistent clients and update
// [SourceDHCP] runtime client information. It must not be nil.
DHCP DHCP
@@ -126,6 +132,9 @@ type Storage struct {
// runtimeIndex contains information about runtime clients.
runtimeIndex *runtimeIndex
// upstreamManager stores and updates custom client upstream configurations.
upstreamManager *upstreamManager
// dhcp is used to update [SourceDHCP] runtime client information.
dhcp DHCP
@@ -163,6 +172,7 @@ func NewStorage(ctx context.Context, conf *StorageConfig) (s *Storage, err error
mu: &sync.Mutex{},
index: newIndex(),
runtimeIndex: newRuntimeIndex(),
upstreamManager: newUpstreamManager(conf.Logger, conf.Clock),
dhcp: conf.DHCP,
etcHosts: conf.EtcHosts,
arpDB: conf.ARPDB,
@@ -200,7 +210,7 @@ func (s *Storage) Start(ctx context.Context) (err error) {
func (s *Storage) Shutdown(_ context.Context) (err error) {
close(s.done)
return s.closeUpstreams()
return s.upstreamManager.close()
}
// periodicARPUpdate periodically reloads runtime clients from ARP. It is
@@ -416,6 +426,7 @@ func (s *Storage) Add(ctx context.Context, p *Persistent) (err error) {
}
s.index.add(p)
s.upstreamManager.updateCustomUpstreamConfig(p)
s.logger.DebugContext(
ctx,
@@ -441,7 +452,7 @@ func (s *Storage) FindByName(name string) (p *Persistent, ok bool) {
return nil, false
}
// Find finds persistent client by string representation of the client ID, IP
// Find finds persistent client by string representation of the ClientID, IP
// address, or MAC. And returns its shallow copy.
//
// TODO(s.chzhen): Accept ClientIDData structure instead, which will contain
@@ -514,12 +525,13 @@ func (s *Storage) RemoveByName(ctx context.Context, name string) (ok bool) {
return false
}
if err := p.CloseUpstreams(); err != nil {
s.logger.ErrorContext(ctx, "removing client", "name", p.Name, slogutil.KeyError, err)
}
s.index.remove(p)
err := s.upstreamManager.remove(p.UID)
if err != nil {
s.logger.DebugContext(ctx, "closing client upstreams", "name", name, slogutil.KeyError, err)
}
return true
}
@@ -556,6 +568,8 @@ func (s *Storage) Update(ctx context.Context, name string, p *Persistent) (err e
s.index.remove(stored)
s.index.add(p)
s.upstreamManager.updateCustomUpstreamConfig(p)
return nil
}
@@ -576,14 +590,6 @@ func (s *Storage) Size() (n int) {
return s.index.size()
}
// closeUpstreams closes upstream configurations of persistent clients.
func (s *Storage) closeUpstreams() (err error) {
s.mu.Lock()
defer s.mu.Unlock()
return s.index.closeUpstreams()
}
// ClientRuntime returns a copy of the saved runtime client by ip. If no such
// client exists, returns nil.
func (s *Storage) ClientRuntime(ip netip.Addr) (rc *Runtime) {
@@ -626,3 +632,42 @@ func (s *Storage) RangeRuntime(f func(rc *Runtime) (cont bool)) {
func (s *Storage) AllowedTags() (tags []string) {
return s.allowedTags
}
// CustomUpstreamConfig implements the [dnsforward.ClientsContainer] interface
// for *Storage
func (s *Storage) CustomUpstreamConfig(
id string,
addr netip.Addr,
) (prxConf *proxy.CustomUpstreamConfig) {
s.mu.Lock()
defer s.mu.Unlock()
c, ok := s.index.findByClientID(id)
if !ok {
c, ok = s.index.findByIP(addr)
}
if !ok {
return nil
}
return s.upstreamManager.customUpstreamConfig(c.UID)
}
// UpdateCommonUpstreamConfig implements the [dnsforward.ClientsContainer]
// interface for *Storage
func (s *Storage) UpdateCommonUpstreamConfig(conf *CommonUpstreamConfig) {
s.mu.Lock()
defer s.mu.Unlock()
s.upstreamManager.updateCommonUpstreamConfig(conf)
}
// ClearUpstreamCache implements the [dnsforward.ClientsContainer] interface for
// *Storage
func (s *Storage) ClearUpstreamCache() {
s.mu.Lock()
defer s.mu.Unlock()
s.upstreamManager.clearUpstreamCache()
}

View File

@@ -13,27 +13,34 @@ import (
"github.com/AdguardTeam/AdGuardHome/internal/client"
"github.com/AdguardTeam/AdGuardHome/internal/dhcpd"
"github.com/AdguardTeam/AdGuardHome/internal/dhcpsvc"
"github.com/AdguardTeam/AdGuardHome/internal/dnsforward"
"github.com/AdguardTeam/AdGuardHome/internal/whois"
"github.com/AdguardTeam/golibs/hostsfile"
"github.com/AdguardTeam/golibs/logutil/slogutil"
"github.com/AdguardTeam/golibs/testutil"
"github.com/AdguardTeam/golibs/testutil/faketime"
"github.com/AdguardTeam/golibs/timeutil"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
// newTestStorage is a helper function that returns initialized storage.
func newTestStorage(tb testing.TB) (s *client.Storage) {
func newTestStorage(tb testing.TB, clock timeutil.Clock) (s *client.Storage) {
tb.Helper()
ctx := testutil.ContextWithTimeout(tb, testTimeout)
s, err := client.NewStorage(ctx, &client.StorageConfig{
Logger: slogutil.NewDiscardLogger(),
Clock: clock,
})
require.NoError(tb, err)
return s
}
// type check
var _ dnsforward.ClientsContainer = (*client.Storage)(nil)
// testHostsContainer is a mock implementation of the [client.HostsContainer]
// interface.
type testHostsContainer struct {
@@ -691,7 +698,7 @@ func TestStorage_Add(t *testing.T) {
}
ctx := testutil.ContextWithTimeout(t, testTimeout)
s := newTestStorage(t)
s := newTestStorage(t, timeutil.SystemClock{})
tags := s.AllowedTags()
require.NotZero(t, len(tags))
require.True(t, slices.IsSorted(tags))
@@ -822,7 +829,7 @@ func TestStorage_RemoveByName(t *testing.T) {
}
ctx := testutil.ContextWithTimeout(t, testTimeout)
s := newTestStorage(t)
s := newTestStorage(t, timeutil.SystemClock{})
err := s.Add(ctx, existingClient)
require.NoError(t, err)
@@ -847,7 +854,7 @@ func TestStorage_RemoveByName(t *testing.T) {
}
t.Run("duplicate_remove", func(t *testing.T) {
s = newTestStorage(t)
s = newTestStorage(t, timeutil.SystemClock{})
err = s.Add(ctx, existingClient)
require.NoError(t, err)
@@ -1278,3 +1285,99 @@ func TestStorage_RangeByName(t *testing.T) {
})
}
}
func TestStorage_CustomUpstreamConfig(t *testing.T) {
const (
existingName = "existing_name"
existingClientID = "existing_client_id"
nonExistingClientID = "non_existing_client_id"
)
var (
existingClientUID = client.MustNewUID()
existingIP = netip.MustParseAddr("192.0.2.1")
nonExistingIP = netip.MustParseAddr("192.0.2.255")
testUpstreamTimeout = time.Second
)
existingClient := &client.Persistent{
Name: existingName,
IPs: []netip.Addr{existingIP},
ClientIDs: []string{existingClientID},
UID: existingClientUID,
Upstreams: []string{"192.0.2.0"},
}
date := time.Now()
clock := &faketime.Clock{
OnNow: func() (now time.Time) {
date = date.Add(time.Second)
return date
},
}
s := newTestStorage(t, clock)
s.UpdateCommonUpstreamConfig(&client.CommonUpstreamConfig{
UpstreamTimeout: testUpstreamTimeout,
})
testutil.CleanupAndRequireSuccess(t, func() (err error) {
return s.Shutdown(testutil.ContextWithTimeout(t, testTimeout))
})
ctx := testutil.ContextWithTimeout(t, testTimeout)
err := s.Add(ctx, existingClient)
require.NoError(t, err)
testCases := []struct {
cliAddr netip.Addr
wantNilConf assert.ValueAssertionFunc
name string
cliID string
}{{
name: "client_id",
cliID: existingClientID,
cliAddr: netip.Addr{},
wantNilConf: assert.NotNil,
}, {
name: "client_addr",
cliID: "",
cliAddr: existingIP,
wantNilConf: assert.NotNil,
}, {
name: "non_existing_client_id",
cliID: nonExistingClientID,
cliAddr: netip.Addr{},
wantNilConf: assert.Nil,
}, {
name: "non_existing_client_addr",
cliID: "",
cliAddr: nonExistingIP,
wantNilConf: assert.Nil,
}}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
conf := s.CustomUpstreamConfig(tc.cliID, tc.cliAddr)
tc.wantNilConf(t, conf)
})
}
t.Run("update_common_config", func(t *testing.T) {
conf := s.CustomUpstreamConfig(existingClientID, existingIP)
require.NotNil(t, conf)
s.UpdateCommonUpstreamConfig(&client.CommonUpstreamConfig{
UpstreamTimeout: testUpstreamTimeout * 2,
})
updConf := s.CustomUpstreamConfig(existingClientID, existingIP)
require.NotNil(t, updConf)
assert.NotEqual(t, conf, updConf)
})
}

View File

@@ -0,0 +1,224 @@
package client
import (
"fmt"
"log/slog"
"slices"
"time"
"github.com/AdguardTeam/AdGuardHome/internal/aghnet"
"github.com/AdguardTeam/dnsproxy/proxy"
"github.com/AdguardTeam/dnsproxy/upstream"
"github.com/AdguardTeam/golibs/errors"
"github.com/AdguardTeam/golibs/logutil/slogutil"
"github.com/AdguardTeam/golibs/stringutil"
"github.com/AdguardTeam/golibs/timeutil"
)
// CommonUpstreamConfig contains common settings for custom client upstream
// configurations.
type CommonUpstreamConfig struct {
Bootstrap upstream.Resolver
UpstreamTimeout time.Duration
BootstrapPreferIPv6 bool
EDNSClientSubnetEnabled bool
UseHTTP3Upstreams bool
}
// customUpstreamConfig contains custom client upstream configuration and the
// timestamp of the latest configuration update.
type customUpstreamConfig struct {
// proxyConf is the constructed upstream configuration for the [proxy],
// derived from the fields below. It is initialized on demand with
// [newCustomUpstreamConfig].
proxyConf *proxy.CustomUpstreamConfig
// commonConfUpdate is the timestamp of the latest configuration update,
// used to check against [upstreamManager.confUpdate] to determine if the
// configuration is up to date.
commonConfUpdate time.Time
// upstreams is the cached list of custom upstream DNS servers used for the
// configuration of proxyConf.
upstreams []string
// upstreamsCacheSize is the cached value of the cache size of the
// upstreams, used for the configuration of proxyConf.
upstreamsCacheSize uint32
// upstreamsCacheEnabled is the cached value indicating whether the cache of
// the upstreams is enabled for the configuration of proxyConf.
upstreamsCacheEnabled bool
// isChanged indicates whether the proxyConf needs to be updated.
isChanged bool
}
// upstreamManager stores and updates custom client upstream configurations.
type upstreamManager struct {
// logger is used for logging the operation of the upstream manager. It
// must not be nil.
//
// TODO(s.chzhen): Consider using a logger with its own prefix.
logger *slog.Logger
// uidToCustomConf maps persistent client UID to the custom client upstream
// configuration. Stored UIDs must be in sync with the [index.uidToClient].
uidToCustomConf map[UID]*customUpstreamConfig
// commonConf is the common upstream configuration.
commonConf *CommonUpstreamConfig
// clock is used to get the current time. It must not be nil.
clock timeutil.Clock
// confUpdate is the timestamp of the latest common upstream configuration
// update.
confUpdate time.Time
}
// newUpstreamManager returns the new properly initialized upstream manager.
func newUpstreamManager(logger *slog.Logger, clock timeutil.Clock) (m *upstreamManager) {
return &upstreamManager{
logger: logger,
uidToCustomConf: make(map[UID]*customUpstreamConfig),
clock: clock,
}
}
// updateCommonUpstreamConfig updates the common upstream configuration and the
// timestamp of the latest configuration update.
func (m *upstreamManager) updateCommonUpstreamConfig(conf *CommonUpstreamConfig) {
m.commonConf = conf
m.confUpdate = m.clock.Now()
}
// updateCustomUpstreamConfig updates the stored custom client upstream
// configuration associated with the persistent client. It also sets
// [customUpstreamConfig.isChanged] to true so [customUpstreamConfig.proxyConf]
// can be updated later in [upstreamManager.customUpstreamConfig].
func (m *upstreamManager) updateCustomUpstreamConfig(c *Persistent) {
cliConf, ok := m.uidToCustomConf[c.UID]
if !ok {
cliConf = &customUpstreamConfig{
commonConfUpdate: m.confUpdate,
}
m.uidToCustomConf[c.UID] = cliConf
}
// TODO(s.chzhen): Compare before cloning.
cliConf.upstreams = slices.Clone(c.Upstreams)
cliConf.upstreamsCacheSize = c.UpstreamsCacheSize
cliConf.upstreamsCacheEnabled = c.UpstreamsCacheEnabled
cliConf.isChanged = true
}
// customUpstreamConfig returns the custom client upstream configuration.
func (m *upstreamManager) customUpstreamConfig(uid UID) (proxyConf *proxy.CustomUpstreamConfig) {
cliConf, ok := m.uidToCustomConf[uid]
if !ok {
// TODO(s.chzhen): Consider panic.
m.logger.Error("no associated custom client upstream config")
return nil
}
if !m.isConfigChanged(cliConf) {
return cliConf.proxyConf
}
if cliConf.proxyConf != nil {
err := cliConf.proxyConf.Close()
if err != nil {
// TODO(s.chzhen): Pass context.
m.logger.Debug("closing custom upstream config", slogutil.KeyError, err)
}
}
proxyConf = newCustomUpstreamConfig(cliConf, m.commonConf)
cliConf.proxyConf = proxyConf
cliConf.isChanged = false
return proxyConf
}
// isConfigChanged returns true if the update is necessary for the custom client
// upstream configuration.
func (m *upstreamManager) isConfigChanged(cliConf *customUpstreamConfig) (ok bool) {
return !m.confUpdate.Equal(cliConf.commonConfUpdate) || cliConf.isChanged
}
// clearUpstreamCache clears the upstream cache for each stored custom client
// upstream configuration.
func (m *upstreamManager) clearUpstreamCache() {
for _, c := range m.uidToCustomConf {
c.proxyConf.ClearCache()
}
}
// remove deletes the custom client upstream configuration and closes
// [customUpstreamConfig.proxyConf] if necessary.
func (m *upstreamManager) remove(uid UID) (err error) {
cliConf, ok := m.uidToCustomConf[uid]
if !ok {
// TODO(s.chzhen): Consider panic.
return errors.Error("no associated custom client upstream config")
}
delete(m.uidToCustomConf, uid)
if cliConf.proxyConf != nil {
return cliConf.proxyConf.Close()
}
return nil
}
// close shuts down each stored custom client upstream configuration.
func (m *upstreamManager) close() (err error) {
var errs []error
for _, c := range m.uidToCustomConf {
if c.proxyConf == nil {
continue
}
errs = append(errs, c.proxyConf.Close())
}
return errors.Join(errs...)
}
// newCustomUpstreamConfig returns the new properly initialized custom proxy
// upstream configuration for the client.
func newCustomUpstreamConfig(
cliConf *customUpstreamConfig,
conf *CommonUpstreamConfig,
) (proxyConf *proxy.CustomUpstreamConfig) {
upstreams := stringutil.FilterOut(cliConf.upstreams, aghnet.IsCommentOrEmpty)
if len(upstreams) == 0 {
return nil
}
upsConf, err := proxy.ParseUpstreamsConfig(
upstreams,
&upstream.Options{
Bootstrap: conf.Bootstrap,
Timeout: time.Duration(conf.UpstreamTimeout),
HTTPVersions: aghnet.UpstreamHTTPVersions(conf.UseHTTP3Upstreams),
PreferIPv6: conf.BootstrapPreferIPv6,
},
)
if err != nil {
// Should not happen because upstreams are already validated. See
// [Persistent.validate].
panic(fmt.Errorf("creating custom upstream config: %w", err))
}
return proxy.NewCustomUpstreamConfig(
upsConf,
cliConf.upstreamsCacheEnabled,
int(cliConf.upstreamsCacheSize),
conf.EDNSClientSubnetEnabled,
)
}

View File

@@ -4,6 +4,7 @@ import (
"encoding/binary"
"fmt"
"net"
"slices"
"sync/atomic"
"time"
@@ -14,18 +15,48 @@ import (
"golang.org/x/net/ipv6"
)
// raCtx is a context for the Router Advertisement logic.
type raCtx struct {
raAllowSLAAC bool // send RA packets without MO flags
raSLAACOnly bool // send RA packets with MO flags
ipAddr net.IP // source IP address (link-local-unicast)
dnsIPAddr net.IP // IP address for DNS Server option
prefixIPAddr net.IP // IP address for Prefix option
ifaceName string
iface *net.Interface
packetSendPeriod time.Duration // how often RA packets are sent
// raAllowSLAAC is used to determine if the ICMP Router Advertisement
// messages should be sent.
//
// If both raAllowSLAAC and raSLAACOnly are false, the Router Advertisement
// messages aren't sent.
raAllowSLAAC bool
conn *icmp.PacketConn // ICMPv6 socket
stop atomic.Value // stop the packet sending loop
// raSLAACOnly is used to determine if the ICMP Router Advertisement
// messages should set M and O flags, see RFC 4861, section 4.2.
//
// If both raAllowSLAAC and raSLAACOnly are false, the Router Advertisement
// messages aren't sent.
raSLAACOnly bool
// ipAddr is an IP address used within the Source Link-Layer Address option.
// See RFC 4861, section 4.6.1.
ipAddr net.IP
// dnsIPAddr is an IP address used within the DNS Server option.
dnsIPAddr net.IP
// prefixIPAddr is an IP address used within the Prefix Information option.
// See RFC 4861, section 4.6.2.
prefixIPAddr net.IP
// ifaceName is the name of the interface used as a scope of the IP
// addresses.
ifaceName string
// iface is the network interface used to send the ICMPv6 packets.
iface *net.Interface
// packetSendPeriod is the interval between sending the ICMPv6 packets.
packetSendPeriod time.Duration
// conn is the ICMPv6 socket.
conn *icmp.PacketConn
// stop is used to stop the packet sending loop.
stop atomic.Value
}
type icmpv6RA struct {
@@ -38,10 +69,11 @@ type icmpv6RA struct {
mtu uint32
}
// hwAddrToLinkLayerAddr converts a hardware address into a form required by
// RFC4861. That is, a byte slice of length divisible by 8.
// hwAddrToLinkLayerAddr clones the hardware address and returns it as a byte
// slice suitable for the Source Link-Layer Address option in the ICMPv6
// Router Advertisement packet.
//
// See https://tools.ietf.org/html/rfc4861#section-4.6.1.
// TODO(e.burkov): Check if it's safe to use the original slice.
func hwAddrToLinkLayerAddr(hwa net.HardwareAddr) (lla []byte, err error) {
err = netutil.ValidateMAC(hwa)
if err != nil {
@@ -50,19 +82,7 @@ func hwAddrToLinkLayerAddr(hwa net.HardwareAddr) (lla []byte, err error) {
return nil, err
}
if len(hwa) == 6 || len(hwa) == 8 {
lla = make([]byte, 8)
copy(lla, hwa)
return lla, nil
}
// Assume that netutil.ValidateMAC prevents lengths other than 20 by
// now.
lla = make([]byte, 24)
copy(lla, hwa)
return lla, nil
return slices.Clone(hwa), nil
}
// Create an ICMPv6.RouterAdvertisement packet with all necessary options.
@@ -103,15 +123,24 @@ func hwAddrToLinkLayerAddr(hwa net.HardwareAddr) (lla []byte, err error) {
//
// TODO(a.garipov): Replace with an existing implementation from a dependency.
func createICMPv6RAPacket(params icmpv6RA) (data []byte, err error) {
var lla []byte
lla, err = hwAddrToLinkLayerAddr(params.sourceLinkLayerAddress)
lla, err := hwAddrToLinkLayerAddr(params.sourceLinkLayerAddress)
if err != nil {
return nil, fmt.Errorf("converting source link layer address: %w", err)
return nil, fmt.Errorf("converting source link-layer address: %w", err)
}
// Calculate length of the source link-layer address option. As per RFC
// 4861, section 4.6.1, the length should be in units of 8 octets, including
// the type and length fields.
//
// See https://datatracker.ietf.org/doc/html/rfc4861#section-4.6.1.
srcLLAOptLen := len(lla) + 2
// Make sure the value is rounded up to the nearest multiple of 8.
srcLLAOptLenValue := (srcLLAOptLen + 7) / 8
srcLLAPadLen := srcLLAOptLenValue*8 - srcLLAOptLen
// TODO(a.garipov): Don't use a magic constant here. Refactor the code
// and make all constants named instead of all those comments..
data = make([]byte, 82+len(lla))
// and make all constants named instead of all those comments.
data = make([]byte, 80+srcLLAOptLen+srcLLAPadLen)
i := 0
// ICMPv6:
@@ -175,12 +204,11 @@ func createICMPv6RAPacket(params icmpv6RA) (data []byte, err error) {
// Option=Source link-layer address:
data[i] = 1 // Type
data[i+1] = 1 // Length
data[i] = 1 // Type
data[i+1] = byte(srcLLAOptLenValue) // Length
i += 2
copy(data[i:], lla) // Link-Layer Address[8/24]
i += len(lla)
i += len(lla) + srcLLAPadLen
// Option=Recursive DNS Server:

View File

@@ -0,0 +1,63 @@
package dhcpd
import (
"net"
"testing"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestCreateICMPv6RAPacket(t *testing.T) {
raConf := icmpv6RA{
managedAddressConfiguration: false,
otherConfiguration: true,
mtu: 1500,
prefix: net.ParseIP("1234::"),
prefixLen: 64,
recursiveDNSServer: net.ParseIP("fe80::800:27ff:fe00:0"),
sourceLinkLayerAddress: []byte{0x0A, 0x00, 0x27, 0x00, 0x00, 0x00},
}
pkt, err := createICMPv6RAPacket(raConf)
require.NoError(t, err)
icmpPkt := &layers.ICMPv6{}
err = icmpPkt.DecodeFromBytes(pkt, gopacket.NilDecodeFeedback)
require.NoError(t, err)
require.Equal(t, layers.LayerTypeICMPv6RouterAdvertisement, icmpPkt.NextLayerType())
raPkt := &layers.ICMPv6RouterAdvertisement{}
err = raPkt.DecodeFromBytes(icmpPkt.LayerPayload(), gopacket.NilDecodeFeedback)
require.NoError(t, err)
assert.Equal(t, raConf.managedAddressConfiguration, raPkt.ManagedAddressConfig())
assert.Equal(t, raConf.otherConfiguration, raPkt.OtherConfig())
wantOpts := layers.ICMPv6Options{{
Type: layers.ICMPv6OptPrefixInfo,
Data: []uint8{
0x40, 0xC0, 0x00, 0x00, 0x0E, 0x10, 0x00, 0x00,
0x0E, 0x10, 0x00, 0x00, 0x00, 0x00, 0x12, 0x34,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
},
}, {
Type: layers.ICMPv6OptMTU,
Data: []uint8{0x00, 0x00, 0x00, 0x00, 0x05, 0xDC},
}, {
Type: layers.ICMPv6OptSourceAddress,
Data: []uint8{0x0A, 0x00, 0x27, 0x00, 0x00, 0x0},
}, {
// Package layers declares no constant for Recursive DNS Server option.
Type: layers.ICMPv6Opt(25),
Data: []uint8{
0x00, 0x00, 0x00, 0x00, 0x0E, 0x10, 0xFE, 0x80,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
0x27, 0xFF, 0xFE, 0x00, 0x00, 0x00,
},
}}
assert.Equal(t, wantOpts, raPkt.Options)
}

View File

@@ -1,38 +0,0 @@
package dhcpd
import (
"net"
"testing"
"github.com/stretchr/testify/assert"
)
func TestCreateICMPv6RAPacket(t *testing.T) {
wantData := []byte{
0x86, 0x00, 0x00, 0x00, 0x40, 0x40, 0x07, 0x08,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x03, 0x04, 0x40, 0xc0, 0x00, 0x00, 0x0e, 0x10,
0x00, 0x00, 0x0e, 0x10, 0x00, 0x00, 0x00, 0x00,
0x12, 0x34, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x05, 0x01, 0x00, 0x00, 0x00, 0x00, 0x05, 0xdc,
0x01, 0x01, 0x0a, 0x00, 0x27, 0x00, 0x00, 0x00,
0x00, 0x00, 0x19, 0x03, 0x00, 0x00, 0x00, 0x00,
0x0e, 0x10, 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x08, 0x00, 0x27, 0xff, 0xfe, 0x00,
0x00, 0x00,
}
gotData, err := createICMPv6RAPacket(icmpv6RA{
managedAddressConfiguration: false,
otherConfiguration: true,
mtu: 1500,
prefix: net.ParseIP("1234::"),
prefixLen: 64,
recursiveDNSServer: net.ParseIP("fe80::800:27ff:fe00:0"),
sourceLinkLayerAddress: []byte{0x0a, 0x00, 0x27, 0x00, 0x00, 0x00},
})
assert.NoError(t, err)
assert.Equal(t, wantData, gotData)
}

View File

@@ -239,7 +239,7 @@ func (s *Server) handleAccessSet(w http.ResponseWriter, r *http.Request) {
err = validateAccessSet(list)
if err != nil {
aghhttp.Error(r, w, http.StatusBadRequest, err.Error())
aghhttp.Error(r, w, http.StatusBadRequest, "%s", err)
return
}

View File

@@ -15,7 +15,7 @@ import (
var _ proxy.BeforeRequestHandler = (*Server)(nil)
// HandleBefore is the handler that is called before any other processing,
// including logs. It performs access checks and puts the client ID, if there
// including logs. It performs access checks and puts the ClientID, if there
// is one, into the server's cache.
//
// TODO(d.kolyshev): Extract to separate package.

View File

@@ -266,6 +266,7 @@ func TestServer_HandleBefore_udp(t *testing.T) {
UpstreamDNS: []string{localUpsAddr},
UpstreamMode: UpstreamModeLoadBalance,
EDNSClientSubnet: &EDNSClientSubnet{Enabled: false},
ClientsContainer: EmptyClientsContainer{},
},
ServePlainDNS: true,
})

View File

@@ -62,7 +62,7 @@ func clientIDFromClientServerName(
return strings.ToLower(clientID), nil
}
// clientIDFromDNSContextHTTPS extracts the client's ID from the path of the
// clientIDFromDNSContextHTTPS extracts the ClientID from the path of the
// client's DNS-over-HTTPS request.
func clientIDFromDNSContextHTTPS(pctx *proxy.DNSContext) (clientID string, err error) {
r := pctx.HTTPRequest

View File

@@ -0,0 +1,46 @@
package dnsforward
import (
"net/netip"
"github.com/AdguardTeam/AdGuardHome/internal/client"
"github.com/AdguardTeam/dnsproxy/proxy"
)
// ClientsContainer provides information about preconfigured DNS clients.
type ClientsContainer interface {
// CustomUpstreamConfig returns the custom client upstream configuration, if
// any. It prioritizes ClientID over client IP address to identify the
// client.
CustomUpstreamConfig(clientID string, cliAddr netip.Addr) (conf *proxy.CustomUpstreamConfig)
// UpdateCommonUpstreamConfig updates the common upstream configuration.
UpdateCommonUpstreamConfig(conf *client.CommonUpstreamConfig)
// ClearUpstreamCache clears the upstream cache for each stored custom
// client upstream configuration.
ClearUpstreamCache()
}
// EmptyClientsContainer is an [ClientsContainer] implementation that does nothing.
type EmptyClientsContainer struct{}
// type check
var _ ClientsContainer = EmptyClientsContainer{}
// CustomUpstreamConfig implements the [ClientsContainer] interface for
// EmptyClientsContainer.
func (EmptyClientsContainer) CustomUpstreamConfig(
clientID string,
cliAddr netip.Addr,
) (conf *proxy.CustomUpstreamConfig) {
return nil
}
// UpdateCommonUpstreamConfig implements the [ClientsContainer] interface for
// EmptyClientsContainer.
func (EmptyClientsContainer) UpdateCommonUpstreamConfig(conf *client.CommonUpstreamConfig) {}
// ClearUpstreamCache implements the [ClientsContainer] interface for
// EmptyClientsContainer.
func (EmptyClientsContainer) ClearUpstreamCache() {}

View File

@@ -29,19 +29,6 @@ import (
"github.com/ameshkov/dnscrypt/v2"
)
// ClientsContainer provides information about preconfigured DNS clients.
type ClientsContainer interface {
// UpstreamConfigByID returns the custom upstream configuration for the
// client having id, using boot to initialize the one if necessary. It
// returns nil if there is no custom upstream configuration for the client.
// The id is expected to be either a string representation of an IP address
// or the ClientID.
UpstreamConfigByID(
id string,
boot upstream.Resolver,
) (conf *proxy.CustomUpstreamConfig, err error)
}
// Config represents the DNS filtering configuration of AdGuard Home. The zero
// Config is empty and ready for use.
type Config struct {
@@ -467,7 +454,7 @@ func (s *Server) prepareIpsetListSettings() (ipsets []string, err error) {
}
ipsets = stringutil.SplitTrimmed(string(data), "\n")
ipsets = slices.DeleteFunc(ipsets, IsCommentOrEmpty)
ipsets = slices.DeleteFunc(ipsets, aghnet.IsCommentOrEmpty)
log.Debug("dns: using %d ipset rules from file %q", len(ipsets), fn)
@@ -478,7 +465,7 @@ func (s *Server) prepareIpsetListSettings() (ipsets []string, err error) {
// the configuration itself.
func (conf *ServerConfig) loadUpstreams() (upstreams []string, err error) {
if conf.UpstreamDNSFileName == "" {
return stringutil.FilterOut(conf.UpstreamDNS, IsCommentOrEmpty), nil
return stringutil.FilterOut(conf.UpstreamDNS, aghnet.IsCommentOrEmpty), nil
}
var data []byte
@@ -491,7 +478,7 @@ func (conf *ServerConfig) loadUpstreams() (upstreams []string, err error) {
log.Debug("dnsforward: got %d upstreams in %q", len(upstreams), conf.UpstreamDNSFileName)
return stringutil.FilterOut(upstreams, IsCommentOrEmpty), nil
return stringutil.FilterOut(upstreams, aghnet.IsCommentOrEmpty), nil
}
// collectListenAddr adds addrPort to addrs. It also adds its port to

View File

@@ -299,6 +299,7 @@ func TestServer_HandleDNSRequest_dns64(t *testing.T) {
Config: Config{
UpstreamMode: UpstreamModeLoadBalance,
EDNSClientSubnet: &EDNSClientSubnet{Enabled: false},
ClientsContainer: EmptyClientsContainer{},
UpstreamDNS: []string{upsAddr},
},
UsePrivateRDNS: true,
@@ -337,6 +338,7 @@ func TestServer_dns64WithDisabledRDNS(t *testing.T) {
Config: Config{
UpstreamMode: UpstreamModeLoadBalance,
EDNSClientSubnet: &EDNSClientSubnet{Enabled: false},
ClientsContainer: EmptyClientsContainer{},
UpstreamDNS: []string{upsAddr},
},
UsePrivateRDNS: false,

View File

@@ -540,7 +540,7 @@ func (s *Server) prepareUpstreamSettings(boot upstream.Resolver) (err error) {
uc, err := newUpstreamConfig(upstreams, defaultDNS, &upstream.Options{
Bootstrap: boot,
Timeout: s.conf.UpstreamTimeout,
HTTPVersions: UpstreamHTTPVersions(s.conf.UseHTTP3Upstreams),
HTTPVersions: aghnet.UpstreamHTTPVersions(s.conf.UseHTTP3Upstreams),
PreferIPv6: s.conf.BootstrapPreferIPv6,
// Use a customized set of RootCAs, because Go's default mechanism of
// loading TLS roots does not always work properly on some routers so we're
@@ -557,6 +557,13 @@ func (s *Server) prepareUpstreamSettings(boot upstream.Resolver) (err error) {
}
s.conf.UpstreamConfig = uc
s.conf.ClientsContainer.UpdateCommonUpstreamConfig(&client.CommonUpstreamConfig{
Bootstrap: boot,
UpstreamTimeout: s.conf.UpstreamTimeout,
BootstrapPreferIPv6: s.conf.BootstrapPreferIPv6,
EDNSClientSubnetEnabled: s.conf.EDNSClientSubnet.Enabled,
UseHTTP3Upstreams: s.conf.UseHTTP3Upstreams,
})
return nil
}
@@ -630,7 +637,7 @@ func (s *Server) prepareInternalDNS() (err error) {
bootOpts := &upstream.Options{
Timeout: DefaultTimeout,
HTTPVersions: UpstreamHTTPVersions(s.conf.UseHTTP3Upstreams),
HTTPVersions: aghnet.UpstreamHTTPVersions(s.conf.UseHTTP3Upstreams),
}
s.bootstrap, s.bootResolvers, err = newBootstrap(s.conf.BootstrapDNS, s.etcHosts, bootOpts)
@@ -661,7 +668,7 @@ func (s *Server) prepareInternalDNS() (err error) {
// setupFallbackDNS initializes the fallback DNS servers.
func (s *Server) setupFallbackDNS() (uc *proxy.UpstreamConfig, err error) {
fallbacks := s.conf.FallbackDNS
fallbacks = stringutil.FilterOut(fallbacks, IsCommentOrEmpty)
fallbacks = stringutil.FilterOut(fallbacks, aghnet.IsCommentOrEmpty)
if len(fallbacks) == 0 {
return nil, nil
}

View File

@@ -23,6 +23,7 @@ import (
"github.com/AdguardTeam/AdGuardHome/internal/aghnet"
"github.com/AdguardTeam/AdGuardHome/internal/aghtest"
"github.com/AdguardTeam/AdGuardHome/internal/client"
"github.com/AdguardTeam/AdGuardHome/internal/filtering"
"github.com/AdguardTeam/AdGuardHome/internal/filtering/hashprefix"
"github.com/AdguardTeam/AdGuardHome/internal/filtering/safesearch"
@@ -61,6 +62,42 @@ const (
// TODO(a.garipov): Use more.
var testClientAddrPort = netip.MustParseAddrPort("1.2.3.4:12345")
// type check
var _ ClientsContainer = (*clientsContainer)(nil)
// clientsContainer is a mock [ClientsContainer] implementation for tests.
type clientsContainer struct {
OnCustomUpstreamConfig func(
clientID string,
cliAddr netip.Addr,
) (conf *proxy.CustomUpstreamConfig)
OnUpdateCommonUpstreamConfig func(conf *client.CommonUpstreamConfig)
OnClearUpstreamCache func()
}
// CustomUpstreamConfig implements the [ClientsContainer] interface for
// *clientsContainer.
func (c *clientsContainer) CustomUpstreamConfig(
clientID string,
cliAddr netip.Addr,
) (conf *proxy.CustomUpstreamConfig) {
return c.OnCustomUpstreamConfig(clientID, cliAddr)
}
// UpdateCommonUpstreamConfig implements the [ClientsContainer] interface for
// *clientsContainer.
func (c *clientsContainer) UpdateCommonUpstreamConfig(conf *client.CommonUpstreamConfig) {
c.OnUpdateCommonUpstreamConfig(conf)
}
// ClearUpstreamCache implements the [ClientsContainer] interface for
// *clientsContainer.
func (c *clientsContainer) ClearUpstreamCache() {
c.OnClearUpstreamCache()
}
func startDeferStop(t *testing.T, s *Server) {
t.Helper()
@@ -168,6 +205,7 @@ func createTestTLS(t *testing.T, tlsConf TLSConfig) (s *Server, certPem []byte)
Config: Config{
UpstreamMode: UpstreamModeLoadBalance,
EDNSClientSubnet: &EDNSClientSubnet{Enabled: false},
ClientsContainer: EmptyClientsContainer{},
},
ServePlainDNS: true,
})
@@ -297,6 +335,7 @@ func TestServer(t *testing.T) {
Config: Config{
UpstreamMode: UpstreamModeLoadBalance,
EDNSClientSubnet: &EDNSClientSubnet{Enabled: false},
ClientsContainer: EmptyClientsContainer{},
},
ServePlainDNS: true,
})
@@ -337,6 +376,7 @@ func TestServer_timeout(t *testing.T) {
Config: Config{
UpstreamMode: UpstreamModeLoadBalance,
EDNSClientSubnet: &EDNSClientSubnet{Enabled: false},
ClientsContainer: EmptyClientsContainer{},
},
ServePlainDNS: true,
}
@@ -364,6 +404,7 @@ func TestServer_timeout(t *testing.T) {
s.conf.Config.EDNSClientSubnet = &EDNSClientSubnet{
Enabled: false,
}
s.conf.Config.ClientsContainer = EmptyClientsContainer{}
err = s.Prepare(&s.conf)
require.NoError(t, err)
@@ -380,6 +421,7 @@ func TestServer_Prepare_fallbacks(t *testing.T) {
},
UpstreamMode: UpstreamModeLoadBalance,
EDNSClientSubnet: &EDNSClientSubnet{Enabled: false},
ClientsContainer: EmptyClientsContainer{},
},
ServePlainDNS: true,
}
@@ -405,6 +447,7 @@ func TestServerWithProtectionDisabled(t *testing.T) {
Config: Config{
UpstreamMode: UpstreamModeLoadBalance,
EDNSClientSubnet: &EDNSClientSubnet{Enabled: false},
ClientsContainer: EmptyClientsContainer{},
},
ServePlainDNS: true,
})
@@ -536,6 +579,7 @@ func TestSafeSearch(t *testing.T) {
EDNSClientSubnet: &EDNSClientSubnet{
Enabled: false,
},
ClientsContainer: EmptyClientsContainer{},
},
ServePlainDNS: true,
}
@@ -629,6 +673,7 @@ func TestInvalidRequest(t *testing.T) {
EDNSClientSubnet: &EDNSClientSubnet{
Enabled: false,
},
ClientsContainer: EmptyClientsContainer{},
},
ServePlainDNS: true,
})
@@ -659,6 +704,7 @@ func TestBlockedRequest(t *testing.T) {
EDNSClientSubnet: &EDNSClientSubnet{
Enabled: false,
},
ClientsContainer: EmptyClientsContainer{},
},
ServePlainDNS: true,
}
@@ -696,6 +742,7 @@ func TestServerCustomClientUpstream(t *testing.T) {
EDNSClientSubnet: &EDNSClientSubnet{
Enabled: false,
},
ClientsContainer: EmptyClientsContainer{},
},
ServePlainDNS: true,
}
@@ -721,12 +768,12 @@ func TestServerCustomClientUpstream(t *testing.T) {
forwardConf.EDNSClientSubnet.Enabled,
)
s.conf.ClientsContainer = &aghtest.ClientsContainer{
OnUpstreamConfigByID: func(
s.conf.ClientsContainer = &clientsContainer{
OnCustomUpstreamConfig: func(
_ string,
_ upstream.Resolver,
) (conf *proxy.CustomUpstreamConfig, err error) {
return customUpsConf, nil
_ netip.Addr,
) (conf *proxy.CustomUpstreamConfig) {
return customUpsConf
},
}
@@ -774,6 +821,7 @@ func TestBlockCNAMEProtectionEnabled(t *testing.T) {
EDNSClientSubnet: &EDNSClientSubnet{
Enabled: false,
},
ClientsContainer: EmptyClientsContainer{},
},
ServePlainDNS: true,
})
@@ -808,6 +856,7 @@ func TestBlockCNAME(t *testing.T) {
EDNSClientSubnet: &EDNSClientSubnet{
Enabled: false,
},
ClientsContainer: EmptyClientsContainer{},
},
ServePlainDNS: true,
}
@@ -884,6 +933,7 @@ func TestClientRulesForCNAMEMatching(t *testing.T) {
EDNSClientSubnet: &EDNSClientSubnet{
Enabled: false,
},
ClientsContainer: EmptyClientsContainer{},
},
ServePlainDNS: true,
}
@@ -930,6 +980,7 @@ func TestNullBlockedRequest(t *testing.T) {
EDNSClientSubnet: &EDNSClientSubnet{
Enabled: false,
},
ClientsContainer: EmptyClientsContainer{},
},
ServePlainDNS: true,
}
@@ -998,6 +1049,7 @@ func TestBlockedCustomIP(t *testing.T) {
EDNSClientSubnet: &EDNSClientSubnet{
Enabled: false,
},
ClientsContainer: EmptyClientsContainer{},
},
ServePlainDNS: true,
}
@@ -1051,6 +1103,7 @@ func TestBlockedByHosts(t *testing.T) {
EDNSClientSubnet: &EDNSClientSubnet{
Enabled: false,
},
ClientsContainer: EmptyClientsContainer{},
},
ServePlainDNS: true,
}
@@ -1103,6 +1156,7 @@ func TestBlockedBySafeBrowsing(t *testing.T) {
EDNSClientSubnet: &EDNSClientSubnet{
Enabled: false,
},
ClientsContainer: EmptyClientsContainer{},
},
ServePlainDNS: true,
}
@@ -1164,6 +1218,7 @@ func TestRewrite(t *testing.T) {
EDNSClientSubnet: &EDNSClientSubnet{
Enabled: false,
},
ClientsContainer: EmptyClientsContainer{},
},
ServePlainDNS: true,
}))
@@ -1290,6 +1345,7 @@ func TestPTRResponseFromDHCPLeases(t *testing.T) {
s.conf.TCPListenAddrs = []*net.TCPAddr{{}}
s.conf.UpstreamDNS = []string{"127.0.0.1:53"}
s.conf.Config.EDNSClientSubnet = &EDNSClientSubnet{Enabled: false}
s.conf.Config.ClientsContainer = EmptyClientsContainer{}
s.conf.Config.UpstreamMode = UpstreamModeLoadBalance
err = s.Prepare(&s.conf)
@@ -1375,6 +1431,7 @@ func TestPTRResponseFromHosts(t *testing.T) {
s.conf.TCPListenAddrs = []*net.TCPAddr{{}}
s.conf.UpstreamDNS = []string{"127.0.0.1:53"}
s.conf.Config.EDNSClientSubnet = &EDNSClientSubnet{Enabled: false}
s.conf.Config.ClientsContainer = EmptyClientsContainer{}
s.conf.Config.UpstreamMode = UpstreamModeLoadBalance
err = s.Prepare(&s.conf)
@@ -1643,6 +1700,7 @@ func TestServer_Exchange(t *testing.T) {
UpstreamDNS: []string{upsAddr},
UpstreamMode: UpstreamModeLoadBalance,
EDNSClientSubnet: &EDNSClientSubnet{Enabled: false},
ClientsContainer: EmptyClientsContainer{},
},
LocalPTRResolvers: []string{localUpsAddr},
UsePrivateRDNS: true,
@@ -1665,6 +1723,7 @@ func TestServer_Exchange(t *testing.T) {
UpstreamDNS: []string{upsAddr},
UpstreamMode: UpstreamModeLoadBalance,
EDNSClientSubnet: &EDNSClientSubnet{Enabled: false},
ClientsContainer: EmptyClientsContainer{},
},
LocalPTRResolvers: []string{},
ServePlainDNS: true,

View File

@@ -40,6 +40,7 @@ func TestServer_FilterDNSRewrite(t *testing.T) {
Config: Config{
UpstreamMode: UpstreamModeLoadBalance,
EDNSClientSubnet: &EDNSClientSubnet{Enabled: false},
ClientsContainer: EmptyClientsContainer{},
},
ServePlainDNS: true,
})

View File

@@ -36,6 +36,7 @@ func TestHandleDNSRequest_handleDNSRequest(t *testing.T) {
EDNSClientSubnet: &EDNSClientSubnet{
Enabled: false,
},
ClientsContainer: EmptyClientsContainer{},
},
ServePlainDNS: true,
}

View File

@@ -11,6 +11,7 @@ import (
"time"
"github.com/AdguardTeam/AdGuardHome/internal/aghhttp"
"github.com/AdguardTeam/AdGuardHome/internal/aghnet"
"github.com/AdguardTeam/AdGuardHome/internal/filtering"
"github.com/AdguardTeam/dnsproxy/proxy"
"github.com/AdguardTeam/dnsproxy/upstream"
@@ -647,7 +648,7 @@ func (s *Server) handleTestUpstreamDNS(w http.ResponseWriter, r *http.Request) {
return
}
req.BootstrapDNS = stringutil.FilterOut(req.BootstrapDNS, IsCommentOrEmpty)
req.BootstrapDNS = stringutil.FilterOut(req.BootstrapDNS, aghnet.IsCommentOrEmpty)
opts := &upstream.Options{
Timeout: s.conf.UpstreamTimeout,
@@ -673,6 +674,8 @@ func (s *Server) handleTestUpstreamDNS(w http.ResponseWriter, r *http.Request) {
// handleCacheClear is the handler for the POST /control/cache_clear HTTP API.
func (s *Server) handleCacheClear(w http.ResponseWriter, _ *http.Request) {
s.dnsProxy.ClearCache()
s.conf.ClientsContainer.ClearUpstreamCache()
_, _ = io.WriteString(w, "OK")
}

View File

@@ -83,6 +83,7 @@ func TestDNSForwardHTTP_handleGetConfig(t *testing.T) {
RatelimitSubnetLenIPv6: 56,
UpstreamMode: UpstreamModeLoadBalance,
EDNSClientSubnet: &EDNSClientSubnet{Enabled: false},
ClientsContainer: EmptyClientsContainer{},
},
ConfigModified: func() {},
ServePlainDNS: true,
@@ -164,6 +165,7 @@ func TestDNSForwardHTTP_handleSetConfig(t *testing.T) {
RatelimitSubnetLenIPv6: 56,
UpstreamMode: UpstreamModeLoadBalance,
EDNSClientSubnet: &EDNSClientSubnet{Enabled: false},
ClientsContainer: EmptyClientsContainer{},
},
ConfigModified: func() {},
ServePlainDNS: true,
@@ -299,24 +301,6 @@ func TestDNSForwardHTTP_handleSetConfig(t *testing.T) {
}
}
func TestIsCommentOrEmpty(t *testing.T) {
for _, tc := range []struct {
want assert.BoolAssertionFunc
str string
}{{
want: assert.True,
str: "",
}, {
want: assert.True,
str: "# comment",
}, {
want: assert.False,
str: "1.2.3.4",
}} {
tc.want(t, IsCommentOrEmpty(tc.str))
}
}
func newLocalUpstreamListener(t *testing.T, port uint16, handler dns.Handler) (real netip.AddrPort) {
t.Helper()
@@ -388,6 +372,7 @@ func TestServer_HandleTestUpstreamDNS(t *testing.T) {
Config: Config{
UpstreamMode: UpstreamModeLoadBalance,
EDNSClientSubnet: &EDNSClientSubnet{Enabled: false},
ClientsContainer: EmptyClientsContainer{},
},
ServePlainDNS: true,
})

View File

@@ -1,7 +1,6 @@
package dnsforward
import (
"cmp"
"context"
"encoding/binary"
"net"
@@ -577,17 +576,14 @@ func (s *Server) setCustomUpstream(pctx *proxy.DNSContext, clientID string) {
return
}
// Use the ClientID first, since it has a higher priority.
id := cmp.Or(clientID, pctx.Addr.Addr().String())
upsConf, err := s.conf.ClientsContainer.UpstreamConfigByID(id, s.bootstrap)
if err != nil {
log.Error("dnsforward: getting custom upstreams for client %s: %s", id, err)
return
}
cliAddr := pctx.Addr.Addr()
upsConf := s.conf.ClientsContainer.CustomUpstreamConfig(clientID, cliAddr)
if upsConf != nil {
log.Debug("dnsforward: using custom upstreams for client %s", id)
log.Debug(
"dnsforward: using custom upstreams for client with ip %s and clientid %q",
cliAddr,
clientID,
)
pctx.CustomUpstreamConfig = upsConf
}

View File

@@ -81,6 +81,7 @@ func TestServer_ProcessInitial(t *testing.T) {
AAAADisabled: tc.aaaaDisabled,
UpstreamMode: UpstreamModeLoadBalance,
EDNSClientSubnet: &EDNSClientSubnet{Enabled: false},
ClientsContainer: EmptyClientsContainer{},
},
ServePlainDNS: true,
}
@@ -180,6 +181,7 @@ func TestServer_ProcessFilteringAfterResponse(t *testing.T) {
AAAADisabled: tc.aaaaDisabled,
UpstreamMode: UpstreamModeLoadBalance,
EDNSClientSubnet: &EDNSClientSubnet{Enabled: false},
ClientsContainer: EmptyClientsContainer{},
},
ServePlainDNS: true,
}
@@ -324,6 +326,7 @@ func TestServer_ProcessDDRQuery(t *testing.T) {
HandleDDR: tc.ddrEnabled,
UpstreamMode: UpstreamModeLoadBalance,
EDNSClientSubnet: &EDNSClientSubnet{Enabled: false},
ClientsContainer: EmptyClientsContainer{},
},
TLSConfig: TLSConfig{
ServerName: ddrTestDomainName,
@@ -660,6 +663,7 @@ func TestServer_HandleDNSRequest_restrictLocal(t *testing.T) {
UpstreamDNS: []string{localUpsAddr},
UpstreamMode: UpstreamModeLoadBalance,
EDNSClientSubnet: &EDNSClientSubnet{Enabled: false},
ClientsContainer: EmptyClientsContainer{},
},
UsePrivateRDNS: true,
LocalPTRResolvers: []string{localUpsAddr},
@@ -788,6 +792,7 @@ func TestServer_ProcessUpstream_localPTR(t *testing.T) {
Config: Config{
UpstreamMode: UpstreamModeLoadBalance,
EDNSClientSubnet: &EDNSClientSubnet{Enabled: false},
ClientsContainer: EmptyClientsContainer{},
},
UsePrivateRDNS: true,
LocalPTRResolvers: []string{localUpsAddr},
@@ -816,6 +821,7 @@ func TestServer_ProcessUpstream_localPTR(t *testing.T) {
Config: Config{
UpstreamMode: UpstreamModeLoadBalance,
EDNSClientSubnet: &EDNSClientSubnet{Enabled: false},
ClientsContainer: EmptyClientsContainer{},
},
UsePrivateRDNS: false,
LocalPTRResolvers: []string{localUpsAddr},

View File

@@ -19,6 +19,7 @@ func TestGenAnswerHTTPS_andSVCB(t *testing.T) {
Config: Config{
UpstreamMode: UpstreamModeLoadBalance,
EDNSClientSubnet: &EDNSClientSubnet{Enabled: false},
ClientsContainer: EmptyClientsContainer{},
},
ServePlainDNS: true,
})

View File

@@ -94,7 +94,7 @@ func newPrivateConfig(
) (uc *proxy.UpstreamConfig, err error) {
confNeedsFiltering := len(addrs) > 0
if confNeedsFiltering {
addrs = stringutil.FilterOut(addrs, IsCommentOrEmpty)
addrs = stringutil.FilterOut(addrs, aghnet.IsCommentOrEmpty)
} else {
sysResolvers := slices.DeleteFunc(slices.Clone(sysResolvers.Addrs()), unwanted.Has)
addrs = make([]string, 0, len(sysResolvers))
@@ -127,20 +127,6 @@ func newPrivateConfig(
return uc, nil
}
// UpstreamHTTPVersions returns the HTTP versions for upstream configuration
// depending on configuration.
func UpstreamHTTPVersions(http3 bool) (v []upstream.HTTPVersion) {
if !http3 {
return upstream.DefaultHTTPVersions
}
return []upstream.HTTPVersion{
upstream.HTTPVersion3,
upstream.HTTPVersion2,
upstream.HTTPVersion11,
}
}
// setProxyUpstreamMode sets the upstream mode and related settings in conf
// based on provided parameters.
func setProxyUpstreamMode(
@@ -162,10 +148,3 @@ func setProxyUpstreamMode(
return nil
}
// IsCommentOrEmpty returns true if s starts with a "#" character or is empty.
// This function is useful for filtering out non-upstream lines from upstream
// configs.
func IsCommentOrEmpty(s string) (ok bool) {
return len(s) == 0 || s[0] == '#'
}

View File

@@ -661,8 +661,6 @@ func TestClientSettings(t *testing.T) {
}
}
// Benchmarks.
func BenchmarkSafeBrowsing(b *testing.B) {
d, setts := newForTest(b, &Config{
SafeBrowsingEnabled: true,
@@ -670,15 +668,26 @@ func BenchmarkSafeBrowsing(b *testing.B) {
}, nil)
b.Cleanup(d.Close)
for range b.N {
res, err := d.CheckHost(sbBlocked, dns.TypeA, setts)
require.NoError(b, err)
assert.Truef(b, res.IsFiltered, "expected hostname %q to match", sbBlocked)
var res Result
var err error
b.ReportAllocs()
for b.Loop() {
res, err = d.CheckHost(sbBlocked, dns.TypeA, setts)
}
require.NoError(b, err)
assert.Truef(b, res.IsFiltered, "expected hostname %q to match", sbBlocked)
// Most recent results:
//
// goos: darwin
// goarch: amd64
// pkg: github.com/AdguardTeam/AdGuardHome/internal/filtering
// cpu: Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
// BenchmarkSafeBrowsing-12 358934 2994 ns/op 1304 B/op 40 allocs/op
}
func BenchmarkSafeBrowsingParallel(b *testing.B) {
func BenchmarkSafeBrowsing_parallel(b *testing.B) {
d, setts := newForTest(b, &Config{
SafeBrowsingEnabled: true,
SafeBrowsingChecker: newChecker(sbBlocked),
@@ -693,4 +702,12 @@ func BenchmarkSafeBrowsingParallel(b *testing.B) {
assert.Truef(b, res.IsFiltered, "expected hostname %q to match", sbBlocked)
}
})
// Most recent results:
//
// goos: darwin
// goarch: amd64
// pkg: github.com/AdguardTeam/AdGuardHome/internal/filtering
// cpu: Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
// BenchmarkSafeBrowsing_parallel-12 507327 2382 ns/op 1352 B/op 42 allocs/op
}

View File

@@ -244,7 +244,7 @@ func (d *DNSFilter) handleFilteringSetURL(w http.ResponseWriter, r *http.Request
restart, err := d.filterSetProperties(fj.URL, filt, fj.Whitelist)
if err != nil {
aghhttp.Error(r, w, http.StatusBadRequest, err.Error())
aghhttp.Error(r, w, http.StatusBadRequest, "%s", err)
return
}

View File

@@ -202,34 +202,30 @@ func TestParser_Parse_checksums(t *testing.T) {
assert.Equal(t, gotWithoutComments, gotWithComments)
}
var (
resSink *rulelist.ParseResult
errSink error
)
func BenchmarkParser_Parse(b *testing.B) {
dst := &bytes.Buffer{}
src := strings.NewReader(strings.Repeat(testRuleTextBlocked, 1000))
buf := make([]byte, rulelist.DefaultRuleBufSize)
p := rulelist.NewParser()
var res *rulelist.ParseResult
var err error
b.ReportAllocs()
b.ResetTimer()
for range b.N {
resSink, errSink = p.Parse(dst, src, buf)
for b.Loop() {
res, err = p.Parse(dst, src, buf)
dst.Reset()
}
require.NoError(b, errSink)
require.NotNil(b, resSink)
require.NoError(b, err)
require.NotNil(b, res)
// Most recent result, on a ThinkPad X13 with a Ryzen Pro 7 CPU:
// Most recent results:
//
// goos: linux
// goos: darwin
// goarch: amd64
// pkg: github.com/AdguardTeam/AdGuardHome/internal/filtering/rulelist
// cpu: AMD Ryzen 7 PRO 4750U with Radeon Graphics
// BenchmarkParser_Parse-16 100000000 128.0 ns/op 48 B/op 1 allocs/op
// cpu: Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
// BenchmarkParser_Parse-12 19635926 53.70 ns/op 48 B/op 1 allocs/op
}
func FuzzParser_Parse(f *testing.F) {

View File

@@ -88,16 +88,25 @@ func TestSafeSearchCacheYandex(t *testing.T) {
assert.Equal(t, cachedValue.Rules[0].IP, yandexIP)
}
const googleHost = "www.google.com"
func BenchmarkDefault_SearchHost(b *testing.B) {
const googleHost = "www.google.com"
var dnsRewriteSink *rules.DNSRewrite
func BenchmarkSafeSearch(b *testing.B) {
ss := newForTest(b, defaultSafeSearchConf)
for range b.N {
dnsRewriteSink = ss.searchHost(googleHost, testQType)
var rewrite *rules.DNSRewrite
b.ReportAllocs()
for b.Loop() {
rewrite = ss.searchHost(googleHost, testQType)
}
assert.Equal(b, "forcesafesearch.google.com", dnsRewriteSink.NewCNAME)
require.NotNil(b, rewrite)
assert.Equal(b, "forcesafesearch.google.com", rewrite.NewCNAME)
// Most recent results:
//
// goos: darwin
// goarch: amd64
// pkg: github.com/AdguardTeam/AdGuardHome/internal/filtering/safesearch
// cpu: Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
// BenchmarkDefault_SearchHost-12 751882 1604 ns/op 129 B/op 5 allocs/op
}

View File

@@ -408,13 +408,12 @@ func (a *Auth) authRequired() bool {
// bytes of sessionTokenSize length.
//
// TODO(e.burkov): Think about using byte array instead of byte slice.
func newSessionToken() (data []byte, err error) {
func newSessionToken() (data []byte) {
randData := make([]byte, sessionTokenSize)
_, err = rand.Read(randData)
if err != nil {
return nil, err
}
// Since Go 1.24, crypto/rand.Read doesn't return an error and crashes
// unrecoverably instead.
_, _ = rand.Read(randData)
return randData, nil
return randData
}

View File

@@ -1,8 +1,6 @@
package home
import (
"bytes"
"crypto/rand"
"encoding/hex"
"path/filepath"
"testing"
@@ -12,23 +10,6 @@ import (
"github.com/stretchr/testify/require"
)
func TestNewSessionToken(t *testing.T) {
// Successful case.
token, err := newSessionToken()
require.NoError(t, err)
assert.Len(t, token, sessionTokenSize)
// Break the rand.Reader.
prevReader := rand.Reader
t.Cleanup(func() { rand.Reader = prevReader })
rand.Reader = &bytes.Buffer{}
// Unsuccessful case.
token, err = newSessionToken()
require.Error(t, err)
assert.Empty(t, token)
}
func TestAuth(t *testing.T) {
dir := t.TempDir()
fn := filepath.Join(dir, "sessions.db")
@@ -47,8 +28,7 @@ func TestAuth(t *testing.T) {
assert.Equal(t, checkSessionNotFound, a.checkSession("notfound"))
a.removeSession("notfound")
sess, err := newSessionToken()
require.NoError(t, err)
sess := newSessionToken()
sessStr := hex.EncodeToString(sess)
now := time.Now().UTC().Unix()

View File

@@ -47,11 +47,7 @@ func (a *Auth) newCookie(req loginJSON, addr string) (c *http.Cookie, err error)
rateLimiter.remove(addr)
}
sess, err := newSessionToken()
if err != nil {
return nil, fmt.Errorf("generating token: %w", err)
}
sess := newSessionToken()
now := time.Now().UTC()
a.addSession(sess, &session{

View File

@@ -12,17 +12,14 @@ import (
"github.com/AdguardTeam/AdGuardHome/internal/aghnet"
"github.com/AdguardTeam/AdGuardHome/internal/arpdb"
"github.com/AdguardTeam/AdGuardHome/internal/client"
"github.com/AdguardTeam/AdGuardHome/internal/dnsforward"
"github.com/AdguardTeam/AdGuardHome/internal/filtering"
"github.com/AdguardTeam/AdGuardHome/internal/filtering/safesearch"
"github.com/AdguardTeam/AdGuardHome/internal/querylog"
"github.com/AdguardTeam/AdGuardHome/internal/schedule"
"github.com/AdguardTeam/AdGuardHome/internal/whois"
"github.com/AdguardTeam/dnsproxy/proxy"
"github.com/AdguardTeam/dnsproxy/upstream"
"github.com/AdguardTeam/golibs/errors"
"github.com/AdguardTeam/golibs/logutil/slogutil"
"github.com/AdguardTeam/golibs/stringutil"
"github.com/AdguardTeam/golibs/timeutil"
)
// clientsContainer is the storage of all runtime and persistent clients.
@@ -75,6 +72,7 @@ func (clients *clientsContainer) Init(
etcHosts *aghnet.HostsContainer,
arpDB arpdb.Interface,
filteringConf *filtering.Config,
sigHdlr *signalHandler,
) (err error) {
// TODO(s.chzhen): Refactor it.
if clients.storage != nil {
@@ -109,6 +107,7 @@ func (clients *clientsContainer) Init(
clients.storage, err = client.NewStorage(ctx, &client.StorageConfig{
Logger: baseLogger.With(slogutil.KeyPrefix, "client_storage"),
Clock: timeutil.SystemClock{},
InitialClients: confClients,
DHCP: dhcpServer,
EtcHosts: hosts,
@@ -120,6 +119,8 @@ func (clients *clientsContainer) Init(
return fmt.Errorf("init client storage: %w", err)
}
sigHdlr.addClientStorage(clients.storage)
return nil
}
@@ -370,63 +371,6 @@ func (clients *clientsContainer) shouldCountClient(ids []string) (y bool) {
return true
}
// type check
var _ dnsforward.ClientsContainer = (*clientsContainer)(nil)
// UpstreamConfigByID implements the [dnsforward.ClientsContainer] interface for
// *clientsContainer. upsConf is nil if the client isn't found or if the client
// has no custom upstreams.
func (clients *clientsContainer) UpstreamConfigByID(
id string,
bootstrap upstream.Resolver,
) (conf *proxy.CustomUpstreamConfig, err error) {
clients.lock.Lock()
defer clients.lock.Unlock()
c, ok := clients.storage.Find(id)
if !ok {
return nil, nil
} else if c.UpstreamConfig != nil {
return c.UpstreamConfig, nil
}
upstreams := stringutil.FilterOut(c.Upstreams, dnsforward.IsCommentOrEmpty)
if len(upstreams) == 0 {
return nil, nil
}
var upsConf *proxy.UpstreamConfig
upsConf, err = proxy.ParseUpstreamsConfig(
upstreams,
&upstream.Options{
Bootstrap: bootstrap,
Timeout: time.Duration(config.DNS.UpstreamTimeout),
HTTPVersions: dnsforward.UpstreamHTTPVersions(config.DNS.UseHTTP3Upstreams),
PreferIPv6: config.DNS.BootstrapPreferIPv6,
},
)
if err != nil {
// Don't wrap the error since it's informative enough as is.
return nil, err
}
conf = proxy.NewCustomUpstreamConfig(
upsConf,
c.UpstreamsCacheEnabled,
int(c.UpstreamsCacheSize),
config.DNS.EDNSClientSubnet.Enabled,
)
c.UpstreamConfig = conf
// TODO(s.chzhen): Pass context.
err = clients.storage.Update(context.TODO(), c.Name, c)
if err != nil {
return nil, fmt.Errorf("setting upstream config: %w", err)
}
return conf, nil
}
// type check
var _ client.AddressUpdater = (*clientsContainer)(nil)

View File

@@ -1,15 +1,12 @@
package home
import (
"net"
"net/netip"
"testing"
"github.com/AdguardTeam/AdGuardHome/internal/client"
"github.com/AdguardTeam/AdGuardHome/internal/filtering"
"github.com/AdguardTeam/golibs/logutil/slogutil"
"github.com/AdguardTeam/golibs/testutil"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@@ -31,34 +28,10 @@ func newClientsContainer(t *testing.T) (c *clientsContainer) {
nil,
nil,
&filtering.Config{},
newSignalHandler(nil, nil),
)
require.NoError(t, err)
return c
}
func TestClientsCustomUpstream(t *testing.T) {
clients := newClientsContainer(t)
ctx := testutil.ContextWithTimeout(t, testTimeout)
// Add client with upstreams.
err := clients.storage.Add(ctx, &client.Persistent{
Name: "client1",
UID: client.MustNewUID(),
IPs: []netip.Addr{netip.MustParseAddr("1.1.1.1"), netip.MustParseAddr("1:2:3::4")},
Upstreams: []string{
"1.1.1.1",
"[/example.org/]8.8.8.8",
},
})
require.NoError(t, err)
upsConf, err := clients.UpstreamConfigByID("1.2.3.4", net.DefaultResolver)
assert.Nil(t, upsConf)
assert.NoError(t, err)
upsConf, err = clients.UpstreamConfigByID("1.1.1.1", net.DefaultResolver)
require.NotNil(t, upsConf)
assert.NoError(t, err)
}

View File

@@ -640,7 +640,7 @@ func readConfigFile() (fileData []byte, err error) {
}
// Saves configuration to the YAML file and also saves the user filter contents to a file
func (c *configuration) write() (err error) {
func (c *configuration) write(tlsMgr *tlsManager) (err error) {
c.Lock()
defer c.Unlock()
@@ -648,9 +648,9 @@ func (c *configuration) write() (err error) {
config.Users = globalContext.auth.usersList()
}
if globalContext.tls != nil {
if tlsMgr != nil {
tlsConf := tlsConfigSettings{}
globalContext.tls.WriteDiskConfig(&tlsConf)
tlsMgr.WriteDiskConfig(&tlsConf)
config.TLS = tlsConf
}

View File

@@ -68,7 +68,8 @@ func appendDNSAddrsWithIfaces(dst []string, src []netip.Addr) (res []string, err
// collectDNSAddresses returns the list of DNS addresses the server is listening
// on, including the addresses on all interfaces in cases of unspecified IPs.
func collectDNSAddresses() (addrs []string, err error) {
// tlsMgr must not be nil.
func collectDNSAddresses(tlsMgr *tlsManager) (addrs []string, err error) {
if hosts := config.DNS.BindHosts; len(hosts) == 0 {
addrs = appendDNSAddrs(addrs, netutil.IPv4Localhost())
} else {
@@ -78,7 +79,7 @@ func collectDNSAddresses() (addrs []string, err error) {
}
}
de := getDNSEncryption()
de := getDNSEncryption(tlsMgr)
if de.https != "" {
addrs = append(addrs, de.https)
}
@@ -113,8 +114,8 @@ type statusResponse struct {
IsRunning bool `json:"running"`
}
func handleStatus(w http.ResponseWriter, r *http.Request) {
dnsAddrs, err := collectDNSAddresses()
func (web *webAPI) handleStatus(w http.ResponseWriter, r *http.Request) {
dnsAddrs, err := collectDNSAddresses(web.tlsManager)
if err != nil {
// Don't add a lot of formatting, since the error is already
// wrapped by collectDNSAddresses.
@@ -167,9 +168,8 @@ func handleStatus(w http.ResponseWriter, r *http.Request) {
aghhttp.WriteJSONResponseOK(w, r, resp)
}
// ------------------------
// registration of handlers
// ------------------------
// registerControlHandlers sets up HTTP handlers for various control endpoints.
// web must not be nil.
func registerControlHandlers(web *webAPI) {
globalContext.mux.HandleFunc(
"/control/version.json",
@@ -177,7 +177,7 @@ func registerControlHandlers(web *webAPI) {
)
httpRegister(http.MethodPost, "/control/update", web.handleUpdate)
httpRegister(http.MethodGet, "/control/status", handleStatus)
httpRegister(http.MethodGet, "/control/status", web.handleStatus)
httpRegister(http.MethodPost, "/control/i18n/change_language", handleI18nChangeLanguage)
httpRegister(http.MethodGet, "/control/i18n/current_language", handleI18nCurrentLanguage)
httpRegister(http.MethodGet, "/control/profile", handleGetProfile)
@@ -189,6 +189,7 @@ func registerControlHandlers(web *webAPI) {
RegisterAuthHandlers()
}
// httpRegister registers an HTTP handler.
func httpRegister(method, url string, handler http.HandlerFunc) {
if method == "" {
// "/dns-query" handler doesn't need auth, gzip and isn't restricted by 1 HTTP method

View File

@@ -452,7 +452,7 @@ func (web *webAPI) handleInstallConfigure(w http.ResponseWriter, r *http.Request
// moment we'll allow setting up TLS in the initial configuration or the
// configuration itself will use HTTPS protocol, because the underlying
// functions potentially restart the HTTPS server.
err = startMods(web.baseLogger)
err = startMods(r.Context(), web.baseLogger, web.tlsManager)
if err != nil {
globalContext.firstRun = true
copyInstallSettings(config, curConfig)
@@ -461,7 +461,7 @@ func (web *webAPI) handleInstallConfigure(w http.ResponseWriter, r *http.Request
return
}
err = config.write()
err = config.write(web.tlsManager)
if err != nil {
globalContext.firstRun = true
copyInstallSettings(config, curConfig)
@@ -527,6 +527,31 @@ func decodeApplyConfigReq(r io.Reader) (req *applyConfigReq, restartHTTP bool, e
return req, restartHTTP, err
}
// startMods initializes and starts the DNS server after installation.
// baseLogger and tlsMgr must not be nil.
func startMods(ctx context.Context, baseLogger *slog.Logger, tlsMgr *tlsManager) (err error) {
statsDir, querylogDir, err := checkStatsAndQuerylogDirs(&globalContext, config)
if err != nil {
return err
}
err = initDNS(baseLogger, tlsMgr, statsDir, querylogDir)
if err != nil {
return err
}
tlsMgr.start(ctx)
err = startDNSServer()
if err != nil {
closeDNSServer()
return err
}
return nil
}
func (web *webAPI) registerInstallHandlers() {
globalContext.mux.HandleFunc("/control/install/get_addresses", preInstall(ensureGET(web.handleInstallGetAddresses)))
globalContext.mux.HandleFunc("/control/install/check_config", preInstall(ensurePOST(web.handleInstallCheckConfig)))

View File

@@ -62,7 +62,7 @@ func (web *webAPI) handleVersionJSON(w http.ResponseWriter, r *http.Request) {
return
}
err = resp.setAllowedToAutoUpdate()
err = resp.setAllowedToAutoUpdate(web.tlsManager)
if err != nil {
// Don't wrap the error, because it's informative enough as is.
aghhttp.Error(r, w, http.StatusInternalServerError, "%s", err)
@@ -158,14 +158,14 @@ type versionResponse struct {
}
// setAllowedToAutoUpdate sets CanAutoUpdate to true if AdGuard Home is actually
// allowed to perform an automatic update by the OS.
func (vr *versionResponse) setAllowedToAutoUpdate() (err error) {
// allowed to perform an automatic update by the OS. tlsMgr must not be nil.
func (vr *versionResponse) setAllowedToAutoUpdate(tlsMgr *tlsManager) (err error) {
if vr.CanAutoUpdate != aghalg.NBTrue {
return nil
}
tlsConf := &tlsConfigSettings{}
globalContext.tls.WriteDiskConfig(tlsConf)
tlsMgr.WriteDiskConfig(tlsConf)
canUpdate := true
if tlsConfUsesPrivilegedPorts(tlsConf) ||

View File

@@ -39,16 +39,22 @@ const (
// Called by other modules when configuration is changed
func onConfigModified() {
err := config.write()
err := config.write(globalContext.tls)
if err != nil {
log.Error("writing config: %s", err)
}
}
// initDNS updates all the fields of the [globalContext] needed to initialize the DNS
// server and initializes it at last. It also must not be called unless
// [config] and [globalContext] are initialized. baseLogger must not be nil.
func initDNS(baseLogger *slog.Logger, statsDir, querylogDir string) (err error) {
// initDNS updates all the fields of the [globalContext] needed to initialize
// the DNS server and initializes it at last. It also must not be called unless
// [config] and [globalContext] are initialized. baseLogger and tlsMgr must not
// be nil.
func initDNS(
baseLogger *slog.Logger,
tlsMgr *tlsManager,
statsDir string,
querylogDir string,
) (err error) {
anonymizer := config.anonymizer()
statsConf := stats.Config{
@@ -104,7 +110,7 @@ func initDNS(baseLogger *slog.Logger, statsDir, querylogDir string) (err error)
}
tlsConf := &tlsConfigSettings{}
globalContext.tls.WriteDiskConfig(tlsConf)
tlsMgr.WriteDiskConfig(tlsConf)
return initDNSServer(
globalContext.filters,
@@ -156,7 +162,13 @@ func initDNSServer(
globalContext.clients.clientChecker = globalContext.dnsServer
dnsConf, err := newServerConfig(&config.DNS, config.Clients.Sources, tlsConf, httpReg)
dnsConf, err := newServerConfig(
&config.DNS,
config.Clients.Sources,
tlsConf,
httpReg,
globalContext.clients.storage,
)
if err != nil {
return fmt.Errorf("newServerConfig: %w", err)
}
@@ -230,12 +242,13 @@ func newServerConfig(
clientSrcConf *clientSourcesConfig,
tlsConf *tlsConfigSettings,
httpReg aghhttp.RegisterFunc,
clientsContainer dnsforward.ClientsContainer,
) (newConf *dnsforward.ServerConfig, err error) {
hosts := aghalg.CoalesceSlice(dnsConf.BindHosts, []netip.Addr{netutil.IPv4Localhost()})
fwdConf := dnsConf.Config
fwdConf.FilterHandler = applyAdditionalFiltering
fwdConf.ClientsContainer = &globalContext.clients
fwdConf.ClientsContainer = clientsContainer
newConf = &dnsforward.ServerConfig{
UDPListenAddrs: ipsToUDPAddrs(hosts, dnsConf.Port),
@@ -350,16 +363,18 @@ func newDNSCryptConfig(
}, nil
}
// dnsEncryption contains different types of TLS encryption addresses.
type dnsEncryption struct {
https string
tls string
quic string
}
func getDNSEncryption() (de dnsEncryption) {
// getDNSEncryption returns the TLS encryption addresses that AdGuard Home
// listens on. tlsMgr must not be nil.
func getDNSEncryption(tlsMgr *tlsManager) (de dnsEncryption) {
tlsConf := tlsConfigSettings{}
globalContext.tls.WriteDiskConfig(&tlsConf)
tlsMgr.WriteDiskConfig(&tlsConf)
if !tlsConf.Enabled || len(tlsConf.ServerName) == 0 {
return dnsEncryption{}
@@ -480,11 +495,19 @@ func startDNSServer() error {
return nil
}
func reconfigureDNSServer() (err error) {
// reconfigureDNSServer updates the DNS server configuration using the provided
// TLS settings. tlsMgr must not be nil.
func reconfigureDNSServer(tlsMgr *tlsManager) (err error) {
tlsConf := &tlsConfigSettings{}
globalContext.tls.WriteDiskConfig(tlsConf)
tlsMgr.WriteDiskConfig(tlsConf)
newConf, err := newServerConfig(&config.DNS, config.Clients.Sources, tlsConf, httpRegister)
newConf, err := newServerConfig(
&config.DNS,
config.Clients.Sources,
tlsConf,
httpRegister,
globalContext.clients.storage,
)
if err != nil {
return fmt.Errorf("generating forwarding dns server config: %w", err)
}

View File

@@ -57,7 +57,12 @@ type homeContext struct {
auth *Auth // HTTP authentication module
filters *filtering.DNSFilter // DNS filtering module
web *webAPI // Web (HTTP, HTTPS) module
tls *tlsManager // TLS module
// tls contains the current configuration and state of TLS encryption.
//
// TODO(s.chzhen): Remove once it is no longer called from different
// modules. See [onConfigModified].
tls *tlsManager
// etcHosts contains IP-hostname mappings taken from the OS-specific hosts
// configuration files, for example /etc/hosts.
@@ -113,31 +118,23 @@ func Main(clientBuildFS fs.FS) {
signals := make(chan os.Signal, 1)
signal.Notify(signals, syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP, syscall.SIGQUIT)
go func() {
ctx := context.Background()
for {
sig := <-signals
log.Info("Received signal %q", sig)
switch sig {
case syscall.SIGHUP:
globalContext.clients.storage.ReloadARP(ctx)
globalContext.tls.reload()
default:
cleanup(ctx)
cleanupAlways()
close(done)
}
}
}()
ctx := context.Background()
sigHdlr := newSignalHandler(signals, func(ctx context.Context) {
cleanup(ctx)
cleanupAlways()
close(done)
})
go sigHdlr.handle(ctx)
if opts.serviceControlAction != "" {
handleServiceControlAction(opts, clientBuildFS, signals, done)
handleServiceControlAction(opts, clientBuildFS, signals, done, sigHdlr)
return
}
// run the protection
run(opts, clientBuildFS, done)
run(opts, clientBuildFS, done, sigHdlr)
}
// setupContext initializes [globalContext] fields. It also reads and upgrades
@@ -278,7 +275,11 @@ func setupOpts(opts options) (err error) {
}
// initContextClients initializes Context clients and related fields.
func initContextClients(ctx context.Context, logger *slog.Logger) (err error) {
func initContextClients(
ctx context.Context,
logger *slog.Logger,
sigHdlr *signalHandler,
) (err error) {
err = setupDNSFilteringConf(ctx, logger, config.Filtering)
if err != nil {
// Don't wrap the error, because it's informative enough as is.
@@ -313,6 +314,7 @@ func initContextClients(ctx context.Context, logger *slog.Logger) (err error) {
globalContext.etcHosts,
arpDB,
config.Filtering,
sigHdlr,
)
}
@@ -522,13 +524,15 @@ func isUpdateEnabled(ctx context.Context, l *slog.Logger, opts *options, customU
}
}
// initWeb initializes the web module. upd and baseLogger must not be nil.
// initWeb initializes the web module. upd, baseLogger, and tlsMgr must not be
// nil.
func initWeb(
ctx context.Context,
opts options,
clientBuildFS fs.FS,
upd *updater.Updater,
baseLogger *slog.Logger,
tlsMgr *tlsManager,
customURL bool,
) (web *webAPI, err error) {
logger := baseLogger.With(slogutil.KeyPrefix, "webapi")
@@ -551,6 +555,7 @@ func initWeb(
updater: upd,
logger: logger,
baseLogger: baseLogger,
tlsManager: tlsMgr,
clientFS: clientFS,
@@ -583,7 +588,7 @@ func fatalOnError(err error) {
// run configures and starts AdGuard Home.
//
// TODO(e.burkov): Make opts a pointer.
func run(opts options, clientBuildFS fs.FS, done chan struct{}) {
func run(opts options, clientBuildFS fs.FS, done chan struct{}, sigHdlr *signalHandler) {
// Configure working dir.
err := initWorkingDir(opts)
fatalOnError(err)
@@ -599,9 +604,10 @@ func run(opts options, clientBuildFS fs.FS, done chan struct{}) {
// TODO(a.garipov): Use slog everywhere.
slogLogger := newSlogLogger(ls)
sigHdlr.swapLogger(slogLogger)
// Print the first message after logger is configured.
log.Info(version.Full())
log.Info("%s", version.Full())
log.Debug("current working directory is %s", globalContext.workDir)
if opts.runningAsService {
log.Info("AdGuard Home is running as a service")
@@ -621,7 +627,7 @@ func run(opts options, clientBuildFS fs.FS, done chan struct{}) {
// TODO(s.chzhen): Use it for the entire initialization process.
ctx := context.Background()
err = initContextClients(ctx, slogLogger)
err = initContextClients(ctx, slogLogger, sigHdlr)
fatalOnError(err)
err = setupOpts(opts)
@@ -640,7 +646,7 @@ func run(opts options, clientBuildFS fs.FS, done chan struct{}) {
if !globalContext.firstRun {
// Save the updated config.
err = config.write()
err = config.write(nil)
fatalOnError(err)
if config.HTTPConfig.Pprof.Enabled {
@@ -658,23 +664,26 @@ func run(opts options, clientBuildFS fs.FS, done chan struct{}) {
globalContext.auth, err = initUsers()
fatalOnError(err)
globalContext.tls, err = newTLSManager(config.TLS, config.DNS.ServePlainDNS)
tlsMgr, err := newTLSManager(config.TLS, config.DNS.ServePlainDNS)
if err != nil {
log.Error("initializing tls: %s", err)
onConfigModified()
}
globalContext.web, err = initWeb(ctx, opts, clientBuildFS, upd, slogLogger, customURL)
globalContext.tls = tlsMgr
sigHdlr.addTLSManager(tlsMgr)
globalContext.web, err = initWeb(ctx, opts, clientBuildFS, upd, slogLogger, tlsMgr, customURL)
fatalOnError(err)
statsDir, querylogDir, err := checkStatsAndQuerylogDirs(&globalContext, config)
fatalOnError(err)
if !globalContext.firstRun {
err = initDNS(slogLogger, statsDir, querylogDir)
err = initDNS(slogLogger, tlsMgr, statsDir, querylogDir)
fatalOnError(err)
globalContext.tls.start()
tlsMgr.start(ctx)
go func() {
startErr := startDNSServer()
@@ -807,31 +816,6 @@ func (c *configuration) anonymizer() (ipmut *aghnet.IPMut) {
return aghnet.NewIPMut(anonFunc)
}
// startMods initializes and starts the DNS server after installation.
// baseLogger must not be nil.
func startMods(baseLogger *slog.Logger) (err error) {
statsDir, querylogDir, err := checkStatsAndQuerylogDirs(&globalContext, config)
if err != nil {
return err
}
err = initDNS(baseLogger, statsDir, querylogDir)
if err != nil {
return err
}
globalContext.tls.start()
err = startDNSServer()
if err != nil {
closeDNSServer()
return err
}
return nil
}
// checkNetworkPermissions checks if the current user permissions are enough to
// use the required networking functionality.
func checkNetworkPermissions() {
@@ -950,10 +934,6 @@ func cleanup(ctx context.Context) {
log.Error("closing hosts container: %s", err)
}
}
if globalContext.tls != nil {
globalContext.tls = nil
}
}
// This function is called before application exits
@@ -975,7 +955,7 @@ func exitWithError() {
func loadCmdLineOpts() (opts options) {
opts, eff, err := parseCmdOpts(os.Args[0], os.Args[1:])
if err != nil {
log.Error(err.Error())
log.Error("%s", err)
printHelp(os.Args[0])
exitWithError()
@@ -984,7 +964,7 @@ func loadCmdLineOpts() (opts options) {
if eff != nil {
err = eff()
if err != nil {
log.Error(err.Error())
log.Error("%s", err)
exitWithError()
}
@@ -1005,10 +985,12 @@ func printWebAddrs(proto, addr string, port uint16) {
// printHTTPAddresses prints the IP addresses which user can use to access the
// admin interface. proto is either schemeHTTP or schemeHTTPS.
func printHTTPAddresses(proto string) {
//
// TODO(s.chzhen): Implement separate functions for HTTP and HTTPS.
func printHTTPAddresses(proto string, tlsMgr *tlsManager) {
tlsConf := tlsConfigSettings{}
if globalContext.tls != nil {
globalContext.tls.WriteDiskConfig(&tlsConf)
if tlsMgr != nil {
tlsMgr.WriteDiskConfig(&tlsConf)
}
port := config.HTTPConfig.Address.Port()
@@ -1016,7 +998,6 @@ func printHTTPAddresses(proto string) {
port = tlsConf.PortHTTPS
}
// TODO(e.burkov): Inspect and perhaps merge with the previous condition.
if proto == urlutil.SchemeHTTPS && tlsConf.ServerName != "" {
printWebAddrs(proto, tlsConf.ServerName, tlsConf.PortHTTPS)

View File

@@ -19,10 +19,8 @@ func setupDNSIPs(t testing.TB) {
t.Helper()
prevConfig := config
prevTLS := globalContext.tls
t.Cleanup(func() {
config = prevConfig
globalContext.tls = prevTLS
})
config = &configuration{
@@ -31,8 +29,6 @@ func setupDNSIPs(t testing.TB) {
Port: defaultPortDNS,
},
}
globalContext.tls = &tlsManager{}
}
func TestHandleMobileConfigDoH(t *testing.T) {
@@ -62,11 +58,6 @@ func TestHandleMobileConfigDoH(t *testing.T) {
})
t.Run("error_no_host", func(t *testing.T) {
oldTLSConf := globalContext.tls
t.Cleanup(func() { globalContext.tls = oldTLSConf })
globalContext.tls = &tlsManager{conf: tlsConfigSettings{}}
r, err := http.NewRequest(http.MethodGet, "https://example.com:12345/apple/doh.mobileconfig", nil)
require.NoError(t, err)
@@ -134,11 +125,6 @@ func TestHandleMobileConfigDoT(t *testing.T) {
})
t.Run("error_no_host", func(t *testing.T) {
oldTLSConf := globalContext.tls
t.Cleanup(func() { globalContext.tls = oldTLSConf })
globalContext.tls = &tlsManager{conf: tlsConfigSettings{}}
r, err := http.NewRequest(http.MethodGet, "https://example.com:12345/apple/dot.mobileconfig", nil)
require.NoError(t, err)

View File

@@ -36,6 +36,7 @@ type program struct {
signals chan os.Signal
done chan struct{}
opts options
sigHdlr *signalHandler
}
// type check
@@ -47,7 +48,7 @@ func (p *program) Start(_ service.Service) (err error) {
args := p.opts
args.runningAsService = true
go run(args, p.clientBuildFS, p.done)
go run(args, p.clientBuildFS, p.done, p.sigHdlr)
return nil
}
@@ -204,13 +205,14 @@ func handleServiceControlAction(
clientBuildFS fs.FS,
signals chan os.Signal,
done chan struct{},
sigHdlr *signalHandler,
) {
// Call chooseSystem explicitly to introduce OpenBSD support for service
// package. It's a noop for other GOOS values.
chooseSystem()
action := opts.serviceControlAction
log.Info(version.Full())
log.Info("%s", version.Full())
log.Info("service: control action: %s", action)
if action == "reload" {
@@ -244,6 +246,7 @@ func handleServiceControlAction(
signals: signals,
done: done,
opts: runOpts,
sigHdlr: sigHdlr,
}, svcConfig)
if err != nil {
log.Fatalf("service: initializing service: %s", err)
@@ -336,7 +339,7 @@ AdGuard Home is successfully installed and will automatically start on boot.
There are a few more things that must be configured before you can use it.
Click on the link below and follow the Installation Wizard steps to finish setup.
AdGuard Home is now available at the following addresses:`)
printHTTPAddresses(urlutil.SchemeHTTP)
printHTTPAddresses(urlutil.SchemeHTTP, nil)
}
}

View File

@@ -392,7 +392,7 @@ type sysLogger struct{}
// Error implements service.Logger interface for sysLogger.
func (sysLogger) Error(v ...any) error {
log.Error(fmt.Sprint(v...))
log.Error("%s", fmt.Sprint(v...))
return nil
}
@@ -406,7 +406,7 @@ func (sysLogger) Warning(v ...any) error {
// Info implements service.Logger interface for sysLogger.
func (sysLogger) Info(v ...any) error {
log.Info(fmt.Sprint(v...))
log.Info("%s", fmt.Sprint(v...))
return nil
}

121
internal/home/signal.go Normal file
View File

@@ -0,0 +1,121 @@
package home
import (
"context"
"log/slog"
"os"
"sync"
"sync/atomic"
"syscall"
"github.com/AdguardTeam/AdGuardHome/internal/client"
"github.com/AdguardTeam/golibs/logutil/slogutil"
"github.com/AdguardTeam/golibs/osutil"
)
// signalHandler processes incoming signals. It reloads configurations of
// stored entities on SIGHUP and performs cleanup on all other signals.
type signalHandler struct {
// logger is used to log the operation of the signal handler. Initially,
// [slog.Default] is used, but it should be swapped later using
// [signalHandler.swapLogger].
logger *atomic.Pointer[slog.Logger]
// mu protects clientStorage and tlsManager.
mu *sync.Mutex
// clientStorage is used to reload information about runtime clients with an
// ARP source.
clientStorage *client.Storage
// tlsManager is used to reload the TLS configuration.
tlsManager *tlsManager
// signals receives incoming signals.
signals <-chan os.Signal
// cleanup is called to perform cleanup on all incoming signals, except
// SIGHUP.
cleanup func(ctx context.Context)
}
// newSignalHandler returns a new properly initialized *signalHandler.
func newSignalHandler(
signals <-chan os.Signal,
cleanup func(ctx context.Context),
) (h *signalHandler) {
h = &signalHandler{
logger: &atomic.Pointer[slog.Logger]{},
mu: &sync.Mutex{},
signals: signals,
cleanup: cleanup,
}
h.logger.Store(slog.Default())
return h
}
// swapLogger replaces the stored logger with the given logger.
func (h *signalHandler) swapLogger(logger *slog.Logger) {
h.logger.Swap(logger)
}
// addClientStorage stores the client storage.
func (h *signalHandler) addClientStorage(s *client.Storage) {
h.mu.Lock()
defer h.mu.Unlock()
h.clientStorage = s
}
// addTLSManager stores the TLS manager.
func (h *signalHandler) addTLSManager(m *tlsManager) {
h.mu.Lock()
defer h.mu.Unlock()
h.tlsManager = m
}
// handle processes incoming signals. It blocks until a signal is received. It
// reloads configurations of stored entities on SIGHUP, or performs cleanup on
// all other signals. It is intended to be used as a goroutine.
func (h *signalHandler) handle(ctx context.Context) {
// NOTE: Avoid using [slogutil.RecoverAndExit] to prevent immediate
// evaluation of the logger.
defer func() {
v := recover()
if v == nil {
return
}
slogutil.PrintRecovered(ctx, h.logger.Load(), v)
os.Exit(osutil.ExitCodeFailure)
}()
for {
sig := <-h.signals
h.logger.Load().InfoContext(ctx, "received signal", "signal", sig)
switch sig {
case syscall.SIGHUP:
h.reloadConfig(ctx)
default:
h.cleanup(ctx)
}
}
}
// reloadConfig refreshes configurations of stored entities.
func (h *signalHandler) reloadConfig(ctx context.Context) {
h.mu.Lock()
defer h.mu.Unlock()
if h.clientStorage != nil {
h.clientStorage.ReloadARP(ctx)
}
if h.tlsManager != nil {
h.tlsManager.reload()
}
}

View File

@@ -102,7 +102,9 @@ func (m *tlsManager) setCertFileTime() {
}
// start updates the configuration of t and starts it.
func (m *tlsManager) start() {
//
// TODO(s.chzhen): Use context.
func (m *tlsManager) start(_ context.Context) {
m.registerWebHandlers()
m.confLock.Lock()
@@ -151,7 +153,7 @@ func (m *tlsManager) reload() {
m.certLastMod = fi.ModTime().UTC()
_ = reconfigureDNSServer()
_ = reconfigureDNSServer(m)
m.confLock.Lock()
tlsConf = m.conf
@@ -440,7 +442,7 @@ func (m *tlsManager) handleTLSConfigure(w http.ResponseWriter, r *http.Request)
onConfigModified()
err = reconfigureDNSServer()
err = reconfigureDNSServer(m)
if err != nil {
aghhttp.Error(r, w, http.StatusInternalServerError, "%s", err)

View File

@@ -49,6 +49,10 @@ type webConfig struct {
// nil.
baseLogger *slog.Logger
// tlsManager contains the current configuration and state of TLS
// encryption. It must not be nil.
tlsManager *tlsManager
clientFS fs.FS
// BindAddr is the binding address with port for plain HTTP web interface.
@@ -108,6 +112,10 @@ type webAPI struct {
// nil.
baseLogger *slog.Logger
// tlsManager contains the current configuration and state of TLS
// encryption.
tlsManager *tlsManager
// httpsServer is the server that handles HTTPS traffic. If it is not nil,
// [Web.http3Server] must also not be nil.
httpsServer httpsServer
@@ -124,6 +132,7 @@ func newWebAPI(ctx context.Context, conf *webConfig) (w *webAPI) {
conf: conf,
logger: conf.logger,
baseLogger: conf.baseLogger,
tlsManager: conf.tlsManager,
}
clientFS := http.FileServer(http.FS(conf.clientFS))
@@ -220,7 +229,7 @@ func (web *webAPI) start(ctx context.Context) {
// this loop is used as an ability to change listening host and/or port
for !web.httpsServer.inShutdown {
printHTTPAddresses(urlutil.SchemeHTTP)
printHTTPAddresses(urlutil.SchemeHTTP, web.tlsManager)
errs := make(chan error, 2)
// Use an h2c handler to support unencrypted HTTP/2, e.g. for proxies.
@@ -330,7 +339,7 @@ func (web *webAPI) tlsServerLoop(ctx context.Context) {
ErrorLog: slog.NewLogLogger(logger.Handler(), slog.LevelError),
}
printHTTPAddresses(urlutil.SchemeHTTPS)
printHTTPAddresses(urlutil.SchemeHTTPS, web.tlsManager)
if web.conf.serveHTTP3 {
go web.mustStartHTTP3(ctx, addr)

View File

@@ -134,9 +134,6 @@ func TestManager_Add(t *testing.T) {
assert.NoError(t, err)
}
// ipsetPropsSink is the typed sink for benchmark results.
var ipsetPropsSink []props
func BenchmarkManager_LookupHost(b *testing.B) {
propsLong := []props{{
name: "example.com",
@@ -155,9 +152,13 @@ func BenchmarkManager_LookupHost(b *testing.B) {
},
}
var ipsetPropsSink []props
b.Run("long", func(b *testing.B) {
const name = "a.very.long.domain.name.inside.the.domain.example.com"
for range b.N {
b.ReportAllocs()
for b.Loop() {
ipsetPropsSink = m.lookupHost(name)
}
@@ -166,10 +167,21 @@ func BenchmarkManager_LookupHost(b *testing.B) {
b.Run("short", func(b *testing.B) {
const name = "example.net"
for range b.N {
b.ReportAllocs()
for b.Loop() {
ipsetPropsSink = m.lookupHost(name)
}
require.Equal(b, propsShort, ipsetPropsSink)
})
// Most recent results:
//
// goos: linux
// goarch: amd64
// pkg: github.com/AdguardTeam/AdGuardHome/internal/ipset
// cpu: Intel(R) Core(TM) i7-10510U CPU @ 1.80GHz
// BenchmarkManager_LookupHost/long-8 6562424 174.8 ns/op 0 B/op 0 allocs/op
// BenchmarkManager_LookupHost/short-8 100000000 10.72 ns/op 0 B/op 0 allocs/op
}

View File

@@ -283,6 +283,8 @@ func anonymizeIPSlow(ip net.IP) {
}
}
// TODO(e.burkov): Investigate the results, it seems that the slow version
// isn't that slow.
func BenchmarkAnonymizeIP(b *testing.B) {
benchCases := []struct {
name string
@@ -320,7 +322,7 @@ func BenchmarkAnonymizeIP(b *testing.B) {
b.Run(bc.name, func(b *testing.B) {
b.ReportAllocs()
for range b.N {
for b.Loop() {
AnonymizeIP(bc.ip)
}
@@ -330,11 +332,26 @@ func BenchmarkAnonymizeIP(b *testing.B) {
b.Run(bc.name+"_slow", func(b *testing.B) {
b.ReportAllocs()
for range b.N {
for b.Loop() {
anonymizeIPSlow(bc.ip)
}
assert.Equal(b, bc.want, bc.ip)
})
}
// Most recent results:
//
// goos: darwin
// goarch: amd64
// pkg: github.com/AdguardTeam/AdGuardHome/internal/querylog
// cpu: Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
// BenchmarkAnonymizeIP/v4-12 426499675 2.687 ns/op 0 B/op 0 allocs/op
// BenchmarkAnonymizeIP/v4_slow-12 510082938 2.412 ns/op 0 B/op 0 allocs/op
// BenchmarkAnonymizeIP/v4_mapped-12 149121745 7.992 ns/op 0 B/op 0 allocs/op
// BenchmarkAnonymizeIP/v4_mapped_slow-12 178441804 6.698 ns/op 0 B/op 0 allocs/op
// BenchmarkAnonymizeIP/v6-12 346746447 3.436 ns/op 0 B/op 0 allocs/op
// BenchmarkAnonymizeIP/v6_slow-12 419062732 2.966 ns/op 0 B/op 0 allocs/op
// BenchmarkAnonymizeIP/invalid-12 316385232 3.941 ns/op 0 B/op 0 allocs/op
// BenchmarkAnonymizeIP/invalid_slow-12 456531592 2.760 ns/op 0 B/op 0 allocs/op
}

View File

@@ -1,68 +0,0 @@
module github.com/AdguardTeam/AdGuardHome/internal/tools
go 1.23.6
require (
github.com/fzipp/gocyclo v0.6.0
github.com/golangci/misspell v0.6.0
github.com/gordonklaus/ineffassign v0.1.0
github.com/jstemmer/go-junit-report/v2 v2.1.0
github.com/kisielk/errcheck v1.8.0
github.com/securego/gosec/v2 v2.22.1
github.com/uudashr/gocognit v1.2.0
golang.org/x/tools v0.30.0
golang.org/x/vuln v1.1.4
honnef.co/go/tools v0.6.0
mvdan.cc/gofumpt v0.7.0
mvdan.cc/sh/v3 v3.10.0
mvdan.cc/unparam v0.0.0-20250211232406-0e51248738fc
)
require (
cloud.google.com/go v0.118.2 // indirect
cloud.google.com/go/ai v0.10.0 // indirect
cloud.google.com/go/auth v0.14.1 // indirect
cloud.google.com/go/auth/oauth2adapt v0.2.7 // indirect
cloud.google.com/go/compute/metadata v0.6.0 // indirect
cloud.google.com/go/longrunning v0.6.4 // indirect
github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c // indirect
github.com/ccojocar/zxcvbn-go v1.0.2 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/google/generative-ai-go v0.19.0 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/renameio/v2 v2.0.0 // indirect
github.com/google/s2a-go v0.1.9 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect
github.com/googleapis/gax-go/v2 v2.14.1 // indirect
github.com/gookit/color v1.5.4 // indirect
github.com/rogpeppe/go-internal v1.13.2-0.20241226121412-a5dc8ff20d0a // indirect
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 // indirect
go.opentelemetry.io/otel v1.34.0 // indirect
go.opentelemetry.io/otel/metric v1.34.0 // indirect
go.opentelemetry.io/otel/trace v1.34.0 // indirect
golang.org/x/crypto v0.33.0 // indirect
golang.org/x/exp v0.0.0-20250207012021-f9890c6ad9f3 // indirect
golang.org/x/exp/typeparams v0.0.0-20250218142911-aa4b98e5adaa // indirect
golang.org/x/mod v0.23.0 // indirect
golang.org/x/net v0.35.0 // indirect
golang.org/x/oauth2 v0.26.0 // indirect
golang.org/x/sync v0.11.0 // indirect
golang.org/x/sys v0.30.0 // indirect
golang.org/x/telemetry v0.0.0-20250214215356-6f9b61db478c // indirect
golang.org/x/term v0.29.0 // indirect
golang.org/x/text v0.22.0 // indirect
golang.org/x/time v0.10.0 // indirect
google.golang.org/api v0.221.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250212204824-5a70512c5d8b // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250212204824-5a70512c5d8b // indirect
google.golang.org/grpc v1.70.0 // indirect
google.golang.org/protobuf v1.36.5 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
mvdan.cc/editorconfig v0.3.0 // indirect
)

View File

@@ -1,178 +0,0 @@
cloud.google.com/go v0.118.2 h1:bKXO7RXMFDkniAAvvuMrAPtQ/VHrs9e7J5UT3yrGdTY=
cloud.google.com/go v0.118.2/go.mod h1:CFO4UPEPi8oV21xoezZCrd3d81K4fFkDTEJu4R8K+9M=
cloud.google.com/go/ai v0.10.0 h1:hwj6CI6sMKubXodoJJGTy/c2T1RbbLGM6TL3QoAvzU8=
cloud.google.com/go/ai v0.10.0/go.mod h1:kvnt2KeHqX8+41PVeMRBETDyQAp/RFvBWGdx/aGjNMo=
cloud.google.com/go/auth v0.14.1 h1:AwoJbzUdxA/whv1qj3TLKwh3XX5sikny2fc40wUl+h0=
cloud.google.com/go/auth v0.14.1/go.mod h1:4JHUxlGXisL0AW8kXPtUF6ztuOksyfUQNFjfsOCXkPM=
cloud.google.com/go/auth/oauth2adapt v0.2.7 h1:/Lc7xODdqcEw8IrZ9SvwnlLX6j9FHQM74z6cBk9Rw6M=
cloud.google.com/go/auth/oauth2adapt v0.2.7/go.mod h1:NTbTTzfvPl1Y3V1nPpOgl2w6d/FjO7NNUQaWSox6ZMc=
cloud.google.com/go/compute/metadata v0.6.0 h1:A6hENjEsCDtC1k8byVsgwvVcioamEHvZ4j01OwKxG9I=
cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg=
cloud.google.com/go/longrunning v0.6.4 h1:3tyw9rO3E2XVXzSApn1gyEEnH2K9SynNQjMlBi3uHLg=
cloud.google.com/go/longrunning v0.6.4/go.mod h1:ttZpLCe6e7EXvn9OxpBRx7kZEB0efv8yBO6YnVMfhJs=
github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c h1:pxW6RcqyfI9/kWtOwnv/G+AzdKuy2ZrqINhenH4HyNs=
github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
github.com/ccojocar/zxcvbn-go v1.0.2 h1:na/czXU8RrhXO4EZme6eQJLR4PzcGsahsBOAwU6I3Vg=
github.com/ccojocar/zxcvbn-go v1.0.2/go.mod h1:g1qkXtUSvHP8lhHp5GrSmTz6uWALGRMQdw6Qnz/hi60=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo=
github.com/fzipp/gocyclo v0.6.0/go.mod h1:rXPyn8fnlpa0R2csP/31uerbiVBugk5whMdlyaLkLoA=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/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-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI=
github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow=
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/golangci/misspell v0.6.0 h1:JCle2HUTNWirNlDIAUO44hUsKhOFqGPoC4LZxlaSXDs=
github.com/golangci/misspell v0.6.0/go.mod h1:keMNyY6R9isGaSAu+4Q8NMBwMPkh15Gtc8UCVoDtAWo=
github.com/google/generative-ai-go v0.19.0 h1:R71szggh8wHMCUlEMsW2A/3T+5LdEIkiaHSYgSpUgdg=
github.com/google/generative-ai-go v0.19.0/go.mod h1:JYolL13VG7j79kM5BtHz4qwONHkeJQzOCkKXnpqtS/E=
github.com/google/go-cmdtest v0.4.1-0.20220921163831-55ab3332a786 h1:rcv+Ippz6RAtvaGgKxc+8FQIpxHgsF+HBzPyYL2cyVU=
github.com/google/go-cmdtest v0.4.1-0.20220921163831-55ab3332a786/go.mod h1:apVn/GCasLZUVpAJ6oWAuyP7Ne7CEsQbTnc0plM3m+o=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad h1:a6HEuzUHeKH6hwfN/ZoQgRgVIWFJljSWa/zetS2WTvg=
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
github.com/google/renameio v0.1.0 h1:GOZbcHa3HfsPKPlmyPyN2KEohoMXOhdMbHrvbpl2QaA=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/renameio/v2 v2.0.0 h1:UifI23ZTGY8Tt29JbYFiuyIU3eX+RNFtUwefq9qAhxg=
github.com/google/renameio/v2 v2.0.0/go.mod h1:BtmJXm5YlszgC+TD4HOEEUFgkJP3nLxehU6hfe7jRt4=
github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0=
github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/enterprise-certificate-proxy v0.3.4 h1:XYIDZApgAnrN1c855gTgghdIA6Stxb52D5RnLI1SLyw=
github.com/googleapis/enterprise-certificate-proxy v0.3.4/go.mod h1:YKe7cfqYXjKGpGvmSg28/fFvhNzinZQm8DGnaburhGA=
github.com/googleapis/gax-go/v2 v2.14.1 h1:hb0FFeiPaQskmvakKu5EbCbpntQn48jyHuvrkurSS/Q=
github.com/googleapis/gax-go/v2 v2.14.1/go.mod h1:Hb/NubMaVM88SrNkvl8X/o8XWwDJEPqouaLeN2IUxoA=
github.com/gookit/color v1.5.4 h1:FZmqs7XOyGgCAxmWyPslpiok1k05wmY3SJTytgvYFs0=
github.com/gookit/color v1.5.4/go.mod h1:pZJOeOS8DM43rXbp4AZo1n9zCU2qjpcRko0b6/QJi9w=
github.com/gordonklaus/ineffassign v0.1.0 h1:y2Gd/9I7MdY1oEIt+n+rowjBNDcLQq3RsH5hwJd0f9s=
github.com/gordonklaus/ineffassign v0.1.0/go.mod h1:Qcp2HIAYhR7mNUVSIxZww3Guk4it82ghYcEXIAk+QT0=
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/kisielk/errcheck v1.8.0 h1:ZX/URYa7ilESY19ik/vBmCn6zdGQLxACwjAcWbHlYlg=
github.com/kisielk/errcheck v1.8.0/go.mod h1:1kLL+jV4e+CFfueBmI1dSK2ADDyQnlrnrY/FqKluHJQ=
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/onsi/ginkgo/v2 v2.22.2 h1:/3X8Panh8/WwhU/3Ssa6rCKqPLuAkVY2I0RoyDLySlU=
github.com/onsi/ginkgo/v2 v2.22.2/go.mod h1:oeMosUL+8LtarXBHu/c0bx2D/K9zyQ6uX3cTyztHwsk=
github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8=
github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY=
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/rogpeppe/go-internal v1.13.2-0.20241226121412-a5dc8ff20d0a h1:w3tdWGKbLGBPtR/8/oO74W6hmz0qE5q0z9aqSAewaaM=
github.com/rogpeppe/go-internal v1.13.2-0.20241226121412-a5dc8ff20d0a/go.mod h1:S8kfXMp+yh77OxPD4fdM6YUknrZpQxLhvxzS4gDHENY=
github.com/securego/gosec/v2 v2.22.1 h1:IcBt3TpI5Y9VN1YlwjSpM2cHu0i3Iw52QM+PQeg7jN8=
github.com/securego/gosec/v2 v2.22.1/go.mod h1:4bb95X4Jz7VSEPdVjC0hD7C/yR6kdeUBvCPOy9gDQ0g=
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=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
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/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0 h1:rgMkmiGfix9vFJDcDi1PK8WEQP4FLQwLDfhp5ZLpFeE=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0/go.mod h1:ijPqXp5P6IRRByFVVg9DY8P5HkxkHE5ARIa+86aXPf4=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 h1:CV7UdSGJt/Ao6Gp4CXckLxVRRsRgDHoI8XjbL3PDl8s=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0/go.mod h1:FRmFuRJfag1IZ2dPkHnEoSFVgTVPUd2qf5Vi69hLb8I=
go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY=
go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI=
go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ=
go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE=
go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A=
go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU=
go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiyYCU9snn1CU=
go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ=
go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k=
go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE=
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.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus=
golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M=
golang.org/x/exp v0.0.0-20250207012021-f9890c6ad9f3 h1:qNgPs5exUA+G0C96DrPwNrvLSj7GT/9D+3WMWUcUg34=
golang.org/x/exp v0.0.0-20250207012021-f9890c6ad9f3/go.mod h1:tujkw807nyEEAamNbDrEGzRav+ilXA7PCRAd6xsmwiU=
golang.org/x/exp/typeparams v0.0.0-20250218142911-aa4b98e5adaa h1:Br3+0EZZohShrmVVc85znGpxw7Ca8hsUJlrdT/JQGw8=
golang.org/x/exp/typeparams v0.0.0-20250218142911-aa4b98e5adaa/go.mod h1:LKZHyeOpPuZcMgxeHjJp4p5yvxrCX1xDvH10zYHhjjQ=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM=
golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8=
golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk=
golang.org/x/oauth2 v0.26.0 h1:afQXWNNaeC4nvZ0Ed9XvCCzXM6UHJG7iCg0W4fPqSBE=
golang.org/x/oauth2 v0.26.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
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.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/telemetry v0.0.0-20250214215356-6f9b61db478c h1:cA79rhMsZfyISI2vyH5j2XJb+QKQ7w/qWJNsR1PsRCI=
golang.org/x/telemetry v0.0.0-20250214215356-6f9b61db478c/go.mod h1:bDzXkYUaHzz51CtDy5kh/jR4lgPxsdbqC37kp/dzhCc=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU=
golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s=
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.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
golang.org/x/time v0.10.0 h1:3usCWA8tQn0L8+hFJQNgzpWbd89begxN66o1Ojdn5L4=
golang.org/x/time v0.10.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY=
golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY=
golang.org/x/vuln v1.1.4 h1:Ju8QsuyhX3Hk8ma3CesTbO8vfJD9EvUBgHvkxHBzj0I=
golang.org/x/vuln v1.1.4/go.mod h1:F+45wmU18ym/ca5PLTPLsSzr2KppzswxPP603ldA67s=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.221.0 h1:qzaJfLhDsbMeFee8zBRdt/Nc+xmOuafD/dbdgGfutOU=
google.golang.org/api v0.221.0/go.mod h1:7sOU2+TL4TxUTdbi0gWgAIg7tH5qBXxoyhtL+9x3biQ=
google.golang.org/genproto/googleapis/api v0.0.0-20250212204824-5a70512c5d8b h1:i+d0RZa8Hs2L/MuaOQYI+krthcxdEbEM2N+Tf3kJ4zk=
google.golang.org/genproto/googleapis/api v0.0.0-20250212204824-5a70512c5d8b/go.mod h1:iYONQfRdizDB8JJBybql13nArx91jcUk7zCXEsOofM4=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250212204824-5a70512c5d8b h1:FQtJ1MxbXoIIrZHZ33M+w5+dAP9o86rgpjoKr/ZmT7k=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250212204824-5a70512c5d8b/go.mod h1:8BS3B93F/U1juMFq9+EDk+qOT5CO1R9IzXxG3PTqiRk=
google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ=
google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw=
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
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=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.6.0 h1:TAODvD3knlq75WCp2nyGJtT4LeRV/o7NN9nYPeVJXf8=
honnef.co/go/tools v0.6.0/go.mod h1:3puzxxljPCe8RGJX7BIy1plGbxEOZni5mR2aXe3/uk4=
mvdan.cc/editorconfig v0.3.0 h1:D1D2wLYEYGpawWT5SpM5pRivgEgXjtEXwC9MWhEY0gQ=
mvdan.cc/editorconfig v0.3.0/go.mod h1:NcJHuDtNOTEJ6251indKiWuzK6+VcrMuLzGMLKBFupQ=
mvdan.cc/gofumpt v0.7.0 h1:bg91ttqXmi9y2xawvkuMXyvAA/1ZGJqYAEGjXuP0JXU=
mvdan.cc/gofumpt v0.7.0/go.mod h1:txVFJy/Sc/mvaycET54pV8SW8gWxTlUuGHVEcncmNUo=
mvdan.cc/sh/v3 v3.10.0 h1:v9z7N1DLZ7owyLM/SXZQkBSXcwr2IGMm2LY2pmhVXj4=
mvdan.cc/sh/v3 v3.10.0/go.mod h1:z/mSSVyLFGZzqb3ZIKojjyqIx/xbmz/UHdCSv9HmqXY=
mvdan.cc/unparam v0.0.0-20250211232406-0e51248738fc h1:mEpjEutR7Qjdis+HqGQNdsJY/uRbH/MnyGXzLKMhDFo=
mvdan.cc/unparam v0.0.0-20250211232406-0e51248738fc/go.mod h1:rthT7OuvRbaGcd5ginj6dA2oLE7YNlta9qhBNNdCaLE=

View File

@@ -1,24 +0,0 @@
//go:build tools
// Package tools and its main module are a nested internal module containing our
// development tool dependencies.
//
// See https://github.com/golang/go/wiki/Modules#how-can-i-track-tool-dependencies-for-a-module.
package tools
import (
_ "github.com/fzipp/gocyclo/cmd/gocyclo"
_ "github.com/golangci/misspell/cmd/misspell"
_ "github.com/gordonklaus/ineffassign"
_ "github.com/jstemmer/go-junit-report/v2"
_ "github.com/kisielk/errcheck"
_ "github.com/securego/gosec/v2/cmd/gosec"
_ "github.com/uudashr/gocognit/cmd/gocognit"
_ "golang.org/x/tools/go/analysis/passes/nilness/cmd/nilness"
_ "golang.org/x/tools/go/analysis/passes/shadow/cmd/shadow"
_ "golang.org/x/vuln/cmd/govulncheck"
_ "honnef.co/go/tools/cmd/staticcheck"
_ "mvdan.cc/gofumpt"
_ "mvdan.cc/sh/v3/cmd/shfmt"
_ "mvdan.cc/unparam"
)

View File

@@ -212,7 +212,6 @@ run_linter gocognit --over='10' \
./internal/rdns/ \
./internal/schedule/ \
./internal/stats/ \
./internal/tools/ \
./internal/version/ \
./internal/whois/ \
./scripts/ \
@@ -296,7 +295,6 @@ run_linter gosec --exclude G115 --quiet \
./internal/rdns/ \
./internal/schedule/ \
./internal/stats/ \
./internal/tools/ \
./internal/version/ \
./internal/whois/ \
;

View File

@@ -3,7 +3,7 @@
# This comment is used to simplify checking local copies of the script. Bump
# this number every time a significant change is made to this script.
#
# AdGuard-Project-Version: 6
# AdGuard-Project-Version: 7
verbose="${VERBOSE:-0}"
readonly verbose
@@ -25,30 +25,6 @@ readonly v_flags x_flags
set -e -f -u
go="${GO:-go}"
readonly go
# Remove only the actual binaries in the bin/ directory, as developers may add
# their own scripts there. Most commonly, a script named “go” for tools that
# call the go binary and need a particular version.
rm -f \
bin/errcheck \
bin/fieldalignment \
bin/go-junit-report \
bin/gocognit \
bin/gocyclo \
bin/gofumpt \
bin/gosec \
bin/govulncheck \
bin/ineffassign \
bin/misspell \
bin/nilness \
bin/shadow \
bin/shfmt \
bin/staticcheck \
bin/unparam \
;
# Reset GOARCH and GOOS to make sure we install the tools for the native
# architecture even when we're cross-compiling the main binary, and also to
# prevent the "cannot install cross-compiled binaries when GOBIN is set" error.
@@ -57,23 +33,5 @@ env \
GOBIN="${PWD}/bin" \
GOOS="" \
GOWORK='off' \
"$go" install \
--modfile=./internal/tools/go.mod \
"$v_flags" \
"$x_flags" \
github.com/fzipp/gocyclo/cmd/gocyclo \
github.com/golangci/misspell/cmd/misspell \
github.com/gordonklaus/ineffassign \
github.com/jstemmer/go-junit-report/v2 \
github.com/kisielk/errcheck \
github.com/securego/gosec/v2/cmd/gosec \
github.com/uudashr/gocognit/cmd/gocognit \
golang.org/x/tools/go/analysis/passes/fieldalignment/cmd/fieldalignment \
golang.org/x/tools/go/analysis/passes/nilness/cmd/nilness \
golang.org/x/tools/go/analysis/passes/shadow/cmd/shadow \
golang.org/x/vuln/cmd/govulncheck \
honnef.co/go/tools/cmd/staticcheck \
mvdan.cc/gofumpt \
mvdan.cc/sh/v3/cmd/shfmt \
mvdan.cc/unparam \
"${GO:-go}" install "$v_flags" "$x_flags" tool \
;

View File

@@ -3,7 +3,7 @@
# This comment is used to simplify checking local copies of the script. Bump
# this number every time a significant change is made to this script.
#
# AdGuard-Project-Version: 3
# AdGuard-Project-Version: 4
verbose="${VERBOSE:-0}"
readonly verbose
@@ -26,7 +26,5 @@ set -e -f -u
go="${GO:-go}"
readonly go
cd ./internal/tools/
"$go" get -u "$x_flags"
"$go" mod tidy
"$go" get -u "$x_flags" tool
"$go" mod tidy "$x_flags"